blob: 1175ab9a45325202aa8ad0c16e1f14b30ca2c5ae [file] [log] [blame]
Patrick Boettchera75763f2006-10-18 08:34:16 -03001/*
2 * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC).
3 *
Patrick Boettcherb6884a12007-07-27 10:08:51 -03004 * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
Patrick Boettchera75763f2006-10-18 08:34:16 -03005 *
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>
12
13#include "dvb_frontend.h"
14
15#include "dib7000p.h"
16
17static int debug;
18module_param(debug, int, 0644);
19MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
20
Patrick Boettcherb6884a12007-07-27 10:08:51 -030021#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P: "); printk(args); printk("\n"); } } while (0)
Patrick Boettchera75763f2006-10-18 08:34:16 -030022
23struct dib7000p_state {
24 struct dvb_frontend demod;
25 struct dib7000p_config cfg;
26
27 u8 i2c_addr;
28 struct i2c_adapter *i2c_adap;
29
30 struct dibx000_i2c_master i2c_master;
31
32 u16 wbd_ref;
33
34 u8 current_band;
35 fe_bandwidth_t current_bandwidth;
36 struct dibx000_agc_config *current_agc;
37 u32 timf;
38
Patrick Boettcher01373a52007-07-30 12:49:04 -030039 u8 div_force_off : 1;
40 u8 div_state : 1;
41 u16 div_sync_wait;
Patrick Boettcherb6884a12007-07-27 10:08:51 -030042
43 u8 agc_state;
44
Patrick Boettchera75763f2006-10-18 08:34:16 -030045 u16 gpio_dir;
46 u16 gpio_val;
47};
48
49enum dib7000p_power_mode {
50 DIB7000P_POWER_ALL = 0,
Patrick Boettcherb6884a12007-07-27 10:08:51 -030051 DIB7000P_POWER_ANALOG_ADC,
Patrick Boettchera75763f2006-10-18 08:34:16 -030052 DIB7000P_POWER_INTERFACE_ONLY,
53};
54
55static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
56{
57 u8 wb[2] = { reg >> 8, reg & 0xff };
58 u8 rb[2];
59 struct i2c_msg msg[2] = {
60 { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 },
61 { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
62 };
63
64 if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
Patrick Boettcherb6884a12007-07-27 10:08:51 -030065 dprintk("i2c read error on %d",reg);
Patrick Boettchera75763f2006-10-18 08:34:16 -030066
67 return (rb[0] << 8) | rb[1];
68}
69
70static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
71{
72 u8 b[4] = {
73 (reg >> 8) & 0xff, reg & 0xff,
74 (val >> 8) & 0xff, val & 0xff,
75 };
76 struct i2c_msg msg = {
77 .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
78 };
79 return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
80}
Patrick Boettcherb6884a12007-07-27 10:08:51 -030081static void dib7000p_write_tab(struct dib7000p_state *state, u16 *buf)
82{
83 u16 l = 0, r, *n;
84 n = buf;
85 l = *n++;
86 while (l) {
87 r = *n++;
88
89 do {
90 dib7000p_write_word(state, r, *n++);
91 r++;
92 } while (--l);
93 l = *n++;
94 }
95}
96
Patrick Boettchera75763f2006-10-18 08:34:16 -030097static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode)
98{
99 int ret = 0;
100 u16 outreg, fifo_threshold, smo_mode;
101
102 outreg = 0;
103 fifo_threshold = 1792;
104 smo_mode = (dib7000p_read_word(state, 235) & 0x0010) | (1 << 1);
105
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300106 dprintk( "setting output mode for demod %p to %d",
Patrick Boettchera75763f2006-10-18 08:34:16 -0300107 &state->demod, mode);
108
109 switch (mode) {
110 case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock
111 outreg = (1 << 10); /* 0x0400 */
112 break;
113 case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock
114 outreg = (1 << 10) | (1 << 6); /* 0x0440 */
115 break;
116 case OUTMODE_MPEG2_SERIAL: // STBs with serial input
117 outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0480 */
118 break;
119 case OUTMODE_DIVERSITY:
120 if (state->cfg.hostbus_diversity)
121 outreg = (1 << 10) | (4 << 6); /* 0x0500 */
122 else
123 outreg = (1 << 11);
124 break;
125 case OUTMODE_MPEG2_FIFO: // e.g. USB feeding
126 smo_mode |= (3 << 1);
127 fifo_threshold = 512;
128 outreg = (1 << 10) | (5 << 6);
129 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300130 case OUTMODE_ANALOG_ADC:
131 outreg = (1 << 10) | (3 << 6);
132 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300133 case OUTMODE_HIGH_Z: // disable
134 outreg = 0;
135 break;
136 default:
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300137 dprintk( "Unhandled output_mode passed to be set for demod %p",&state->demod);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300138 break;
139 }
140
141 if (state->cfg.output_mpeg2_in_188_bytes)
142 smo_mode |= (1 << 5) ;
143
144 ret |= dib7000p_write_word(state, 235, smo_mode);
145 ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */
146 ret |= dib7000p_write_word(state, 1286, outreg); /* P_Div_active */
147
148 return ret;
149}
150
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300151static int dib7000p_set_diversity_in(struct dvb_frontend *demod, int onoff)
152{
153 struct dib7000p_state *state = demod->demodulator_priv;
154
155 if (state->div_force_off) {
156 dprintk( "diversity combination deactivated - forced by COFDM parameters");
157 onoff = 0;
158 }
Patrick Boettcher01373a52007-07-30 12:49:04 -0300159 state->div_state = (u8)onoff;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300160
161 if (onoff) {
162 dib7000p_write_word(state, 204, 6);
163 dib7000p_write_word(state, 205, 16);
164 /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
165 dib7000p_write_word(state, 207, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
166 } else {
167 dib7000p_write_word(state, 204, 1);
168 dib7000p_write_word(state, 205, 0);
169 dib7000p_write_word(state, 207, 0);
170 }
171
172 return 0;
173}
174
Patrick Boettchera75763f2006-10-18 08:34:16 -0300175static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode)
176{
177 /* by default everything is powered off */
178 u16 reg_774 = 0xffff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899 = 0x0003,
179 reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff);
180
181 /* now, depending on the requested mode, we power on */
182 switch (mode) {
183 /* power up everything in the demod */
184 case DIB7000P_POWER_ALL:
185 reg_774 = 0x0000; reg_775 = 0x0000; reg_776 = 0x0; reg_899 = 0x0; reg_1280 &= 0x01ff;
186 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300187
188 case DIB7000P_POWER_ANALOG_ADC:
189 /* dem, cfg, iqc, sad, agc */
190 reg_774 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10) | (1 << 9));
191 /* nud */
192 reg_776 &= ~((1 << 0));
193 /* Dout */
194 reg_1280 &= ~((1 << 11));
195 /* fall through wanted to enable the interfaces */
196
Patrick Boettchera75763f2006-10-18 08:34:16 -0300197 /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */
198 case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */
199 reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10));
200 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300201
Patrick Boettchera75763f2006-10-18 08:34:16 -0300202/* TODO following stuff is just converted from the dib7000-driver - check when is used what */
203 }
204
205 dib7000p_write_word(state, 774, reg_774);
206 dib7000p_write_word(state, 775, reg_775);
207 dib7000p_write_word(state, 776, reg_776);
208 dib7000p_write_word(state, 899, reg_899);
209 dib7000p_write_word(state, 1280, reg_1280);
210
211 return 0;
212}
213
214static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no)
215{
216 u16 reg_908 = dib7000p_read_word(state, 908),
217 reg_909 = dib7000p_read_word(state, 909);
218
219 switch (no) {
220 case DIBX000_SLOW_ADC_ON:
221 reg_909 |= (1 << 1) | (1 << 0);
222 dib7000p_write_word(state, 909, reg_909);
223 reg_909 &= ~(1 << 1);
224 break;
225
226 case DIBX000_SLOW_ADC_OFF:
227 reg_909 |= (1 << 1) | (1 << 0);
228 break;
229
230 case DIBX000_ADC_ON:
231 reg_908 &= 0x0fff;
232 reg_909 &= 0x0003;
233 break;
234
235 case DIBX000_ADC_OFF: // leave the VBG voltage on
236 reg_908 |= (1 << 14) | (1 << 13) | (1 << 12);
237 reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
238 break;
239
240 case DIBX000_VBG_ENABLE:
241 reg_908 &= ~(1 << 15);
242 break;
243
244 case DIBX000_VBG_DISABLE:
245 reg_908 |= (1 << 15);
246 break;
247
248 default:
249 break;
250 }
251
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300252// dprintk( "908: %x, 909: %x\n", reg_908, reg_909);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300253
254 dib7000p_write_word(state, 908, reg_908);
255 dib7000p_write_word(state, 909, reg_909);
256}
257
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300258static int dib7000p_set_bandwidth(struct dib7000p_state *state, u32 bw)
Patrick Boettchera75763f2006-10-18 08:34:16 -0300259{
Patrick Boettchera75763f2006-10-18 08:34:16 -0300260 u32 timf;
261
262 // store the current bandwidth for later use
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300263 state->current_bandwidth = bw;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300264
265 if (state->timf == 0) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300266 dprintk( "using default timf");
Patrick Boettchera75763f2006-10-18 08:34:16 -0300267 timf = state->cfg.bw->timf;
268 } else {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300269 dprintk( "using updated timf");
Patrick Boettchera75763f2006-10-18 08:34:16 -0300270 timf = state->timf;
271 }
272
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300273 timf = timf * (bw / 50) / 160;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300274
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300275 dib7000p_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
276 dib7000p_write_word(state, 24, (u16) ((timf ) & 0xffff));
Patrick Boettchera75763f2006-10-18 08:34:16 -0300277
278 return 0;
279}
280
281static int dib7000p_sad_calib(struct dib7000p_state *state)
282{
283/* internal */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300284// dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth
Patrick Boettchera75763f2006-10-18 08:34:16 -0300285 dib7000p_write_word(state, 73, (0 << 1) | (0 << 0));
286 dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096
287
288 /* do the calibration */
289 dib7000p_write_word(state, 73, (1 << 0));
290 dib7000p_write_word(state, 73, (0 << 0));
291
292 msleep(1);
293
294 return 0;
295}
296
Patrick Boettcher01373a52007-07-30 12:49:04 -0300297int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
298{
299 struct dib7000p_state *state = demod->demodulator_priv;
300 if (value > 4095)
301 value = 4095;
302 state->wbd_ref = value;
303 return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
304}
305
306EXPORT_SYMBOL(dib7000p_set_wbd_ref);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300307static void dib7000p_reset_pll(struct dib7000p_state *state)
308{
309 struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300310 u16 clk_cfg0;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300311
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300312 /* force PLL bypass */
313 clk_cfg0 = (1 << 15) | ((bw->pll_ratio & 0x3f) << 9) |
314 (bw->modulo << 7) | (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) |
315 (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0);
316
317 dib7000p_write_word(state, 900, clk_cfg0);
318
319 /* P_pll_cfg */
Patrick Boettchera75763f2006-10-18 08:34:16 -0300320 dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300321 clk_cfg0 = (bw->pll_bypass << 15) | (clk_cfg0 & 0x7fff);
322 dib7000p_write_word(state, 900, clk_cfg0);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300323
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300324 dib7000p_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff));
325 dib7000p_write_word(state, 19, (u16) ( (bw->internal*1000 ) & 0xffff));
326 dib7000p_write_word(state, 21, (u16) ( (bw->ifreq >> 16) & 0xffff));
327 dib7000p_write_word(state, 22, (u16) ( (bw->ifreq ) & 0xffff));
Patrick Boettchera75763f2006-10-18 08:34:16 -0300328
329 dib7000p_write_word(state, 72, bw->sad_cfg);
330}
331
332static int dib7000p_reset_gpio(struct dib7000p_state *st)
333{
334 /* reset the GPIOs */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300335 dprintk( "gpio dir: %x: val: %x, pwm_pos: %x",st->gpio_dir, st->gpio_val,st->cfg.gpio_pwm_pos);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300336
337 dib7000p_write_word(st, 1029, st->gpio_dir);
338 dib7000p_write_word(st, 1030, st->gpio_val);
339
340 /* TODO 1031 is P_gpio_od */
341
342 dib7000p_write_word(st, 1032, st->cfg.gpio_pwm_pos);
343
344 dib7000p_write_word(st, 1037, st->cfg.pwm_freq_div);
345 return 0;
346}
347
Patrick Boettcher01373a52007-07-30 12:49:04 -0300348static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
349{
350 st->gpio_dir = dib7000p_read_word(st, 1029);
351 st->gpio_dir &= ~(1 << num); /* reset the direction bit */
352 st->gpio_dir |= (dir & 0x1) << num; /* set the new direction */
353 dib7000p_write_word(st, 1029, st->gpio_dir);
354
355 st->gpio_val = dib7000p_read_word(st, 1030);
356 st->gpio_val &= ~(1 << num); /* reset the direction bit */
357 st->gpio_val |= (val & 0x01) << num; /* set the new value */
358 dib7000p_write_word(st, 1030, st->gpio_val);
359
360 return 0;
361}
362
363int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
364{
365 struct dib7000p_state *state = demod->demodulator_priv;
366 return dib7000p_cfg_gpio(state, num, dir, val);
367}
368
369EXPORT_SYMBOL(dib7000p_set_gpio);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300370static u16 dib7000p_defaults[] =
371
372{
373 // auto search configuration
374 3, 2,
375 0x0004,
376 0x1000,
377 0x0814, /* Equal Lock */
378
379 12, 6,
380 0x001b,
381 0x7740,
382 0x005b,
383 0x8d80,
384 0x01c9,
385 0xc380,
386 0x0000,
387 0x0080,
388 0x0000,
389 0x0090,
390 0x0001,
391 0xd4c0,
392
393 1, 26,
394 0x6680, // P_timf_alpha=6, P_corm_alpha=6, P_corm_thres=128 default: 6,4,26
395
396 /* set ADC level to -16 */
397 11, 79,
398 (1 << 13) - 825 - 117,
399 (1 << 13) - 837 - 117,
400 (1 << 13) - 811 - 117,
401 (1 << 13) - 766 - 117,
402 (1 << 13) - 737 - 117,
403 (1 << 13) - 693 - 117,
404 (1 << 13) - 648 - 117,
405 (1 << 13) - 619 - 117,
406 (1 << 13) - 575 - 117,
407 (1 << 13) - 531 - 117,
408 (1 << 13) - 501 - 117,
409
410 1, 142,
411 0x0410, // P_palf_filter_on=1, P_palf_filter_freeze=0, P_palf_alpha_regul=16
412
413 /* disable power smoothing */
414 8, 145,
415 0,
416 0,
417 0,
418 0,
419 0,
420 0,
421 0,
422 0,
423
424 1, 154,
425 1 << 13, // P_fft_freq_dir=1, P_fft_nb_to_cut=0
426
427 1, 168,
428 0x0ccd, // P_pha3_thres, default 0x3000
429
430// 1, 169,
431// 0x0010, // P_cti_use_cpe=0, P_cti_use_prog=0, P_cti_win_len=16, default: 0x0010
432
433 1, 183,
434 0x200f, // P_cspu_regul=512, P_cspu_win_cut=15, default: 0x2005
435
436 5, 187,
437 0x023d, // P_adp_regul_cnt=573, default: 410
438 0x00a4, // P_adp_noise_cnt=
439 0x00a4, // P_adp_regul_ext
440 0x7ff0, // P_adp_noise_ext
441 0x3ccc, // P_adp_fil
442
443 1, 198,
444 0x800, // P_equal_thres_wgn
445
446 1, 222,
447 0x0010, // P_fec_ber_rs_len=2
448
449 1, 235,
450 0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
451
452 2, 901,
453 0x0006, // P_clk_cfg1
454 (3 << 10) | (1 << 6), // P_divclksel=3 P_divbitsel=1
455
456 1, 905,
457 0x2c8e, // Tuner IO bank: max drive (14mA) + divout pads max drive
458
459 0,
460};
461
Patrick Boettchera75763f2006-10-18 08:34:16 -0300462static int dib7000p_demod_reset(struct dib7000p_state *state)
463{
464 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
465
466 dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE);
467
468 /* restart all parts */
469 dib7000p_write_word(state, 770, 0xffff);
470 dib7000p_write_word(state, 771, 0xffff);
471 dib7000p_write_word(state, 772, 0x001f);
472 dib7000p_write_word(state, 898, 0x0003);
473 /* except i2c, sdio, gpio - control interfaces */
474 dib7000p_write_word(state, 1280, 0x01fc - ((1 << 7) | (1 << 6) | (1 << 5)) );
475
476 dib7000p_write_word(state, 770, 0);
477 dib7000p_write_word(state, 771, 0);
478 dib7000p_write_word(state, 772, 0);
479 dib7000p_write_word(state, 898, 0);
480 dib7000p_write_word(state, 1280, 0);
481
482 /* default */
483 dib7000p_reset_pll(state);
484
485 if (dib7000p_reset_gpio(state) != 0)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300486 dprintk( "GPIO reset was not successful.");
Patrick Boettchera75763f2006-10-18 08:34:16 -0300487
488 if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300489 dprintk( "OUTPUT_MODE could not be reset.");
Patrick Boettchera75763f2006-10-18 08:34:16 -0300490
491 /* unforce divstr regardless whether i2c enumeration was done or not */
492 dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1) );
493
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300494 dib7000p_set_bandwidth(state, 8000);
495
496 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
497 dib7000p_sad_calib(state);
498 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
499
500 // P_iqc_alpha_pha, P_iqc_alpha_amp_dcc_alpha, ...
501 if(state->cfg.tuner_is_baseband)
502 dib7000p_write_word(state, 36,0x0755);
503 else
504 dib7000p_write_word(state, 36,0x1f55);
505
506 dib7000p_write_tab(state, dib7000p_defaults);
507
Patrick Boettchera75763f2006-10-18 08:34:16 -0300508 dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
509
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300510
Patrick Boettchera75763f2006-10-18 08:34:16 -0300511 return 0;
512}
513
Patrick Boettchera75763f2006-10-18 08:34:16 -0300514static void dib7000p_pll_clk_cfg(struct dib7000p_state *state)
515{
516 u16 tmp = 0;
517 tmp = dib7000p_read_word(state, 903);
518 dib7000p_write_word(state, 903, (tmp | 0x1)); //pwr-up pll
519 tmp = dib7000p_read_word(state, 900);
520 dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6)); //use High freq clock
521}
522
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300523static void dib7000p_restart_agc(struct dib7000p_state *state)
Patrick Boettchera75763f2006-10-18 08:34:16 -0300524{
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300525 // P_restart_iqc & P_restart_agc
526 dib7000p_write_word(state, 770, (1 << 11) | (1 << 9));
527 dib7000p_write_word(state, 770, 0x0000);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300528}
529
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300530static int dib7000p_update_lna(struct dib7000p_state *state)
Patrick Boettchera75763f2006-10-18 08:34:16 -0300531{
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300532 u16 dyn_gain;
533
534 // when there is no LNA to program return immediatly
535 if (state->cfg.update_lna) {
Patrick Boettcher01373a52007-07-30 12:49:04 -0300536 // read dyn_gain here (because it is demod-dependent and not fe)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300537 dyn_gain = dib7000p_read_word(state, 394);
538 if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
539 dib7000p_restart_agc(state);
540 return 1;
541 }
542 }
543
544 return 0;
545}
546
547static int dib7000p_set_agc_config(struct dib7000p_state *state, u8 band)
548{
549 struct dibx000_agc_config *agc = NULL;
550 int i;
551 if (state->current_band == band && state->current_agc != NULL)
552 return 0;
553 state->current_band = band;
554
555 for (i = 0; i < state->cfg.agc_config_count; i++)
556 if (state->cfg.agc[i].band_caps & band) {
557 agc = &state->cfg.agc[i];
558 break;
559 }
560
561 if (agc == NULL) {
562 dprintk( "no valid AGC configuration found for band 0x%02x",band);
563 return -EINVAL;
564 }
565
566 state->current_agc = agc;
567
568 /* AGC */
569 dib7000p_write_word(state, 75 , agc->setup );
570 dib7000p_write_word(state, 76 , agc->inv_gain );
571 dib7000p_write_word(state, 77 , agc->time_stabiliz );
572 dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock);
573
574 // Demod AGC loop configuration
575 dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp);
576 dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp);
577
578 /* AGC continued */
579 dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d",
580 state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
581
582 if (state->wbd_ref != 0)
583 dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref);
584 else
585 dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref);
586
587 dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
588
589 dib7000p_write_word(state, 107, agc->agc1_max);
590 dib7000p_write_word(state, 108, agc->agc1_min);
591 dib7000p_write_word(state, 109, agc->agc2_max);
592 dib7000p_write_word(state, 110, agc->agc2_min);
593 dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
594 dib7000p_write_word(state, 112, agc->agc1_pt3);
595 dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
596 dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
597 dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
598 return 0;
599}
600
601static int dib7000p_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
602{
603 struct dib7000p_state *state = demod->demodulator_priv;
604 int ret = -1;
605 u8 *agc_state = &state->agc_state;
606 u8 agc_split;
607
608 switch (state->agc_state) {
609 case 0:
610 // set power-up level: interf+analog+AGC
611 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
612 dib7000p_set_adc_state(state, DIBX000_ADC_ON);
613 dib7000p_pll_clk_cfg(state);
614
615 if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0)
616 return -1;
617
618 ret = 7;
619 (*agc_state)++;
620 break;
621
622 case 1:
623 // AGC initialization
624 if (state->cfg.agc_control)
625 state->cfg.agc_control(&state->demod, 1);
626
627 dib7000p_write_word(state, 78, 32768);
628 if (!state->current_agc->perform_agc_softsplit) {
629 /* we are using the wbd - so slow AGC startup */
630 /* force 0 split on WBD and restart AGC */
631 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | (1 << 8));
632 (*agc_state)++;
633 ret = 5;
634 } else {
635 /* default AGC startup */
636 (*agc_state) = 4;
637 /* wait AGC rough lock time */
638 ret = 7;
639 }
640
641 dib7000p_restart_agc(state);
642 break;
643
644 case 2: /* fast split search path after 5sec */
645 dib7000p_write_word(state, 75, state->current_agc->setup | (1 << 4)); /* freeze AGC loop */
646 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (2 << 9) | (0 << 8)); /* fast split search 0.25kHz */
647 (*agc_state)++;
648 ret = 14;
649 break;
650
651 case 3: /* split search ended */
Patrick Boettcher01373a52007-07-30 12:49:04 -0300652 agc_split = (u8)dib7000p_read_word(state, 396); /* store the split value for the next time */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300653 dib7000p_write_word(state, 78, dib7000p_read_word(state, 394)); /* set AGC gain start value */
654
655 dib7000p_write_word(state, 75, state->current_agc->setup); /* std AGC loop */
656 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
657
658 dib7000p_restart_agc(state);
659
660 dprintk( "SPLIT %p: %hd", demod, agc_split);
661
662 (*agc_state)++;
663 ret = 5;
664 break;
665
666 case 4: /* LNA startup */
667 // wait AGC accurate lock time
668 ret = 7;
669
670 if (dib7000p_update_lna(state))
671 // wait only AGC rough lock time
672 ret = 5;
673 else // nothing was done, go to the next state
674 (*agc_state)++;
675 break;
676
677 case 5:
678 if (state->cfg.agc_control)
679 state->cfg.agc_control(&state->demod, 0);
680 (*agc_state)++;
681 break;
682 default:
683 break;
684 }
685 return ret;
686}
687
688static void dib7000p_update_timf(struct dib7000p_state *state)
689{
690 u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428);
691 state->timf = timf * 160 / (state->current_bandwidth / 50);
692 dib7000p_write_word(state, 23, (u16) (timf >> 16));
693 dib7000p_write_word(state, 24, (u16) (timf & 0xffff));
694 dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->cfg.bw->timf);
695
696}
697
698static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_frontend_parameters *ch, u8 seq)
699{
700 u16 value, est[4];
701
702 dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
Patrick Boettchera75763f2006-10-18 08:34:16 -0300703
704 /* nfft, guard, qam, alpha */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300705 value = 0;
706 switch (ch->u.ofdm.transmission_mode) {
707 case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
708 case /* 4K MODE */ 255: value |= (2 << 7); break;
709 default:
710 case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
711 }
712 switch (ch->u.ofdm.guard_interval) {
713 case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
714 case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
715 case GUARD_INTERVAL_1_4: value |= (3 << 5); break;
716 default:
717 case GUARD_INTERVAL_1_8: value |= (2 << 5); break;
718 }
719 switch (ch->u.ofdm.constellation) {
720 case QPSK: value |= (0 << 3); break;
721 case QAM_16: value |= (1 << 3); break;
722 default:
723 case QAM_64: value |= (2 << 3); break;
724 }
725 switch (HIERARCHY_1) {
726 case HIERARCHY_2: value |= 2; break;
727 case HIERARCHY_4: value |= 4; break;
728 default:
729 case HIERARCHY_1: value |= 1; break;
730 }
731 dib7000p_write_word(state, 0, value);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300732 dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */
733
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300734 /* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
735 value = 0;
736 if (1 != 0)
737 value |= (1 << 6);
738 if (ch->u.ofdm.hierarchy_information == 1)
739 value |= (1 << 4);
740 if (1 == 1)
741 value |= 1;
742 switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
743 case FEC_2_3: value |= (2 << 1); break;
744 case FEC_3_4: value |= (3 << 1); break;
745 case FEC_5_6: value |= (5 << 1); break;
746 case FEC_7_8: value |= (7 << 1); break;
747 default:
748 case FEC_1_2: value |= (1 << 1); break;
749 }
750 dib7000p_write_word(state, 208, value);
751
752 /* offset loop parameters */
753 dib7000p_write_word(state, 26, 0x6680); // timf(6xxx)
754 dib7000p_write_word(state, 29, 0x1273); // isi inh1273 on1073
755 dib7000p_write_word(state, 32, 0x0003); // pha_off_max(xxx3)
756 dib7000p_write_word(state, 33, 0x0005); // sfreq(xxx5)
Patrick Boettchera75763f2006-10-18 08:34:16 -0300757
758 /* P_dvsy_sync_wait */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300759 switch (ch->u.ofdm.transmission_mode) {
760 case TRANSMISSION_MODE_8K: value = 256; break;
761 case /* 4K MODE */ 255: value = 128; break;
762 case TRANSMISSION_MODE_2K:
763 default: value = 64; break;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300764 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300765 switch (ch->u.ofdm.guard_interval) {
766 case GUARD_INTERVAL_1_16: value *= 2; break;
767 case GUARD_INTERVAL_1_8: value *= 4; break;
768 case GUARD_INTERVAL_1_4: value *= 8; break;
769 default:
770 case GUARD_INTERVAL_1_32: value *= 1; break;
771 }
772 state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO
Patrick Boettchera75763f2006-10-18 08:34:16 -0300773
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300774 /* deactive the possibility of diversity reception if extended interleaver */
775 state->div_force_off = !1 && ch->u.ofdm.transmission_mode != TRANSMISSION_MODE_8K;
776 dib7000p_set_diversity_in(&state->demod, state->div_state);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300777
778 /* channel estimation fine configuration */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300779 switch (ch->u.ofdm.constellation) {
780 case QAM_64:
Patrick Boettchera75763f2006-10-18 08:34:16 -0300781 est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
782 est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
783 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
784 est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */
785 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300786 case QAM_16:
Patrick Boettchera75763f2006-10-18 08:34:16 -0300787 est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */
788 est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */
789 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
790 est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */
791 break;
792 default:
793 est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */
794 est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */
795 est[2] = 0x0333; /* P_adp_regul_ext 0.1 */
796 est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */
797 break;
798 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300799 for (value = 0; value < 4; value++)
800 dib7000p_write_word(state, 187 + value, est[value]);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300801}
802
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300803static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
Patrick Boettchera75763f2006-10-18 08:34:16 -0300804{
805 struct dib7000p_state *state = demod->demodulator_priv;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300806 struct dvb_frontend_parameters schan;
807 u32 value, factor;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300808
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300809 schan = *ch;
810 schan.u.ofdm.constellation = QAM_64;
811 schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
812 schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
813 schan.u.ofdm.code_rate_HP = FEC_2_3;
814 schan.u.ofdm.code_rate_LP = FEC_3_4;
815 schan.u.ofdm.hierarchy_information = 0;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300816
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300817 dib7000p_set_channel(state, &schan, 7);
818
819 factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth);
820 if (factor >= 5000)
821 factor = 1;
822 else
823 factor = 6;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300824
825 // always use the setting for 8MHz here lock_time for 7,6 MHz are longer
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300826 value = 30 * state->cfg.bw->internal * factor;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300827 dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time
828 dib7000p_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300829 value = 100 * state->cfg.bw->internal * factor;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300830 dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time
831 dib7000p_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300832 value = 500 * state->cfg.bw->internal * factor;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300833 dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
834 dib7000p_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time
835
836 value = dib7000p_read_word(state, 0);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300837 dib7000p_write_word(state, 0, (u16) ((1 << 9) | value));
Patrick Boettchera75763f2006-10-18 08:34:16 -0300838 dib7000p_read_word(state, 1284);
839 dib7000p_write_word(state, 0, (u16) value);
840
841 return 0;
842}
843
844static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod)
845{
846 struct dib7000p_state *state = demod->demodulator_priv;
847 u16 irq_pending = dib7000p_read_word(state, 1284);
848
849 if (irq_pending & 0x1) // failed
850 return 1;
851
852 if (irq_pending & 0x2) // succeeded
853 return 2;
854
855 return 0; // still pending
856}
857
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300858static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 bw)
859{
860 static s16 notch[]={16143, 14402, 12238, 9713, 6902, 3888, 759, -2392};
861 static u8 sine [] ={0, 2, 3, 5, 6, 8, 9, 11, 13, 14, 16, 17, 19, 20, 22,
862 24, 25, 27, 28, 30, 31, 33, 34, 36, 38, 39, 41, 42, 44, 45, 47, 48, 50, 51,
863 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80,
864 82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, 104, 105,
865 107, 108, 109, 111, 112, 114, 115, 117, 118, 119, 121, 122, 123, 125, 126,
866 128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 144, 145, 146,
867 147, 149, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 162, 164, 165,
868 166, 167, 168, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182,
869 183, 184, 185, 186, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
870 199, 200, 201, 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 212,
871 213, 214, 215, 215, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 224,
872 225, 226, 227, 227, 228, 229, 229, 230, 231, 231, 232, 233, 233, 234, 235,
873 235, 236, 237, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 243,
874 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 248, 249, 249, 249,
875 250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 254,
876 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
877 255, 255, 255, 255, 255, 255};
878
879 u32 xtal = state->cfg.bw->xtal_hz / 1000;
880 int f_rel = ( (rf_khz + xtal/2) / xtal) * xtal - rf_khz;
881 int k;
882 int coef_re[8],coef_im[8];
883 int bw_khz = bw;
884 u32 pha;
885
886 dprintk( "relative position of the Spur: %dk (RF: %dk, XTAL: %dk)", f_rel, rf_khz, xtal);
887
888
889 if (f_rel < -bw_khz/2 || f_rel > bw_khz/2)
890 return;
891
892 bw_khz /= 100;
893
894 dib7000p_write_word(state, 142 ,0x0610);
895
896 for (k = 0; k < 8; k++) {
897 pha = ((f_rel * (k+1) * 112 * 80/bw_khz) /1000) & 0x3ff;
898
899 if (pha==0) {
900 coef_re[k] = 256;
901 coef_im[k] = 0;
902 } else if(pha < 256) {
903 coef_re[k] = sine[256-(pha&0xff)];
904 coef_im[k] = sine[pha&0xff];
905 } else if (pha == 256) {
906 coef_re[k] = 0;
907 coef_im[k] = 256;
908 } else if (pha < 512) {
909 coef_re[k] = -sine[pha&0xff];
910 coef_im[k] = sine[256 - (pha&0xff)];
911 } else if (pha == 512) {
912 coef_re[k] = -256;
913 coef_im[k] = 0;
914 } else if (pha < 768) {
915 coef_re[k] = -sine[256-(pha&0xff)];
916 coef_im[k] = -sine[pha&0xff];
917 } else if (pha == 768) {
918 coef_re[k] = 0;
919 coef_im[k] = -256;
920 } else {
921 coef_re[k] = sine[pha&0xff];
922 coef_im[k] = -sine[256 - (pha&0xff)];
923 }
924
925 coef_re[k] *= notch[k];
926 coef_re[k] += (1<<14);
927 if (coef_re[k] >= (1<<24))
928 coef_re[k] = (1<<24) - 1;
929 coef_re[k] /= (1<<15);
930
931 coef_im[k] *= notch[k];
932 coef_im[k] += (1<<14);
933 if (coef_im[k] >= (1<<24))
934 coef_im[k] = (1<<24)-1;
935 coef_im[k] /= (1<<15);
936
937 dprintk( "PALF COEF: %d re: %d im: %d", k, coef_re[k], coef_im[k]);
938
939 dib7000p_write_word(state, 143, (0 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
940 dib7000p_write_word(state, 144, coef_im[k] & 0x3ff);
941 dib7000p_write_word(state, 143, (1 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
942 }
943 dib7000p_write_word(state,143 ,0);
944}
945
946static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
Patrick Boettchera75763f2006-10-18 08:34:16 -0300947{
948 struct dib7000p_state *state = demod->demodulator_priv;
949 u16 tmp = 0;
950
951 if (ch != NULL)
952 dib7000p_set_channel(state, ch, 0);
953 else
954 return -EINVAL;
955
956 // restart demod
957 dib7000p_write_word(state, 770, 0x4000);
958 dib7000p_write_word(state, 770, 0x0000);
959 msleep(45);
960
961 /* 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 */
962 dib7000p_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3));
963
964 // never achieved a lock with that bandwidth so far - wait for osc-freq to update
965 if (state->timf == 0)
966 msleep(200);
967
968 /* offset loop parameters */
969
970 /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
971 tmp = (6 << 8) | 0x80;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300972 switch (ch->u.ofdm.transmission_mode) {
973 case TRANSMISSION_MODE_2K: tmp |= (7 << 12); break;
974 case /* 4K MODE */ 255: tmp |= (8 << 12); break;
975 default:
976 case TRANSMISSION_MODE_8K: tmp |= (9 << 12); break;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300977 }
978 dib7000p_write_word(state, 26, tmp); /* timf_a(6xxx) */
979
980 /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
981 tmp = (0 << 4);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300982 switch (ch->u.ofdm.transmission_mode) {
983 case TRANSMISSION_MODE_2K: tmp |= 0x6; break;
984 case /* 4K MODE */ 255: tmp |= 0x7; break;
985 default:
986 case TRANSMISSION_MODE_8K: tmp |= 0x8; break;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300987 }
988 dib7000p_write_word(state, 32, tmp);
989
990 /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
991 tmp = (0 << 4);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300992 switch (ch->u.ofdm.transmission_mode) {
993 case TRANSMISSION_MODE_2K: tmp |= 0x6; break;
994 case /* 4K MODE */ 255: tmp |= 0x7; break;
995 default:
996 case TRANSMISSION_MODE_8K: tmp |= 0x8; break;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300997 }
998 dib7000p_write_word(state, 33, tmp);
999
1000 tmp = dib7000p_read_word(state,509);
1001 if (!((tmp >> 6) & 0x1)) {
1002 /* restart the fec */
1003 tmp = dib7000p_read_word(state,771);
1004 dib7000p_write_word(state, 771, tmp | (1 << 1));
1005 dib7000p_write_word(state, 771, tmp);
1006 msleep(10);
1007 tmp = dib7000p_read_word(state,509);
1008 }
1009
1010 // we achieved a lock - it's time to update the osc freq
1011 if ((tmp >> 6) & 0x1)
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001012 dib7000p_update_timf(state);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001013
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001014 if (state->cfg.spur_protect)
1015 dib7000p_spur_protect(state, ch->frequency/1000, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
1016
1017 dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
Patrick Boettchera75763f2006-10-18 08:34:16 -03001018 return 0;
1019}
1020
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001021static int dib7000p_wakeup(struct dvb_frontend *demod)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001022{
Patrick Boettchera75763f2006-10-18 08:34:16 -03001023 struct dib7000p_state *state = demod->demodulator_priv;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001024 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
1025 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001026 return 0;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001027}
1028
1029static int dib7000p_sleep(struct dvb_frontend *demod)
1030{
1031 struct dib7000p_state *state = demod->demodulator_priv;
1032 return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
1033}
1034
1035static int dib7000p_identify(struct dib7000p_state *st)
1036{
1037 u16 value;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001038 dprintk( "checking demod on I2C address: %d (%x)",
Patrick Boettchera75763f2006-10-18 08:34:16 -03001039 st->i2c_addr, st->i2c_addr);
1040
1041 if ((value = dib7000p_read_word(st, 768)) != 0x01b3) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001042 dprintk( "wrong Vendor ID (read=0x%x)",value);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001043 return -EREMOTEIO;
1044 }
1045
1046 if ((value = dib7000p_read_word(st, 769)) != 0x4000) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001047 dprintk( "wrong Device ID (%x)",value);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001048 return -EREMOTEIO;
1049 }
1050
1051 return 0;
1052}
1053
1054
1055static int dib7000p_get_frontend(struct dvb_frontend* fe,
1056 struct dvb_frontend_parameters *fep)
1057{
1058 struct dib7000p_state *state = fe->demodulator_priv;
1059 u16 tps = dib7000p_read_word(state,463);
1060
1061 fep->inversion = INVERSION_AUTO;
1062
1063 fep->u.ofdm.bandwidth = state->current_bandwidth;
1064
1065 switch ((tps >> 8) & 0x3) {
1066 case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
1067 case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
1068 /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
1069 }
1070
1071 switch (tps & 0x3) {
1072 case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
1073 case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
1074 case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
1075 case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
1076 }
1077
1078 switch ((tps >> 14) & 0x3) {
1079 case 0: fep->u.ofdm.constellation = QPSK; break;
1080 case 1: fep->u.ofdm.constellation = QAM_16; break;
1081 case 2:
1082 default: fep->u.ofdm.constellation = QAM_64; break;
1083 }
1084
1085 /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
1086 /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
1087
1088 fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
1089 switch ((tps >> 5) & 0x7) {
1090 case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
1091 case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
1092 case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
1093 case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
1094 case 7:
1095 default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
1096
1097 }
1098
1099 switch ((tps >> 2) & 0x7) {
1100 case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
1101 case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
1102 case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
1103 case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
1104 case 7:
1105 default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
1106 }
1107
1108 /* native interleaver: (dib7000p_read_word(state, 464) >> 5) & 0x1 */
1109
1110 return 0;
1111}
1112
1113static int dib7000p_set_frontend(struct dvb_frontend* fe,
1114 struct dvb_frontend_parameters *fep)
1115{
1116 struct dib7000p_state *state = fe->demodulator_priv;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001117 int time;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001118
1119 state->current_bandwidth = fep->u.ofdm.bandwidth;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001120 dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
Patrick Boettchera75763f2006-10-18 08:34:16 -03001121
1122 if (fe->ops.tuner_ops.set_params)
1123 fe->ops.tuner_ops.set_params(fe, fep);
1124
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001125 /* start up the AGC */
1126 state->agc_state = 0;
1127 do {
1128 time = dib7000p_agc_startup(fe, fep);
1129 if (time != -1)
1130 msleep(time);
1131 } while (time != -1);
1132
Patrick Boettchera75763f2006-10-18 08:34:16 -03001133 if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
1134 fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
1135 fep->u.ofdm.constellation == QAM_AUTO ||
1136 fep->u.ofdm.code_rate_HP == FEC_AUTO) {
1137 int i = 800, found;
1138
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001139 dib7000p_autosearch_start(fe, fep);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001140 do {
1141 msleep(1);
1142 found = dib7000p_autosearch_is_irq(fe);
1143 } while (found == 0 && i--);
1144
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001145 dprintk("autosearch returns: %d",found);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001146 if (found == 0 || found == 1)
1147 return 0; // no channel found
1148
1149 dib7000p_get_frontend(fe, fep);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001150 }
1151
1152 /* make this a config parameter */
1153 dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO);
1154
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001155 return dib7000p_tune(fe, fep);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001156}
1157
1158static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat)
1159{
1160 struct dib7000p_state *state = fe->demodulator_priv;
1161 u16 lock = dib7000p_read_word(state, 509);
1162
1163 *stat = 0;
1164
1165 if (lock & 0x8000)
1166 *stat |= FE_HAS_SIGNAL;
1167 if (lock & 0x3000)
1168 *stat |= FE_HAS_CARRIER;
1169 if (lock & 0x0100)
1170 *stat |= FE_HAS_VITERBI;
1171 if (lock & 0x0010)
1172 *stat |= FE_HAS_SYNC;
1173 if (lock & 0x0008)
1174 *stat |= FE_HAS_LOCK;
1175
1176 return 0;
1177}
1178
1179static int dib7000p_read_ber(struct dvb_frontend *fe, u32 *ber)
1180{
1181 struct dib7000p_state *state = fe->demodulator_priv;
1182 *ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501);
1183 return 0;
1184}
1185
1186static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
1187{
1188 struct dib7000p_state *state = fe->demodulator_priv;
1189 *unc = dib7000p_read_word(state, 506);
1190 return 0;
1191}
1192
1193static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
1194{
1195 struct dib7000p_state *state = fe->demodulator_priv;
1196 u16 val = dib7000p_read_word(state, 394);
1197 *strength = 65535 - val;
1198 return 0;
1199}
1200
1201static int dib7000p_read_snr(struct dvb_frontend* fe, u16 *snr)
1202{
1203 *snr = 0x0000;
1204 return 0;
1205}
1206
1207static int dib7000p_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
1208{
1209 tune->min_delay_ms = 1000;
1210 return 0;
1211}
1212
1213static void dib7000p_release(struct dvb_frontend *demod)
1214{
1215 struct dib7000p_state *st = demod->demodulator_priv;
1216 dibx000_exit_i2c_master(&st->i2c_master);
1217 kfree(st);
1218}
1219
1220int dib7000pc_detection(struct i2c_adapter *i2c_adap)
1221{
1222 u8 tx[2], rx[2];
1223 struct i2c_msg msg[2] = {
1224 { .addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2 },
1225 { .addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2 },
1226 };
1227
1228 tx[0] = 0x03;
1229 tx[1] = 0x00;
1230
1231 if (i2c_transfer(i2c_adap, msg, 2) == 2)
1232 if (rx[0] == 0x01 && rx[1] == 0xb3) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001233 dprintk("-D- DiB7000PC detected");
Patrick Boettchera75763f2006-10-18 08:34:16 -03001234 return 1;
1235 }
1236
1237 msg[0].addr = msg[1].addr = 0x40;
1238
1239 if (i2c_transfer(i2c_adap, msg, 2) == 2)
1240 if (rx[0] == 0x01 && rx[1] == 0xb3) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001241 dprintk("-D- DiB7000PC detected");
Patrick Boettchera75763f2006-10-18 08:34:16 -03001242 return 1;
1243 }
1244
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001245 dprintk("-D- DiB7000PC not detected");
Patrick Boettchera75763f2006-10-18 08:34:16 -03001246 return 0;
1247}
1248EXPORT_SYMBOL(dib7000pc_detection);
1249
1250struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
1251{
1252 struct dib7000p_state *st = demod->demodulator_priv;
1253 return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
1254}
1255EXPORT_SYMBOL(dib7000p_get_i2c_master);
1256
1257int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
1258{
1259 struct dib7000p_state st = { .i2c_adap = i2c };
1260 int k = 0;
1261 u8 new_addr = 0;
1262
1263 for (k = no_of_demods-1; k >= 0; k--) {
1264 st.cfg = cfg[k];
1265
1266 /* designated i2c address */
1267 new_addr = (0x40 + k) << 1;
1268 st.i2c_addr = new_addr;
1269 if (dib7000p_identify(&st) != 0) {
1270 st.i2c_addr = default_addr;
1271 if (dib7000p_identify(&st) != 0) {
1272 dprintk("DiB7000P #%d: not identified\n", k);
1273 return -EIO;
1274 }
1275 }
1276
1277 /* start diversity to pull_down div_str - just for i2c-enumeration */
1278 dib7000p_set_output_mode(&st, OUTMODE_DIVERSITY);
1279
1280 /* set new i2c address and force divstart */
1281 dib7000p_write_word(&st, 1285, (new_addr << 2) | 0x2);
1282
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001283 dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001284 }
1285
1286 for (k = 0; k < no_of_demods; k++) {
1287 st.cfg = cfg[k];
1288 st.i2c_addr = (0x40 + k) << 1;
1289
1290 // unforce divstr
1291 dib7000p_write_word(&st, 1285, st.i2c_addr << 2);
1292
1293 /* deactivate div - it was just for i2c-enumeration */
1294 dib7000p_set_output_mode(&st, OUTMODE_HIGH_Z);
1295 }
1296
1297 return 0;
1298}
1299EXPORT_SYMBOL(dib7000p_i2c_enumeration);
1300
1301static struct dvb_frontend_ops dib7000p_ops;
1302struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
1303{
1304 struct dvb_frontend *demod;
1305 struct dib7000p_state *st;
1306 st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
1307 if (st == NULL)
1308 return NULL;
1309
1310 memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config));
1311 st->i2c_adap = i2c_adap;
1312 st->i2c_addr = i2c_addr;
1313 st->gpio_val = cfg->gpio_val;
1314 st->gpio_dir = cfg->gpio_dir;
1315
1316 demod = &st->demod;
1317 demod->demodulator_priv = st;
1318 memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
1319
1320 if (dib7000p_identify(st) != 0)
1321 goto error;
1322
1323 dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
1324
1325 dib7000p_demod_reset(st);
1326
1327 return demod;
1328
1329error:
1330 kfree(st);
1331 return NULL;
1332}
1333EXPORT_SYMBOL(dib7000p_attach);
1334
1335static struct dvb_frontend_ops dib7000p_ops = {
1336 .info = {
1337 .name = "DiBcom 7000PC",
1338 .type = FE_OFDM,
1339 .frequency_min = 44250000,
1340 .frequency_max = 867250000,
1341 .frequency_stepsize = 62500,
1342 .caps = FE_CAN_INVERSION_AUTO |
1343 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1344 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1345 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
1346 FE_CAN_TRANSMISSION_MODE_AUTO |
1347 FE_CAN_GUARD_INTERVAL_AUTO |
1348 FE_CAN_RECOVER |
1349 FE_CAN_HIERARCHY_AUTO,
1350 },
1351
1352 .release = dib7000p_release,
1353
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001354 .init = dib7000p_wakeup,
Patrick Boettchera75763f2006-10-18 08:34:16 -03001355 .sleep = dib7000p_sleep,
1356
1357 .set_frontend = dib7000p_set_frontend,
1358 .get_tune_settings = dib7000p_fe_get_tune_settings,
1359 .get_frontend = dib7000p_get_frontend,
1360
1361 .read_status = dib7000p_read_status,
1362 .read_ber = dib7000p_read_ber,
1363 .read_signal_strength = dib7000p_read_signal_strength,
1364 .read_snr = dib7000p_read_snr,
1365 .read_ucblocks = dib7000p_read_unc_blocks,
1366};
1367
1368MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
1369MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator");
1370MODULE_LICENSE("GPL");