aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/dib7000p.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/frontends/dib7000p.c')
-rw-r--r--drivers/media/dvb/frontends/dib7000p.c2426
1 files changed, 2426 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
new file mode 100644
index 00000000000..4eb9c2b49cd
--- /dev/null
+++ b/drivers/media/dvb/frontends/dib7000p.c
@@ -0,0 +1,2426 @@
1/*
2 * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC).
3 *
4 * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2.
9 */
10#include <linux/kernel.h>
11#include <linux/slab.h>
12#include <linux/i2c.h>
13#include <linux/mutex.h>
14
15#include "dvb_math.h"
16#include "dvb_frontend.h"
17
18#include "dib7000p.h"
19
20static int debug;
21module_param(debug, int, 0644);
22MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
23
24static int buggy_sfn_workaround;
25module_param(buggy_sfn_workaround, int, 0644);
26MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
27
28#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P: "); printk(args); printk("\n"); } } while (0)
29
30struct i2c_device {
31 struct i2c_adapter *i2c_adap;
32 u8 i2c_addr;
33};
34
35struct dib7000p_state {
36 struct dvb_frontend demod;
37 struct dib7000p_config cfg;
38
39 u8 i2c_addr;
40 struct i2c_adapter *i2c_adap;
41
42 struct dibx000_i2c_master i2c_master;
43
44 u16 wbd_ref;
45
46 u8 current_band;
47 u32 current_bandwidth;
48 struct dibx000_agc_config *current_agc;
49 u32 timf;
50
51 u8 div_force_off:1;
52 u8 div_state:1;
53 u16 div_sync_wait;
54
55 u8 agc_state;
56
57 u16 gpio_dir;
58 u16 gpio_val;
59
60 u8 sfn_workaround_active:1;
61
62#define SOC7090 0x7090
63 u16 version;
64
65 u16 tuner_enable;
66 struct i2c_adapter dib7090_tuner_adap;
67
68 /* for the I2C transfer */
69 struct i2c_msg msg[2];
70 u8 i2c_write_buffer[4];
71 u8 i2c_read_buffer[2];
72 struct mutex i2c_buffer_lock;
73};
74
75enum dib7000p_power_mode {
76 DIB7000P_POWER_ALL = 0,
77 DIB7000P_POWER_ANALOG_ADC,
78 DIB7000P_POWER_INTERFACE_ONLY,
79};
80
81static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode);
82static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff);
83
84static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
85{
86 u16 ret;
87
88 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
89 dprintk("could not acquire lock");
90 return 0;
91 }
92
93 state->i2c_write_buffer[0] = reg >> 8;
94 state->i2c_write_buffer[1] = reg & 0xff;
95
96 memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
97 state->msg[0].addr = state->i2c_addr >> 1;
98 state->msg[0].flags = 0;
99 state->msg[0].buf = state->i2c_write_buffer;
100 state->msg[0].len = 2;
101 state->msg[1].addr = state->i2c_addr >> 1;
102 state->msg[1].flags = I2C_M_RD;
103 state->msg[1].buf = state->i2c_read_buffer;
104 state->msg[1].len = 2;
105
106 if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
107 dprintk("i2c read error on %d", reg);
108
109 ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
110 mutex_unlock(&state->i2c_buffer_lock);
111 return ret;
112}
113
114static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
115{
116 int ret;
117
118 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
119 dprintk("could not acquire lock");
120 return -EINVAL;
121 }
122
123 state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
124 state->i2c_write_buffer[1] = reg & 0xff;
125 state->i2c_write_buffer[2] = (val >> 8) & 0xff;
126 state->i2c_write_buffer[3] = val & 0xff;
127
128 memset(&state->msg[0], 0, sizeof(struct i2c_msg));
129 state->msg[0].addr = state->i2c_addr >> 1;
130 state->msg[0].flags = 0;
131 state->msg[0].buf = state->i2c_write_buffer;
132 state->msg[0].len = 4;
133
134 ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
135 -EREMOTEIO : 0);
136 mutex_unlock(&state->i2c_buffer_lock);
137 return ret;
138}
139
140static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
141{
142 u16 l = 0, r, *n;
143 n = buf;
144 l = *n++;
145 while (l) {
146 r = *n++;
147
148 do {
149 dib7000p_write_word(state, r, *n++);
150 r++;
151 } while (--l);
152 l = *n++;
153 }
154}
155
156static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode)
157{
158 int ret = 0;
159 u16 outreg, fifo_threshold, smo_mode;
160
161 outreg = 0;
162 fifo_threshold = 1792;
163 smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1);
164
165 dprintk("setting output mode for demod %p to %d", &state->demod, mode);
166
167 switch (mode) {
168 case OUTMODE_MPEG2_PAR_GATED_CLK:
169 outreg = (1 << 10); /* 0x0400 */
170 break;
171 case OUTMODE_MPEG2_PAR_CONT_CLK:
172 outreg = (1 << 10) | (1 << 6); /* 0x0440 */
173 break;
174 case OUTMODE_MPEG2_SERIAL:
175 outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0480 */
176 break;
177 case OUTMODE_DIVERSITY:
178 if (state->cfg.hostbus_diversity)
179 outreg = (1 << 10) | (4 << 6); /* 0x0500 */
180 else
181 outreg = (1 << 11);
182 break;
183 case OUTMODE_MPEG2_FIFO:
184 smo_mode |= (3 << 1);
185 fifo_threshold = 512;
186 outreg = (1 << 10) | (5 << 6);
187 break;
188 case OUTMODE_ANALOG_ADC:
189 outreg = (1 << 10) | (3 << 6);
190 break;
191 case OUTMODE_HIGH_Z:
192 outreg = 0;
193 break;
194 default:
195 dprintk("Unhandled output_mode passed to be set for demod %p", &state->demod);
196 break;
197 }
198
199 if (state->cfg.output_mpeg2_in_188_bytes)
200 smo_mode |= (1 << 5);
201
202 ret |= dib7000p_write_word(state, 235, smo_mode);
203 ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */
204 if (state->version != SOC7090)
205 ret |= dib7000p_write_word(state, 1286, outreg); /* P_Div_active */
206
207 return ret;
208}
209
210static int dib7000p_set_diversity_in(struct dvb_frontend *demod, int onoff)
211{
212 struct dib7000p_state *state = demod->demodulator_priv;
213
214 if (state->div_force_off) {
215 dprintk("diversity combination deactivated - forced by COFDM parameters");
216 onoff = 0;
217 dib7000p_write_word(state, 207, 0);
218 } else
219 dib7000p_write_word(state, 207, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
220
221 state->div_state = (u8) onoff;
222
223 if (onoff) {
224 dib7000p_write_word(state, 204, 6);
225 dib7000p_write_word(state, 205, 16);
226 /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
227 } else {
228 dib7000p_write_word(state, 204, 1);
229 dib7000p_write_word(state, 205, 0);
230 }
231
232 return 0;
233}
234
235static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode)
236{
237 /* by default everything is powered off */
238 u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899 = 0x0003, reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff);
239
240 /* now, depending on the requested mode, we power on */
241 switch (mode) {
242 /* power up everything in the demod */
243 case DIB7000P_POWER_ALL:
244 reg_774 = 0x0000;
245 reg_775 = 0x0000;
246 reg_776 = 0x0;
247 reg_899 = 0x0;
248 if (state->version == SOC7090)
249 reg_1280 &= 0x001f;
250 else
251 reg_1280 &= 0x01ff;
252 break;
253
254 case DIB7000P_POWER_ANALOG_ADC:
255 /* dem, cfg, iqc, sad, agc */
256 reg_774 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10) | (1 << 9));
257 /* nud */
258 reg_776 &= ~((1 << 0));
259 /* Dout */
260 if (state->version != SOC7090)
261 reg_1280 &= ~((1 << 11));
262 reg_1280 &= ~(1 << 6);
263 /* fall through wanted to enable the interfaces */
264
265 /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */
266 case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */
267 if (state->version == SOC7090)
268 reg_1280 &= ~((1 << 7) | (1 << 5));
269 else
270 reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10));
271 break;
272
273/* TODO following stuff is just converted from the dib7000-driver - check when is used what */
274 }
275
276 dib7000p_write_word(state, 774, reg_774);
277 dib7000p_write_word(state, 775, reg_775);
278 dib7000p_write_word(state, 776, reg_776);
279 dib7000p_write_word(state, 899, reg_899);
280 dib7000p_write_word(state, 1280, reg_1280);
281
282 return 0;
283}
284
285static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no)
286{
287 u16 reg_908 = dib7000p_read_word(state, 908), reg_909 = dib7000p_read_word(state, 909);
288 u16 reg;
289
290 switch (no) {
291 case DIBX000_SLOW_ADC_ON:
292 if (state->version == SOC7090) {
293 reg = dib7000p_read_word(state, 1925);
294
295 dib7000p_write_word(state, 1925, reg | (1 << 4) | (1 << 2)); /* en_slowAdc = 1 & reset_sladc = 1 */
296
297 reg = dib7000p_read_word(state, 1925); /* read acces to make it works... strange ... */
298 msleep(200);
299 dib7000p_write_word(state, 1925, reg & ~(1 << 4)); /* en_slowAdc = 1 & reset_sladc = 0 */
300
301 reg = dib7000p_read_word(state, 72) & ~((0x3 << 14) | (0x3 << 12));
302 dib7000p_write_word(state, 72, reg | (1 << 14) | (3 << 12) | 524); /* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ; (Vin2 = Vcm) */
303 } else {
304 reg_909 |= (1 << 1) | (1 << 0);
305 dib7000p_write_word(state, 909, reg_909);
306 reg_909 &= ~(1 << 1);
307 }
308 break;
309
310 case DIBX000_SLOW_ADC_OFF:
311 if (state->version == SOC7090) {
312 reg = dib7000p_read_word(state, 1925);
313 dib7000p_write_word(state, 1925, (reg & ~(1 << 2)) | (1 << 4)); /* reset_sladc = 1 en_slowAdc = 0 */
314 } else
315 reg_909 |= (1 << 1) | (1 << 0);
316 break;
317
318 case DIBX000_ADC_ON:
319 reg_908 &= 0x0fff;
320 reg_909 &= 0x0003;
321 break;
322
323 case DIBX000_ADC_OFF:
324 reg_908 |= (1 << 14) | (1 << 13) | (1 << 12);
325 reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
326 break;
327
328 case DIBX000_VBG_ENABLE:
329 reg_908 &= ~(1 << 15);
330 break;
331
332 case DIBX000_VBG_DISABLE:
333 reg_908 |= (1 << 15);
334 break;
335
336 default:
337 break;
338 }
339
340// dprintk( "908: %x, 909: %x\n", reg_908, reg_909);
341
342 reg_909 |= (state->cfg.disable_sample_and_hold & 1) << 4;
343 reg_908 |= (state->cfg.enable_current_mirror & 1) << 7;
344
345 dib7000p_write_word(state, 908, reg_908);
346 dib7000p_write_word(state, 909, reg_909);
347}
348
349static int dib7000p_set_bandwidth(struct dib7000p_state *state, u32 bw)
350{
351 u32 timf;
352
353 // store the current bandwidth for later use
354 state->current_bandwidth = bw;
355
356 if (state->timf == 0) {
357 dprintk("using default timf");
358 timf = state->cfg.bw->timf;
359 } else {
360 dprintk("using updated timf");
361 timf = state->timf;
362 }
363
364 timf = timf * (bw / 50) / 160;
365
366 dib7000p_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
367 dib7000p_write_word(state, 24, (u16) ((timf) & 0xffff));
368
369 return 0;
370}
371
372static int dib7000p_sad_calib(struct dib7000p_state *state)
373{
374/* internal */
375 dib7000p_write_word(state, 73, (0 << 1) | (0 << 0));
376
377 if (state->version == SOC7090)
378 dib7000p_write_word(state, 74, 2048);
379 else
380 dib7000p_write_word(state, 74, 776);
381
382 /* do the calibration */
383 dib7000p_write_word(state, 73, (1 << 0));
384 dib7000p_write_word(state, 73, (0 << 0));
385
386 msleep(1);
387
388 return 0;
389}
390
391int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
392{
393 struct dib7000p_state *state = demod->demodulator_priv;
394 if (value > 4095)
395 value = 4095;
396 state->wbd_ref = value;
397 return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
398}
399EXPORT_SYMBOL(dib7000p_set_wbd_ref);
400
401static void dib7000p_reset_pll(struct dib7000p_state *state)
402{
403 struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
404 u16 clk_cfg0;
405
406 if (state->version == SOC7090) {
407 dib7000p_write_word(state, 1856, (!bw->pll_reset << 13) | (bw->pll_range << 12) | (bw->pll_ratio << 6) | (bw->pll_prediv));
408
409 while (((dib7000p_read_word(state, 1856) >> 15) & 0x1) != 1)
410 ;
411
412 dib7000p_write_word(state, 1857, dib7000p_read_word(state, 1857) | (!bw->pll_bypass << 15));
413 } else {
414 /* force PLL bypass */
415 clk_cfg0 = (1 << 15) | ((bw->pll_ratio & 0x3f) << 9) |
416 (bw->modulo << 7) | (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0);
417
418 dib7000p_write_word(state, 900, clk_cfg0);
419
420 /* P_pll_cfg */
421 dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset);
422 clk_cfg0 = (bw->pll_bypass << 15) | (clk_cfg0 & 0x7fff);
423 dib7000p_write_word(state, 900, clk_cfg0);
424 }
425
426 dib7000p_write_word(state, 18, (u16) (((bw->internal * 1000) >> 16) & 0xffff));
427 dib7000p_write_word(state, 19, (u16) ((bw->internal * 1000) & 0xffff));
428 dib7000p_write_word(state, 21, (u16) ((bw->ifreq >> 16) & 0xffff));
429 dib7000p_write_word(state, 22, (u16) ((bw->ifreq) & 0xffff));
430
431 dib7000p_write_word(state, 72, bw->sad_cfg);
432}
433
434static u32 dib7000p_get_internal_freq(struct dib7000p_state *state)
435{
436 u32 internal = (u32) dib7000p_read_word(state, 18) << 16;
437 internal |= (u32) dib7000p_read_word(state, 19);
438 internal /= 1000;
439
440 return internal;
441}
442
443int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
444{
445 struct dib7000p_state *state = fe->demodulator_priv;
446 u16 reg_1857, reg_1856 = dib7000p_read_word(state, 1856);
447 u8 loopdiv, prediv;
448 u32 internal, xtal;
449
450 /* get back old values */
451 prediv = reg_1856 & 0x3f;
452 loopdiv = (reg_1856 >> 6) & 0x3f;
453
454 if ((bw != NULL) && (bw->pll_prediv != prediv || bw->pll_ratio != loopdiv)) {
455 dprintk("Updating pll (prediv: old = %d new = %d ; loopdiv : old = %d new = %d)", prediv, bw->pll_prediv, loopdiv, bw->pll_ratio);
456 reg_1856 &= 0xf000;
457 reg_1857 = dib7000p_read_word(state, 1857);
458 dib7000p_write_word(state, 1857, reg_1857 & ~(1 << 15));
459
460 dib7000p_write_word(state, 1856, reg_1856 | ((bw->pll_ratio & 0x3f) << 6) | (bw->pll_prediv & 0x3f));
461
462 /* write new system clk into P_sec_len */
463 internal = dib7000p_get_internal_freq(state);
464 xtal = (internal / loopdiv) * prediv;
465 internal = 1000 * (xtal / bw->pll_prediv) * bw->pll_ratio; /* new internal */
466 dib7000p_write_word(state, 18, (u16) ((internal >> 16) & 0xffff));
467 dib7000p_write_word(state, 19, (u16) (internal & 0xffff));
468
469 dib7000p_write_word(state, 1857, reg_1857 | (1 << 15));
470
471 while (((dib7000p_read_word(state, 1856) >> 15) & 0x1) != 1)
472 dprintk("Waiting for PLL to lock");
473
474 return 0;
475 }
476 return -EIO;
477}
478EXPORT_SYMBOL(dib7000p_update_pll);
479
480static int dib7000p_reset_gpio(struct dib7000p_state *st)
481{
482 /* reset the GPIOs */
483 dprintk("gpio dir: %x: val: %x, pwm_pos: %x", st->gpio_dir, st->gpio_val, st->cfg.gpio_pwm_pos);
484
485 dib7000p_write_word(st, 1029, st->gpio_dir);
486 dib7000p_write_word(st, 1030, st->gpio_val);
487
488 /* TODO 1031 is P_gpio_od */
489
490 dib7000p_write_word(st, 1032, st->cfg.gpio_pwm_pos);
491
492 dib7000p_write_word(st, 1037, st->cfg.pwm_freq_div);
493 return 0;
494}
495
496static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
497{
498 st->gpio_dir = dib7000p_read_word(st, 1029);
499 st->gpio_dir &= ~(1 << num); /* reset the direction bit */
500 st->gpio_dir |= (dir & 0x1) << num; /* set the new direction */
501 dib7000p_write_word(st, 1029, st->gpio_dir);
502
503 st->gpio_val = dib7000p_read_word(st, 1030);
504 st->gpio_val &= ~(1 << num); /* reset the direction bit */
505 st->gpio_val |= (val & 0x01) << num; /* set the new value */
506 dib7000p_write_word(st, 1030, st->gpio_val);
507
508 return 0;
509}
510
511int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
512{
513 struct dib7000p_state *state = demod->demodulator_priv;
514 return dib7000p_cfg_gpio(state, num, dir, val);
515}
516EXPORT_SYMBOL(dib7000p_set_gpio);
517
518static u16 dib7000p_defaults[] = {
519 // auto search configuration
520 3, 2,
521 0x0004,
522 0x1000,
523 0x0814, /* Equal Lock */
524
525 12, 6,
526 0x001b,
527 0x7740,
528 0x005b,
529 0x8d80,
530 0x01c9,
531 0xc380,
532 0x0000,
533 0x0080,
534 0x0000,
535 0x0090,
536 0x0001,
537 0xd4c0,
538
539 1, 26,
540 0x6680,
541
542 /* set ADC level to -16 */
543 11, 79,
544 (1 << 13) - 825 - 117,
545 (1 << 13) - 837 - 117,
546 (1 << 13) - 811 - 117,
547 (1 << 13) - 766 - 117,
548 (1 << 13) - 737 - 117,
549 (1 << 13) - 693 - 117,
550 (1 << 13) - 648 - 117,
551 (1 << 13) - 619 - 117,
552 (1 << 13) - 575 - 117,
553 (1 << 13) - 531 - 117,
554 (1 << 13) - 501 - 117,
555
556 1, 142,
557 0x0410,
558
559 /* disable power smoothing */
560 8, 145,
561 0,
562 0,
563 0,
564 0,
565 0,
566 0,
567 0,
568 0,
569
570 1, 154,
571 1 << 13,
572
573 1, 168,
574 0x0ccd,
575
576 1, 183,
577 0x200f,
578
579 1, 212,
580 0x169,
581
582 5, 187,
583 0x023d,
584 0x00a4,
585 0x00a4,
586 0x7ff0,
587 0x3ccc,
588
589 1, 198,
590 0x800,
591
592 1, 222,
593 0x0010,
594
595 1, 235,
596 0x0062,
597
598 2, 901,
599 0x0006,
600 (3 << 10) | (1 << 6),
601
602 1, 905,
603 0x2c8e,
604
605 0,
606};
607
608static int dib7000p_demod_reset(struct dib7000p_state *state)
609{
610 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
611
612 if (state->version == SOC7090)
613 dibx000_reset_i2c_master(&state->i2c_master);
614
615 dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE);
616
617 /* restart all parts */
618 dib7000p_write_word(state, 770, 0xffff);
619 dib7000p_write_word(state, 771, 0xffff);
620 dib7000p_write_word(state, 772, 0x001f);
621 dib7000p_write_word(state, 898, 0x0003);
622 dib7000p_write_word(state, 1280, 0x001f - ((1 << 4) | (1 << 3)));
623
624 dib7000p_write_word(state, 770, 0);
625 dib7000p_write_word(state, 771, 0);
626 dib7000p_write_word(state, 772, 0);
627 dib7000p_write_word(state, 898, 0);
628 dib7000p_write_word(state, 1280, 0);
629
630 /* default */
631 dib7000p_reset_pll(state);
632
633 if (dib7000p_reset_gpio(state) != 0)
634 dprintk("GPIO reset was not successful.");
635
636 if (state->version == SOC7090) {
637 dib7000p_write_word(state, 899, 0);
638
639 /* impulse noise */
640 dib7000p_write_word(state, 42, (1<<5) | 3); /* P_iqc_thsat_ipc = 1 ; P_iqc_win2 = 3 */
641 dib7000p_write_word(state, 43, 0x2d4); /*-300 fag P_iqc_dect_min = -280 */
642 dib7000p_write_word(state, 44, 300); /* 300 fag P_iqc_dect_min = +280 */
643 dib7000p_write_word(state, 273, (1<<6) | 30);
644 }
645 if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
646 dprintk("OUTPUT_MODE could not be reset.");
647
648 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
649 dib7000p_sad_calib(state);
650 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
651
652 /* unforce divstr regardless whether i2c enumeration was done or not */
653 dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1));
654
655 dib7000p_set_bandwidth(state, 8000);
656
657 if (state->version == SOC7090) {
658 dib7000p_write_word(state, 36, 0x5755);/* P_iqc_impnc_on =1 & P_iqc_corr_inh = 1 for impulsive noise */
659 } else {
660 if (state->cfg.tuner_is_baseband)
661 dib7000p_write_word(state, 36, 0x0755);
662 else
663 dib7000p_write_word(state, 36, 0x1f55);
664 }
665
666 dib7000p_write_tab(state, dib7000p_defaults);
667
668 dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
669
670 return 0;
671}
672
673static void dib7000p_pll_clk_cfg(struct dib7000p_state *state)
674{
675 u16 tmp = 0;
676 tmp = dib7000p_read_word(state, 903);
677 dib7000p_write_word(state, 903, (tmp | 0x1));
678 tmp = dib7000p_read_word(state, 900);
679 dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6));
680}
681
682static void dib7000p_restart_agc(struct dib7000p_state *state)
683{
684 // P_restart_iqc & P_restart_agc
685 dib7000p_write_word(state, 770, (1 << 11) | (1 << 9));
686 dib7000p_write_word(state, 770, 0x0000);
687}
688
689static int dib7000p_update_lna(struct dib7000p_state *state)
690{
691 u16 dyn_gain;
692
693 if (state->cfg.update_lna) {
694 dyn_gain = dib7000p_read_word(state, 394);
695 if (state->cfg.update_lna(&state->demod, dyn_gain)) {
696 dib7000p_restart_agc(state);
697 return 1;
698 }
699 }
700
701 return 0;
702}
703
704static int dib7000p_set_agc_config(struct dib7000p_state *state, u8 band)
705{
706 struct dibx000_agc_config *agc = NULL;
707 int i;
708 if (state->current_band == band && state->current_agc != NULL)
709 return 0;
710 state->current_band = band;
711
712 for (i = 0; i < state->cfg.agc_config_count; i++)
713 if (state->cfg.agc[i].band_caps & band) {
714 agc = &state->cfg.agc[i];
715 break;
716 }
717
718 if (agc == NULL) {
719 dprintk("no valid AGC configuration found for band 0x%02x", band);
720 return -EINVAL;
721 }
722
723 state->current_agc = agc;
724
725 /* AGC */
726 dib7000p_write_word(state, 75, agc->setup);
727 dib7000p_write_word(state, 76, agc->inv_gain);
728 dib7000p_write_word(state, 77, agc->time_stabiliz);
729 dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock);
730
731 // Demod AGC loop configuration
732 dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp);
733 dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp);
734
735 /* AGC continued */
736 dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d",
737 state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
738
739 if (state->wbd_ref != 0)
740 dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref);
741 else
742 dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref);
743
744 dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
745
746 dib7000p_write_word(state, 107, agc->agc1_max);
747 dib7000p_write_word(state, 108, agc->agc1_min);
748 dib7000p_write_word(state, 109, agc->agc2_max);
749 dib7000p_write_word(state, 110, agc->agc2_min);
750 dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
751 dib7000p_write_word(state, 112, agc->agc1_pt3);
752 dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
753 dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
754 dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
755 return 0;
756}
757
758static void dib7000p_set_dds(struct dib7000p_state *state, s32 offset_khz)
759{
760 u32 internal = dib7000p_get_internal_freq(state);
761 s32 unit_khz_dds_val = 67108864 / (internal); /* 2**26 / Fsampling is the unit 1KHz offset */
762 u32 abs_offset_khz = ABS(offset_khz);
763 u32 dds = state->cfg.bw->ifreq & 0x1ffffff;
764 u8 invert = !!(state->cfg.bw->ifreq & (1 << 25));
765
766 dprintk("setting a frequency offset of %dkHz internal freq = %d invert = %d", offset_khz, internal, invert);
767
768 if (offset_khz < 0)
769 unit_khz_dds_val *= -1;
770
771 /* IF tuner */
772 if (invert)
773 dds -= (abs_offset_khz * unit_khz_dds_val); /* /100 because of /100 on the unit_khz_dds_val line calc for better accuracy */
774 else
775 dds += (abs_offset_khz * unit_khz_dds_val);
776
777 if (abs_offset_khz <= (internal / 2)) { /* Max dds offset is the half of the demod freq */
778 dib7000p_write_word(state, 21, (u16) (((dds >> 16) & 0x1ff) | (0 << 10) | (invert << 9)));
779 dib7000p_write_word(state, 22, (u16) (dds & 0xffff));
780 }
781}
782
783static int dib7000p_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
784{
785 struct dib7000p_state *state = demod->demodulator_priv;
786 int ret = -1;
787 u8 *agc_state = &state->agc_state;
788 u8 agc_split;
789 u16 reg;
790 u32 upd_demod_gain_period = 0x1000;
791
792 switch (state->agc_state) {
793 case 0:
794 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
795 if (state->version == SOC7090) {
796 reg = dib7000p_read_word(state, 0x79b) & 0xff00;
797 dib7000p_write_word(state, 0x79a, upd_demod_gain_period & 0xFFFF); /* lsb */
798 dib7000p_write_word(state, 0x79b, reg | (1 << 14) | ((upd_demod_gain_period >> 16) & 0xFF));
799
800 /* enable adc i & q */
801 reg = dib7000p_read_word(state, 0x780);
802 dib7000p_write_word(state, 0x780, (reg | (0x3)) & (~(1 << 7)));
803 } else {
804 dib7000p_set_adc_state(state, DIBX000_ADC_ON);
805 dib7000p_pll_clk_cfg(state);
806 }
807
808 if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency / 1000)) != 0)
809 return -1;
810
811 dib7000p_set_dds(state, 0);
812 ret = 7;
813 (*agc_state)++;
814 break;
815
816 case 1:
817 if (state->cfg.agc_control)
818 state->cfg.agc_control(&state->demod, 1);
819
820 dib7000p_write_word(state, 78, 32768);
821 if (!state->current_agc->perform_agc_softsplit) {
822 /* we are using the wbd - so slow AGC startup */
823 /* force 0 split on WBD and restart AGC */
824 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | (1 << 8));
825 (*agc_state)++;
826 ret = 5;
827 } else {
828 /* default AGC startup */
829 (*agc_state) = 4;
830 /* wait AGC rough lock time */
831 ret = 7;
832 }
833
834 dib7000p_restart_agc(state);
835 break;
836
837 case 2: /* fast split search path after 5sec */
838 dib7000p_write_word(state, 75, state->current_agc->setup | (1 << 4)); /* freeze AGC loop */
839 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (2 << 9) | (0 << 8)); /* fast split search 0.25kHz */
840 (*agc_state)++;
841 ret = 14;
842 break;
843
844 case 3: /* split search ended */
845 agc_split = (u8) dib7000p_read_word(state, 396); /* store the split value for the next time */
846 dib7000p_write_word(state, 78, dib7000p_read_word(state, 394)); /* set AGC gain start value */
847
848 dib7000p_write_word(state, 75, state->current_agc->setup); /* std AGC loop */
849 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
850
851 dib7000p_restart_agc(state);
852
853 dprintk("SPLIT %p: %hd", demod, agc_split);
854
855 (*agc_state)++;
856 ret = 5;
857 break;
858
859 case 4: /* LNA startup */
860 ret = 7;
861
862 if (dib7000p_update_lna(state))
863 ret = 5;
864 else
865 (*agc_state)++;
866 break;
867
868 case 5:
869 if (state->cfg.agc_control)
870 state->cfg.agc_control(&state->demod, 0);
871 (*agc_state)++;
872 break;
873 default:
874 break;
875 }
876 return ret;
877}
878
879static void dib7000p_update_timf(struct dib7000p_state *state)
880{
881 u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428);
882 state->timf = timf * 160 / (state->current_bandwidth / 50);
883 dib7000p_write_word(state, 23, (u16) (timf >> 16));
884 dib7000p_write_word(state, 24, (u16) (timf & 0xffff));
885 dprintk("updated timf_frequency: %d (default: %d)", state->timf, state->cfg.bw->timf);
886
887}
888
889u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
890{
891 struct dib7000p_state *state = fe->demodulator_priv;
892 switch (op) {
893 case DEMOD_TIMF_SET:
894 state->timf = timf;
895 break;
896 case DEMOD_TIMF_UPDATE:
897 dib7000p_update_timf(state);
898 break;
899 case DEMOD_TIMF_GET:
900 break;
901 }
902 dib7000p_set_bandwidth(state, state->current_bandwidth);
903 return state->timf;
904}
905EXPORT_SYMBOL(dib7000p_ctrl_timf);
906
907static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_frontend_parameters *ch, u8 seq)
908{
909 u16 value, est[4];
910
911 dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
912
913 /* nfft, guard, qam, alpha */
914 value = 0;
915 switch (ch->u.ofdm.transmission_mode) {
916 case TRANSMISSION_MODE_2K:
917 value |= (0 << 7);
918 break;
919 case TRANSMISSION_MODE_4K:
920 value |= (2 << 7);
921 break;
922 default:
923 case TRANSMISSION_MODE_8K:
924 value |= (1 << 7);
925 break;
926 }
927 switch (ch->u.ofdm.guard_interval) {
928 case GUARD_INTERVAL_1_32:
929 value |= (0 << 5);
930 break;
931 case GUARD_INTERVAL_1_16:
932 value |= (1 << 5);
933 break;
934 case GUARD_INTERVAL_1_4:
935 value |= (3 << 5);
936 break;
937 default:
938 case GUARD_INTERVAL_1_8:
939 value |= (2 << 5);
940 break;
941 }
942 switch (ch->u.ofdm.constellation) {
943 case QPSK:
944 value |= (0 << 3);
945 break;
946 case QAM_16:
947 value |= (1 << 3);
948 break;
949 default:
950 case QAM_64:
951 value |= (2 << 3);
952 break;
953 }
954 switch (HIERARCHY_1) {
955 case HIERARCHY_2:
956 value |= 2;
957 break;
958 case HIERARCHY_4:
959 value |= 4;
960 break;
961 default:
962 case HIERARCHY_1:
963 value |= 1;
964 break;
965 }
966 dib7000p_write_word(state, 0, value);
967 dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */
968
969 /* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
970 value = 0;
971 if (1 != 0)
972 value |= (1 << 6);
973 if (ch->u.ofdm.hierarchy_information == 1)
974 value |= (1 << 4);
975 if (1 == 1)
976 value |= 1;
977 switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
978 case FEC_2_3:
979 value |= (2 << 1);
980 break;
981 case FEC_3_4:
982 value |= (3 << 1);
983 break;
984 case FEC_5_6:
985 value |= (5 << 1);
986 break;
987 case FEC_7_8:
988 value |= (7 << 1);
989 break;
990 default:
991 case FEC_1_2:
992 value |= (1 << 1);
993 break;
994 }
995 dib7000p_write_word(state, 208, value);
996
997 /* offset loop parameters */
998 dib7000p_write_word(state, 26, 0x6680);
999 dib7000p_write_word(state, 32, 0x0003);
1000 dib7000p_write_word(state, 29, 0x1273);
1001 dib7000p_write_word(state, 33, 0x0005);
1002
1003 /* P_dvsy_sync_wait */
1004 switch (ch->u.ofdm.transmission_mode) {
1005 case TRANSMISSION_MODE_8K:
1006 value = 256;
1007 break;
1008 case TRANSMISSION_MODE_4K:
1009 value = 128;
1010 break;
1011 case TRANSMISSION_MODE_2K:
1012 default:
1013 value = 64;
1014 break;
1015 }
1016 switch (ch->u.ofdm.guard_interval) {
1017 case GUARD_INTERVAL_1_16:
1018 value *= 2;
1019 break;
1020 case GUARD_INTERVAL_1_8:
1021 value *= 4;
1022 break;
1023 case GUARD_INTERVAL_1_4:
1024 value *= 8;
1025 break;
1026 default:
1027 case GUARD_INTERVAL_1_32:
1028 value *= 1;
1029 break;
1030 }
1031 if (state->cfg.diversity_delay == 0)
1032 state->div_sync_wait = (value * 3) / 2 + 48;
1033 else
1034 state->div_sync_wait = (value * 3) / 2 + state->cfg.diversity_delay;
1035
1036 /* deactive the possibility of diversity reception if extended interleaver */
1037 state->div_force_off = !1 && ch->u.ofdm.transmission_mode != TRANSMISSION_MODE_8K;
1038 dib7000p_set_diversity_in(&state->demod, state->div_state);
1039
1040 /* channel estimation fine configuration */
1041 switch (ch->u.ofdm.constellation) {
1042 case QAM_64:
1043 est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
1044 est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
1045 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
1046 est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */
1047 break;
1048 case QAM_16:
1049 est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */
1050 est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */
1051 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
1052 est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */
1053 break;
1054 default:
1055 est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */
1056 est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */
1057 est[2] = 0x0333; /* P_adp_regul_ext 0.1 */
1058 est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */
1059 break;
1060 }
1061 for (value = 0; value < 4; value++)
1062 dib7000p_write_word(state, 187 + value, est[value]);
1063}
1064
1065static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
1066{
1067 struct dib7000p_state *state = demod->demodulator_priv;
1068 struct dvb_frontend_parameters schan;
1069 u32 value, factor;
1070 u32 internal = dib7000p_get_internal_freq(state);
1071
1072 schan = *ch;
1073 schan.u.ofdm.constellation = QAM_64;
1074 schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
1075 schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
1076 schan.u.ofdm.code_rate_HP = FEC_2_3;
1077 schan.u.ofdm.code_rate_LP = FEC_3_4;
1078 schan.u.ofdm.hierarchy_information = 0;
1079
1080 dib7000p_set_channel(state, &schan, 7);
1081
1082 factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth);
1083 if (factor >= 5000)
1084 factor = 1;
1085 else
1086 factor = 6;
1087
1088 value = 30 * internal * factor;
1089 dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff));
1090 dib7000p_write_word(state, 7, (u16) (value & 0xffff));
1091 value = 100 * internal * factor;
1092 dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff));
1093 dib7000p_write_word(state, 9, (u16) (value & 0xffff));
1094 value = 500 * internal * factor;
1095 dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff));
1096 dib7000p_write_word(state, 11, (u16) (value & 0xffff));
1097
1098 value = dib7000p_read_word(state, 0);
1099 dib7000p_write_word(state, 0, (u16) ((1 << 9) | value));
1100 dib7000p_read_word(state, 1284);
1101 dib7000p_write_word(state, 0, (u16) value);
1102
1103 return 0;
1104}
1105
1106static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod)
1107{
1108 struct dib7000p_state *state = demod->demodulator_priv;
1109 u16 irq_pending = dib7000p_read_word(state, 1284);
1110
1111 if (irq_pending & 0x1)
1112 return 1;
1113
1114 if (irq_pending & 0x2)
1115 return 2;
1116
1117 return 0;
1118}
1119
1120static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 bw)
1121{
1122 static s16 notch[] = { 16143, 14402, 12238, 9713, 6902, 3888, 759, -2392 };
1123 static u8 sine[] = { 0, 2, 3, 5, 6, 8, 9, 11, 13, 14, 16, 17, 19, 20, 22,
1124 24, 25, 27, 28, 30, 31, 33, 34, 36, 38, 39, 41, 42, 44, 45, 47, 48, 50, 51,
1125 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80,
1126 82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, 104, 105,
1127 107, 108, 109, 111, 112, 114, 115, 117, 118, 119, 121, 122, 123, 125, 126,
1128 128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 144, 145, 146,
1129 147, 149, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 162, 164, 165,
1130 166, 167, 168, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182,
1131 183, 184, 185, 186, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
1132 199, 200, 201, 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 212,
1133 213, 214, 215, 215, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 224,
1134 225, 226, 227, 227, 228, 229, 229, 230, 231, 231, 232, 233, 233, 234, 235,
1135 235, 236, 237, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 243,
1136 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 248, 249, 249, 249,
1137 250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 254,
1138 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1139 255, 255, 255, 255, 255, 255
1140 };
1141
1142 u32 xtal = state->cfg.bw->xtal_hz / 1000;
1143 int f_rel = DIV_ROUND_CLOSEST(rf_khz, xtal) * xtal - rf_khz;
1144 int k;
1145 int coef_re[8], coef_im[8];
1146 int bw_khz = bw;
1147 u32 pha;
1148
1149 dprintk("relative position of the Spur: %dk (RF: %dk, XTAL: %dk)", f_rel, rf_khz, xtal);
1150
1151 if (f_rel < -bw_khz / 2 || f_rel > bw_khz / 2)
1152 return;
1153
1154 bw_khz /= 100;
1155
1156 dib7000p_write_word(state, 142, 0x0610);
1157
1158 for (k = 0; k < 8; k++) {
1159 pha = ((f_rel * (k + 1) * 112 * 80 / bw_khz) / 1000) & 0x3ff;
1160
1161 if (pha == 0) {
1162 coef_re[k] = 256;
1163 coef_im[k] = 0;
1164 } else if (pha < 256) {
1165 coef_re[k] = sine[256 - (pha & 0xff)];
1166 coef_im[k] = sine[pha & 0xff];
1167 } else if (pha == 256) {
1168 coef_re[k] = 0;
1169 coef_im[k] = 256;
1170 } else if (pha < 512) {
1171 coef_re[k] = -sine[pha & 0xff];
1172 coef_im[k] = sine[256 - (pha & 0xff)];
1173 } else if (pha == 512) {
1174 coef_re[k] = -256;
1175 coef_im[k] = 0;
1176 } else if (pha < 768) {
1177 coef_re[k] = -sine[256 - (pha & 0xff)];
1178 coef_im[k] = -sine[pha & 0xff];
1179 } else if (pha == 768) {
1180 coef_re[k] = 0;
1181 coef_im[k] = -256;
1182 } else {
1183 coef_re[k] = sine[pha & 0xff];
1184 coef_im[k] = -sine[256 - (pha & 0xff)];
1185 }
1186
1187 coef_re[k] *= notch[k];
1188 coef_re[k] += (1 << 14);
1189 if (coef_re[k] >= (1 << 24))
1190 coef_re[k] = (1 << 24) - 1;
1191 coef_re[k] /= (1 << 15);
1192
1193 coef_im[k] *= notch[k];
1194 coef_im[k] += (1 << 14);
1195 if (coef_im[k] >= (1 << 24))
1196 coef_im[k] = (1 << 24) - 1;
1197 coef_im[k] /= (1 << 15);
1198
1199 dprintk("PALF COEF: %d re: %d im: %d", k, coef_re[k], coef_im[k]);
1200
1201 dib7000p_write_word(state, 143, (0 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
1202 dib7000p_write_word(state, 144, coef_im[k] & 0x3ff);
1203 dib7000p_write_word(state, 143, (1 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
1204 }
1205 dib7000p_write_word(state, 143, 0);
1206}
1207
1208static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
1209{
1210 struct dib7000p_state *state = demod->demodulator_priv;
1211 u16 tmp = 0;
1212
1213 if (ch != NULL)
1214 dib7000p_set_channel(state, ch, 0);
1215 else
1216 return -EINVAL;
1217
1218 // restart demod
1219 dib7000p_write_word(state, 770, 0x4000);
1220 dib7000p_write_word(state, 770, 0x0000);
1221 msleep(45);
1222
1223 /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
1224 tmp = (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3);
1225 if (state->sfn_workaround_active) {
1226 dprintk("SFN workaround is active");
1227 tmp |= (1 << 9);
1228 dib7000p_write_word(state, 166, 0x4000);
1229 } else {
1230 dib7000p_write_word(state, 166, 0x0000);
1231 }
1232 dib7000p_write_word(state, 29, tmp);
1233
1234 // never achieved a lock with that bandwidth so far - wait for osc-freq to update
1235 if (state->timf == 0)
1236 msleep(200);
1237
1238 /* offset loop parameters */
1239
1240 /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
1241 tmp = (6 << 8) | 0x80;
1242 switch (ch->u.ofdm.transmission_mode) {
1243 case TRANSMISSION_MODE_2K:
1244 tmp |= (2 << 12);
1245 break;
1246 case TRANSMISSION_MODE_4K:
1247 tmp |= (3 << 12);
1248 break;
1249 default:
1250 case TRANSMISSION_MODE_8K:
1251 tmp |= (4 << 12);
1252 break;
1253 }
1254 dib7000p_write_word(state, 26, tmp); /* timf_a(6xxx) */
1255
1256 /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
1257 tmp = (0 << 4);
1258 switch (ch->u.ofdm.transmission_mode) {
1259 case TRANSMISSION_MODE_2K:
1260 tmp |= 0x6;
1261 break;
1262 case TRANSMISSION_MODE_4K:
1263 tmp |= 0x7;
1264 break;
1265 default:
1266 case TRANSMISSION_MODE_8K:
1267 tmp |= 0x8;
1268 break;
1269 }
1270 dib7000p_write_word(state, 32, tmp);
1271
1272 /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
1273 tmp = (0 << 4);
1274 switch (ch->u.ofdm.transmission_mode) {
1275 case TRANSMISSION_MODE_2K:
1276 tmp |= 0x6;
1277 break;
1278 case TRANSMISSION_MODE_4K:
1279 tmp |= 0x7;
1280 break;
1281 default:
1282 case TRANSMISSION_MODE_8K:
1283 tmp |= 0x8;
1284 break;
1285 }
1286 dib7000p_write_word(state, 33, tmp);
1287
1288 tmp = dib7000p_read_word(state, 509);
1289 if (!((tmp >> 6) & 0x1)) {
1290 /* restart the fec */
1291 tmp = dib7000p_read_word(state, 771);
1292 dib7000p_write_word(state, 771, tmp | (1 << 1));
1293 dib7000p_write_word(state, 771, tmp);
1294 msleep(40);
1295 tmp = dib7000p_read_word(state, 509);
1296 }
1297 // we achieved a lock - it's time to update the osc freq
1298 if ((tmp >> 6) & 0x1) {
1299 dib7000p_update_timf(state);
1300 /* P_timf_alpha += 2 */
1301 tmp = dib7000p_read_word(state, 26);
1302 dib7000p_write_word(state, 26, (tmp & ~(0xf << 12)) | ((((tmp >> 12) & 0xf) + 5) << 12));
1303 }
1304
1305 if (state->cfg.spur_protect)
1306 dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
1307
1308 dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
1309 return 0;
1310}
1311
1312static int dib7000p_wakeup(struct dvb_frontend *demod)
1313{
1314 struct dib7000p_state *state = demod->demodulator_priv;
1315 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
1316 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
1317 if (state->version == SOC7090)
1318 dib7000p_sad_calib(state);
1319 return 0;
1320}
1321
1322static int dib7000p_sleep(struct dvb_frontend *demod)
1323{
1324 struct dib7000p_state *state = demod->demodulator_priv;
1325 if (state->version == SOC7090)
1326 return dib7090_set_output_mode(demod, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
1327 return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
1328}
1329
1330static int dib7000p_identify(struct dib7000p_state *st)
1331{
1332 u16 value;
1333 dprintk("checking demod on I2C address: %d (%x)", st->i2c_addr, st->i2c_addr);
1334
1335 if ((value = dib7000p_read_word(st, 768)) != 0x01b3) {
1336 dprintk("wrong Vendor ID (read=0x%x)", value);
1337 return -EREMOTEIO;
1338 }
1339
1340 if ((value = dib7000p_read_word(st, 769)) != 0x4000) {
1341 dprintk("wrong Device ID (%x)", value);
1342 return -EREMOTEIO;
1343 }
1344
1345 return 0;
1346}
1347
1348static int dib7000p_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
1349{
1350 struct dib7000p_state *state = fe->demodulator_priv;
1351 u16 tps = dib7000p_read_word(state, 463);
1352
1353 fep->inversion = INVERSION_AUTO;
1354
1355 fep->u.ofdm.bandwidth = BANDWIDTH_TO_INDEX(state->current_bandwidth);
1356
1357 switch ((tps >> 8) & 0x3) {
1358 case 0:
1359 fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
1360 break;
1361 case 1:
1362 fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
1363 break;
1364 /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
1365 }
1366
1367 switch (tps & 0x3) {
1368 case 0:
1369 fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
1370 break;
1371 case 1:
1372 fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
1373 break;
1374 case 2:
1375 fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;
1376 break;
1377 case 3:
1378 fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;
1379 break;
1380 }
1381
1382 switch ((tps >> 14) & 0x3) {
1383 case 0:
1384 fep->u.ofdm.constellation = QPSK;
1385 break;
1386 case 1:
1387 fep->u.ofdm.constellation = QAM_16;
1388 break;
1389 case 2:
1390 default:
1391 fep->u.ofdm.constellation = QAM_64;
1392 break;
1393 }
1394
1395 /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
1396 /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
1397
1398 fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
1399 switch ((tps >> 5) & 0x7) {
1400 case 1:
1401 fep->u.ofdm.code_rate_HP = FEC_1_2;
1402 break;
1403 case 2:
1404 fep->u.ofdm.code_rate_HP = FEC_2_3;
1405 break;
1406 case 3:
1407 fep->u.ofdm.code_rate_HP = FEC_3_4;
1408 break;
1409 case 5:
1410 fep->u.ofdm.code_rate_HP = FEC_5_6;
1411 break;
1412 case 7:
1413 default:
1414 fep->u.ofdm.code_rate_HP = FEC_7_8;
1415 break;
1416
1417 }
1418
1419 switch ((tps >> 2) & 0x7) {
1420 case 1:
1421 fep->u.ofdm.code_rate_LP = FEC_1_2;
1422 break;
1423 case 2:
1424 fep->u.ofdm.code_rate_LP = FEC_2_3;
1425 break;
1426 case 3:
1427 fep->u.ofdm.code_rate_LP = FEC_3_4;
1428 break;
1429 case 5:
1430 fep->u.ofdm.code_rate_LP = FEC_5_6;
1431 break;
1432 case 7:
1433 default:
1434 fep->u.ofdm.code_rate_LP = FEC_7_8;
1435 break;
1436 }
1437
1438 /* native interleaver: (dib7000p_read_word(state, 464) >> 5) & 0x1 */
1439
1440 return 0;
1441}
1442
1443static int dib7000p_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
1444{
1445 struct dib7000p_state *state = fe->demodulator_priv;
1446 int time, ret;
1447
1448 if (state->version == SOC7090) {
1449 dib7090_set_diversity_in(fe, 0);
1450 dib7090_set_output_mode(fe, OUTMODE_HIGH_Z);
1451 } else
1452 dib7000p_set_output_mode(state, OUTMODE_HIGH_Z);
1453
1454 /* maybe the parameter has been changed */
1455 state->sfn_workaround_active = buggy_sfn_workaround;
1456
1457 if (fe->ops.tuner_ops.set_params)
1458 fe->ops.tuner_ops.set_params(fe, fep);
1459
1460 /* start up the AGC */
1461 state->agc_state = 0;
1462 do {
1463 time = dib7000p_agc_startup(fe, fep);
1464 if (time != -1)
1465 msleep(time);
1466 } while (time != -1);
1467
1468 if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
1469 fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || fep->u.ofdm.constellation == QAM_AUTO || fep->u.ofdm.code_rate_HP == FEC_AUTO) {
1470 int i = 800, found;
1471
1472 dib7000p_autosearch_start(fe, fep);
1473 do {
1474 msleep(1);
1475 found = dib7000p_autosearch_is_irq(fe);
1476 } while (found == 0 && i--);
1477
1478 dprintk("autosearch returns: %d", found);
1479 if (found == 0 || found == 1)
1480 return 0;
1481
1482 dib7000p_get_frontend(fe, fep);
1483 }
1484
1485 ret = dib7000p_tune(fe, fep);
1486
1487 /* make this a config parameter */
1488 if (state->version == SOC7090)
1489 dib7090_set_output_mode(fe, state->cfg.output_mode);
1490 else
1491 dib7000p_set_output_mode(state, state->cfg.output_mode);
1492
1493 return ret;
1494}
1495
1496static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat)
1497{
1498 struct dib7000p_state *state = fe->demodulator_priv;
1499 u16 lock = dib7000p_read_word(state, 509);
1500
1501 *stat = 0;
1502
1503 if (lock & 0x8000)
1504 *stat |= FE_HAS_SIGNAL;
1505 if (lock & 0x3000)
1506 *stat |= FE_HAS_CARRIER;
1507 if (lock & 0x0100)
1508 *stat |= FE_HAS_VITERBI;
1509 if (lock & 0x0010)
1510 *stat |= FE_HAS_SYNC;
1511 if ((lock & 0x0038) == 0x38)
1512 *stat |= FE_HAS_LOCK;
1513
1514 return 0;
1515}
1516
1517static int dib7000p_read_ber(struct dvb_frontend *fe, u32 * ber)
1518{
1519 struct dib7000p_state *state = fe->demodulator_priv;
1520 *ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501);
1521 return 0;
1522}
1523
1524static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
1525{
1526 struct dib7000p_state *state = fe->demodulator_priv;
1527 *unc = dib7000p_read_word(state, 506);
1528 return 0;
1529}
1530
1531static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
1532{
1533 struct dib7000p_state *state = fe->demodulator_priv;
1534 u16 val = dib7000p_read_word(state, 394);
1535 *strength = 65535 - val;
1536 return 0;
1537}
1538
1539static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr)
1540{
1541 struct dib7000p_state *state = fe->demodulator_priv;
1542 u16 val;
1543 s32 signal_mant, signal_exp, noise_mant, noise_exp;
1544 u32 result = 0;
1545
1546 val = dib7000p_read_word(state, 479);
1547 noise_mant = (val >> 4) & 0xff;
1548 noise_exp = ((val & 0xf) << 2);
1549 val = dib7000p_read_word(state, 480);
1550 noise_exp += ((val >> 14) & 0x3);
1551 if ((noise_exp & 0x20) != 0)
1552 noise_exp -= 0x40;
1553
1554 signal_mant = (val >> 6) & 0xFF;
1555 signal_exp = (val & 0x3F);
1556 if ((signal_exp & 0x20) != 0)
1557 signal_exp -= 0x40;
1558
1559 if (signal_mant != 0)
1560 result = intlog10(2) * 10 * signal_exp + 10 * intlog10(signal_mant);
1561 else
1562 result = intlog10(2) * 10 * signal_exp - 100;
1563
1564 if (noise_mant != 0)
1565 result -= intlog10(2) * 10 * noise_exp + 10 * intlog10(noise_mant);
1566 else
1567 result -= intlog10(2) * 10 * noise_exp - 100;
1568
1569 *snr = result / ((1 << 24) / 10);
1570 return 0;
1571}
1572
1573static int dib7000p_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
1574{
1575 tune->min_delay_ms = 1000;
1576 return 0;
1577}
1578
1579static void dib7000p_release(struct dvb_frontend *demod)
1580{
1581 struct dib7000p_state *st = demod->demodulator_priv;
1582 dibx000_exit_i2c_master(&st->i2c_master);
1583 i2c_del_adapter(&st->dib7090_tuner_adap);
1584 kfree(st);
1585}
1586
1587int dib7000pc_detection(struct i2c_adapter *i2c_adap)
1588{
1589 u8 *tx, *rx;
1590 struct i2c_msg msg[2] = {
1591 {.addr = 18 >> 1, .flags = 0, .len = 2},
1592 {.addr = 18 >> 1, .flags = I2C_M_RD, .len = 2},
1593 };
1594 int ret = 0;
1595
1596 tx = kzalloc(2*sizeof(u8), GFP_KERNEL);
1597 if (!tx)
1598 return -ENOMEM;
1599 rx = kzalloc(2*sizeof(u8), GFP_KERNEL);
1600 if (!rx) {
1601 goto rx_memory_error;
1602 ret = -ENOMEM;
1603 }
1604
1605 msg[0].buf = tx;
1606 msg[1].buf = rx;
1607
1608 tx[0] = 0x03;
1609 tx[1] = 0x00;
1610
1611 if (i2c_transfer(i2c_adap, msg, 2) == 2)
1612 if (rx[0] == 0x01 && rx[1] == 0xb3) {
1613 dprintk("-D- DiB7000PC detected");
1614 return 1;
1615 }
1616
1617 msg[0].addr = msg[1].addr = 0x40;
1618
1619 if (i2c_transfer(i2c_adap, msg, 2) == 2)
1620 if (rx[0] == 0x01 && rx[1] == 0xb3) {
1621 dprintk("-D- DiB7000PC detected");
1622 return 1;
1623 }
1624
1625 dprintk("-D- DiB7000PC not detected");
1626
1627 kfree(rx);
1628rx_memory_error:
1629 kfree(tx);
1630 return ret;
1631}
1632EXPORT_SYMBOL(dib7000pc_detection);
1633
1634struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
1635{
1636 struct dib7000p_state *st = demod->demodulator_priv;
1637 return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
1638}
1639EXPORT_SYMBOL(dib7000p_get_i2c_master);
1640
1641int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
1642{
1643 struct dib7000p_state *state = fe->demodulator_priv;
1644 u16 val = dib7000p_read_word(state, 235) & 0xffef;
1645 val |= (onoff & 0x1) << 4;
1646 dprintk("PID filter enabled %d", onoff);
1647 return dib7000p_write_word(state, 235, val);
1648}
1649EXPORT_SYMBOL(dib7000p_pid_filter_ctrl);
1650
1651int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
1652{
1653 struct dib7000p_state *state = fe->demodulator_priv;
1654 dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
1655 return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0);
1656}
1657EXPORT_SYMBOL(dib7000p_pid_filter);
1658
1659int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
1660{
1661 struct dib7000p_state *dpst;
1662 int k = 0;
1663 u8 new_addr = 0;
1664
1665 dpst = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
1666 if (!dpst)
1667 return -ENOMEM;
1668
1669 dpst->i2c_adap = i2c;
1670 mutex_init(&dpst->i2c_buffer_lock);
1671
1672 for (k = no_of_demods - 1; k >= 0; k--) {
1673 dpst->cfg = cfg[k];
1674
1675 /* designated i2c address */
1676 if (cfg[k].default_i2c_addr != 0)
1677 new_addr = cfg[k].default_i2c_addr + (k << 1);
1678 else
1679 new_addr = (0x40 + k) << 1;
1680 dpst->i2c_addr = new_addr;
1681 dib7000p_write_word(dpst, 1287, 0x0003); /* sram lead in, rdy */
1682 if (dib7000p_identify(dpst) != 0) {
1683 dpst->i2c_addr = default_addr;
1684 dib7000p_write_word(dpst, 1287, 0x0003); /* sram lead in, rdy */
1685 if (dib7000p_identify(dpst) != 0) {
1686 dprintk("DiB7000P #%d: not identified\n", k);
1687 kfree(dpst);
1688 return -EIO;
1689 }
1690 }
1691
1692 /* start diversity to pull_down div_str - just for i2c-enumeration */
1693 dib7000p_set_output_mode(dpst, OUTMODE_DIVERSITY);
1694
1695 /* set new i2c address and force divstart */
1696 dib7000p_write_word(dpst, 1285, (new_addr << 2) | 0x2);
1697
1698 dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
1699 }
1700
1701 for (k = 0; k < no_of_demods; k++) {
1702 dpst->cfg = cfg[k];
1703 if (cfg[k].default_i2c_addr != 0)
1704 dpst->i2c_addr = (cfg[k].default_i2c_addr + k) << 1;
1705 else
1706 dpst->i2c_addr = (0x40 + k) << 1;
1707
1708 // unforce divstr
1709 dib7000p_write_word(dpst, 1285, dpst->i2c_addr << 2);
1710
1711 /* deactivate div - it was just for i2c-enumeration */
1712 dib7000p_set_output_mode(dpst, OUTMODE_HIGH_Z);
1713 }
1714
1715 kfree(dpst);
1716 return 0;
1717}
1718EXPORT_SYMBOL(dib7000p_i2c_enumeration);
1719
1720static const s32 lut_1000ln_mant[] = {
1721 6908, 6956, 7003, 7047, 7090, 7131, 7170, 7208, 7244, 7279, 7313, 7346, 7377, 7408, 7438, 7467, 7495, 7523, 7549, 7575, 7600
1722};
1723
1724static s32 dib7000p_get_adc_power(struct dvb_frontend *fe)
1725{
1726 struct dib7000p_state *state = fe->demodulator_priv;
1727 u32 tmp_val = 0, exp = 0, mant = 0;
1728 s32 pow_i;
1729 u16 buf[2];
1730 u8 ix = 0;
1731
1732 buf[0] = dib7000p_read_word(state, 0x184);
1733 buf[1] = dib7000p_read_word(state, 0x185);
1734 pow_i = (buf[0] << 16) | buf[1];
1735 dprintk("raw pow_i = %d", pow_i);
1736
1737 tmp_val = pow_i;
1738 while (tmp_val >>= 1)
1739 exp++;
1740
1741 mant = (pow_i * 1000 / (1 << exp));
1742 dprintk(" mant = %d exp = %d", mant / 1000, exp);
1743
1744 ix = (u8) ((mant - 1000) / 100); /* index of the LUT */
1745 dprintk(" ix = %d", ix);
1746
1747 pow_i = (lut_1000ln_mant[ix] + 693 * (exp - 20) - 6908);
1748 pow_i = (pow_i << 8) / 1000;
1749 dprintk(" pow_i = %d", pow_i);
1750
1751 return pow_i;
1752}
1753
1754static int map_addr_to_serpar_number(struct i2c_msg *msg)
1755{
1756 if ((msg->buf[0] <= 15))
1757 msg->buf[0] -= 1;
1758 else if (msg->buf[0] == 17)
1759 msg->buf[0] = 15;
1760 else if (msg->buf[0] == 16)
1761 msg->buf[0] = 17;
1762 else if (msg->buf[0] == 19)
1763 msg->buf[0] = 16;
1764 else if (msg->buf[0] >= 21 && msg->buf[0] <= 25)
1765 msg->buf[0] -= 3;
1766 else if (msg->buf[0] == 28)
1767 msg->buf[0] = 23;
1768 else
1769 return -EINVAL;
1770 return 0;
1771}
1772
1773static int w7090p_tuner_write_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
1774{
1775 struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
1776 u8 n_overflow = 1;
1777 u16 i = 1000;
1778 u16 serpar_num = msg[0].buf[0];
1779
1780 while (n_overflow == 1 && i) {
1781 n_overflow = (dib7000p_read_word(state, 1984) >> 1) & 0x1;
1782 i--;
1783 if (i == 0)
1784 dprintk("Tuner ITF: write busy (overflow)");
1785 }
1786 dib7000p_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f));
1787 dib7000p_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]);
1788
1789 return num;
1790}
1791
1792static int w7090p_tuner_read_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
1793{
1794 struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
1795 u8 n_overflow = 1, n_empty = 1;
1796 u16 i = 1000;
1797 u16 serpar_num = msg[0].buf[0];
1798 u16 read_word;
1799
1800 while (n_overflow == 1 && i) {
1801 n_overflow = (dib7000p_read_word(state, 1984) >> 1) & 0x1;
1802 i--;
1803 if (i == 0)
1804 dprintk("TunerITF: read busy (overflow)");
1805 }
1806 dib7000p_write_word(state, 1985, (0 << 6) | (serpar_num & 0x3f));
1807
1808 i = 1000;
1809 while (n_empty == 1 && i) {
1810 n_empty = dib7000p_read_word(state, 1984) & 0x1;
1811 i--;
1812 if (i == 0)
1813 dprintk("TunerITF: read busy (empty)");
1814 }
1815 read_word = dib7000p_read_word(state, 1987);
1816 msg[1].buf[0] = (read_word >> 8) & 0xff;
1817 msg[1].buf[1] = (read_word) & 0xff;
1818
1819 return num;
1820}
1821
1822static int w7090p_tuner_rw_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
1823{
1824 if (map_addr_to_serpar_number(&msg[0]) == 0) { /* else = Tuner regs to ignore : DIG_CFG, CTRL_RF_LT, PLL_CFG, PWM1_REG, ADCCLK, DIG_CFG_3; SLEEP_EN... */
1825 if (num == 1) { /* write */
1826 return w7090p_tuner_write_serpar(i2c_adap, msg, 1);
1827 } else { /* read */
1828 return w7090p_tuner_read_serpar(i2c_adap, msg, 2);
1829 }
1830 }
1831 return num;
1832}
1833
1834int dib7090p_rw_on_apb(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num, u16 apb_address)
1835{
1836 struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
1837 u16 word;
1838
1839 if (num == 1) { /* write */
1840 dib7000p_write_word(state, apb_address, ((msg[0].buf[1] << 8) | (msg[0].buf[2])));
1841 } else {
1842 word = dib7000p_read_word(state, apb_address);
1843 msg[1].buf[0] = (word >> 8) & 0xff;
1844 msg[1].buf[1] = (word) & 0xff;
1845 }
1846
1847 return num;
1848}
1849
1850static int dib7090_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
1851{
1852 struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
1853
1854 u16 apb_address = 0, word;
1855 int i = 0;
1856 switch (msg[0].buf[0]) {
1857 case 0x12:
1858 apb_address = 1920;
1859 break;
1860 case 0x14:
1861 apb_address = 1921;
1862 break;
1863 case 0x24:
1864 apb_address = 1922;
1865 break;
1866 case 0x1a:
1867 apb_address = 1923;
1868 break;
1869 case 0x22:
1870 apb_address = 1924;
1871 break;
1872 case 0x33:
1873 apb_address = 1926;
1874 break;
1875 case 0x34:
1876 apb_address = 1927;
1877 break;
1878 case 0x35:
1879 apb_address = 1928;
1880 break;
1881 case 0x36:
1882 apb_address = 1929;
1883 break;
1884 case 0x37:
1885 apb_address = 1930;
1886 break;
1887 case 0x38:
1888 apb_address = 1931;
1889 break;
1890 case 0x39:
1891 apb_address = 1932;
1892 break;
1893 case 0x2a:
1894 apb_address = 1935;
1895 break;
1896 case 0x2b:
1897 apb_address = 1936;
1898 break;
1899 case 0x2c:
1900 apb_address = 1937;
1901 break;
1902 case 0x2d:
1903 apb_address = 1938;
1904 break;
1905 case 0x2e:
1906 apb_address = 1939;
1907 break;
1908 case 0x2f:
1909 apb_address = 1940;
1910 break;
1911 case 0x30:
1912 apb_address = 1941;
1913 break;
1914 case 0x31:
1915 apb_address = 1942;
1916 break;
1917 case 0x32:
1918 apb_address = 1943;
1919 break;
1920 case 0x3e:
1921 apb_address = 1944;
1922 break;
1923 case 0x3f:
1924 apb_address = 1945;
1925 break;
1926 case 0x40:
1927 apb_address = 1948;
1928 break;
1929 case 0x25:
1930 apb_address = 914;
1931 break;
1932 case 0x26:
1933 apb_address = 915;
1934 break;
1935 case 0x27:
1936 apb_address = 916;
1937 break;
1938 case 0x28:
1939 apb_address = 917;
1940 break;
1941 case 0x1d:
1942 i = ((dib7000p_read_word(state, 72) >> 12) & 0x3);
1943 word = dib7000p_read_word(state, 384 + i);
1944 msg[1].buf[0] = (word >> 8) & 0xff;
1945 msg[1].buf[1] = (word) & 0xff;
1946 return num;
1947 case 0x1f:
1948 if (num == 1) { /* write */
1949 word = (u16) ((msg[0].buf[1] << 8) | msg[0].buf[2]);
1950 word &= 0x3;
1951 word = (dib7000p_read_word(state, 72) & ~(3 << 12)) | (word << 12);
1952 dib7000p_write_word(state, 72, word); /* Set the proper input */
1953 return num;
1954 }
1955 }
1956
1957 if (apb_address != 0) /* R/W acces via APB */
1958 return dib7090p_rw_on_apb(i2c_adap, msg, num, apb_address);
1959 else /* R/W access via SERPAR */
1960 return w7090p_tuner_rw_serpar(i2c_adap, msg, num);
1961
1962 return 0;
1963}
1964
1965static u32 dib7000p_i2c_func(struct i2c_adapter *adapter)
1966{
1967 return I2C_FUNC_I2C;
1968}
1969
1970static struct i2c_algorithm dib7090_tuner_xfer_algo = {
1971 .master_xfer = dib7090_tuner_xfer,
1972 .functionality = dib7000p_i2c_func,
1973};
1974
1975struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
1976{
1977 struct dib7000p_state *st = fe->demodulator_priv;
1978 return &st->dib7090_tuner_adap;
1979}
1980EXPORT_SYMBOL(dib7090_get_i2c_tuner);
1981
1982static int dib7090_host_bus_drive(struct dib7000p_state *state, u8 drive)
1983{
1984 u16 reg;
1985
1986 /* drive host bus 2, 3, 4 */
1987 reg = dib7000p_read_word(state, 1798) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
1988 reg |= (drive << 12) | (drive << 6) | drive;
1989 dib7000p_write_word(state, 1798, reg);
1990
1991 /* drive host bus 5,6 */
1992 reg = dib7000p_read_word(state, 1799) & ~((0x7 << 2) | (0x7 << 8));
1993 reg |= (drive << 8) | (drive << 2);
1994 dib7000p_write_word(state, 1799, reg);
1995
1996 /* drive host bus 7, 8, 9 */
1997 reg = dib7000p_read_word(state, 1800) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
1998 reg |= (drive << 12) | (drive << 6) | drive;
1999 dib7000p_write_word(state, 1800, reg);
2000
2001 /* drive host bus 10, 11 */
2002 reg = dib7000p_read_word(state, 1801) & ~((0x7 << 2) | (0x7 << 8));
2003 reg |= (drive << 8) | (drive << 2);
2004 dib7000p_write_word(state, 1801, reg);
2005
2006 /* drive host bus 12, 13, 14 */
2007 reg = dib7000p_read_word(state, 1802) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
2008 reg |= (drive << 12) | (drive << 6) | drive;
2009 dib7000p_write_word(state, 1802, reg);
2010
2011 return 0;
2012}
2013
2014static u32 dib7090_calcSyncFreq(u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 syncSize)
2015{
2016 u32 quantif = 3;
2017 u32 nom = (insertExtSynchro * P_Kin + syncSize);
2018 u32 denom = P_Kout;
2019 u32 syncFreq = ((nom << quantif) / denom);
2020
2021 if ((syncFreq & ((1 << quantif) - 1)) != 0)
2022 syncFreq = (syncFreq >> quantif) + 1;
2023 else
2024 syncFreq = (syncFreq >> quantif);
2025
2026 if (syncFreq != 0)
2027 syncFreq = syncFreq - 1;
2028
2029 return syncFreq;
2030}
2031
2032static int dib7090_cfg_DibTx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 synchroMode, u32 syncWord, u32 syncSize)
2033{
2034 u8 index_buf;
2035 u16 rx_copy_buf[22];
2036
2037 dprintk("Configure DibStream Tx");
2038 for (index_buf = 0; index_buf < 22; index_buf++)
2039 rx_copy_buf[index_buf] = dib7000p_read_word(state, 1536+index_buf);
2040
2041 dib7000p_write_word(state, 1615, 1);
2042 dib7000p_write_word(state, 1603, P_Kin);
2043 dib7000p_write_word(state, 1605, P_Kout);
2044 dib7000p_write_word(state, 1606, insertExtSynchro);
2045 dib7000p_write_word(state, 1608, synchroMode);
2046 dib7000p_write_word(state, 1609, (syncWord >> 16) & 0xffff);
2047 dib7000p_write_word(state, 1610, syncWord & 0xffff);
2048 dib7000p_write_word(state, 1612, syncSize);
2049 dib7000p_write_word(state, 1615, 0);
2050
2051 for (index_buf = 0; index_buf < 22; index_buf++)
2052 dib7000p_write_word(state, 1536+index_buf, rx_copy_buf[index_buf]);
2053
2054 return 0;
2055}
2056
2057static int dib7090_cfg_DibRx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 synchroMode, u32 insertExtSynchro, u32 syncWord, u32 syncSize,
2058 u32 dataOutRate)
2059{
2060 u32 syncFreq;
2061
2062 dprintk("Configure DibStream Rx");
2063 if ((P_Kin != 0) && (P_Kout != 0)) {
2064 syncFreq = dib7090_calcSyncFreq(P_Kin, P_Kout, insertExtSynchro, syncSize);
2065 dib7000p_write_word(state, 1542, syncFreq);
2066 }
2067 dib7000p_write_word(state, 1554, 1);
2068 dib7000p_write_word(state, 1536, P_Kin);
2069 dib7000p_write_word(state, 1537, P_Kout);
2070 dib7000p_write_word(state, 1539, synchroMode);
2071 dib7000p_write_word(state, 1540, (syncWord >> 16) & 0xffff);
2072 dib7000p_write_word(state, 1541, syncWord & 0xffff);
2073 dib7000p_write_word(state, 1543, syncSize);
2074 dib7000p_write_word(state, 1544, dataOutRate);
2075 dib7000p_write_word(state, 1554, 0);
2076
2077 return 0;
2078}
2079
2080static int dib7090_enDivOnHostBus(struct dib7000p_state *state)
2081{
2082 u16 reg;
2083
2084 dprintk("Enable Diversity on host bus");
2085 reg = (1 << 8) | (1 << 5);
2086 dib7000p_write_word(state, 1288, reg);
2087
2088 return dib7090_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
2089}
2090
2091static int dib7090_enAdcOnHostBus(struct dib7000p_state *state)
2092{
2093 u16 reg;
2094
2095 dprintk("Enable ADC on host bus");
2096 reg = (1 << 7) | (1 << 5);
2097 dib7000p_write_word(state, 1288, reg);
2098
2099 return dib7090_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
2100}
2101
2102static int dib7090_enMpegOnHostBus(struct dib7000p_state *state)
2103{
2104 u16 reg;
2105
2106 dprintk("Enable Mpeg on host bus");
2107 reg = (1 << 9) | (1 << 5);
2108 dib7000p_write_word(state, 1288, reg);
2109
2110 return dib7090_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
2111}
2112
2113static int dib7090_enMpegInput(struct dib7000p_state *state)
2114{
2115 dprintk("Enable Mpeg input");
2116 return dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0); /*outputRate = 8 */
2117}
2118
2119static int dib7090_enMpegMux(struct dib7000p_state *state, u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
2120{
2121 u16 reg = (1 << 7) | ((pulseWidth & 0x1f) << 2) | ((enSerialMode & 0x1) << 1) | (enSerialClkDiv2 & 0x1);
2122
2123 dprintk("Enable Mpeg mux");
2124 dib7000p_write_word(state, 1287, reg);
2125
2126 reg &= ~(1 << 7);
2127 dib7000p_write_word(state, 1287, reg);
2128
2129 reg = (1 << 4);
2130 dib7000p_write_word(state, 1288, reg);
2131
2132 return 0;
2133}
2134
2135static int dib7090_disableMpegMux(struct dib7000p_state *state)
2136{
2137 u16 reg;
2138
2139 dprintk("Disable Mpeg mux");
2140 dib7000p_write_word(state, 1288, 0);
2141
2142 reg = dib7000p_read_word(state, 1287);
2143 reg &= ~(1 << 7);
2144 dib7000p_write_word(state, 1287, reg);
2145
2146 return 0;
2147}
2148
2149static int dib7090_set_input_mode(struct dvb_frontend *fe, int mode)
2150{
2151 struct dib7000p_state *state = fe->demodulator_priv;
2152
2153 switch (mode) {
2154 case INPUT_MODE_DIVERSITY:
2155 dprintk("Enable diversity INPUT");
2156 dib7090_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
2157 break;
2158 case INPUT_MODE_MPEG:
2159 dprintk("Enable Mpeg INPUT");
2160 dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0); /*outputRate = 8 */
2161 break;
2162 case INPUT_MODE_OFF:
2163 default:
2164 dprintk("Disable INPUT");
2165 dib7090_cfg_DibRx(state, 0, 0, 0, 0, 0, 0, 0);
2166 break;
2167 }
2168 return 0;
2169}
2170
2171static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff)
2172{
2173 switch (onoff) {
2174 case 0: /* only use the internal way - not the diversity input */
2175 dib7090_set_input_mode(fe, INPUT_MODE_MPEG);
2176 break;
2177 case 1: /* both ways */
2178 case 2: /* only the diversity input */
2179 dib7090_set_input_mode(fe, INPUT_MODE_DIVERSITY);
2180 break;
2181 }
2182
2183 return 0;
2184}
2185
2186static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode)
2187{
2188 struct dib7000p_state *state = fe->demodulator_priv;
2189
2190 u16 outreg, smo_mode, fifo_threshold;
2191 u8 prefer_mpeg_mux_use = 1;
2192 int ret = 0;
2193
2194 dib7090_host_bus_drive(state, 1);
2195
2196 fifo_threshold = 1792;
2197 smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1);
2198 outreg = dib7000p_read_word(state, 1286) & ~((1 << 10) | (0x7 << 6) | (1 << 1));
2199
2200 switch (mode) {
2201 case OUTMODE_HIGH_Z:
2202 outreg = 0;
2203 break;
2204
2205 case OUTMODE_MPEG2_SERIAL:
2206 if (prefer_mpeg_mux_use) {
2207 dprintk("Sip 7090P setting output mode TS_SERIAL using Mpeg Mux");
2208 dib7090_enMpegOnHostBus(state);
2209 dib7090_enMpegInput(state);
2210 if (state->cfg.enMpegOutput == 1)
2211 dib7090_enMpegMux(state, 3, 1, 1);
2212
2213 } else { /* Use Smooth block */
2214 dprintk("Sip 7090P setting output mode TS_SERIAL using Smooth bloc");
2215 dib7090_disableMpegMux(state);
2216 dib7000p_write_word(state, 1288, (1 << 6));
2217 outreg |= (2 << 6) | (0 << 1);
2218 }
2219 break;
2220
2221 case OUTMODE_MPEG2_PAR_GATED_CLK:
2222 if (prefer_mpeg_mux_use) {
2223 dprintk("Sip 7090P setting output mode TS_PARALLEL_GATED using Mpeg Mux");
2224 dib7090_enMpegOnHostBus(state);
2225 dib7090_enMpegInput(state);
2226 if (state->cfg.enMpegOutput == 1)
2227 dib7090_enMpegMux(state, 2, 0, 0);
2228 } else { /* Use Smooth block */
2229 dprintk("Sip 7090P setting output mode TS_PARALLEL_GATED using Smooth block");
2230 dib7090_disableMpegMux(state);
2231 dib7000p_write_word(state, 1288, (1 << 6));
2232 outreg |= (0 << 6);
2233 }
2234 break;
2235
2236 case OUTMODE_MPEG2_PAR_CONT_CLK: /* Using Smooth block only */
2237 dprintk("Sip 7090P setting output mode TS_PARALLEL_CONT using Smooth block");
2238 dib7090_disableMpegMux(state);
2239 dib7000p_write_word(state, 1288, (1 << 6));
2240 outreg |= (1 << 6);
2241 break;
2242
2243 case OUTMODE_MPEG2_FIFO: /* Using Smooth block because not supported by new Mpeg Mux bloc */
2244 dprintk("Sip 7090P setting output mode TS_FIFO using Smooth block");
2245 dib7090_disableMpegMux(state);
2246 dib7000p_write_word(state, 1288, (1 << 6));
2247 outreg |= (5 << 6);
2248 smo_mode |= (3 << 1);
2249 fifo_threshold = 512;
2250 break;
2251
2252 case OUTMODE_DIVERSITY:
2253 dprintk("Sip 7090P setting output mode MODE_DIVERSITY");
2254 dib7090_disableMpegMux(state);
2255 dib7090_enDivOnHostBus(state);
2256 break;
2257
2258 case OUTMODE_ANALOG_ADC:
2259 dprintk("Sip 7090P setting output mode MODE_ANALOG_ADC");
2260 dib7090_enAdcOnHostBus(state);
2261 break;
2262 }
2263
2264 if (state->cfg.output_mpeg2_in_188_bytes)
2265 smo_mode |= (1 << 5);
2266
2267 ret |= dib7000p_write_word(state, 235, smo_mode);
2268 ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */
2269 ret |= dib7000p_write_word(state, 1286, outreg | (1 << 10)); /* allways set Dout active = 1 !!! */
2270
2271 return ret;
2272}
2273
2274int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
2275{
2276 struct dib7000p_state *state = fe->demodulator_priv;
2277 u16 en_cur_state;
2278
2279 dprintk("sleep dib7090: %d", onoff);
2280
2281 en_cur_state = dib7000p_read_word(state, 1922);
2282
2283 if (en_cur_state > 0xff)
2284 state->tuner_enable = en_cur_state;
2285
2286 if (onoff)
2287 en_cur_state &= 0x00ff;
2288 else {
2289 if (state->tuner_enable != 0)
2290 en_cur_state = state->tuner_enable;
2291 }
2292
2293 dib7000p_write_word(state, 1922, en_cur_state);
2294
2295 return 0;
2296}
2297EXPORT_SYMBOL(dib7090_tuner_sleep);
2298
2299int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart)
2300{
2301 dprintk("AGC restart callback: %d", restart);
2302 return 0;
2303}
2304EXPORT_SYMBOL(dib7090_agc_restart);
2305
2306int dib7090_get_adc_power(struct dvb_frontend *fe)
2307{
2308 return dib7000p_get_adc_power(fe);
2309}
2310EXPORT_SYMBOL(dib7090_get_adc_power);
2311
2312int dib7090_slave_reset(struct dvb_frontend *fe)
2313{
2314 struct dib7000p_state *state = fe->demodulator_priv;
2315 u16 reg;
2316
2317 reg = dib7000p_read_word(state, 1794);
2318 dib7000p_write_word(state, 1794, reg | (4 << 12));
2319
2320 dib7000p_write_word(state, 1032, 0xffff);
2321 return 0;
2322}
2323EXPORT_SYMBOL(dib7090_slave_reset);
2324
2325static struct dvb_frontend_ops dib7000p_ops;
2326struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
2327{
2328 struct dvb_frontend *demod;
2329 struct dib7000p_state *st;
2330 st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
2331 if (st == NULL)
2332 return NULL;
2333
2334 memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config));
2335 st->i2c_adap = i2c_adap;
2336 st->i2c_addr = i2c_addr;
2337 st->gpio_val = cfg->gpio_val;
2338 st->gpio_dir = cfg->gpio_dir;
2339
2340 /* Ensure the output mode remains at the previous default if it's
2341 * not specifically set by the caller.
2342 */
2343 if ((st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (st->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
2344 st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
2345
2346 demod = &st->demod;
2347 demod->demodulator_priv = st;
2348 memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
2349 mutex_init(&st->i2c_buffer_lock);
2350
2351 dib7000p_write_word(st, 1287, 0x0003); /* sram lead in, rdy */
2352
2353 if (dib7000p_identify(st) != 0)
2354 goto error;
2355
2356 st->version = dib7000p_read_word(st, 897);
2357
2358 /* FIXME: make sure the dev.parent field is initialized, or else
2359 request_firmware() will hit an OOPS (this should be moved somewhere
2360 more common) */
2361 st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
2362
2363 /* FIXME: make sure the dev.parent field is initialized, or else
2364 request_firmware() will hit an OOPS (this should be moved somewhere
2365 more common) */
2366 st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
2367
2368 dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
2369
2370 /* init 7090 tuner adapter */
2371 strncpy(st->dib7090_tuner_adap.name, "DiB7090 tuner interface", sizeof(st->dib7090_tuner_adap.name));
2372 st->dib7090_tuner_adap.algo = &dib7090_tuner_xfer_algo;
2373 st->dib7090_tuner_adap.algo_data = NULL;
2374 st->dib7090_tuner_adap.dev.parent = st->i2c_adap->dev.parent;
2375 i2c_set_adapdata(&st->dib7090_tuner_adap, st);
2376 i2c_add_adapter(&st->dib7090_tuner_adap);
2377
2378 dib7000p_demod_reset(st);
2379
2380 if (st->version == SOC7090) {
2381 dib7090_set_output_mode(demod, st->cfg.output_mode);
2382 dib7090_set_diversity_in(demod, 0);
2383 }
2384
2385 return demod;
2386
2387error:
2388 kfree(st);
2389 return NULL;
2390}
2391EXPORT_SYMBOL(dib7000p_attach);
2392
2393static struct dvb_frontend_ops dib7000p_ops = {
2394 .info = {
2395 .name = "DiBcom 7000PC",
2396 .type = FE_OFDM,
2397 .frequency_min = 44250000,
2398 .frequency_max = 867250000,
2399 .frequency_stepsize = 62500,
2400 .caps = FE_CAN_INVERSION_AUTO |
2401 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
2402 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
2403 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
2404 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
2405 },
2406
2407 .release = dib7000p_release,
2408
2409 .init = dib7000p_wakeup,
2410 .sleep = dib7000p_sleep,
2411
2412 .set_frontend = dib7000p_set_frontend,
2413 .get_tune_settings = dib7000p_fe_get_tune_settings,
2414 .get_frontend = dib7000p_get_frontend,
2415
2416 .read_status = dib7000p_read_status,
2417 .read_ber = dib7000p_read_ber,
2418 .read_signal_strength = dib7000p_read_signal_strength,
2419 .read_snr = dib7000p_read_snr,
2420 .read_ucblocks = dib7000p_read_unc_blocks,
2421};
2422
2423MODULE_AUTHOR("Olivier Grenie <ogrenie@dibcom.fr>");
2424MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
2425MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator");
2426MODULE_LICENSE("GPL");