]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - drivers/media/dvb-frontends/dib3000mc.c
Merge remote-tracking branches 'asoc/topic/ac97', 'asoc/topic/ac97-mfd', 'asoc/topic...
[mirror_ubuntu-focal-kernel.git] / drivers / media / dvb-frontends / dib3000mc.c
CommitLineData
1da177e4 1/*
b7571f8d 2 * Driver for DiBcom DiB3000MC/P-demodulator.
1da177e4 3 *
b6884a17 4 * Copyright (C) 2004-7 DiBcom (http://www.dibcom.fr/)
99e44da7 5 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de)
1da177e4 6 *
b7571f8d 7 * This code is partially based on the previous dib3000mc.c .
1da177e4 8 *
b7571f8d 9 * This program is free software; you can redistribute it and/or
1da177e4
LT
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2.
1da177e4 12 */
b7571f8d 13
441d54e3
MCC
14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15
1da177e4 16#include <linux/kernel.h>
5a0e3ad6 17#include <linux/slab.h>
b7571f8d 18#include <linux/i2c.h>
b7571f8d
PB
19
20#include "dvb_frontend.h"
21
22#include "dib3000mc.h"
23
1da177e4
LT
24static int debug;
25module_param(debug, int, 0644);
b7571f8d 26MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
1da177e4 27
8f6956c7
MD
28static int buggy_sfn_workaround;
29module_param(buggy_sfn_workaround, int, 0644);
8d99996b 30MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
8f6956c7 31
441d54e3
MCC
32#define dprintk(fmt, arg...) do { \
33 if (debug) \
34 printk(KERN_DEBUG pr_fmt("%s: " fmt), \
35 __func__, ##arg); \
36} while (0)
b7571f8d
PB
37
38struct dib3000mc_state {
39 struct dvb_frontend demod;
40 struct dib3000mc_config *cfg;
41
42 u8 i2c_addr;
43 struct i2c_adapter *i2c_adap;
44
45 struct dibx000_i2c_master i2c_master;
46
01b4bf31
PB
47 u32 timf;
48
88ab898f 49 u32 current_bandwidth;
b7571f8d
PB
50
51 u16 dev_id;
8f6956c7
MD
52
53 u8 sfn_workaround_active :1;
b7571f8d
PB
54};
55
56static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg)
57{
b7571f8d 58 struct i2c_msg msg[2] = {
b4756707
SY
59 { .addr = state->i2c_addr >> 1, .flags = 0, .len = 2 },
60 { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .len = 2 },
b7571f8d 61 };
b4756707
SY
62 u16 word;
63 u8 *b;
64
65 b = kmalloc(4, GFP_KERNEL);
66 if (!b)
67 return 0;
68
69 b[0] = (reg >> 8) | 0x80;
70 b[1] = reg;
71 b[2] = 0;
72 b[3] = 0;
73
74 msg[0].buf = b;
75 msg[1].buf = b + 2;
b7571f8d
PB
76
77 if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
78 dprintk("i2c read error on %d\n",reg);
79
b4756707
SY
80 word = (b[2] << 8) | b[3];
81 kfree(b);
82
83 return word;
b7571f8d
PB
84}
85
86static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val)
87{
b7571f8d 88 struct i2c_msg msg = {
b4756707 89 .addr = state->i2c_addr >> 1, .flags = 0, .len = 4
b7571f8d 90 };
b4756707
SY
91 int rc;
92 u8 *b;
93
94 b = kmalloc(4, GFP_KERNEL);
95 if (!b)
96 return -ENOMEM;
97
98 b[0] = reg >> 8;
99 b[1] = reg;
100 b[2] = val >> 8;
101 b[3] = val;
102
103 msg.buf = b;
104
105 rc = i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
106 kfree(b);
107
108 return rc;
b7571f8d
PB
109}
110
b7571f8d 111static int dib3000mc_identify(struct dib3000mc_state *state)
1da177e4 112{
b7571f8d
PB
113 u16 value;
114 if ((value = dib3000mc_read_word(state, 1025)) != 0x01b3) {
115 dprintk("-E- DiB3000MC/P: wrong Vendor ID (read=0x%x)\n",value);
116 return -EREMOTEIO;
117 }
1da177e4 118
b7571f8d
PB
119 value = dib3000mc_read_word(state, 1026);
120 if (value != 0x3001 && value != 0x3002) {
121 dprintk("-E- DiB3000MC/P: wrong Device ID (%x)\n",value);
122 return -EREMOTEIO;
1da177e4 123 }
b7571f8d
PB
124 state->dev_id = value;
125
126 dprintk("-I- found DiB3000MC/P: %x\n",state->dev_id);
127
128 return 0;
129}
130
b6884a17 131static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u32 bw, u8 update_offset)
b7571f8d 132{
01b4bf31 133 u32 timf;
b7571f8d 134
01b4bf31
PB
135 if (state->timf == 0) {
136 timf = 1384402; // default value for 8MHz
137 if (update_offset)
138 msleep(200); // first time we do an update
1da177e4 139 } else
01b4bf31 140 timf = state->timf;
1da177e4 141
b6884a17 142 timf *= (bw / 1000);
1da177e4 143
01b4bf31
PB
144 if (update_offset) {
145 s16 tim_offs = dib3000mc_read_word(state, 416);
146
147 if (tim_offs & 0x2000)
148 tim_offs -= 0x4000;
149
b6884a17 150 if (nfft == TRANSMISSION_MODE_2K)
01b4bf31
PB
151 tim_offs *= 4;
152
153 timf += tim_offs;
b6884a17 154 state->timf = timf / (bw / 1000);
01b4bf31 155 }
b7571f8d 156
01b4bf31 157 dprintk("timf: %d\n", timf);
1da177e4 158
b6884a17
PB
159 dib3000mc_write_word(state, 23, (u16) (timf >> 16));
160 dib3000mc_write_word(state, 24, (u16) (timf ) & 0xffff);
1da177e4 161
1da177e4
LT
162 return 0;
163}
164
01b4bf31 165static int dib3000mc_setup_pwm_state(struct dib3000mc_state *state)
1da177e4 166{
01b4bf31 167 u16 reg_51, reg_52 = state->cfg->agc->setup & 0xfefb;
c7a092e3 168 if (state->cfg->pwm3_inversion) {
01b4bf31
PB
169 reg_51 = (2 << 14) | (0 << 10) | (7 << 6) | (2 << 2) | (2 << 0);
170 reg_52 |= (1 << 2);
1da177e4 171 } else {
01b4bf31
PB
172 reg_51 = (2 << 14) | (4 << 10) | (7 << 6) | (2 << 2) | (2 << 0);
173 reg_52 |= (1 << 8);
1da177e4 174 }
01b4bf31
PB
175 dib3000mc_write_word(state, 51, reg_51);
176 dib3000mc_write_word(state, 52, reg_52);
b7571f8d 177
c7a092e3 178 if (state->cfg->use_pwm3)
b7571f8d
PB
179 dib3000mc_write_word(state, 245, (1 << 3) | (1 << 0));
180 else
181 dib3000mc_write_word(state, 245, 0);
182
f9e2e0e8 183 dib3000mc_write_word(state, 1040, 0x3);
1da177e4
LT
184 return 0;
185}
186
b7571f8d 187static int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode)
1da177e4 188{
b7571f8d
PB
189 int ret = 0;
190 u16 fifo_threshold = 1792;
191 u16 outreg = 0;
192 u16 outmode = 0;
193 u16 elecout = 1;
fb6065bb 194 u16 smo_reg = dib3000mc_read_word(state, 206) & 0x0010; /* keep the pid_parse bit */
b7571f8d
PB
195
196 dprintk("-I- Setting output mode for demod %p to %d\n",
197 &state->demod, mode);
198
199 switch (mode) {
200 case OUTMODE_HIGH_Z: // disable
201 elecout = 0;
202 break;
203 case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock
204 outmode = 0;
205 break;
206 case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock
207 outmode = 1;
208 break;
209 case OUTMODE_MPEG2_SERIAL: // STBs with serial input
210 outmode = 2;
211 break;
212 case OUTMODE_MPEG2_FIFO: // e.g. USB feeding
213 elecout = 3;
214 /*ADDR @ 206 :
215 P_smo_error_discard [1;6:6] = 0
216 P_smo_rs_discard [1;5:5] = 0
217 P_smo_pid_parse [1;4:4] = 0
218 P_smo_fifo_flush [1;3:3] = 0
219 P_smo_mode [2;2:1] = 11
220 P_smo_ovf_prot [1;0:0] = 0
221 */
fb6065bb 222 smo_reg |= 3 << 1;
b7571f8d
PB
223 fifo_threshold = 512;
224 outmode = 5;
225 break;
226 case OUTMODE_DIVERSITY:
227 outmode = 4;
228 elecout = 1;
1da177e4
LT
229 break;
230 default:
b7571f8d
PB
231 dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod);
232 outmode = 0;
1da177e4
LT
233 break;
234 }
b7571f8d
PB
235
236 if ((state->cfg->output_mpeg2_in_188_bytes))
559463bb 237 smo_reg |= (1 << 5); // P_smo_rs_discard [1;5:5] = 1
b7571f8d
PB
238
239 outreg = dib3000mc_read_word(state, 244) & 0x07FF;
240 outreg |= (outmode << 11);
241 ret |= dib3000mc_write_word(state, 244, outreg);
242 ret |= dib3000mc_write_word(state, 206, smo_reg); /*smo_ mode*/
243 ret |= dib3000mc_write_word(state, 207, fifo_threshold); /* synchronous fread */
244 ret |= dib3000mc_write_word(state, 1040, elecout); /* P_out_cfg */
245 return ret;
1da177e4
LT
246}
247
b6884a17 248static int dib3000mc_set_bandwidth(struct dib3000mc_state *state, u32 bw)
1da177e4 249{
b7571f8d
PB
250 u16 bw_cfg[6] = { 0 };
251 u16 imp_bw_cfg[3] = { 0 };
252 u16 reg;
1da177e4 253
b7571f8d
PB
254/* settings here are for 27.7MHz */
255 switch (bw) {
b6884a17 256 case 8000:
b7571f8d
PB
257 bw_cfg[0] = 0x0019; bw_cfg[1] = 0x5c30; bw_cfg[2] = 0x0054; bw_cfg[3] = 0x88a0; bw_cfg[4] = 0x01a6; bw_cfg[5] = 0xab20;
258 imp_bw_cfg[0] = 0x04db; imp_bw_cfg[1] = 0x00db; imp_bw_cfg[2] = 0x00b7;
259 break;
1da177e4 260
b6884a17 261 case 7000:
b7571f8d
PB
262 bw_cfg[0] = 0x001c; bw_cfg[1] = 0xfba5; bw_cfg[2] = 0x0060; bw_cfg[3] = 0x9c25; bw_cfg[4] = 0x01e3; bw_cfg[5] = 0x0cb7;
263 imp_bw_cfg[0] = 0x04c0; imp_bw_cfg[1] = 0x00c0; imp_bw_cfg[2] = 0x00a0;
264 break;
1da177e4 265
b6884a17 266 case 6000:
b7571f8d
PB
267 bw_cfg[0] = 0x0021; bw_cfg[1] = 0xd040; bw_cfg[2] = 0x0070; bw_cfg[3] = 0xb62b; bw_cfg[4] = 0x0233; bw_cfg[5] = 0x8ed5;
268 imp_bw_cfg[0] = 0x04a5; imp_bw_cfg[1] = 0x00a5; imp_bw_cfg[2] = 0x0089;
1da177e4 269 break;
b7571f8d 270
b6884a17 271 case 5000:
b7571f8d
PB
272 bw_cfg[0] = 0x0028; bw_cfg[1] = 0x9380; bw_cfg[2] = 0x0087; bw_cfg[3] = 0x4100; bw_cfg[4] = 0x02a4; bw_cfg[5] = 0x4500;
273 imp_bw_cfg[0] = 0x0489; imp_bw_cfg[1] = 0x0089; imp_bw_cfg[2] = 0x0072;
1da177e4 274 break;
b7571f8d
PB
275
276 default: return -EINVAL;
1da177e4
LT
277 }
278
b7571f8d
PB
279 for (reg = 6; reg < 12; reg++)
280 dib3000mc_write_word(state, reg, bw_cfg[reg - 6]);
281 dib3000mc_write_word(state, 12, 0x0000);
282 dib3000mc_write_word(state, 13, 0x03e8);
283 dib3000mc_write_word(state, 14, 0x0000);
284 dib3000mc_write_word(state, 15, 0x03f2);
285 dib3000mc_write_word(state, 16, 0x0001);
286 dib3000mc_write_word(state, 17, 0xb0d0);
287 // P_sec_len
288 dib3000mc_write_word(state, 18, 0x0393);
289 dib3000mc_write_word(state, 19, 0x8700);
1da177e4 290
b7571f8d
PB
291 for (reg = 55; reg < 58; reg++)
292 dib3000mc_write_word(state, reg, imp_bw_cfg[reg - 55]);
1da177e4 293
b7571f8d 294 // Timing configuration
b6884a17 295 dib3000mc_set_timing(state, TRANSMISSION_MODE_2K, bw, 0);
1da177e4 296
b7571f8d
PB
297 return 0;
298}
1da177e4 299
b7571f8d 300static u16 impulse_noise_val[29] =
1da177e4 301
b7571f8d
PB
302{
303 0x38, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c, 0x3ffe, 0x7f3,
304 0x2d94, 0x76, 0x53d, 0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3, 0x3feb, 0x7d2,
305 0x365e, 0x76, 0x48c, 0x3ffe, 0x5b3, 0x3feb, 0x76, 0x0000, 0xd
306};
1da177e4 307
b7571f8d
PB
308static void dib3000mc_set_impulse_noise(struct dib3000mc_state *state, u8 mode, s16 nfft)
309{
310 u16 i;
311 for (i = 58; i < 87; i++)
312 dib3000mc_write_word(state, i, impulse_noise_val[i-58]);
313
b6884a17 314 if (nfft == TRANSMISSION_MODE_8K) {
b7571f8d
PB
315 dib3000mc_write_word(state, 58, 0x3b);
316 dib3000mc_write_word(state, 84, 0x00);
317 dib3000mc_write_word(state, 85, 0x8200);
1da177e4
LT
318 }
319
b7571f8d
PB
320 dib3000mc_write_word(state, 34, 0x1294);
321 dib3000mc_write_word(state, 35, 0x1ff8);
322 if (mode == 1)
323 dib3000mc_write_word(state, 55, dib3000mc_read_word(state, 55) | (1 << 10));
324}
325
326static int dib3000mc_init(struct dvb_frontend *demod)
327{
328 struct dib3000mc_state *state = demod->demodulator_priv;
329 struct dibx000_agc_config *agc = state->cfg->agc;
330
331 // Restart Configuration
332 dib3000mc_write_word(state, 1027, 0x8000);
333 dib3000mc_write_word(state, 1027, 0x0000);
334
335 // power up the demod + mobility configuration
336 dib3000mc_write_word(state, 140, 0x0000);
337 dib3000mc_write_word(state, 1031, 0);
338
339 if (state->cfg->mobile_mode) {
340 dib3000mc_write_word(state, 139, 0x0000);
341 dib3000mc_write_word(state, 141, 0x0000);
342 dib3000mc_write_word(state, 175, 0x0002);
343 dib3000mc_write_word(state, 1032, 0x0000);
1da177e4 344 } else {
b7571f8d
PB
345 dib3000mc_write_word(state, 139, 0x0001);
346 dib3000mc_write_word(state, 141, 0x0000);
347 dib3000mc_write_word(state, 175, 0x0000);
348 dib3000mc_write_word(state, 1032, 0x012C);
1da177e4 349 }
303cbeaa 350 dib3000mc_write_word(state, 1033, 0x0000);
1da177e4 351
b7571f8d 352 // P_clk_cfg
303cbeaa 353 dib3000mc_write_word(state, 1037, 0x3130);
1da177e4 354
b7571f8d 355 // other configurations
1da177e4 356
b7571f8d
PB
357 // P_ctrl_sfreq
358 dib3000mc_write_word(state, 33, (5 << 0));
359 dib3000mc_write_word(state, 88, (1 << 10) | (0x10 << 0));
1da177e4 360
b7571f8d
PB
361 // Phase noise control
362 // P_fft_phacor_inh, P_fft_phacor_cpe, P_fft_powrange
363 dib3000mc_write_word(state, 99, (1 << 9) | (0x20 << 0));
1da177e4 364
b7571f8d
PB
365 if (state->cfg->phase_noise_mode == 0)
366 dib3000mc_write_word(state, 111, 0x00);
367 else
368 dib3000mc_write_word(state, 111, 0x02);
369
370 // P_agc_global
371 dib3000mc_write_word(state, 50, 0x8000);
372
373 // agc setup misc
01b4bf31 374 dib3000mc_setup_pwm_state(state);
b7571f8d
PB
375
376 // P_agc_counter_lock
377 dib3000mc_write_word(state, 53, 0x87);
378 // P_agc_counter_unlock
379 dib3000mc_write_word(state, 54, 0x87);
380
381 /* agc */
382 dib3000mc_write_word(state, 36, state->cfg->max_time);
5570dd02 383 dib3000mc_write_word(state, 37, (state->cfg->agc_command1 << 13) | (state->cfg->agc_command2 << 12) | (0x1d << 0));
b7571f8d
PB
384 dib3000mc_write_word(state, 38, state->cfg->pwm3_value);
385 dib3000mc_write_word(state, 39, state->cfg->ln_adc_level);
386
387 // set_agc_loop_Bw
388 dib3000mc_write_word(state, 40, 0x0179);
389 dib3000mc_write_word(state, 41, 0x03f0);
390
391 dib3000mc_write_word(state, 42, agc->agc1_max);
392 dib3000mc_write_word(state, 43, agc->agc1_min);
393 dib3000mc_write_word(state, 44, agc->agc2_max);
394 dib3000mc_write_word(state, 45, agc->agc2_min);
395 dib3000mc_write_word(state, 46, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
396 dib3000mc_write_word(state, 47, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
397 dib3000mc_write_word(state, 48, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
398 dib3000mc_write_word(state, 49, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
399
400// Begin: TimeOut registers
401 // P_pha3_thres
402 dib3000mc_write_word(state, 110, 3277);
403 // P_timf_alpha = 6, P_corm_alpha = 6, P_corm_thres = 0x80
404 dib3000mc_write_word(state, 26, 0x6680);
405 // lock_mask0
406 dib3000mc_write_word(state, 1, 4);
407 // lock_mask1
408 dib3000mc_write_word(state, 2, 4);
409 // lock_mask2
410 dib3000mc_write_word(state, 3, 0x1000);
411 // P_search_maxtrial=1
412 dib3000mc_write_word(state, 5, 1);
413
b6884a17 414 dib3000mc_set_bandwidth(state, 8000);
b7571f8d
PB
415
416 // div_lock_mask
417 dib3000mc_write_word(state, 4, 0x814);
418
419 dib3000mc_write_word(state, 21, (1 << 9) | 0x164);
420 dib3000mc_write_word(state, 22, 0x463d);
421
422 // Spurious rm cfg
423 // P_cspu_regul, P_cspu_win_cut
424 dib3000mc_write_word(state, 120, 0x200f);
425 // P_adp_selec_monit
426 dib3000mc_write_word(state, 134, 0);
427
428 // Fec cfg
429 dib3000mc_write_word(state, 195, 0x10);
430
431 // diversity register: P_dvsy_sync_wait..
432 dib3000mc_write_word(state, 180, 0x2FF0);
433
434 // Impulse noise configuration
b6884a17 435 dib3000mc_set_impulse_noise(state, 0, TRANSMISSION_MODE_8K);
b7571f8d
PB
436
437 // output mode set-up
438 dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
439
440 /* close the i2c-gate */
441 dib3000mc_write_word(state, 769, (1 << 7) );
1da177e4 442
b7571f8d
PB
443 return 0;
444}
1da177e4 445
b7571f8d
PB
446static int dib3000mc_sleep(struct dvb_frontend *demod)
447{
448 struct dib3000mc_state *state = demod->demodulator_priv;
1da177e4 449
b7571f8d
PB
450 dib3000mc_write_word(state, 1031, 0xFFFF);
451 dib3000mc_write_word(state, 1032, 0xFFFF);
303cbeaa 452 dib3000mc_write_word(state, 1033, 0xFFF0);
1da177e4 453
c7a092e3 454 return 0;
b7571f8d 455}
1da177e4 456
b7571f8d
PB
457static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
458{
459 u16 cfg[4] = { 0 },reg;
460 switch (qam) {
b6884a17 461 case QPSK:
b7571f8d
PB
462 cfg[0] = 0x099a; cfg[1] = 0x7fae; cfg[2] = 0x0333; cfg[3] = 0x7ff0;
463 break;
b6884a17 464 case QAM_16:
b7571f8d
PB
465 cfg[0] = 0x023d; cfg[1] = 0x7fdf; cfg[2] = 0x00a4; cfg[3] = 0x7ff0;
466 break;
b6884a17 467 case QAM_64:
b7571f8d
PB
468 cfg[0] = 0x0148; cfg[1] = 0x7ff0; cfg[2] = 0x00a4; cfg[3] = 0x7ff8;
469 break;
1da177e4 470 }
b7571f8d
PB
471 for (reg = 129; reg < 133; reg++)
472 dib3000mc_write_word(state, reg, cfg[reg - 129]);
1da177e4
LT
473}
474
c1f814f4
MCC
475static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state,
476 struct dtv_frontend_properties *ch, u16 seq)
1da177e4 477{
b6884a17 478 u16 value;
c1f814f4
MCC
479 u32 bw = BANDWIDTH_TO_KHZ(ch->bandwidth_hz);
480
481 dib3000mc_set_bandwidth(state, bw);
482 dib3000mc_set_timing(state, ch->transmission_mode, bw, 0);
1da177e4 483
c7a092e3
MCC
484#if 1
485 dib3000mc_write_word(state, 100, (16 << 6) + 9);
486#else
487 if (boost)
488 dib3000mc_write_word(state, 100, (11 << 6) + 6);
489 else
b7571f8d 490 dib3000mc_write_word(state, 100, (16 << 6) + 9);
c7a092e3 491#endif
1da177e4 492
b7571f8d
PB
493 dib3000mc_write_word(state, 1027, 0x0800);
494 dib3000mc_write_word(state, 1027, 0x0000);
1da177e4 495
b7571f8d
PB
496 //Default cfg isi offset adp
497 dib3000mc_write_word(state, 26, 0x6680);
498 dib3000mc_write_word(state, 29, 0x1273);
499 dib3000mc_write_word(state, 33, 5);
b6884a17 500 dib3000mc_set_adp_cfg(state, QAM_16);
b7571f8d 501 dib3000mc_write_word(state, 133, 15564);
1da177e4 502
b7571f8d
PB
503 dib3000mc_write_word(state, 12 , 0x0);
504 dib3000mc_write_word(state, 13 , 0x3e8);
505 dib3000mc_write_word(state, 14 , 0x0);
506 dib3000mc_write_word(state, 15 , 0x3f2);
1da177e4 507
b7571f8d
PB
508 dib3000mc_write_word(state, 93,0);
509 dib3000mc_write_word(state, 94,0);
510 dib3000mc_write_word(state, 95,0);
511 dib3000mc_write_word(state, 96,0);
512 dib3000mc_write_word(state, 97,0);
513 dib3000mc_write_word(state, 98,0);
1da177e4 514
c1f814f4 515 dib3000mc_set_impulse_noise(state, 0, ch->transmission_mode);
e4d6c1f7 516
b6884a17 517 value = 0;
c1f814f4 518 switch (ch->transmission_mode) {
b6884a17
PB
519 case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
520 default:
521 case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
522 }
c1f814f4 523 switch (ch->guard_interval) {
b6884a17
PB
524 case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
525 case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
526 case GUARD_INTERVAL_1_4: value |= (3 << 5); break;
527 default:
528 case GUARD_INTERVAL_1_8: value |= (2 << 5); break;
529 }
c1f814f4 530 switch (ch->modulation) {
b6884a17
PB
531 case QPSK: value |= (0 << 3); break;
532 case QAM_16: value |= (1 << 3); break;
533 default:
534 case QAM_64: value |= (2 << 3); break;
535 }
536 switch (HIERARCHY_1) {
537 case HIERARCHY_2: value |= 2; break;
538 case HIERARCHY_4: value |= 4; break;
539 default:
540 case HIERARCHY_1: value |= 1; break;
541 }
542 dib3000mc_write_word(state, 0, value);
e3ab2fdd 543 dib3000mc_write_word(state, 5, (1 << 8) | ((seq & 0xf) << 4));
1da177e4 544
b6884a17 545 value = 0;
c1f814f4 546 if (ch->hierarchy == 1)
b6884a17
PB
547 value |= (1 << 4);
548 if (1 == 1)
549 value |= 1;
c1f814f4 550 switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
b6884a17
PB
551 case FEC_2_3: value |= (2 << 1); break;
552 case FEC_3_4: value |= (3 << 1); break;
553 case FEC_5_6: value |= (5 << 1); break;
554 case FEC_7_8: value |= (7 << 1); break;
555 default:
556 case FEC_1_2: value |= (1 << 1); break;
557 }
558 dib3000mc_write_word(state, 181, value);
1da177e4 559
b6884a17 560 // diversity synchro delay add 50% SFN margin
c1f814f4 561 switch (ch->transmission_mode) {
b6884a17
PB
562 case TRANSMISSION_MODE_8K: value = 256; break;
563 case TRANSMISSION_MODE_2K:
564 default: value = 64; break;
565 }
c1f814f4 566 switch (ch->guard_interval) {
b6884a17
PB
567 case GUARD_INTERVAL_1_16: value *= 2; break;
568 case GUARD_INTERVAL_1_8: value *= 4; break;
569 case GUARD_INTERVAL_1_4: value *= 8; break;
570 default:
571 case GUARD_INTERVAL_1_32: value *= 1; break;
572 }
573 value <<= 4;
574 value |= dib3000mc_read_word(state, 180) & 0x000f;
575 dib3000mc_write_word(state, 180, value);
1da177e4 576
b7571f8d 577 // restart demod
b6884a17
PB
578 value = dib3000mc_read_word(state, 0);
579 dib3000mc_write_word(state, 0, value | (1 << 9));
580 dib3000mc_write_word(state, 0, value);
1da177e4 581
b7571f8d 582 msleep(30);
1da177e4 583
c1f814f4 584 dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, ch->transmission_mode);
b7571f8d 585}
1da177e4 586
c1f814f4 587static int dib3000mc_autosearch_start(struct dvb_frontend *demod)
b7571f8d 588{
c1f814f4 589 struct dtv_frontend_properties *chan = &demod->dtv_property_cache;
b7571f8d
PB
590 struct dib3000mc_state *state = demod->demodulator_priv;
591 u16 reg;
592// u32 val;
c1f814f4 593 struct dtv_frontend_properties schan;
1da177e4 594
b6884a17 595 schan = *chan;
1da177e4 596
b6884a17 597 /* TODO what is that ? */
1da177e4 598
b7571f8d 599 /* a channel for autosearch */
c1f814f4
MCC
600 schan.transmission_mode = TRANSMISSION_MODE_8K;
601 schan.guard_interval = GUARD_INTERVAL_1_32;
602 schan.modulation = QAM_64;
603 schan.code_rate_HP = FEC_2_3;
604 schan.code_rate_LP = FEC_2_3;
605 schan.hierarchy = 0;
1da177e4 606
b6884a17 607 dib3000mc_set_channel_cfg(state, &schan, 11);
1da177e4 608
b7571f8d
PB
609 reg = dib3000mc_read_word(state, 0);
610 dib3000mc_write_word(state, 0, reg | (1 << 8));
01b4bf31 611 dib3000mc_read_word(state, 511);
b7571f8d 612 dib3000mc_write_word(state, 0, reg);
1da177e4 613
b7571f8d
PB
614 return 0;
615}
1da177e4 616
b7571f8d
PB
617static int dib3000mc_autosearch_is_irq(struct dvb_frontend *demod)
618{
619 struct dib3000mc_state *state = demod->demodulator_priv;
620 u16 irq_pending = dib3000mc_read_word(state, 511);
1da177e4 621
b7571f8d
PB
622 if (irq_pending & 0x1) // failed
623 return 1;
1da177e4 624
b7571f8d
PB
625 if (irq_pending & 0x2) // succeeded
626 return 2;
a16bf5d5 627
b7571f8d 628 return 0; // still pending
1da177e4 629}
b7571f8d 630
c1f814f4 631static int dib3000mc_tune(struct dvb_frontend *demod)
1da177e4 632{
c1f814f4 633 struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
b7571f8d 634 struct dib3000mc_state *state = demod->demodulator_priv;
1da177e4 635
b7571f8d
PB
636 // ** configure demod **
637 dib3000mc_set_channel_cfg(state, ch, 0);
638
639 // activates isi
8f6956c7
MD
640 if (state->sfn_workaround_active) {
641 dprintk("SFN workaround is active\n");
642 dib3000mc_write_word(state, 29, 0x1273);
643 dib3000mc_write_word(state, 108, 0x4000); // P_pha3_force_pha_shift
644 } else {
645 dib3000mc_write_word(state, 29, 0x1073);
646 dib3000mc_write_word(state, 108, 0x0000); // P_pha3_force_pha_shift
647 }
1da177e4 648
c1f814f4
MCC
649 dib3000mc_set_adp_cfg(state, (u8)ch->modulation);
650 if (ch->transmission_mode == TRANSMISSION_MODE_8K) {
b7571f8d
PB
651 dib3000mc_write_word(state, 26, 38528);
652 dib3000mc_write_word(state, 33, 8);
653 } else {
654 dib3000mc_write_word(state, 26, 30336);
655 dib3000mc_write_word(state, 33, 6);
656 }
657
01b4bf31 658 if (dib3000mc_read_word(state, 509) & 0x80)
c1f814f4
MCC
659 dib3000mc_set_timing(state, ch->transmission_mode,
660 BANDWIDTH_TO_KHZ(ch->bandwidth_hz), 1);
1da177e4
LT
661
662 return 0;
663}
664
b7571f8d 665struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating)
1da177e4 666{
b7571f8d
PB
667 struct dib3000mc_state *st = demod->demodulator_priv;
668 return dibx000_get_i2c_adapter(&st->i2c_master, DIBX000_I2C_INTERFACE_TUNER, gating);
1da177e4
LT
669}
670
b7571f8d
PB
671EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master);
672
7e3e68bc
MCC
673static int dib3000mc_get_frontend(struct dvb_frontend* fe,
674 struct dtv_frontend_properties *fep)
1da177e4 675{
b7571f8d
PB
676 struct dib3000mc_state *state = fe->demodulator_priv;
677 u16 tps = dib3000mc_read_word(state,458);
1da177e4 678
b7571f8d
PB
679 fep->inversion = INVERSION_AUTO;
680
c1f814f4 681 fep->bandwidth_hz = state->current_bandwidth;
b7571f8d
PB
682
683 switch ((tps >> 8) & 0x1) {
c1f814f4
MCC
684 case 0: fep->transmission_mode = TRANSMISSION_MODE_2K; break;
685 case 1: fep->transmission_mode = TRANSMISSION_MODE_8K; break;
b7571f8d
PB
686 }
687
688 switch (tps & 0x3) {
c1f814f4
MCC
689 case 0: fep->guard_interval = GUARD_INTERVAL_1_32; break;
690 case 1: fep->guard_interval = GUARD_INTERVAL_1_16; break;
691 case 2: fep->guard_interval = GUARD_INTERVAL_1_8; break;
692 case 3: fep->guard_interval = GUARD_INTERVAL_1_4; break;
b7571f8d
PB
693 }
694
695 switch ((tps >> 13) & 0x3) {
c1f814f4
MCC
696 case 0: fep->modulation = QPSK; break;
697 case 1: fep->modulation = QAM_16; break;
b7571f8d 698 case 2:
c1f814f4 699 default: fep->modulation = QAM_64; break;
b7571f8d
PB
700 }
701
702 /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
703 /* (tps >> 12) & 0x1 == hrch is used, (tps >> 9) & 0x7 == alpha */
704
c1f814f4 705 fep->hierarchy = HIERARCHY_NONE;
b7571f8d 706 switch ((tps >> 5) & 0x7) {
c1f814f4
MCC
707 case 1: fep->code_rate_HP = FEC_1_2; break;
708 case 2: fep->code_rate_HP = FEC_2_3; break;
709 case 3: fep->code_rate_HP = FEC_3_4; break;
710 case 5: fep->code_rate_HP = FEC_5_6; break;
b7571f8d 711 case 7:
c1f814f4 712 default: fep->code_rate_HP = FEC_7_8; break;
b7571f8d
PB
713
714 }
715
716 switch ((tps >> 2) & 0x7) {
c1f814f4
MCC
717 case 1: fep->code_rate_LP = FEC_1_2; break;
718 case 2: fep->code_rate_LP = FEC_2_3; break;
719 case 3: fep->code_rate_LP = FEC_3_4; break;
720 case 5: fep->code_rate_LP = FEC_5_6; break;
b7571f8d 721 case 7:
c1f814f4 722 default: fep->code_rate_LP = FEC_7_8; break;
b7571f8d 723 }
1da177e4 724
1da177e4
LT
725 return 0;
726}
727
c1f814f4 728static int dib3000mc_set_frontend(struct dvb_frontend *fe)
1da177e4 729{
7c61d80a 730 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
b7571f8d 731 struct dib3000mc_state *state = fe->demodulator_priv;
c1f814f4 732 int ret;
853ea132
SM
733
734 dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
b7571f8d 735
c1f814f4
MCC
736 state->current_bandwidth = fep->bandwidth_hz;
737 dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->bandwidth_hz));
b7571f8d 738
8f6956c7
MD
739 /* maybe the parameter has been changed */
740 state->sfn_workaround_active = buggy_sfn_workaround;
741
b7571f8d 742 if (fe->ops.tuner_ops.set_params) {
14d24d14 743 fe->ops.tuner_ops.set_params(fe);
b7571f8d
PB
744 msleep(100);
745 }
746
c1f814f4
MCC
747 if (fep->transmission_mode == TRANSMISSION_MODE_AUTO ||
748 fep->guard_interval == GUARD_INTERVAL_AUTO ||
749 fep->modulation == QAM_AUTO ||
750 fep->code_rate_HP == FEC_AUTO) {
3a0311c6 751 int i = 1000, found;
b7571f8d 752
c1f814f4 753 dib3000mc_autosearch_start(fe);
b7571f8d
PB
754 do {
755 msleep(1);
756 found = dib3000mc_autosearch_is_irq(fe);
757 } while (found == 0 && i--);
758
759 dprintk("autosearch returns: %d\n",found);
760 if (found == 0 || found == 1)
761 return 0; // no channel found
762
7e3e68bc 763 dib3000mc_get_frontend(fe, fep);
b7571f8d
PB
764 }
765
c1f814f4 766 ret = dib3000mc_tune(fe);
853ea132 767
b7571f8d
PB
768 /* make this a config parameter */
769 dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO);
c1f814f4 770 return ret;
1da177e4
LT
771}
772
0df289a2 773static int dib3000mc_read_status(struct dvb_frontend *fe, enum fe_status *stat)
1da177e4 774{
b7571f8d
PB
775 struct dib3000mc_state *state = fe->demodulator_priv;
776 u16 lock = dib3000mc_read_word(state, 509);
777
778 *stat = 0;
779
780 if (lock & 0x8000)
781 *stat |= FE_HAS_SIGNAL;
782 if (lock & 0x3000)
783 *stat |= FE_HAS_CARRIER;
784 if (lock & 0x0100)
785 *stat |= FE_HAS_VITERBI;
786 if (lock & 0x0010)
787 *stat |= FE_HAS_SYNC;
788 if (lock & 0x0008)
789 *stat |= FE_HAS_LOCK;
790
1da177e4
LT
791 return 0;
792}
793
b7571f8d 794static int dib3000mc_read_ber(struct dvb_frontend *fe, u32 *ber)
1da177e4 795{
b7571f8d
PB
796 struct dib3000mc_state *state = fe->demodulator_priv;
797 *ber = (dib3000mc_read_word(state, 500) << 16) | dib3000mc_read_word(state, 501);
798 return 0;
1da177e4
LT
799}
800
b7571f8d 801static int dib3000mc_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
1da177e4 802{
b7571f8d
PB
803 struct dib3000mc_state *state = fe->demodulator_priv;
804 *unc = dib3000mc_read_word(state, 508);
805 return 0;
1da177e4
LT
806}
807
b7571f8d 808static int dib3000mc_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
1da177e4 809{
b7571f8d
PB
810 struct dib3000mc_state *state = fe->demodulator_priv;
811 u16 val = dib3000mc_read_word(state, 392);
812 *strength = 65535 - val;
813 return 0;
1da177e4
LT
814}
815
b7571f8d 816static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr)
1da177e4 817{
b7571f8d 818 *snr = 0x0000;
1da177e4
LT
819 return 0;
820}
821
b7571f8d 822static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
1da177e4 823{
b7571f8d 824 tune->min_delay_ms = 1000;
1da177e4
LT
825 return 0;
826}
827
b7571f8d 828static void dib3000mc_release(struct dvb_frontend *fe)
1da177e4 829{
b7571f8d
PB
830 struct dib3000mc_state *state = fe->demodulator_priv;
831 dibx000_exit_i2c_master(&state->i2c_master);
832 kfree(state);
1da177e4
LT
833}
834
b7571f8d 835int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff)
1da177e4 836{
b7571f8d
PB
837 struct dib3000mc_state *state = fe->demodulator_priv;
838 dib3000mc_write_word(state, 212 + index, onoff ? (1 << 13) | pid : 0);
1da177e4
LT
839 return 0;
840}
b7571f8d 841EXPORT_SYMBOL(dib3000mc_pid_control);
1da177e4 842
b7571f8d 843int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff)
1da177e4 844{
b7571f8d
PB
845 struct dib3000mc_state *state = fe->demodulator_priv;
846 u16 tmp = dib3000mc_read_word(state, 206) & ~(1 << 4);
847 tmp |= (onoff << 4);
848 return dib3000mc_write_word(state, 206, tmp);
1da177e4 849}
b7571f8d 850EXPORT_SYMBOL(dib3000mc_pid_parse);
1da177e4 851
b7571f8d 852void dib3000mc_set_config(struct dvb_frontend *fe, struct dib3000mc_config *cfg)
e4d6c1f7 853{
b7571f8d
PB
854 struct dib3000mc_state *state = fe->demodulator_priv;
855 state->cfg = cfg;
e4d6c1f7 856}
b7571f8d 857EXPORT_SYMBOL(dib3000mc_set_config);
1da177e4 858
136cafbf 859int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib3000mc_config cfg[])
1da177e4 860{
0de8e353 861 struct dib3000mc_state *dmcst;
136cafbf
PB
862 int k;
863 u8 new_addr;
1da177e4 864
136cafbf 865 static u8 DIB3000MC_I2C_ADDRESS[] = {20,22,24,26};
1da177e4 866
0de8e353
RD
867 dmcst = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
868 if (dmcst == NULL)
febe2ea1 869 return -ENOMEM;
0de8e353
RD
870
871 dmcst->i2c_adap = i2c;
872
136cafbf 873 for (k = no_of_demods-1; k >= 0; k--) {
0de8e353 874 dmcst->cfg = &cfg[k];
1da177e4 875
136cafbf
PB
876 /* designated i2c address */
877 new_addr = DIB3000MC_I2C_ADDRESS[k];
0de8e353
RD
878 dmcst->i2c_addr = new_addr;
879 if (dib3000mc_identify(dmcst) != 0) {
880 dmcst->i2c_addr = default_addr;
881 if (dib3000mc_identify(dmcst) != 0) {
136cafbf 882 dprintk("-E- DiB3000P/MC #%d: not identified\n", k);
0de8e353 883 kfree(dmcst);
136cafbf
PB
884 return -ENODEV;
885 }
886 }
1da177e4 887
0de8e353 888 dib3000mc_set_output_mode(dmcst, OUTMODE_MPEG2_PAR_CONT_CLK);
1da177e4 889
136cafbf 890 // set new i2c address and force divstr (Bit 1) to value 0 (Bit 0)
0de8e353
RD
891 dib3000mc_write_word(dmcst, 1024, (new_addr << 3) | 0x1);
892 dmcst->i2c_addr = new_addr;
b7571f8d 893 }
1da177e4 894
136cafbf 895 for (k = 0; k < no_of_demods; k++) {
0de8e353
RD
896 dmcst->cfg = &cfg[k];
897 dmcst->i2c_addr = DIB3000MC_I2C_ADDRESS[k];
1da177e4 898
0de8e353 899 dib3000mc_write_word(dmcst, 1024, dmcst->i2c_addr << 3);
1da177e4 900
136cafbf 901 /* turn off data output */
0de8e353 902 dib3000mc_set_output_mode(dmcst, OUTMODE_HIGH_Z);
136cafbf 903 }
0de8e353
RD
904
905 kfree(dmcst);
b7571f8d 906 return 0;
136cafbf
PB
907}
908EXPORT_SYMBOL(dib3000mc_i2c_enumeration);
909
bd336e63 910static const struct dvb_frontend_ops dib3000mc_ops;
136cafbf
PB
911
912struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg)
913{
914 struct dvb_frontend *demod;
915 struct dib3000mc_state *st;
916 st = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
917 if (st == NULL)
918 return NULL;
919
920 st->cfg = cfg;
921 st->i2c_adap = i2c_adap;
6958effe 922 st->i2c_addr = i2c_addr;
136cafbf
PB
923
924 demod = &st->demod;
925 demod->demodulator_priv = st;
926 memcpy(&st->demod.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
927
928 if (dib3000mc_identify(st) != 0)
929 goto error;
930
931 dibx000_init_i2c_master(&st->i2c_master, DIB3000MC, st->i2c_adap, st->i2c_addr);
932
303cbeaa
PB
933 dib3000mc_write_word(st, 1037, 0x3130);
934
136cafbf 935 return demod;
1da177e4
LT
936
937error:
136cafbf
PB
938 kfree(st);
939 return NULL;
1da177e4 940}
e4d6c1f7 941EXPORT_SYMBOL(dib3000mc_attach);
1da177e4 942
bd336e63 943static const struct dvb_frontend_ops dib3000mc_ops = {
c1f814f4 944 .delsys = { SYS_DVBT },
1da177e4 945 .info = {
b7571f8d 946 .name = "DiBcom 3000MC/P",
b7571f8d
PB
947 .frequency_min = 44250000,
948 .frequency_max = 867250000,
949 .frequency_stepsize = 62500,
1da177e4 950 .caps = FE_CAN_INVERSION_AUTO |
b7571f8d
PB
951 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
952 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
953 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
954 FE_CAN_TRANSMISSION_MODE_AUTO |
955 FE_CAN_GUARD_INTERVAL_AUTO |
956 FE_CAN_RECOVER |
957 FE_CAN_HIERARCHY_AUTO,
1da177e4
LT
958 },
959
b7571f8d 960 .release = dib3000mc_release,
1da177e4 961
b7571f8d
PB
962 .init = dib3000mc_init,
963 .sleep = dib3000mc_sleep,
1da177e4 964
c1f814f4 965 .set_frontend = dib3000mc_set_frontend,
b7571f8d 966 .get_tune_settings = dib3000mc_fe_get_tune_settings,
c1f814f4 967 .get_frontend = dib3000mc_get_frontend,
1da177e4 968
b7571f8d
PB
969 .read_status = dib3000mc_read_status,
970 .read_ber = dib3000mc_read_ber,
1da177e4 971 .read_signal_strength = dib3000mc_read_signal_strength,
b7571f8d
PB
972 .read_snr = dib3000mc_read_snr,
973 .read_ucblocks = dib3000mc_read_unc_blocks,
1da177e4
LT
974};
975
99e44da7 976MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
b7571f8d 977MODULE_DESCRIPTION("Driver for the DiBcom 3000MC/P COFDM demodulator");
1da177e4 978MODULE_LICENSE("GPL");