[ARM] pxa: Gumstix Verdex PCMCIA support
[linux-2.6/verdex.git] / drivers / media / dvb / frontends / dib7000p.c
blob55ef6eeb0769f9b8f9aa352962be6418e2f8f827
1 /*
2 * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC).
4 * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
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/i2c.h>
13 #include "dvb_math.h"
14 #include "dvb_frontend.h"
16 #include "dib7000p.h"
18 static int debug;
19 module_param(debug, int, 0644);
20 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
22 static int buggy_sfn_workaround;
23 module_param(buggy_sfn_workaround, int, 0644);
24 MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
26 #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P: "); printk(args); printk("\n"); } } while (0)
28 struct dib7000p_state {
29 struct dvb_frontend demod;
30 struct dib7000p_config cfg;
32 u8 i2c_addr;
33 struct i2c_adapter *i2c_adap;
35 struct dibx000_i2c_master i2c_master;
37 u16 wbd_ref;
39 u8 current_band;
40 u32 current_bandwidth;
41 struct dibx000_agc_config *current_agc;
42 u32 timf;
44 u8 div_force_off : 1;
45 u8 div_state : 1;
46 u16 div_sync_wait;
48 u8 agc_state;
50 u16 gpio_dir;
51 u16 gpio_val;
53 u8 sfn_workaround_active :1;
56 enum dib7000p_power_mode {
57 DIB7000P_POWER_ALL = 0,
58 DIB7000P_POWER_ANALOG_ADC,
59 DIB7000P_POWER_INTERFACE_ONLY,
62 static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
64 u8 wb[2] = { reg >> 8, reg & 0xff };
65 u8 rb[2];
66 struct i2c_msg msg[2] = {
67 { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 },
68 { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
71 if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
72 dprintk("i2c read error on %d",reg);
74 return (rb[0] << 8) | rb[1];
77 static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
79 u8 b[4] = {
80 (reg >> 8) & 0xff, reg & 0xff,
81 (val >> 8) & 0xff, val & 0xff,
83 struct i2c_msg msg = {
84 .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
86 return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
88 static void dib7000p_write_tab(struct dib7000p_state *state, u16 *buf)
90 u16 l = 0, r, *n;
91 n = buf;
92 l = *n++;
93 while (l) {
94 r = *n++;
96 do {
97 dib7000p_write_word(state, r, *n++);
98 r++;
99 } while (--l);
100 l = *n++;
104 static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode)
106 int ret = 0;
107 u16 outreg, fifo_threshold, smo_mode;
109 outreg = 0;
110 fifo_threshold = 1792;
111 smo_mode = (dib7000p_read_word(state, 235) & 0x0010) | (1 << 1);
113 dprintk( "setting output mode for demod %p to %d",
114 &state->demod, mode);
116 switch (mode) {
117 case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock
118 outreg = (1 << 10); /* 0x0400 */
119 break;
120 case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock
121 outreg = (1 << 10) | (1 << 6); /* 0x0440 */
122 break;
123 case OUTMODE_MPEG2_SERIAL: // STBs with serial input
124 outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0480 */
125 break;
126 case OUTMODE_DIVERSITY:
127 if (state->cfg.hostbus_diversity)
128 outreg = (1 << 10) | (4 << 6); /* 0x0500 */
129 else
130 outreg = (1 << 11);
131 break;
132 case OUTMODE_MPEG2_FIFO: // e.g. USB feeding
133 smo_mode |= (3 << 1);
134 fifo_threshold = 512;
135 outreg = (1 << 10) | (5 << 6);
136 break;
137 case OUTMODE_ANALOG_ADC:
138 outreg = (1 << 10) | (3 << 6);
139 break;
140 case OUTMODE_HIGH_Z: // disable
141 outreg = 0;
142 break;
143 default:
144 dprintk( "Unhandled output_mode passed to be set for demod %p",&state->demod);
145 break;
148 if (state->cfg.output_mpeg2_in_188_bytes)
149 smo_mode |= (1 << 5) ;
151 ret |= dib7000p_write_word(state, 235, smo_mode);
152 ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */
153 ret |= dib7000p_write_word(state, 1286, outreg); /* P_Div_active */
155 return ret;
158 static int dib7000p_set_diversity_in(struct dvb_frontend *demod, int onoff)
160 struct dib7000p_state *state = demod->demodulator_priv;
162 if (state->div_force_off) {
163 dprintk( "diversity combination deactivated - forced by COFDM parameters");
164 onoff = 0;
166 state->div_state = (u8)onoff;
168 if (onoff) {
169 dib7000p_write_word(state, 204, 6);
170 dib7000p_write_word(state, 205, 16);
171 /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
172 dib7000p_write_word(state, 207, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
173 } else {
174 dib7000p_write_word(state, 204, 1);
175 dib7000p_write_word(state, 205, 0);
176 dib7000p_write_word(state, 207, 0);
179 return 0;
182 static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode)
184 /* by default everything is powered off */
185 u16 reg_774 = 0xffff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899 = 0x0003,
186 reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff);
188 /* now, depending on the requested mode, we power on */
189 switch (mode) {
190 /* power up everything in the demod */
191 case DIB7000P_POWER_ALL:
192 reg_774 = 0x0000; reg_775 = 0x0000; reg_776 = 0x0; reg_899 = 0x0; reg_1280 &= 0x01ff;
193 break;
195 case DIB7000P_POWER_ANALOG_ADC:
196 /* dem, cfg, iqc, sad, agc */
197 reg_774 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10) | (1 << 9));
198 /* nud */
199 reg_776 &= ~((1 << 0));
200 /* Dout */
201 reg_1280 &= ~((1 << 11));
202 /* fall through wanted to enable the interfaces */
204 /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */
205 case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */
206 reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10));
207 break;
209 /* TODO following stuff is just converted from the dib7000-driver - check when is used what */
212 dib7000p_write_word(state, 774, reg_774);
213 dib7000p_write_word(state, 775, reg_775);
214 dib7000p_write_word(state, 776, reg_776);
215 dib7000p_write_word(state, 899, reg_899);
216 dib7000p_write_word(state, 1280, reg_1280);
218 return 0;
221 static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no)
223 u16 reg_908 = dib7000p_read_word(state, 908),
224 reg_909 = dib7000p_read_word(state, 909);
226 switch (no) {
227 case DIBX000_SLOW_ADC_ON:
228 reg_909 |= (1 << 1) | (1 << 0);
229 dib7000p_write_word(state, 909, reg_909);
230 reg_909 &= ~(1 << 1);
231 break;
233 case DIBX000_SLOW_ADC_OFF:
234 reg_909 |= (1 << 1) | (1 << 0);
235 break;
237 case DIBX000_ADC_ON:
238 reg_908 &= 0x0fff;
239 reg_909 &= 0x0003;
240 break;
242 case DIBX000_ADC_OFF: // leave the VBG voltage on
243 reg_908 |= (1 << 14) | (1 << 13) | (1 << 12);
244 reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
245 break;
247 case DIBX000_VBG_ENABLE:
248 reg_908 &= ~(1 << 15);
249 break;
251 case DIBX000_VBG_DISABLE:
252 reg_908 |= (1 << 15);
253 break;
255 default:
256 break;
259 // dprintk( "908: %x, 909: %x\n", reg_908, reg_909);
261 dib7000p_write_word(state, 908, reg_908);
262 dib7000p_write_word(state, 909, reg_909);
265 static int dib7000p_set_bandwidth(struct dib7000p_state *state, u32 bw)
267 u32 timf;
269 // store the current bandwidth for later use
270 state->current_bandwidth = bw;
272 if (state->timf == 0) {
273 dprintk( "using default timf");
274 timf = state->cfg.bw->timf;
275 } else {
276 dprintk( "using updated timf");
277 timf = state->timf;
280 timf = timf * (bw / 50) / 160;
282 dib7000p_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
283 dib7000p_write_word(state, 24, (u16) ((timf ) & 0xffff));
285 return 0;
288 static int dib7000p_sad_calib(struct dib7000p_state *state)
290 /* internal */
291 // dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth
292 dib7000p_write_word(state, 73, (0 << 1) | (0 << 0));
293 dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096
295 /* do the calibration */
296 dib7000p_write_word(state, 73, (1 << 0));
297 dib7000p_write_word(state, 73, (0 << 0));
299 msleep(1);
301 return 0;
304 int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
306 struct dib7000p_state *state = demod->demodulator_priv;
307 if (value > 4095)
308 value = 4095;
309 state->wbd_ref = value;
310 return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
313 EXPORT_SYMBOL(dib7000p_set_wbd_ref);
314 static void dib7000p_reset_pll(struct dib7000p_state *state)
316 struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
317 u16 clk_cfg0;
319 /* force PLL bypass */
320 clk_cfg0 = (1 << 15) | ((bw->pll_ratio & 0x3f) << 9) |
321 (bw->modulo << 7) | (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) |
322 (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0);
324 dib7000p_write_word(state, 900, clk_cfg0);
326 /* P_pll_cfg */
327 dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset);
328 clk_cfg0 = (bw->pll_bypass << 15) | (clk_cfg0 & 0x7fff);
329 dib7000p_write_word(state, 900, clk_cfg0);
331 dib7000p_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff));
332 dib7000p_write_word(state, 19, (u16) ( (bw->internal*1000 ) & 0xffff));
333 dib7000p_write_word(state, 21, (u16) ( (bw->ifreq >> 16) & 0xffff));
334 dib7000p_write_word(state, 22, (u16) ( (bw->ifreq ) & 0xffff));
336 dib7000p_write_word(state, 72, bw->sad_cfg);
339 static int dib7000p_reset_gpio(struct dib7000p_state *st)
341 /* reset the GPIOs */
342 dprintk( "gpio dir: %x: val: %x, pwm_pos: %x",st->gpio_dir, st->gpio_val,st->cfg.gpio_pwm_pos);
344 dib7000p_write_word(st, 1029, st->gpio_dir);
345 dib7000p_write_word(st, 1030, st->gpio_val);
347 /* TODO 1031 is P_gpio_od */
349 dib7000p_write_word(st, 1032, st->cfg.gpio_pwm_pos);
351 dib7000p_write_word(st, 1037, st->cfg.pwm_freq_div);
352 return 0;
355 static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
357 st->gpio_dir = dib7000p_read_word(st, 1029);
358 st->gpio_dir &= ~(1 << num); /* reset the direction bit */
359 st->gpio_dir |= (dir & 0x1) << num; /* set the new direction */
360 dib7000p_write_word(st, 1029, st->gpio_dir);
362 st->gpio_val = dib7000p_read_word(st, 1030);
363 st->gpio_val &= ~(1 << num); /* reset the direction bit */
364 st->gpio_val |= (val & 0x01) << num; /* set the new value */
365 dib7000p_write_word(st, 1030, st->gpio_val);
367 return 0;
370 int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
372 struct dib7000p_state *state = demod->demodulator_priv;
373 return dib7000p_cfg_gpio(state, num, dir, val);
376 EXPORT_SYMBOL(dib7000p_set_gpio);
377 static u16 dib7000p_defaults[] =
380 // auto search configuration
381 3, 2,
382 0x0004,
383 0x1000,
384 0x0814, /* Equal Lock */
386 12, 6,
387 0x001b,
388 0x7740,
389 0x005b,
390 0x8d80,
391 0x01c9,
392 0xc380,
393 0x0000,
394 0x0080,
395 0x0000,
396 0x0090,
397 0x0001,
398 0xd4c0,
400 1, 26,
401 0x6680, // P_timf_alpha=6, P_corm_alpha=6, P_corm_thres=128 default: 6,4,26
403 /* set ADC level to -16 */
404 11, 79,
405 (1 << 13) - 825 - 117,
406 (1 << 13) - 837 - 117,
407 (1 << 13) - 811 - 117,
408 (1 << 13) - 766 - 117,
409 (1 << 13) - 737 - 117,
410 (1 << 13) - 693 - 117,
411 (1 << 13) - 648 - 117,
412 (1 << 13) - 619 - 117,
413 (1 << 13) - 575 - 117,
414 (1 << 13) - 531 - 117,
415 (1 << 13) - 501 - 117,
417 1, 142,
418 0x0410, // P_palf_filter_on=1, P_palf_filter_freeze=0, P_palf_alpha_regul=16
420 /* disable power smoothing */
421 8, 145,
431 1, 154,
432 1 << 13, // P_fft_freq_dir=1, P_fft_nb_to_cut=0
434 1, 168,
435 0x0ccd, // P_pha3_thres, default 0x3000
437 // 1, 169,
438 // 0x0010, // P_cti_use_cpe=0, P_cti_use_prog=0, P_cti_win_len=16, default: 0x0010
440 1, 183,
441 0x200f, // P_cspu_regul=512, P_cspu_win_cut=15, default: 0x2005
443 5, 187,
444 0x023d, // P_adp_regul_cnt=573, default: 410
445 0x00a4, // P_adp_noise_cnt=
446 0x00a4, // P_adp_regul_ext
447 0x7ff0, // P_adp_noise_ext
448 0x3ccc, // P_adp_fil
450 1, 198,
451 0x800, // P_equal_thres_wgn
453 1, 222,
454 0x0010, // P_fec_ber_rs_len=2
456 1, 235,
457 0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
459 2, 901,
460 0x0006, // P_clk_cfg1
461 (3 << 10) | (1 << 6), // P_divclksel=3 P_divbitsel=1
463 1, 905,
464 0x2c8e, // Tuner IO bank: max drive (14mA) + divout pads max drive
469 static int dib7000p_demod_reset(struct dib7000p_state *state)
471 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
473 dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE);
475 /* restart all parts */
476 dib7000p_write_word(state, 770, 0xffff);
477 dib7000p_write_word(state, 771, 0xffff);
478 dib7000p_write_word(state, 772, 0x001f);
479 dib7000p_write_word(state, 898, 0x0003);
480 /* except i2c, sdio, gpio - control interfaces */
481 dib7000p_write_word(state, 1280, 0x01fc - ((1 << 7) | (1 << 6) | (1 << 5)) );
483 dib7000p_write_word(state, 770, 0);
484 dib7000p_write_word(state, 771, 0);
485 dib7000p_write_word(state, 772, 0);
486 dib7000p_write_word(state, 898, 0);
487 dib7000p_write_word(state, 1280, 0);
489 /* default */
490 dib7000p_reset_pll(state);
492 if (dib7000p_reset_gpio(state) != 0)
493 dprintk( "GPIO reset was not successful.");
495 if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
496 dprintk( "OUTPUT_MODE could not be reset.");
498 /* unforce divstr regardless whether i2c enumeration was done or not */
499 dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1) );
501 dib7000p_set_bandwidth(state, 8000);
503 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
504 dib7000p_sad_calib(state);
505 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
507 // P_iqc_alpha_pha, P_iqc_alpha_amp_dcc_alpha, ...
508 if(state->cfg.tuner_is_baseband)
509 dib7000p_write_word(state, 36,0x0755);
510 else
511 dib7000p_write_word(state, 36,0x1f55);
513 dib7000p_write_tab(state, dib7000p_defaults);
515 dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
518 return 0;
521 static void dib7000p_pll_clk_cfg(struct dib7000p_state *state)
523 u16 tmp = 0;
524 tmp = dib7000p_read_word(state, 903);
525 dib7000p_write_word(state, 903, (tmp | 0x1)); //pwr-up pll
526 tmp = dib7000p_read_word(state, 900);
527 dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6)); //use High freq clock
530 static void dib7000p_restart_agc(struct dib7000p_state *state)
532 // P_restart_iqc & P_restart_agc
533 dib7000p_write_word(state, 770, (1 << 11) | (1 << 9));
534 dib7000p_write_word(state, 770, 0x0000);
537 static int dib7000p_update_lna(struct dib7000p_state *state)
539 u16 dyn_gain;
541 // when there is no LNA to program return immediatly
542 if (state->cfg.update_lna) {
543 // read dyn_gain here (because it is demod-dependent and not fe)
544 dyn_gain = dib7000p_read_word(state, 394);
545 if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
546 dib7000p_restart_agc(state);
547 return 1;
551 return 0;
554 static int dib7000p_set_agc_config(struct dib7000p_state *state, u8 band)
556 struct dibx000_agc_config *agc = NULL;
557 int i;
558 if (state->current_band == band && state->current_agc != NULL)
559 return 0;
560 state->current_band = band;
562 for (i = 0; i < state->cfg.agc_config_count; i++)
563 if (state->cfg.agc[i].band_caps & band) {
564 agc = &state->cfg.agc[i];
565 break;
568 if (agc == NULL) {
569 dprintk( "no valid AGC configuration found for band 0x%02x",band);
570 return -EINVAL;
573 state->current_agc = agc;
575 /* AGC */
576 dib7000p_write_word(state, 75 , agc->setup );
577 dib7000p_write_word(state, 76 , agc->inv_gain );
578 dib7000p_write_word(state, 77 , agc->time_stabiliz );
579 dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock);
581 // Demod AGC loop configuration
582 dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp);
583 dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp);
585 /* AGC continued */
586 dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d",
587 state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
589 if (state->wbd_ref != 0)
590 dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref);
591 else
592 dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref);
594 dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
596 dib7000p_write_word(state, 107, agc->agc1_max);
597 dib7000p_write_word(state, 108, agc->agc1_min);
598 dib7000p_write_word(state, 109, agc->agc2_max);
599 dib7000p_write_word(state, 110, agc->agc2_min);
600 dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
601 dib7000p_write_word(state, 112, agc->agc1_pt3);
602 dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
603 dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
604 dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
605 return 0;
608 static int dib7000p_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
610 struct dib7000p_state *state = demod->demodulator_priv;
611 int ret = -1;
612 u8 *agc_state = &state->agc_state;
613 u8 agc_split;
615 switch (state->agc_state) {
616 case 0:
617 // set power-up level: interf+analog+AGC
618 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
619 dib7000p_set_adc_state(state, DIBX000_ADC_ON);
620 dib7000p_pll_clk_cfg(state);
622 if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0)
623 return -1;
625 ret = 7;
626 (*agc_state)++;
627 break;
629 case 1:
630 // AGC initialization
631 if (state->cfg.agc_control)
632 state->cfg.agc_control(&state->demod, 1);
634 dib7000p_write_word(state, 78, 32768);
635 if (!state->current_agc->perform_agc_softsplit) {
636 /* we are using the wbd - so slow AGC startup */
637 /* force 0 split on WBD and restart AGC */
638 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | (1 << 8));
639 (*agc_state)++;
640 ret = 5;
641 } else {
642 /* default AGC startup */
643 (*agc_state) = 4;
644 /* wait AGC rough lock time */
645 ret = 7;
648 dib7000p_restart_agc(state);
649 break;
651 case 2: /* fast split search path after 5sec */
652 dib7000p_write_word(state, 75, state->current_agc->setup | (1 << 4)); /* freeze AGC loop */
653 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (2 << 9) | (0 << 8)); /* fast split search 0.25kHz */
654 (*agc_state)++;
655 ret = 14;
656 break;
658 case 3: /* split search ended */
659 agc_split = (u8)dib7000p_read_word(state, 396); /* store the split value for the next time */
660 dib7000p_write_word(state, 78, dib7000p_read_word(state, 394)); /* set AGC gain start value */
662 dib7000p_write_word(state, 75, state->current_agc->setup); /* std AGC loop */
663 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
665 dib7000p_restart_agc(state);
667 dprintk( "SPLIT %p: %hd", demod, agc_split);
669 (*agc_state)++;
670 ret = 5;
671 break;
673 case 4: /* LNA startup */
674 // wait AGC accurate lock time
675 ret = 7;
677 if (dib7000p_update_lna(state))
678 // wait only AGC rough lock time
679 ret = 5;
680 else // nothing was done, go to the next state
681 (*agc_state)++;
682 break;
684 case 5:
685 if (state->cfg.agc_control)
686 state->cfg.agc_control(&state->demod, 0);
687 (*agc_state)++;
688 break;
689 default:
690 break;
692 return ret;
695 static void dib7000p_update_timf(struct dib7000p_state *state)
697 u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428);
698 state->timf = timf * 160 / (state->current_bandwidth / 50);
699 dib7000p_write_word(state, 23, (u16) (timf >> 16));
700 dib7000p_write_word(state, 24, (u16) (timf & 0xffff));
701 dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->cfg.bw->timf);
705 static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_frontend_parameters *ch, u8 seq)
707 u16 value, est[4];
709 dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
711 /* nfft, guard, qam, alpha */
712 value = 0;
713 switch (ch->u.ofdm.transmission_mode) {
714 case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
715 case /* 4K MODE */ 255: value |= (2 << 7); break;
716 default:
717 case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
719 switch (ch->u.ofdm.guard_interval) {
720 case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
721 case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
722 case GUARD_INTERVAL_1_4: value |= (3 << 5); break;
723 default:
724 case GUARD_INTERVAL_1_8: value |= (2 << 5); break;
726 switch (ch->u.ofdm.constellation) {
727 case QPSK: value |= (0 << 3); break;
728 case QAM_16: value |= (1 << 3); break;
729 default:
730 case QAM_64: value |= (2 << 3); break;
732 switch (HIERARCHY_1) {
733 case HIERARCHY_2: value |= 2; break;
734 case HIERARCHY_4: value |= 4; break;
735 default:
736 case HIERARCHY_1: value |= 1; break;
738 dib7000p_write_word(state, 0, value);
739 dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */
741 /* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
742 value = 0;
743 if (1 != 0)
744 value |= (1 << 6);
745 if (ch->u.ofdm.hierarchy_information == 1)
746 value |= (1 << 4);
747 if (1 == 1)
748 value |= 1;
749 switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
750 case FEC_2_3: value |= (2 << 1); break;
751 case FEC_3_4: value |= (3 << 1); break;
752 case FEC_5_6: value |= (5 << 1); break;
753 case FEC_7_8: value |= (7 << 1); break;
754 default:
755 case FEC_1_2: value |= (1 << 1); break;
757 dib7000p_write_word(state, 208, value);
759 /* offset loop parameters */
760 dib7000p_write_word(state, 26, 0x6680); // timf(6xxx)
761 dib7000p_write_word(state, 32, 0x0003); // pha_off_max(xxx3)
762 dib7000p_write_word(state, 29, 0x1273); // isi
763 dib7000p_write_word(state, 33, 0x0005); // sfreq(xxx5)
765 /* P_dvsy_sync_wait */
766 switch (ch->u.ofdm.transmission_mode) {
767 case TRANSMISSION_MODE_8K: value = 256; break;
768 case /* 4K MODE */ 255: value = 128; break;
769 case TRANSMISSION_MODE_2K:
770 default: value = 64; break;
772 switch (ch->u.ofdm.guard_interval) {
773 case GUARD_INTERVAL_1_16: value *= 2; break;
774 case GUARD_INTERVAL_1_8: value *= 4; break;
775 case GUARD_INTERVAL_1_4: value *= 8; break;
776 default:
777 case GUARD_INTERVAL_1_32: value *= 1; break;
779 state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO
781 /* deactive the possibility of diversity reception if extended interleaver */
782 state->div_force_off = !1 && ch->u.ofdm.transmission_mode != TRANSMISSION_MODE_8K;
783 dib7000p_set_diversity_in(&state->demod, state->div_state);
785 /* channel estimation fine configuration */
786 switch (ch->u.ofdm.constellation) {
787 case QAM_64:
788 est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
789 est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
790 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
791 est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */
792 break;
793 case QAM_16:
794 est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */
795 est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */
796 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
797 est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */
798 break;
799 default:
800 est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */
801 est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */
802 est[2] = 0x0333; /* P_adp_regul_ext 0.1 */
803 est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */
804 break;
806 for (value = 0; value < 4; value++)
807 dib7000p_write_word(state, 187 + value, est[value]);
810 static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
812 struct dib7000p_state *state = demod->demodulator_priv;
813 struct dvb_frontend_parameters schan;
814 u32 value, factor;
816 schan = *ch;
817 schan.u.ofdm.constellation = QAM_64;
818 schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
819 schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
820 schan.u.ofdm.code_rate_HP = FEC_2_3;
821 schan.u.ofdm.code_rate_LP = FEC_3_4;
822 schan.u.ofdm.hierarchy_information = 0;
824 dib7000p_set_channel(state, &schan, 7);
826 factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth);
827 if (factor >= 5000)
828 factor = 1;
829 else
830 factor = 6;
832 // always use the setting for 8MHz here lock_time for 7,6 MHz are longer
833 value = 30 * state->cfg.bw->internal * factor;
834 dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time
835 dib7000p_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time
836 value = 100 * state->cfg.bw->internal * factor;
837 dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time
838 dib7000p_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time
839 value = 500 * state->cfg.bw->internal * factor;
840 dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
841 dib7000p_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time
843 value = dib7000p_read_word(state, 0);
844 dib7000p_write_word(state, 0, (u16) ((1 << 9) | value));
845 dib7000p_read_word(state, 1284);
846 dib7000p_write_word(state, 0, (u16) value);
848 return 0;
851 static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod)
853 struct dib7000p_state *state = demod->demodulator_priv;
854 u16 irq_pending = dib7000p_read_word(state, 1284);
856 if (irq_pending & 0x1) // failed
857 return 1;
859 if (irq_pending & 0x2) // succeeded
860 return 2;
862 return 0; // still pending
865 static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 bw)
867 static s16 notch[]={16143, 14402, 12238, 9713, 6902, 3888, 759, -2392};
868 static u8 sine [] ={0, 2, 3, 5, 6, 8, 9, 11, 13, 14, 16, 17, 19, 20, 22,
869 24, 25, 27, 28, 30, 31, 33, 34, 36, 38, 39, 41, 42, 44, 45, 47, 48, 50, 51,
870 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80,
871 82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, 104, 105,
872 107, 108, 109, 111, 112, 114, 115, 117, 118, 119, 121, 122, 123, 125, 126,
873 128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 144, 145, 146,
874 147, 149, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 162, 164, 165,
875 166, 167, 168, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182,
876 183, 184, 185, 186, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
877 199, 200, 201, 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 212,
878 213, 214, 215, 215, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 224,
879 225, 226, 227, 227, 228, 229, 229, 230, 231, 231, 232, 233, 233, 234, 235,
880 235, 236, 237, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 243,
881 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 248, 249, 249, 249,
882 250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 254,
883 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
884 255, 255, 255, 255, 255, 255};
886 u32 xtal = state->cfg.bw->xtal_hz / 1000;
887 int f_rel = DIV_ROUND_CLOSEST(rf_khz, xtal) * xtal - rf_khz;
888 int k;
889 int coef_re[8],coef_im[8];
890 int bw_khz = bw;
891 u32 pha;
893 dprintk( "relative position of the Spur: %dk (RF: %dk, XTAL: %dk)", f_rel, rf_khz, xtal);
896 if (f_rel < -bw_khz/2 || f_rel > bw_khz/2)
897 return;
899 bw_khz /= 100;
901 dib7000p_write_word(state, 142 ,0x0610);
903 for (k = 0; k < 8; k++) {
904 pha = ((f_rel * (k+1) * 112 * 80/bw_khz) /1000) & 0x3ff;
906 if (pha==0) {
907 coef_re[k] = 256;
908 coef_im[k] = 0;
909 } else if(pha < 256) {
910 coef_re[k] = sine[256-(pha&0xff)];
911 coef_im[k] = sine[pha&0xff];
912 } else if (pha == 256) {
913 coef_re[k] = 0;
914 coef_im[k] = 256;
915 } else if (pha < 512) {
916 coef_re[k] = -sine[pha&0xff];
917 coef_im[k] = sine[256 - (pha&0xff)];
918 } else if (pha == 512) {
919 coef_re[k] = -256;
920 coef_im[k] = 0;
921 } else if (pha < 768) {
922 coef_re[k] = -sine[256-(pha&0xff)];
923 coef_im[k] = -sine[pha&0xff];
924 } else if (pha == 768) {
925 coef_re[k] = 0;
926 coef_im[k] = -256;
927 } else {
928 coef_re[k] = sine[pha&0xff];
929 coef_im[k] = -sine[256 - (pha&0xff)];
932 coef_re[k] *= notch[k];
933 coef_re[k] += (1<<14);
934 if (coef_re[k] >= (1<<24))
935 coef_re[k] = (1<<24) - 1;
936 coef_re[k] /= (1<<15);
938 coef_im[k] *= notch[k];
939 coef_im[k] += (1<<14);
940 if (coef_im[k] >= (1<<24))
941 coef_im[k] = (1<<24)-1;
942 coef_im[k] /= (1<<15);
944 dprintk( "PALF COEF: %d re: %d im: %d", k, coef_re[k], coef_im[k]);
946 dib7000p_write_word(state, 143, (0 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
947 dib7000p_write_word(state, 144, coef_im[k] & 0x3ff);
948 dib7000p_write_word(state, 143, (1 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
950 dib7000p_write_word(state,143 ,0);
953 static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
955 struct dib7000p_state *state = demod->demodulator_priv;
956 u16 tmp = 0;
958 if (ch != NULL)
959 dib7000p_set_channel(state, ch, 0);
960 else
961 return -EINVAL;
963 // restart demod
964 dib7000p_write_word(state, 770, 0x4000);
965 dib7000p_write_word(state, 770, 0x0000);
966 msleep(45);
968 /* 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 */
969 tmp = (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3);
970 if (state->sfn_workaround_active) {
971 dprintk( "SFN workaround is active");
972 tmp |= (1 << 9);
973 dib7000p_write_word(state, 166, 0x4000); // P_pha3_force_pha_shift
974 } else {
975 dib7000p_write_word(state, 166, 0x0000); // P_pha3_force_pha_shift
977 dib7000p_write_word(state, 29, tmp);
979 // never achieved a lock with that bandwidth so far - wait for osc-freq to update
980 if (state->timf == 0)
981 msleep(200);
983 /* offset loop parameters */
985 /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
986 tmp = (6 << 8) | 0x80;
987 switch (ch->u.ofdm.transmission_mode) {
988 case TRANSMISSION_MODE_2K: tmp |= (7 << 12); break;
989 case /* 4K MODE */ 255: tmp |= (8 << 12); break;
990 default:
991 case TRANSMISSION_MODE_8K: tmp |= (9 << 12); break;
993 dib7000p_write_word(state, 26, tmp); /* timf_a(6xxx) */
995 /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
996 tmp = (0 << 4);
997 switch (ch->u.ofdm.transmission_mode) {
998 case TRANSMISSION_MODE_2K: tmp |= 0x6; break;
999 case /* 4K MODE */ 255: tmp |= 0x7; break;
1000 default:
1001 case TRANSMISSION_MODE_8K: tmp |= 0x8; break;
1003 dib7000p_write_word(state, 32, tmp);
1005 /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
1006 tmp = (0 << 4);
1007 switch (ch->u.ofdm.transmission_mode) {
1008 case TRANSMISSION_MODE_2K: tmp |= 0x6; break;
1009 case /* 4K MODE */ 255: tmp |= 0x7; break;
1010 default:
1011 case TRANSMISSION_MODE_8K: tmp |= 0x8; break;
1013 dib7000p_write_word(state, 33, tmp);
1015 tmp = dib7000p_read_word(state,509);
1016 if (!((tmp >> 6) & 0x1)) {
1017 /* restart the fec */
1018 tmp = dib7000p_read_word(state,771);
1019 dib7000p_write_word(state, 771, tmp | (1 << 1));
1020 dib7000p_write_word(state, 771, tmp);
1021 msleep(10);
1022 tmp = dib7000p_read_word(state,509);
1025 // we achieved a lock - it's time to update the osc freq
1026 if ((tmp >> 6) & 0x1)
1027 dib7000p_update_timf(state);
1029 if (state->cfg.spur_protect)
1030 dib7000p_spur_protect(state, ch->frequency/1000, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
1032 dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
1033 return 0;
1036 static int dib7000p_wakeup(struct dvb_frontend *demod)
1038 struct dib7000p_state *state = demod->demodulator_priv;
1039 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
1040 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
1041 return 0;
1044 static int dib7000p_sleep(struct dvb_frontend *demod)
1046 struct dib7000p_state *state = demod->demodulator_priv;
1047 return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
1050 static int dib7000p_identify(struct dib7000p_state *st)
1052 u16 value;
1053 dprintk( "checking demod on I2C address: %d (%x)",
1054 st->i2c_addr, st->i2c_addr);
1056 if ((value = dib7000p_read_word(st, 768)) != 0x01b3) {
1057 dprintk( "wrong Vendor ID (read=0x%x)",value);
1058 return -EREMOTEIO;
1061 if ((value = dib7000p_read_word(st, 769)) != 0x4000) {
1062 dprintk( "wrong Device ID (%x)",value);
1063 return -EREMOTEIO;
1066 return 0;
1070 static int dib7000p_get_frontend(struct dvb_frontend* fe,
1071 struct dvb_frontend_parameters *fep)
1073 struct dib7000p_state *state = fe->demodulator_priv;
1074 u16 tps = dib7000p_read_word(state,463);
1076 fep->inversion = INVERSION_AUTO;
1078 fep->u.ofdm.bandwidth = BANDWIDTH_TO_INDEX(state->current_bandwidth);
1080 switch ((tps >> 8) & 0x3) {
1081 case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
1082 case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
1083 /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
1086 switch (tps & 0x3) {
1087 case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
1088 case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
1089 case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
1090 case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
1093 switch ((tps >> 14) & 0x3) {
1094 case 0: fep->u.ofdm.constellation = QPSK; break;
1095 case 1: fep->u.ofdm.constellation = QAM_16; break;
1096 case 2:
1097 default: fep->u.ofdm.constellation = QAM_64; break;
1100 /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
1101 /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
1103 fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
1104 switch ((tps >> 5) & 0x7) {
1105 case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
1106 case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
1107 case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
1108 case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
1109 case 7:
1110 default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
1114 switch ((tps >> 2) & 0x7) {
1115 case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
1116 case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
1117 case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
1118 case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
1119 case 7:
1120 default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
1123 /* native interleaver: (dib7000p_read_word(state, 464) >> 5) & 0x1 */
1125 return 0;
1128 static int dib7000p_set_frontend(struct dvb_frontend* fe,
1129 struct dvb_frontend_parameters *fep)
1131 struct dib7000p_state *state = fe->demodulator_priv;
1132 int time, ret;
1134 dib7000p_set_output_mode(state, OUTMODE_HIGH_Z);
1136 /* maybe the parameter has been changed */
1137 state->sfn_workaround_active = buggy_sfn_workaround;
1139 if (fe->ops.tuner_ops.set_params)
1140 fe->ops.tuner_ops.set_params(fe, fep);
1142 /* start up the AGC */
1143 state->agc_state = 0;
1144 do {
1145 time = dib7000p_agc_startup(fe, fep);
1146 if (time != -1)
1147 msleep(time);
1148 } while (time != -1);
1150 if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
1151 fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
1152 fep->u.ofdm.constellation == QAM_AUTO ||
1153 fep->u.ofdm.code_rate_HP == FEC_AUTO) {
1154 int i = 800, found;
1156 dib7000p_autosearch_start(fe, fep);
1157 do {
1158 msleep(1);
1159 found = dib7000p_autosearch_is_irq(fe);
1160 } while (found == 0 && i--);
1162 dprintk("autosearch returns: %d",found);
1163 if (found == 0 || found == 1)
1164 return 0; // no channel found
1166 dib7000p_get_frontend(fe, fep);
1169 ret = dib7000p_tune(fe, fep);
1171 /* make this a config parameter */
1172 dib7000p_set_output_mode(state, state->cfg.output_mode);
1173 return ret;
1176 static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat)
1178 struct dib7000p_state *state = fe->demodulator_priv;
1179 u16 lock = dib7000p_read_word(state, 509);
1181 *stat = 0;
1183 if (lock & 0x8000)
1184 *stat |= FE_HAS_SIGNAL;
1185 if (lock & 0x3000)
1186 *stat |= FE_HAS_CARRIER;
1187 if (lock & 0x0100)
1188 *stat |= FE_HAS_VITERBI;
1189 if (lock & 0x0010)
1190 *stat |= FE_HAS_SYNC;
1191 if (lock & 0x0008)
1192 *stat |= FE_HAS_LOCK;
1194 return 0;
1197 static int dib7000p_read_ber(struct dvb_frontend *fe, u32 *ber)
1199 struct dib7000p_state *state = fe->demodulator_priv;
1200 *ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501);
1201 return 0;
1204 static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
1206 struct dib7000p_state *state = fe->demodulator_priv;
1207 *unc = dib7000p_read_word(state, 506);
1208 return 0;
1211 static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
1213 struct dib7000p_state *state = fe->demodulator_priv;
1214 u16 val = dib7000p_read_word(state, 394);
1215 *strength = 65535 - val;
1216 return 0;
1219 static int dib7000p_read_snr(struct dvb_frontend* fe, u16 *snr)
1221 struct dib7000p_state *state = fe->demodulator_priv;
1222 u16 val;
1223 s32 signal_mant, signal_exp, noise_mant, noise_exp;
1224 u32 result = 0;
1226 val = dib7000p_read_word(state, 479);
1227 noise_mant = (val >> 4) & 0xff;
1228 noise_exp = ((val & 0xf) << 2);
1229 val = dib7000p_read_word(state, 480);
1230 noise_exp += ((val >> 14) & 0x3);
1231 if ((noise_exp & 0x20) != 0)
1232 noise_exp -= 0x40;
1234 signal_mant = (val >> 6) & 0xFF;
1235 signal_exp = (val & 0x3F);
1236 if ((signal_exp & 0x20) != 0)
1237 signal_exp -= 0x40;
1239 if (signal_mant != 0)
1240 result = intlog10(2) * 10 * signal_exp + 10 *
1241 intlog10(signal_mant);
1242 else
1243 result = intlog10(2) * 10 * signal_exp - 100;
1245 if (noise_mant != 0)
1246 result -= intlog10(2) * 10 * noise_exp + 10 *
1247 intlog10(noise_mant);
1248 else
1249 result -= intlog10(2) * 10 * noise_exp - 100;
1251 *snr = result / ((1 << 24) / 10);
1252 return 0;
1255 static int dib7000p_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
1257 tune->min_delay_ms = 1000;
1258 return 0;
1261 static void dib7000p_release(struct dvb_frontend *demod)
1263 struct dib7000p_state *st = demod->demodulator_priv;
1264 dibx000_exit_i2c_master(&st->i2c_master);
1265 kfree(st);
1268 int dib7000pc_detection(struct i2c_adapter *i2c_adap)
1270 u8 tx[2], rx[2];
1271 struct i2c_msg msg[2] = {
1272 { .addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2 },
1273 { .addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2 },
1276 tx[0] = 0x03;
1277 tx[1] = 0x00;
1279 if (i2c_transfer(i2c_adap, msg, 2) == 2)
1280 if (rx[0] == 0x01 && rx[1] == 0xb3) {
1281 dprintk("-D- DiB7000PC detected");
1282 return 1;
1285 msg[0].addr = msg[1].addr = 0x40;
1287 if (i2c_transfer(i2c_adap, msg, 2) == 2)
1288 if (rx[0] == 0x01 && rx[1] == 0xb3) {
1289 dprintk("-D- DiB7000PC detected");
1290 return 1;
1293 dprintk("-D- DiB7000PC not detected");
1294 return 0;
1296 EXPORT_SYMBOL(dib7000pc_detection);
1298 struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
1300 struct dib7000p_state *st = demod->demodulator_priv;
1301 return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
1303 EXPORT_SYMBOL(dib7000p_get_i2c_master);
1305 int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
1307 struct dib7000p_state st = { .i2c_adap = i2c };
1308 int k = 0;
1309 u8 new_addr = 0;
1311 for (k = no_of_demods-1; k >= 0; k--) {
1312 st.cfg = cfg[k];
1314 /* designated i2c address */
1315 new_addr = (0x40 + k) << 1;
1316 st.i2c_addr = new_addr;
1317 if (dib7000p_identify(&st) != 0) {
1318 st.i2c_addr = default_addr;
1319 if (dib7000p_identify(&st) != 0) {
1320 dprintk("DiB7000P #%d: not identified\n", k);
1321 return -EIO;
1325 /* start diversity to pull_down div_str - just for i2c-enumeration */
1326 dib7000p_set_output_mode(&st, OUTMODE_DIVERSITY);
1328 /* set new i2c address and force divstart */
1329 dib7000p_write_word(&st, 1285, (new_addr << 2) | 0x2);
1331 dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
1334 for (k = 0; k < no_of_demods; k++) {
1335 st.cfg = cfg[k];
1336 st.i2c_addr = (0x40 + k) << 1;
1338 // unforce divstr
1339 dib7000p_write_word(&st, 1285, st.i2c_addr << 2);
1341 /* deactivate div - it was just for i2c-enumeration */
1342 dib7000p_set_output_mode(&st, OUTMODE_HIGH_Z);
1345 return 0;
1347 EXPORT_SYMBOL(dib7000p_i2c_enumeration);
1349 static struct dvb_frontend_ops dib7000p_ops;
1350 struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
1352 struct dvb_frontend *demod;
1353 struct dib7000p_state *st;
1354 st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
1355 if (st == NULL)
1356 return NULL;
1358 memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config));
1359 st->i2c_adap = i2c_adap;
1360 st->i2c_addr = i2c_addr;
1361 st->gpio_val = cfg->gpio_val;
1362 st->gpio_dir = cfg->gpio_dir;
1364 /* Ensure the output mode remains at the previous default if it's
1365 * not specifically set by the caller.
1367 if ((st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) &&
1368 (st->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
1369 st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
1371 demod = &st->demod;
1372 demod->demodulator_priv = st;
1373 memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
1375 if (dib7000p_identify(st) != 0)
1376 goto error;
1378 dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
1380 dib7000p_demod_reset(st);
1382 return demod;
1384 error:
1385 kfree(st);
1386 return NULL;
1388 EXPORT_SYMBOL(dib7000p_attach);
1390 static struct dvb_frontend_ops dib7000p_ops = {
1391 .info = {
1392 .name = "DiBcom 7000PC",
1393 .type = FE_OFDM,
1394 .frequency_min = 44250000,
1395 .frequency_max = 867250000,
1396 .frequency_stepsize = 62500,
1397 .caps = FE_CAN_INVERSION_AUTO |
1398 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1399 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1400 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
1401 FE_CAN_TRANSMISSION_MODE_AUTO |
1402 FE_CAN_GUARD_INTERVAL_AUTO |
1403 FE_CAN_RECOVER |
1404 FE_CAN_HIERARCHY_AUTO,
1407 .release = dib7000p_release,
1409 .init = dib7000p_wakeup,
1410 .sleep = dib7000p_sleep,
1412 .set_frontend = dib7000p_set_frontend,
1413 .get_tune_settings = dib7000p_fe_get_tune_settings,
1414 .get_frontend = dib7000p_get_frontend,
1416 .read_status = dib7000p_read_status,
1417 .read_ber = dib7000p_read_ber,
1418 .read_signal_strength = dib7000p_read_signal_strength,
1419 .read_snr = dib7000p_read_snr,
1420 .read_ucblocks = dib7000p_read_unc_blocks,
1423 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
1424 MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator");
1425 MODULE_LICENSE("GPL");