blob: 608156a691de98dacf2f9f99beedee0ea6d90164 [file] [log] [blame]
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001/*
2 * Linux-DVB Driver for DiBcom's DiB7000M and
3 * first generation DiB7000P-demodulator-family.
4 *
Patrick Boettcherb6884a12007-07-27 10:08:51 -03005 * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02006 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, version 2.
10 */
11#include <linux/kernel.h>
12#include <linux/i2c.h>
13
14#include "dvb_frontend.h"
15
16#include "dib7000m.h"
17
18static int debug;
19module_param(debug, int, 0644);
20MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
21
Patrick Boettcherb6884a12007-07-27 10:08:51 -030022#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M: "); printk(args); printk("\n"); } } while (0)
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020023
24struct dib7000m_state {
25 struct dvb_frontend demod;
26 struct dib7000m_config cfg;
27
28 u8 i2c_addr;
29 struct i2c_adapter *i2c_adap;
30
31 struct dibx000_i2c_master i2c_master;
32
33/* offset is 1 in case of the 7000MC */
34 u8 reg_offs;
35
36 u16 wbd_ref;
37
38 u8 current_band;
39 fe_bandwidth_t current_bandwidth;
40 struct dibx000_agc_config *current_agc;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -030041 u32 timf;
Patrick Boettcherb6884a12007-07-27 10:08:51 -030042 u32 timf_default;
43 u32 internal_clk;
44
45 uint8_t div_force_off : 1;
46 uint8_t div_state : 1;
47 uint16_t div_sync_wait;
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020048
49 u16 revision;
Patrick Boettcherb6884a12007-07-27 10:08:51 -030050
51 u8 agc_state;
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020052};
53
Patrick Boettcher69ea31e2006-10-17 18:28:14 -030054enum dib7000m_power_mode {
55 DIB7000M_POWER_ALL = 0,
56
57 DIB7000M_POWER_NO,
58 DIB7000M_POWER_INTERF_ANALOG_AGC,
59 DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD,
60 DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD,
61 DIB7000M_POWER_INTERFACE_ONLY,
62};
63
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020064static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
65{
66 u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
67 u8 rb[2];
68 struct i2c_msg msg[2] = {
69 { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 },
70 { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
71 };
72
73 if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
Patrick Boettcherb6884a12007-07-27 10:08:51 -030074 dprintk("i2c read error on %d",reg);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020075
76 return (rb[0] << 8) | rb[1];
77}
78
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020079static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
80{
81 u8 b[4] = {
82 (reg >> 8) & 0xff, reg & 0xff,
83 (val >> 8) & 0xff, val & 0xff,
84 };
85 struct i2c_msg msg = {
86 .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
87 };
88 return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
89}
Patrick Boettcherb6884a12007-07-27 10:08:51 -030090static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
91{
92 u16 l = 0, r, *n;
93 n = buf;
94 l = *n++;
95 while (l) {
96 r = *n++;
97
98 if (state->reg_offs && (r >= 112 && r <= 331)) // compensate for 7000MC
99 r++;
100
101 do {
102 dib7000m_write_word(state, r, *n++);
103 r++;
104 } while (--l);
105 l = *n++;
106 }
107}
108
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300109static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode)
110{
111 int ret = 0;
112 u16 outreg, fifo_threshold, smo_mode,
113 sram = 0x0005; /* by default SRAM output is disabled */
114
115 outreg = 0;
116 fifo_threshold = 1792;
117 smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1);
118
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300119 dprintk( "setting output mode for demod %p to %d", &state->demod, mode);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300120
121 switch (mode) {
122 case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock
123 outreg = (1 << 10); /* 0x0400 */
124 break;
125 case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock
126 outreg = (1 << 10) | (1 << 6); /* 0x0440 */
127 break;
128 case OUTMODE_MPEG2_SERIAL: // STBs with serial input
129 outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */
130 break;
131 case OUTMODE_DIVERSITY:
132 if (state->cfg.hostbus_diversity)
133 outreg = (1 << 10) | (4 << 6); /* 0x0500 */
134 else
135 sram |= 0x0c00;
136 break;
137 case OUTMODE_MPEG2_FIFO: // e.g. USB feeding
138 smo_mode |= (3 << 1);
139 fifo_threshold = 512;
140 outreg = (1 << 10) | (5 << 6);
141 break;
142 case OUTMODE_HIGH_Z: // disable
143 outreg = 0;
144 break;
145 default:
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300146 dprintk( "Unhandled output_mode passed to be set for demod %p",&state->demod);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300147 break;
148 }
149
150 if (state->cfg.output_mpeg2_in_188_bytes)
151 smo_mode |= (1 << 5) ;
152
153 ret |= dib7000m_write_word(state, 294 + state->reg_offs, smo_mode);
154 ret |= dib7000m_write_word(state, 295 + state->reg_offs, fifo_threshold); /* synchronous fread */
155 ret |= dib7000m_write_word(state, 1795, outreg);
156 ret |= dib7000m_write_word(state, 1805, sram);
157
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300158 if (state->revision == 0x4003) {
159 u16 clk_cfg1 = dib7000m_read_word(state, 909) & 0xfffd;
160 if (mode == OUTMODE_DIVERSITY)
161 clk_cfg1 |= (1 << 1); // P_O_CLK_en
162 dib7000m_write_word(state, 909, clk_cfg1);
163 }
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300164 return ret;
165}
166
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300167static void dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300168{
169 /* by default everything is going to be powered off */
170 u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906 = 0x3fff;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300171 u8 offset = 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300172
173 /* now, depending on the requested mode, we power on */
174 switch (mode) {
175 /* power up everything in the demod */
176 case DIB7000M_POWER_ALL:
177 reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000;
178 break;
179
180 /* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */
181 case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */
182 reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2));
183 break;
184
185 case DIB7000M_POWER_INTERF_ANALOG_AGC:
186 reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10));
187 reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2));
188 reg_906 &= ~((1 << 0));
189 break;
190
191 case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD:
192 reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000;
193 break;
194
195 case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD:
196 reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000;
197 break;
198 case DIB7000M_POWER_NO:
199 break;
200 }
201
202 /* always power down unused parts */
203 if (!state->cfg.mobile_mode)
204 reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1);
205
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300206 /* P_sdio_select_clk = 0 on MC and after*/
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300207 if (state->revision != 0x4000)
208 reg_906 <<= 1;
209
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300210 if (state->revision == 0x4003)
211 offset = 1;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300212
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300213 dib7000m_write_word(state, 903 + offset, reg_903);
214 dib7000m_write_word(state, 904 + offset, reg_904);
215 dib7000m_write_word(state, 905 + offset, reg_905);
216 dib7000m_write_word(state, 906 + offset, reg_906);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300217}
218
219static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no)
220{
221 int ret = 0;
222 u16 reg_913 = dib7000m_read_word(state, 913),
223 reg_914 = dib7000m_read_word(state, 914);
224
225 switch (no) {
226 case DIBX000_SLOW_ADC_ON:
227 reg_914 |= (1 << 1) | (1 << 0);
228 ret |= dib7000m_write_word(state, 914, reg_914);
229 reg_914 &= ~(1 << 1);
230 break;
231
232 case DIBX000_SLOW_ADC_OFF:
233 reg_914 |= (1 << 1) | (1 << 0);
234 break;
235
236 case DIBX000_ADC_ON:
237 if (state->revision == 0x4000) { // workaround for PA/MA
238 // power-up ADC
239 dib7000m_write_word(state, 913, 0);
240 dib7000m_write_word(state, 914, reg_914 & 0x3);
241 // power-down bandgag
242 dib7000m_write_word(state, 913, (1 << 15));
243 dib7000m_write_word(state, 914, reg_914 & 0x3);
244 }
245
246 reg_913 &= 0x0fff;
247 reg_914 &= 0x0003;
248 break;
249
250 case DIBX000_ADC_OFF: // leave the VBG voltage on
251 reg_913 |= (1 << 14) | (1 << 13) | (1 << 12);
252 reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
253 break;
254
255 case DIBX000_VBG_ENABLE:
256 reg_913 &= ~(1 << 15);
257 break;
258
259 case DIBX000_VBG_DISABLE:
260 reg_913 |= (1 << 15);
261 break;
262
263 default:
264 break;
265 }
266
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300267// dprintk( "913: %x, 914: %x", reg_913, reg_914);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300268 ret |= dib7000m_write_word(state, 913, reg_913);
269 ret |= dib7000m_write_word(state, 914, reg_914);
270
271 return ret;
272}
273
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300274static int dib7000m_set_bandwidth(struct dib7000m_state *state, u32 bw)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300275{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300276 u32 timf;
277
278 // store the current bandwidth for later use
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300279 state->current_bandwidth = bw;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300280
281 if (state->timf == 0) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300282 dprintk( "using default timf");
283 timf = state->timf_default;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300284 } else {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300285 dprintk( "using updated timf");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300286 timf = state->timf;
287 }
288
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300289 timf = timf * (bw / 50) / 160;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300290
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300291 dib7000m_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
292 dib7000m_write_word(state, 24, (u16) ((timf ) & 0xffff));
293
294 return 0;
295}
296
297static int dib7000m_set_diversity_in(struct dvb_frontend *demod, int onoff)
298{
299 struct dib7000m_state *state = demod->demodulator_priv;
300
301 if (state->div_force_off) {
302 dprintk( "diversity combination deactivated - forced by COFDM parameters");
303 onoff = 0;
304 }
305 state->div_state = (uint8_t)onoff;
306
307 if (onoff) {
308 dib7000m_write_word(state, 263 + state->reg_offs, 6);
309 dib7000m_write_word(state, 264 + state->reg_offs, 6);
310 dib7000m_write_word(state, 266 + state->reg_offs, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
311 } else {
312 dib7000m_write_word(state, 263 + state->reg_offs, 1);
313 dib7000m_write_word(state, 264 + state->reg_offs, 0);
314 dib7000m_write_word(state, 266 + state->reg_offs, 0);
315 }
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300316
317 return 0;
318}
319
320static int dib7000m_sad_calib(struct dib7000m_state *state)
321{
322
323/* internal */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300324// dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300325 dib7000m_write_word(state, 929, (0 << 1) | (0 << 0));
326 dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096
327
328 /* do the calibration */
329 dib7000m_write_word(state, 929, (1 << 0));
330 dib7000m_write_word(state, 929, (0 << 0));
331
332 msleep(1);
333
334 return 0;
335}
336
337static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw)
338{
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300339 dib7000m_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff));
340 dib7000m_write_word(state, 19, (u16) ( (bw->internal*1000) & 0xffff));
341 dib7000m_write_word(state, 21, (u16) ( (bw->ifreq >> 16) & 0xffff));
342 dib7000m_write_word(state, 22, (u16) ( bw->ifreq & 0xffff));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300343
344 dib7000m_write_word(state, 928, bw->sad_cfg);
345}
346
347static void dib7000m_reset_pll(struct dib7000m_state *state)
348{
349 const struct dibx000_bandwidth_config *bw = state->cfg.bw;
350 u16 reg_907,reg_910;
351
352 /* default */
353 reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) |
354 (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) |
355 (bw->enable_refdiv << 1) | (0 << 0);
356 reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset;
357
358 // for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value)
359 // this is only working only for 30 MHz crystals
360 if (!state->cfg.quartz_direct) {
361 reg_910 |= (1 << 5); // forcing the predivider to 1
362
363 // if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2)
364 if(state->cfg.input_clk_is_div_2)
365 reg_907 |= (16 << 9);
366 else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary
367 reg_907 |= (8 << 9);
368 } else {
369 reg_907 |= (bw->pll_ratio & 0x3f) << 9;
370 reg_910 |= (bw->pll_prediv << 5);
371 }
372
373 dib7000m_write_word(state, 910, reg_910); // pll cfg
374 dib7000m_write_word(state, 907, reg_907); // clk cfg0
375 dib7000m_write_word(state, 908, 0x0006); // clk_cfg1
376
377 dib7000m_reset_pll_common(state, bw);
378}
379
380static void dib7000mc_reset_pll(struct dib7000m_state *state)
381{
382 const struct dibx000_bandwidth_config *bw = state->cfg.bw;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300383 u16 clk_cfg1;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300384
385 // clk_cfg0
386 dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0));
387
388 // clk_cfg1
389 //dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) |
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300390 clk_cfg1 = (0 << 14) | (3 << 12) |(0 << 11) |
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300391 (bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) |
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300392 (1 << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0);
393 dib7000m_write_word(state, 908, clk_cfg1);
394 clk_cfg1 = (clk_cfg1 & 0xfff7) | (bw->pll_bypass << 3);
395 dib7000m_write_word(state, 908, clk_cfg1);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300396
397 // smpl_cfg
398 dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7));
399
400 dib7000m_reset_pll_common(state, bw);
401}
402
403static int dib7000m_reset_gpio(struct dib7000m_state *st)
404{
405 /* reset the GPIOs */
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300406 dib7000m_write_word(st, 773, st->cfg.gpio_dir);
407 dib7000m_write_word(st, 774, st->cfg.gpio_val);
408
409 /* TODO 782 is P_gpio_od */
410
411 dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos);
412
413 dib7000m_write_word(st, 780, st->cfg.pwm_freq_div);
414 return 0;
415}
416
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300417static u16 dib7000m_defaults_common[] =
418
419{
420 // auto search configuration
421 3, 2,
422 0x0004,
423 0x1000,
424 0x0814,
425
426 12, 6,
427 0x001b,
428 0x7740,
429 0x005b,
430 0x8d80,
431 0x01c9,
432 0xc380,
433 0x0000,
434 0x0080,
435 0x0000,
436 0x0090,
437 0x0001,
438 0xd4c0,
439
440 1, 26,
441 0x6680, // P_corm_thres Lock algorithms configuration
442
443 1, 170,
444 0x0410, // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on
445
446 8, 173,
447 0,
448 0,
449 0,
450 0,
451 0,
452 0,
453 0,
454 0,
455
456 1, 182,
457 8192, // P_fft_nb_to_cut
458
459 2, 195,
460 0x0ccd, // P_pha3_thres
461 0, // P_cti_use_cpe, P_cti_use_prog
462
463 1, 205,
464 0x200f, // P_cspu_regul, P_cspu_win_cut
465
466 5, 214,
467 0x023d, // P_adp_regul_cnt
468 0x00a4, // P_adp_noise_cnt
469 0x00a4, // P_adp_regul_ext
470 0x7ff0, // P_adp_noise_ext
471 0x3ccc, // P_adp_fil
472
473 1, 226,
474 0, // P_2d_byp_ti_num
475
476 1, 255,
477 0x800, // P_equal_thres_wgn
478
479 1, 263,
480 0x0001,
481
482 1, 281,
483 0x0010, // P_fec_*
484
485 1, 294,
486 0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
487
488 0
489};
490
491static u16 dib7000m_defaults[] =
492
493{
494 /* set ADC level to -16 */
495 11, 76,
496 (1 << 13) - 825 - 117,
497 (1 << 13) - 837 - 117,
498 (1 << 13) - 811 - 117,
499 (1 << 13) - 766 - 117,
500 (1 << 13) - 737 - 117,
501 (1 << 13) - 693 - 117,
502 (1 << 13) - 648 - 117,
503 (1 << 13) - 619 - 117,
504 (1 << 13) - 575 - 117,
505 (1 << 13) - 531 - 117,
506 (1 << 13) - 501 - 117,
507
508 // Tuner IO bank: max drive (14mA)
509 1, 912,
510 0x2c8a,
511
512 1, 1817,
513 1,
514
515 0,
516};
517
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300518static int dib7000m_demod_reset(struct dib7000m_state *state)
519{
520 dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
521
522 /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
523 dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE);
524
525 /* restart all parts */
526 dib7000m_write_word(state, 898, 0xffff);
527 dib7000m_write_word(state, 899, 0xffff);
528 dib7000m_write_word(state, 900, 0xff0f);
529 dib7000m_write_word(state, 901, 0xfffc);
530
531 dib7000m_write_word(state, 898, 0);
532 dib7000m_write_word(state, 899, 0);
533 dib7000m_write_word(state, 900, 0);
534 dib7000m_write_word(state, 901, 0);
535
536 if (state->revision == 0x4000)
537 dib7000m_reset_pll(state);
538 else
539 dib7000mc_reset_pll(state);
540
541 if (dib7000m_reset_gpio(state) != 0)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300542 dprintk( "GPIO reset was not successful.");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300543
544 if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300545 dprintk( "OUTPUT_MODE could not be reset.");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300546
547 /* unforce divstr regardless whether i2c enumeration was done or not */
548 dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) );
549
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300550 dib7000m_set_bandwidth(state, 8000);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300551
552 dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON);
553 dib7000m_sad_calib(state);
554 dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
555
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300556 if (state->cfg.dvbt_mode)
557 dib7000m_write_word(state, 1796, 0x0); // select DVB-T output
558
559 if (state->cfg.mobile_mode)
560 dib7000m_write_word(state, 261 + state->reg_offs, 2);
561 else
562 dib7000m_write_word(state, 224 + state->reg_offs, 1);
563
564 // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ...
565 if(state->cfg.tuner_is_baseband)
566 dib7000m_write_word(state, 36, 0x0755);
567 else
568 dib7000m_write_word(state, 36, 0x1f55);
569
570 // P_divclksel=3 P_divbitsel=1
571 if (state->revision == 0x4000)
572 dib7000m_write_word(state, 909, (3 << 10) | (1 << 6));
573 else
574 dib7000m_write_word(state, 909, (3 << 4) | 1);
575
576 dib7000m_write_tab(state, dib7000m_defaults_common);
577 dib7000m_write_tab(state, dib7000m_defaults);
578
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300579 dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY);
580
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300581 state->internal_clk = state->cfg.bw->internal;
582
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300583 return 0;
584}
585
586static void dib7000m_restart_agc(struct dib7000m_state *state)
587{
588 // P_restart_iqc & P_restart_agc
589 dib7000m_write_word(state, 898, 0x0c00);
590 dib7000m_write_word(state, 898, 0x0000);
591}
592
593static int dib7000m_agc_soft_split(struct dib7000m_state *state)
594{
595 u16 agc,split_offset;
596
597 if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
598 return 0;
599
600 // n_agc_global
601 agc = dib7000m_read_word(state, 390);
602
603 if (agc > state->current_agc->split.min_thres)
604 split_offset = state->current_agc->split.min;
605 else if (agc < state->current_agc->split.max_thres)
606 split_offset = state->current_agc->split.max;
607 else
608 split_offset = state->current_agc->split.max *
609 (agc - state->current_agc->split.min_thres) /
610 (state->current_agc->split.max_thres - state->current_agc->split.min_thres);
611
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300612 dprintk( "AGC split_offset: %d",split_offset);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300613
614 // P_agc_force_split and P_agc_split_offset
615 return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset);
616}
617
618static int dib7000m_update_lna(struct dib7000m_state *state)
619{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300620 u16 dyn_gain;
621
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300622 if (state->cfg.update_lna) {
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300623 // read dyn_gain here (because it is demod-dependent and not tuner)
624 dyn_gain = dib7000m_read_word(state, 390);
625
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300626 if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
627 dib7000m_restart_agc(state);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300628 return 1;
629 }
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300630 }
631 return 0;
632}
633
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300634static int dib7000m_set_agc_config(struct dib7000m_state *state, u8 band)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300635{
636 struct dibx000_agc_config *agc = NULL;
637 int i;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300638 if (state->current_band == band && state->current_agc != NULL)
639 return 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300640 state->current_band = band;
641
642 for (i = 0; i < state->cfg.agc_config_count; i++)
643 if (state->cfg.agc[i].band_caps & band) {
644 agc = &state->cfg.agc[i];
645 break;
646 }
647
648 if (agc == NULL) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300649 dprintk( "no valid AGC configuration found for band 0x%02x",band);
650 return -EINVAL;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300651 }
652
653 state->current_agc = agc;
654
655 /* AGC */
656 dib7000m_write_word(state, 72 , agc->setup);
657 dib7000m_write_word(state, 73 , agc->inv_gain);
658 dib7000m_write_word(state, 74 , agc->time_stabiliz);
659 dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock);
660
661 // Demod AGC loop configuration
662 dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp);
663 dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp);
664
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300665 dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d",
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300666 state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
667
668 /* AGC continued */
669 if (state->wbd_ref != 0)
670 dib7000m_write_word(state, 102, state->wbd_ref);
671 else // use default
672 dib7000m_write_word(state, 102, agc->wbd_ref);
673
674 dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) );
675 dib7000m_write_word(state, 104, agc->agc1_max);
676 dib7000m_write_word(state, 105, agc->agc1_min);
677 dib7000m_write_word(state, 106, agc->agc2_max);
678 dib7000m_write_word(state, 107, agc->agc2_min);
679 dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 );
680 dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
681 dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
682 dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
683
684 if (state->revision > 0x4000) { // settings for the MC
685 dib7000m_write_word(state, 71, agc->agc1_pt3);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300686// dprintk( "929: %x %d %d",
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300687// (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel);
688 dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2));
689 } else {
690 // wrong default values
691 u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 };
692 for (i = 0; i < 9; i++)
693 dib7000m_write_word(state, 88 + i, b[i]);
694 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300695 return 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300696}
697
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300698static void dib7000m_update_timf(struct dib7000m_state *state)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300699{
700 u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300701 state->timf = timf * 160 / (state->current_bandwidth / 50);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300702 dib7000m_write_word(state, 23, (u16) (timf >> 16));
703 dib7000m_write_word(state, 24, (u16) (timf & 0xffff));
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300704 dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->timf_default);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300705}
706
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300707static int dib7000m_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
708{
709 struct dib7000m_state *state = demod->demodulator_priv;
710 u16 cfg_72 = dib7000m_read_word(state, 72);
711 int ret = -1;
712 u8 *agc_state = &state->agc_state;
713 u8 agc_split;
714
715 switch (state->agc_state) {
716 case 0:
717 // set power-up level: interf+analog+AGC
718 dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC);
719 dib7000m_set_adc_state(state, DIBX000_ADC_ON);
720
721 if (dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0)
722 return -1;
723
724 ret = 7; /* ADC power up */
725 (*agc_state)++;
726 break;
727
728 case 1:
729 /* AGC initialization */
730 if (state->cfg.agc_control)
731 state->cfg.agc_control(&state->demod, 1);
732
733 dib7000m_write_word(state, 75, 32768);
734 if (!state->current_agc->perform_agc_softsplit) {
735 /* we are using the wbd - so slow AGC startup */
736 dib7000m_write_word(state, 103, 1 << 8); /* force 0 split on WBD and restart AGC */
737 (*agc_state)++;
738 ret = 5;
739 } else {
740 /* default AGC startup */
741 (*agc_state) = 4;
742 /* wait AGC rough lock time */
743 ret = 7;
744 }
745
746 dib7000m_restart_agc(state);
747 break;
748
749 case 2: /* fast split search path after 5sec */
750 dib7000m_write_word(state, 72, cfg_72 | (1 << 4)); /* freeze AGC loop */
751 dib7000m_write_word(state, 103, 2 << 9); /* fast split search 0.25kHz */
752 (*agc_state)++;
753 ret = 14;
754 break;
755
756 case 3: /* split search ended */
757 agc_split = (uint8_t)dib7000m_read_word(state, 392); /* store the split value for the next time */
758 dib7000m_write_word(state, 75, dib7000m_read_word(state, 390)); /* set AGC gain start value */
759
760 dib7000m_write_word(state, 72, cfg_72 & ~(1 << 4)); /* std AGC loop */
761 dib7000m_write_word(state, 103, (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
762
763 dib7000m_restart_agc(state);
764
765 dprintk( "SPLIT %p: %hd", demod, agc_split);
766
767 (*agc_state)++;
768 ret = 5;
769 break;
770
771 case 4: /* LNA startup */
772 /* wait AGC accurate lock time */
773 ret = 7;
774
775 if (dib7000m_update_lna(state))
776 // wait only AGC rough lock time
777 ret = 5;
778 else
779 (*agc_state)++;
780 break;
781
782 case 5:
783 dib7000m_agc_soft_split(state);
784
785 if (state->cfg.agc_control)
786 state->cfg.agc_control(&state->demod, 0);
787
788 (*agc_state)++;
789 break;
790
791 default:
792 break;
793 }
794 return ret;
795}
796
797static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_frontend_parameters *ch, u8 seq)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300798{
799 u16 value, est[4];
800
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300801 dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300802
803 /* nfft, guard, qam, alpha */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300804 value = 0;
805 switch (ch->u.ofdm.transmission_mode) {
806 case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
807 case /* 4K MODE */ 255: value |= (2 << 7); break;
808 default:
809 case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
810 }
811 switch (ch->u.ofdm.guard_interval) {
812 case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
813 case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
814 case GUARD_INTERVAL_1_4: value |= (3 << 5); break;
815 default:
816 case GUARD_INTERVAL_1_8: value |= (2 << 5); break;
817 }
818 switch (ch->u.ofdm.constellation) {
819 case QPSK: value |= (0 << 3); break;
820 case QAM_16: value |= (1 << 3); break;
821 default:
822 case QAM_64: value |= (2 << 3); break;
823 }
824 switch (HIERARCHY_1) {
825 case HIERARCHY_2: value |= 2; break;
826 case HIERARCHY_4: value |= 4; break;
827 default:
828 case HIERARCHY_1: value |= 1; break;
829 }
830 dib7000m_write_word(state, 0, value);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300831 dib7000m_write_word(state, 5, (seq << 4));
832
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300833 /* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
834 value = 0;
835 if (1 != 0)
836 value |= (1 << 6);
837 if (ch->u.ofdm.hierarchy_information == 1)
838 value |= (1 << 4);
839 if (1 == 1)
840 value |= 1;
841 switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
842 case FEC_2_3: value |= (2 << 1); break;
843 case FEC_3_4: value |= (3 << 1); break;
844 case FEC_5_6: value |= (5 << 1); break;
845 case FEC_7_8: value |= (7 << 1); break;
846 default:
847 case FEC_1_2: value |= (1 << 1); break;
848 }
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300849 dib7000m_write_word(state, 267 + state->reg_offs, value);
850
851 /* offset loop parameters */
852
853 /* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */
854 dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80);
855
856 /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=1, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
857 dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3));
858
859 /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */
860 dib7000m_write_word(state, 32, (0 << 4) | 0x3);
861
862 /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */
863 dib7000m_write_word(state, 33, (0 << 4) | 0x5);
864
865 /* P_dvsy_sync_wait */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300866 switch (ch->u.ofdm.transmission_mode) {
867 case TRANSMISSION_MODE_8K: value = 256; break;
868 case /* 4K MODE */ 255: value = 128; break;
869 case TRANSMISSION_MODE_2K:
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300870 default: value = 64; break;
871 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300872 switch (ch->u.ofdm.guard_interval) {
873 case GUARD_INTERVAL_1_16: value *= 2; break;
874 case GUARD_INTERVAL_1_8: value *= 4; break;
875 case GUARD_INTERVAL_1_4: value *= 8; break;
876 default:
877 case GUARD_INTERVAL_1_32: value *= 1; break;
878 }
879 state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300880
881 /* deactive the possibility of diversity reception if extended interleave - not for 7000MC */
882 /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300883 if (1 == 1 || state->revision > 0x4000)
884 state->div_force_off = 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300885 else
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300886 state->div_force_off = 1;
887 dib7000m_set_diversity_in(&state->demod, state->div_state);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300888
889 /* channel estimation fine configuration */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300890 switch (ch->u.ofdm.constellation) {
891 case QAM_64:
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300892 est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
893 est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
894 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
895 est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */
896 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300897 case QAM_16:
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300898 est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */
899 est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */
900 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
901 est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */
902 break;
903 default:
904 est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */
905 est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */
906 est[2] = 0x0333; /* P_adp_regul_ext 0.1 */
907 est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */
908 break;
909 }
910 for (value = 0; value < 4; value++)
911 dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]);
912
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300913 // set power-up level: autosearch
914 dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD);
915}
916
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300917static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300918{
919 struct dib7000m_state *state = demod->demodulator_priv;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300920 struct dvb_frontend_parameters schan;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300921 int ret = 0;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300922 u32 value, factor;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300923
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300924 schan = *ch;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300925
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300926 schan.u.ofdm.constellation = QAM_64;
927 schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
928 schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
929 schan.u.ofdm.code_rate_HP = FEC_2_3;
930 schan.u.ofdm.code_rate_LP = FEC_3_4;
931 schan.u.ofdm.hierarchy_information = 0;
932
933 dib7000m_set_channel(state, &schan, 7);
934
935 factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth);
936 if (factor >= 5000)
937 factor = 1;
938 else
939 factor = 6;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300940
941 // always use the setting for 8MHz here lock_time for 7,6 MHz are longer
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300942 value = 30 * state->internal_clk * factor;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300943 ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time
944 ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300945 value = 100 * state->internal_clk * factor;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300946 ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time
947 ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300948 value = 500 * state->internal_clk * factor;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300949 ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
950 ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time
951
952 // start search
953 value = dib7000m_read_word(state, 0);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300954 ret |= dib7000m_write_word(state, 0, (u16) (value | (1 << 9)));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300955
956 /* clear n_irq_pending */
957 if (state->revision == 0x4000)
958 dib7000m_write_word(state, 1793, 0);
959 else
960 dib7000m_read_word(state, 537);
961
962 ret |= dib7000m_write_word(state, 0, (u16) value);
963
964 return ret;
965}
966
967static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg)
968{
969 u16 irq_pending = dib7000m_read_word(state, reg);
970
971 if (irq_pending & 0x1) { // failed
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300972 dprintk( "autosearch failed");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300973 return 1;
974 }
975
976 if (irq_pending & 0x2) { // succeeded
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300977 dprintk( "autosearch succeeded");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300978 return 2;
979 }
980 return 0; // still pending
981}
982
983static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod)
984{
985 struct dib7000m_state *state = demod->demodulator_priv;
986 if (state->revision == 0x4000)
987 return dib7000m_autosearch_irq(state, 1793);
988 else
989 return dib7000m_autosearch_irq(state, 537);
990}
991
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300992static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300993{
994 struct dib7000m_state *state = demod->demodulator_priv;
995 int ret = 0;
996 u16 value;
997
998 // we are already tuned - just resuming from suspend
999 if (ch != NULL)
1000 dib7000m_set_channel(state, ch, 0);
1001 else
1002 return -EINVAL;
1003
1004 // restart demod
1005 ret |= dib7000m_write_word(state, 898, 0x4000);
1006 ret |= dib7000m_write_word(state, 898, 0x0000);
1007 msleep(45);
1008
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001009 dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001010 /* 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 */
1011 ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3));
1012
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001013 // never achieved a lock before - wait for timfreq to update
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001014 if (state->timf == 0)
1015 msleep(200);
1016
1017 //dump_reg(state);
1018 /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
1019 value = (6 << 8) | 0x80;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001020 switch (ch->u.ofdm.transmission_mode) {
1021 case TRANSMISSION_MODE_2K: value |= (7 << 12); break;
1022 case /* 4K MODE */ 255: value |= (8 << 12); break;
1023 default:
1024 case TRANSMISSION_MODE_8K: value |= (9 << 12); break;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001025 }
1026 ret |= dib7000m_write_word(state, 26, value);
1027
1028 /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
1029 value = (0 << 4);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001030 switch (ch->u.ofdm.transmission_mode) {
1031 case TRANSMISSION_MODE_2K: value |= 0x6; break;
1032 case /* 4K MODE */ 255: value |= 0x7; break;
1033 default:
1034 case TRANSMISSION_MODE_8K: value |= 0x8; break;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001035 }
1036 ret |= dib7000m_write_word(state, 32, value);
1037
1038 /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
1039 value = (0 << 4);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001040 switch (ch->u.ofdm.transmission_mode) {
1041 case TRANSMISSION_MODE_2K: value |= 0x6; break;
1042 case /* 4K MODE */ 255: value |= 0x7; break;
1043 default:
1044 case TRANSMISSION_MODE_8K: value |= 0x8; break;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001045 }
1046 ret |= dib7000m_write_word(state, 33, value);
1047
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001048 // we achieved a lock - it's time to update the timf freq
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001049 if ((dib7000m_read_word(state, 535) >> 6) & 0x1)
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001050 dib7000m_update_timf(state);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001051
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001052 dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001053 return ret;
1054}
1055
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001056static int dib7000m_wakeup(struct dvb_frontend *demod)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001057{
1058 struct dib7000m_state *state = demod->demodulator_priv;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001059
1060 dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
1061
1062 if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001063 dprintk( "could not start Slow ADC");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001064
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001065 return 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001066}
1067
1068static int dib7000m_sleep(struct dvb_frontend *demod)
1069{
1070 struct dib7000m_state *st = demod->demodulator_priv;
1071 dib7000m_set_output_mode(st, OUTMODE_HIGH_Z);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001072 dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY);
1073 return dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) |
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001074 dib7000m_set_adc_state(st, DIBX000_ADC_OFF);
1075}
1076
1077static int dib7000m_identify(struct dib7000m_state *state)
1078{
1079 u16 value;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001080
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001081 if ((value = dib7000m_read_word(state, 896)) != 0x01b3) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001082 dprintk( "wrong Vendor ID (0x%x)",value);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001083 return -EREMOTEIO;
1084 }
1085
1086 state->revision = dib7000m_read_word(state, 897);
1087 if (state->revision != 0x4000 &&
1088 state->revision != 0x4001 &&
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001089 state->revision != 0x4002 &&
1090 state->revision != 0x4003) {
1091 dprintk( "wrong Device ID (0x%x)",value);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001092 return -EREMOTEIO;
1093 }
1094
1095 /* protect this driver to be used with 7000PC */
1096 if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001097 dprintk( "this driver does not work with DiB7000PC");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001098 return -EREMOTEIO;
1099 }
1100
1101 switch (state->revision) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001102 case 0x4000: dprintk( "found DiB7000MA/PA/MB/PB"); break;
1103 case 0x4001: state->reg_offs = 1; dprintk( "found DiB7000HC"); break;
1104 case 0x4002: state->reg_offs = 1; dprintk( "found DiB7000MC"); break;
1105 case 0x4003: state->reg_offs = 1; dprintk( "found DiB9000"); break;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001106 }
1107
1108 return 0;
1109}
1110
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001111
1112static int dib7000m_get_frontend(struct dvb_frontend* fe,
1113 struct dvb_frontend_parameters *fep)
1114{
1115 struct dib7000m_state *state = fe->demodulator_priv;
1116 u16 tps = dib7000m_read_word(state,480);
1117
1118 fep->inversion = INVERSION_AUTO;
1119
1120 fep->u.ofdm.bandwidth = state->current_bandwidth;
1121
Patrick Boettcherd92532d2006-10-18 08:35:16 -03001122 switch ((tps >> 8) & 0x3) {
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001123 case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
1124 case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
1125 /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
1126 }
1127
1128 switch (tps & 0x3) {
1129 case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
1130 case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
1131 case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
1132 case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
1133 }
1134
1135 switch ((tps >> 14) & 0x3) {
1136 case 0: fep->u.ofdm.constellation = QPSK; break;
1137 case 1: fep->u.ofdm.constellation = QAM_16; break;
1138 case 2:
1139 default: fep->u.ofdm.constellation = QAM_64; break;
1140 }
1141
1142 /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
1143 /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
1144
1145 fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
1146 switch ((tps >> 5) & 0x7) {
1147 case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
1148 case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
1149 case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
1150 case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
1151 case 7:
1152 default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
1153
1154 }
1155
1156 switch ((tps >> 2) & 0x7) {
1157 case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
1158 case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
1159 case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
1160 case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
1161 case 7:
1162 default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
1163 }
1164
1165 /* native interleaver: (dib7000m_read_word(state, 481) >> 5) & 0x1 */
1166
1167 return 0;
1168}
1169
1170static int dib7000m_set_frontend(struct dvb_frontend* fe,
1171 struct dvb_frontend_parameters *fep)
1172{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001173 struct dib7000m_state *state = fe->demodulator_priv;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001174 int time;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001175
1176 state->current_bandwidth = fep->u.ofdm.bandwidth;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001177 dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001178
1179 if (fe->ops.tuner_ops.set_params)
1180 fe->ops.tuner_ops.set_params(fe, fep);
1181
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001182 /* start up the AGC */
1183 state->agc_state = 0;
1184 do {
1185 time = dib7000m_agc_startup(fe, fep);
1186 if (time != -1)
1187 msleep(time);
1188 } while (time != -1);
1189
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001190 if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
1191 fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
1192 fep->u.ofdm.constellation == QAM_AUTO ||
1193 fep->u.ofdm.code_rate_HP == FEC_AUTO) {
1194 int i = 800, found;
1195
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001196 dib7000m_autosearch_start(fe, fep);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001197 do {
1198 msleep(1);
1199 found = dib7000m_autosearch_is_irq(fe);
1200 } while (found == 0 && i--);
1201
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001202 dprintk("autosearch returns: %d",found);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001203 if (found == 0 || found == 1)
1204 return 0; // no channel found
1205
1206 dib7000m_get_frontend(fe, fep);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001207 }
1208
1209 /* make this a config parameter */
1210 dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO);
1211
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001212 return dib7000m_tune(fe, fep);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001213}
1214
1215static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat)
1216{
1217 struct dib7000m_state *state = fe->demodulator_priv;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001218 u16 lock = dib7000m_read_word(state, 535);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001219
1220 *stat = 0;
1221
1222 if (lock & 0x8000)
1223 *stat |= FE_HAS_SIGNAL;
1224 if (lock & 0x3000)
1225 *stat |= FE_HAS_CARRIER;
1226 if (lock & 0x0100)
1227 *stat |= FE_HAS_VITERBI;
1228 if (lock & 0x0010)
1229 *stat |= FE_HAS_SYNC;
1230 if (lock & 0x0008)
1231 *stat |= FE_HAS_LOCK;
1232
1233 return 0;
1234}
1235
1236static int dib7000m_read_ber(struct dvb_frontend *fe, u32 *ber)
1237{
1238 struct dib7000m_state *state = fe->demodulator_priv;
1239 *ber = (dib7000m_read_word(state, 526) << 16) | dib7000m_read_word(state, 527);
1240 return 0;
1241}
1242
1243static int dib7000m_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
1244{
1245 struct dib7000m_state *state = fe->demodulator_priv;
1246 *unc = dib7000m_read_word(state, 534);
1247 return 0;
1248}
1249
1250static int dib7000m_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
1251{
1252 struct dib7000m_state *state = fe->demodulator_priv;
1253 u16 val = dib7000m_read_word(state, 390);
1254 *strength = 65535 - val;
1255 return 0;
1256}
1257
1258static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr)
1259{
1260 *snr = 0x0000;
1261 return 0;
1262}
1263
1264static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
1265{
1266 tune->min_delay_ms = 1000;
1267 return 0;
1268}
1269
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001270static void dib7000m_release(struct dvb_frontend *demod)
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001271{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001272 struct dib7000m_state *st = demod->demodulator_priv;
1273 dibx000_exit_i2c_master(&st->i2c_master);
1274 kfree(st);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001275}
1276
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001277struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001278{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001279 struct dib7000m_state *st = demod->demodulator_priv;
1280 return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
1281}
1282EXPORT_SYMBOL(dib7000m_get_i2c_master);
1283
1284int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000m_config cfg[])
1285{
1286 struct dib7000m_state st = { .i2c_adap = i2c };
1287 int k = 0;
1288 u8 new_addr = 0;
1289
1290 for (k = no_of_demods-1; k >= 0; k--) {
1291 st.cfg = cfg[k];
1292
1293 /* designated i2c address */
1294 new_addr = (0x40 + k) << 1;
1295 st.i2c_addr = new_addr;
1296 if (dib7000m_identify(&st) != 0) {
1297 st.i2c_addr = default_addr;
1298 if (dib7000m_identify(&st) != 0) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001299 dprintk("DiB7000M #%d: not identified", k);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001300 return -EIO;
1301 }
1302 }
1303
1304 /* start diversity to pull_down div_str - just for i2c-enumeration */
1305 dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY);
1306
1307 dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output
1308
1309 /* set new i2c address and force divstart */
1310 dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2);
1311
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001312 dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001313 }
1314
1315 for (k = 0; k < no_of_demods; k++) {
1316 st.cfg = cfg[k];
1317 st.i2c_addr = (0x40 + k) << 1;
1318
1319 // unforce divstr
1320 dib7000m_write_word(&st,1794, st.i2c_addr << 2);
1321
1322 /* deactivate div - it was just for i2c-enumeration */
1323 dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z);
1324 }
1325
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001326 return 0;
1327}
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001328EXPORT_SYMBOL(dib7000m_i2c_enumeration);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001329
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001330static struct dvb_frontend_ops dib7000m_ops;
1331struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg)
1332{
1333 struct dvb_frontend *demod;
1334 struct dib7000m_state *st;
1335 st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL);
1336 if (st == NULL)
1337 return NULL;
1338
1339 memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config));
1340 st->i2c_adap = i2c_adap;
1341 st->i2c_addr = i2c_addr;
1342
1343 demod = &st->demod;
1344 demod->demodulator_priv = st;
1345 memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops));
1346
1347 if (dib7000m_identify(st) != 0)
1348 goto error;
1349
1350 if (st->revision == 0x4000)
1351 dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr);
1352 else
1353 dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr);
1354
1355 dib7000m_demod_reset(st);
1356
1357 return demod;
1358
1359error:
1360 kfree(st);
1361 return NULL;
1362}
1363EXPORT_SYMBOL(dib7000m_attach);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001364
1365static struct dvb_frontend_ops dib7000m_ops = {
1366 .info = {
1367 .name = "DiBcom 7000MA/MB/PA/PB/MC",
1368 .type = FE_OFDM,
1369 .frequency_min = 44250000,
1370 .frequency_max = 867250000,
1371 .frequency_stepsize = 62500,
1372 .caps = FE_CAN_INVERSION_AUTO |
1373 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1374 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1375 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
1376 FE_CAN_TRANSMISSION_MODE_AUTO |
1377 FE_CAN_GUARD_INTERVAL_AUTO |
1378 FE_CAN_RECOVER |
1379 FE_CAN_HIERARCHY_AUTO,
1380 },
1381
1382 .release = dib7000m_release,
1383
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001384 .init = dib7000m_wakeup,
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001385 .sleep = dib7000m_sleep,
1386
1387 .set_frontend = dib7000m_set_frontend,
1388 .get_tune_settings = dib7000m_fe_get_tune_settings,
1389 .get_frontend = dib7000m_get_frontend,
1390
1391 .read_status = dib7000m_read_status,
1392 .read_ber = dib7000m_read_ber,
1393 .read_signal_strength = dib7000m_read_signal_strength,
1394 .read_snr = dib7000m_read_snr,
1395 .read_ucblocks = dib7000m_read_unc_blocks,
1396};
1397
1398MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
1399MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator");
1400MODULE_LICENSE("GPL");