blob: c7f5ccf54aa5f1ea93b182e59a070ee234e4730b [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>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090012#include <linux/slab.h>
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020013#include <linux/i2c.h>
14
15#include "dvb_frontend.h"
16
17#include "dib7000m.h"
18
19static int debug;
20module_param(debug, int, 0644);
21MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
22
Patrick Boettcherb6884a12007-07-27 10:08:51 -030023#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M: "); printk(args); printk("\n"); } } while (0)
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020024
25struct dib7000m_state {
26 struct dvb_frontend demod;
27 struct dib7000m_config cfg;
28
29 u8 i2c_addr;
30 struct i2c_adapter *i2c_adap;
31
32 struct dibx000_i2c_master i2c_master;
33
34/* offset is 1 in case of the 7000MC */
35 u8 reg_offs;
36
37 u16 wbd_ref;
38
39 u8 current_band;
40 fe_bandwidth_t current_bandwidth;
41 struct dibx000_agc_config *current_agc;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -030042 u32 timf;
Patrick Boettcherb6884a12007-07-27 10:08:51 -030043 u32 timf_default;
44 u32 internal_clk;
45
Patrick Boettcher01373a52007-07-30 12:49:04 -030046 u8 div_force_off : 1;
47 u8 div_state : 1;
48 u16 div_sync_wait;
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020049
50 u16 revision;
Patrick Boettcherb6884a12007-07-27 10:08:51 -030051
52 u8 agc_state;
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020053};
54
Patrick Boettcher69ea31e2006-10-17 18:28:14 -030055enum dib7000m_power_mode {
56 DIB7000M_POWER_ALL = 0,
57
58 DIB7000M_POWER_NO,
59 DIB7000M_POWER_INTERF_ANALOG_AGC,
60 DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD,
61 DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD,
62 DIB7000M_POWER_INTERFACE_ONLY,
63};
64
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020065static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
66{
67 u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
68 u8 rb[2];
69 struct i2c_msg msg[2] = {
70 { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 },
71 { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
72 };
73
74 if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
Patrick Boettcherb6884a12007-07-27 10:08:51 -030075 dprintk("i2c read error on %d",reg);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020076
77 return (rb[0] << 8) | rb[1];
78}
79
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020080static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
81{
82 u8 b[4] = {
83 (reg >> 8) & 0xff, reg & 0xff,
84 (val >> 8) & 0xff, val & 0xff,
85 };
86 struct i2c_msg msg = {
87 .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
88 };
89 return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
90}
Patrick Boettcherb6884a12007-07-27 10:08:51 -030091static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
92{
93 u16 l = 0, r, *n;
94 n = buf;
95 l = *n++;
96 while (l) {
97 r = *n++;
98
99 if (state->reg_offs && (r >= 112 && r <= 331)) // compensate for 7000MC
100 r++;
101
102 do {
103 dib7000m_write_word(state, r, *n++);
104 r++;
105 } while (--l);
106 l = *n++;
107 }
108}
109
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300110static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode)
111{
112 int ret = 0;
113 u16 outreg, fifo_threshold, smo_mode,
114 sram = 0x0005; /* by default SRAM output is disabled */
115
116 outreg = 0;
117 fifo_threshold = 1792;
118 smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1);
119
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300120 dprintk( "setting output mode for demod %p to %d", &state->demod, mode);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300121
122 switch (mode) {
123 case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock
124 outreg = (1 << 10); /* 0x0400 */
125 break;
126 case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock
127 outreg = (1 << 10) | (1 << 6); /* 0x0440 */
128 break;
129 case OUTMODE_MPEG2_SERIAL: // STBs with serial input
130 outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */
131 break;
132 case OUTMODE_DIVERSITY:
133 if (state->cfg.hostbus_diversity)
134 outreg = (1 << 10) | (4 << 6); /* 0x0500 */
135 else
136 sram |= 0x0c00;
137 break;
138 case OUTMODE_MPEG2_FIFO: // e.g. USB feeding
139 smo_mode |= (3 << 1);
140 fifo_threshold = 512;
141 outreg = (1 << 10) | (5 << 6);
142 break;
143 case OUTMODE_HIGH_Z: // disable
144 outreg = 0;
145 break;
146 default:
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300147 dprintk( "Unhandled output_mode passed to be set for demod %p",&state->demod);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300148 break;
149 }
150
151 if (state->cfg.output_mpeg2_in_188_bytes)
152 smo_mode |= (1 << 5) ;
153
154 ret |= dib7000m_write_word(state, 294 + state->reg_offs, smo_mode);
155 ret |= dib7000m_write_word(state, 295 + state->reg_offs, fifo_threshold); /* synchronous fread */
156 ret |= dib7000m_write_word(state, 1795, outreg);
157 ret |= dib7000m_write_word(state, 1805, sram);
158
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300159 if (state->revision == 0x4003) {
160 u16 clk_cfg1 = dib7000m_read_word(state, 909) & 0xfffd;
161 if (mode == OUTMODE_DIVERSITY)
162 clk_cfg1 |= (1 << 1); // P_O_CLK_en
163 dib7000m_write_word(state, 909, clk_cfg1);
164 }
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300165 return ret;
166}
167
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300168static void dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300169{
170 /* by default everything is going to be powered off */
171 u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906 = 0x3fff;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300172 u8 offset = 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300173
174 /* now, depending on the requested mode, we power on */
175 switch (mode) {
176 /* power up everything in the demod */
177 case DIB7000M_POWER_ALL:
178 reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000;
179 break;
180
181 /* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */
182 case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */
183 reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2));
184 break;
185
186 case DIB7000M_POWER_INTERF_ANALOG_AGC:
187 reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10));
188 reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2));
189 reg_906 &= ~((1 << 0));
190 break;
191
192 case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD:
193 reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000;
194 break;
195
196 case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD:
197 reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000;
198 break;
199 case DIB7000M_POWER_NO:
200 break;
201 }
202
203 /* always power down unused parts */
204 if (!state->cfg.mobile_mode)
205 reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1);
206
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300207 /* P_sdio_select_clk = 0 on MC and after*/
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300208 if (state->revision != 0x4000)
209 reg_906 <<= 1;
210
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300211 if (state->revision == 0x4003)
212 offset = 1;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300213
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300214 dib7000m_write_word(state, 903 + offset, reg_903);
215 dib7000m_write_word(state, 904 + offset, reg_904);
216 dib7000m_write_word(state, 905 + offset, reg_905);
217 dib7000m_write_word(state, 906 + offset, reg_906);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300218}
219
220static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no)
221{
222 int ret = 0;
223 u16 reg_913 = dib7000m_read_word(state, 913),
224 reg_914 = dib7000m_read_word(state, 914);
225
226 switch (no) {
227 case DIBX000_SLOW_ADC_ON:
228 reg_914 |= (1 << 1) | (1 << 0);
229 ret |= dib7000m_write_word(state, 914, reg_914);
230 reg_914 &= ~(1 << 1);
231 break;
232
233 case DIBX000_SLOW_ADC_OFF:
234 reg_914 |= (1 << 1) | (1 << 0);
235 break;
236
237 case DIBX000_ADC_ON:
238 if (state->revision == 0x4000) { // workaround for PA/MA
239 // power-up ADC
240 dib7000m_write_word(state, 913, 0);
241 dib7000m_write_word(state, 914, reg_914 & 0x3);
242 // power-down bandgag
243 dib7000m_write_word(state, 913, (1 << 15));
244 dib7000m_write_word(state, 914, reg_914 & 0x3);
245 }
246
247 reg_913 &= 0x0fff;
248 reg_914 &= 0x0003;
249 break;
250
251 case DIBX000_ADC_OFF: // leave the VBG voltage on
252 reg_913 |= (1 << 14) | (1 << 13) | (1 << 12);
253 reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
254 break;
255
256 case DIBX000_VBG_ENABLE:
257 reg_913 &= ~(1 << 15);
258 break;
259
260 case DIBX000_VBG_DISABLE:
261 reg_913 |= (1 << 15);
262 break;
263
264 default:
265 break;
266 }
267
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300268// dprintk( "913: %x, 914: %x", reg_913, reg_914);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300269 ret |= dib7000m_write_word(state, 913, reg_913);
270 ret |= dib7000m_write_word(state, 914, reg_914);
271
272 return ret;
273}
274
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300275static int dib7000m_set_bandwidth(struct dib7000m_state *state, u32 bw)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300276{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300277 u32 timf;
278
279 // store the current bandwidth for later use
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300280 state->current_bandwidth = bw;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300281
282 if (state->timf == 0) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300283 dprintk( "using default timf");
284 timf = state->timf_default;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300285 } else {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300286 dprintk( "using updated timf");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300287 timf = state->timf;
288 }
289
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300290 timf = timf * (bw / 50) / 160;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300291
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300292 dib7000m_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
293 dib7000m_write_word(state, 24, (u16) ((timf ) & 0xffff));
294
295 return 0;
296}
297
298static int dib7000m_set_diversity_in(struct dvb_frontend *demod, int onoff)
299{
300 struct dib7000m_state *state = demod->demodulator_priv;
301
302 if (state->div_force_off) {
303 dprintk( "diversity combination deactivated - forced by COFDM parameters");
304 onoff = 0;
305 }
Patrick Boettcher01373a52007-07-30 12:49:04 -0300306 state->div_state = (u8)onoff;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300307
308 if (onoff) {
309 dib7000m_write_word(state, 263 + state->reg_offs, 6);
310 dib7000m_write_word(state, 264 + state->reg_offs, 6);
311 dib7000m_write_word(state, 266 + state->reg_offs, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
312 } else {
313 dib7000m_write_word(state, 263 + state->reg_offs, 1);
314 dib7000m_write_word(state, 264 + state->reg_offs, 0);
315 dib7000m_write_word(state, 266 + state->reg_offs, 0);
316 }
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300317
318 return 0;
319}
320
321static int dib7000m_sad_calib(struct dib7000m_state *state)
322{
323
324/* internal */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300325// 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 -0300326 dib7000m_write_word(state, 929, (0 << 1) | (0 << 0));
327 dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096
328
329 /* do the calibration */
330 dib7000m_write_word(state, 929, (1 << 0));
331 dib7000m_write_word(state, 929, (0 << 0));
332
333 msleep(1);
334
335 return 0;
336}
337
338static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw)
339{
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300340 dib7000m_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff));
341 dib7000m_write_word(state, 19, (u16) ( (bw->internal*1000) & 0xffff));
342 dib7000m_write_word(state, 21, (u16) ( (bw->ifreq >> 16) & 0xffff));
343 dib7000m_write_word(state, 22, (u16) ( bw->ifreq & 0xffff));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300344
345 dib7000m_write_word(state, 928, bw->sad_cfg);
346}
347
348static void dib7000m_reset_pll(struct dib7000m_state *state)
349{
350 const struct dibx000_bandwidth_config *bw = state->cfg.bw;
351 u16 reg_907,reg_910;
352
353 /* default */
354 reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) |
355 (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) |
356 (bw->enable_refdiv << 1) | (0 << 0);
357 reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset;
358
359 // for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value)
360 // this is only working only for 30 MHz crystals
361 if (!state->cfg.quartz_direct) {
362 reg_910 |= (1 << 5); // forcing the predivider to 1
363
364 // if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2)
365 if(state->cfg.input_clk_is_div_2)
366 reg_907 |= (16 << 9);
367 else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary
368 reg_907 |= (8 << 9);
369 } else {
370 reg_907 |= (bw->pll_ratio & 0x3f) << 9;
371 reg_910 |= (bw->pll_prediv << 5);
372 }
373
374 dib7000m_write_word(state, 910, reg_910); // pll cfg
375 dib7000m_write_word(state, 907, reg_907); // clk cfg0
376 dib7000m_write_word(state, 908, 0x0006); // clk_cfg1
377
378 dib7000m_reset_pll_common(state, bw);
379}
380
381static void dib7000mc_reset_pll(struct dib7000m_state *state)
382{
383 const struct dibx000_bandwidth_config *bw = state->cfg.bw;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300384 u16 clk_cfg1;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300385
386 // clk_cfg0
387 dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0));
388
389 // clk_cfg1
390 //dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) |
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300391 clk_cfg1 = (0 << 14) | (3 << 12) |(0 << 11) |
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300392 (bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) |
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300393 (1 << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0);
394 dib7000m_write_word(state, 908, clk_cfg1);
395 clk_cfg1 = (clk_cfg1 & 0xfff7) | (bw->pll_bypass << 3);
396 dib7000m_write_word(state, 908, clk_cfg1);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300397
398 // smpl_cfg
399 dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7));
400
401 dib7000m_reset_pll_common(state, bw);
402}
403
404static int dib7000m_reset_gpio(struct dib7000m_state *st)
405{
406 /* reset the GPIOs */
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300407 dib7000m_write_word(st, 773, st->cfg.gpio_dir);
408 dib7000m_write_word(st, 774, st->cfg.gpio_val);
409
410 /* TODO 782 is P_gpio_od */
411
412 dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos);
413
414 dib7000m_write_word(st, 780, st->cfg.pwm_freq_div);
415 return 0;
416}
417
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300418static u16 dib7000m_defaults_common[] =
419
420{
421 // auto search configuration
422 3, 2,
423 0x0004,
424 0x1000,
425 0x0814,
426
427 12, 6,
428 0x001b,
429 0x7740,
430 0x005b,
431 0x8d80,
432 0x01c9,
433 0xc380,
434 0x0000,
435 0x0080,
436 0x0000,
437 0x0090,
438 0x0001,
439 0xd4c0,
440
441 1, 26,
442 0x6680, // P_corm_thres Lock algorithms configuration
443
444 1, 170,
445 0x0410, // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on
446
447 8, 173,
448 0,
449 0,
450 0,
451 0,
452 0,
453 0,
454 0,
455 0,
456
457 1, 182,
458 8192, // P_fft_nb_to_cut
459
460 2, 195,
461 0x0ccd, // P_pha3_thres
462 0, // P_cti_use_cpe, P_cti_use_prog
463
464 1, 205,
465 0x200f, // P_cspu_regul, P_cspu_win_cut
466
467 5, 214,
468 0x023d, // P_adp_regul_cnt
469 0x00a4, // P_adp_noise_cnt
470 0x00a4, // P_adp_regul_ext
471 0x7ff0, // P_adp_noise_ext
472 0x3ccc, // P_adp_fil
473
474 1, 226,
475 0, // P_2d_byp_ti_num
476
477 1, 255,
478 0x800, // P_equal_thres_wgn
479
480 1, 263,
481 0x0001,
482
483 1, 281,
484 0x0010, // P_fec_*
485
486 1, 294,
487 0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
488
489 0
490};
491
492static u16 dib7000m_defaults[] =
493
494{
495 /* set ADC level to -16 */
496 11, 76,
497 (1 << 13) - 825 - 117,
498 (1 << 13) - 837 - 117,
499 (1 << 13) - 811 - 117,
500 (1 << 13) - 766 - 117,
501 (1 << 13) - 737 - 117,
502 (1 << 13) - 693 - 117,
503 (1 << 13) - 648 - 117,
504 (1 << 13) - 619 - 117,
505 (1 << 13) - 575 - 117,
506 (1 << 13) - 531 - 117,
507 (1 << 13) - 501 - 117,
508
509 // Tuner IO bank: max drive (14mA)
510 1, 912,
511 0x2c8a,
512
513 1, 1817,
514 1,
515
516 0,
517};
518
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300519static int dib7000m_demod_reset(struct dib7000m_state *state)
520{
521 dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
522
523 /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
524 dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE);
525
526 /* restart all parts */
527 dib7000m_write_word(state, 898, 0xffff);
528 dib7000m_write_word(state, 899, 0xffff);
529 dib7000m_write_word(state, 900, 0xff0f);
530 dib7000m_write_word(state, 901, 0xfffc);
531
532 dib7000m_write_word(state, 898, 0);
533 dib7000m_write_word(state, 899, 0);
534 dib7000m_write_word(state, 900, 0);
535 dib7000m_write_word(state, 901, 0);
536
537 if (state->revision == 0x4000)
538 dib7000m_reset_pll(state);
539 else
540 dib7000mc_reset_pll(state);
541
542 if (dib7000m_reset_gpio(state) != 0)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300543 dprintk( "GPIO reset was not successful.");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300544
545 if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300546 dprintk( "OUTPUT_MODE could not be reset.");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300547
548 /* unforce divstr regardless whether i2c enumeration was done or not */
549 dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) );
550
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300551 dib7000m_set_bandwidth(state, 8000);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300552
553 dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON);
554 dib7000m_sad_calib(state);
555 dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
556
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300557 if (state->cfg.dvbt_mode)
558 dib7000m_write_word(state, 1796, 0x0); // select DVB-T output
559
560 if (state->cfg.mobile_mode)
561 dib7000m_write_word(state, 261 + state->reg_offs, 2);
562 else
563 dib7000m_write_word(state, 224 + state->reg_offs, 1);
564
565 // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ...
566 if(state->cfg.tuner_is_baseband)
567 dib7000m_write_word(state, 36, 0x0755);
568 else
569 dib7000m_write_word(state, 36, 0x1f55);
570
571 // P_divclksel=3 P_divbitsel=1
572 if (state->revision == 0x4000)
573 dib7000m_write_word(state, 909, (3 << 10) | (1 << 6));
574 else
575 dib7000m_write_word(state, 909, (3 << 4) | 1);
576
577 dib7000m_write_tab(state, dib7000m_defaults_common);
578 dib7000m_write_tab(state, dib7000m_defaults);
579
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300580 dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY);
581
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300582 state->internal_clk = state->cfg.bw->internal;
583
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300584 return 0;
585}
586
587static void dib7000m_restart_agc(struct dib7000m_state *state)
588{
589 // P_restart_iqc & P_restart_agc
590 dib7000m_write_word(state, 898, 0x0c00);
591 dib7000m_write_word(state, 898, 0x0000);
592}
593
594static int dib7000m_agc_soft_split(struct dib7000m_state *state)
595{
596 u16 agc,split_offset;
597
598 if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
599 return 0;
600
601 // n_agc_global
602 agc = dib7000m_read_word(state, 390);
603
604 if (agc > state->current_agc->split.min_thres)
605 split_offset = state->current_agc->split.min;
606 else if (agc < state->current_agc->split.max_thres)
607 split_offset = state->current_agc->split.max;
608 else
609 split_offset = state->current_agc->split.max *
610 (agc - state->current_agc->split.min_thres) /
611 (state->current_agc->split.max_thres - state->current_agc->split.min_thres);
612
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300613 dprintk( "AGC split_offset: %d",split_offset);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300614
615 // P_agc_force_split and P_agc_split_offset
616 return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset);
617}
618
619static int dib7000m_update_lna(struct dib7000m_state *state)
620{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300621 u16 dyn_gain;
622
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300623 if (state->cfg.update_lna) {
Patrick Boettcher01373a52007-07-30 12:49:04 -0300624 // read dyn_gain here (because it is demod-dependent and not fe)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300625 dyn_gain = dib7000m_read_word(state, 390);
626
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300627 if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
628 dib7000m_restart_agc(state);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300629 return 1;
630 }
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300631 }
632 return 0;
633}
634
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300635static int dib7000m_set_agc_config(struct dib7000m_state *state, u8 band)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300636{
637 struct dibx000_agc_config *agc = NULL;
638 int i;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300639 if (state->current_band == band && state->current_agc != NULL)
640 return 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300641 state->current_band = band;
642
643 for (i = 0; i < state->cfg.agc_config_count; i++)
644 if (state->cfg.agc[i].band_caps & band) {
645 agc = &state->cfg.agc[i];
646 break;
647 }
648
649 if (agc == NULL) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300650 dprintk( "no valid AGC configuration found for band 0x%02x",band);
651 return -EINVAL;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300652 }
653
654 state->current_agc = agc;
655
656 /* AGC */
657 dib7000m_write_word(state, 72 , agc->setup);
658 dib7000m_write_word(state, 73 , agc->inv_gain);
659 dib7000m_write_word(state, 74 , agc->time_stabiliz);
660 dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock);
661
662 // Demod AGC loop configuration
663 dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp);
664 dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp);
665
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300666 dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d",
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300667 state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
668
669 /* AGC continued */
670 if (state->wbd_ref != 0)
671 dib7000m_write_word(state, 102, state->wbd_ref);
672 else // use default
673 dib7000m_write_word(state, 102, agc->wbd_ref);
674
675 dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) );
676 dib7000m_write_word(state, 104, agc->agc1_max);
677 dib7000m_write_word(state, 105, agc->agc1_min);
678 dib7000m_write_word(state, 106, agc->agc2_max);
679 dib7000m_write_word(state, 107, agc->agc2_min);
680 dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 );
681 dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
682 dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
683 dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
684
685 if (state->revision > 0x4000) { // settings for the MC
686 dib7000m_write_word(state, 71, agc->agc1_pt3);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300687// dprintk( "929: %x %d %d",
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300688// (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel);
689 dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2));
690 } else {
691 // wrong default values
692 u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 };
693 for (i = 0; i < 9; i++)
694 dib7000m_write_word(state, 88 + i, b[i]);
695 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300696 return 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300697}
698
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300699static void dib7000m_update_timf(struct dib7000m_state *state)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300700{
701 u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300702 state->timf = timf * 160 / (state->current_bandwidth / 50);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300703 dib7000m_write_word(state, 23, (u16) (timf >> 16));
704 dib7000m_write_word(state, 24, (u16) (timf & 0xffff));
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300705 dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->timf_default);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300706}
707
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300708static int dib7000m_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
709{
710 struct dib7000m_state *state = demod->demodulator_priv;
711 u16 cfg_72 = dib7000m_read_word(state, 72);
712 int ret = -1;
713 u8 *agc_state = &state->agc_state;
714 u8 agc_split;
715
716 switch (state->agc_state) {
717 case 0:
718 // set power-up level: interf+analog+AGC
719 dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC);
720 dib7000m_set_adc_state(state, DIBX000_ADC_ON);
721
722 if (dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0)
723 return -1;
724
725 ret = 7; /* ADC power up */
726 (*agc_state)++;
727 break;
728
729 case 1:
730 /* AGC initialization */
731 if (state->cfg.agc_control)
732 state->cfg.agc_control(&state->demod, 1);
733
734 dib7000m_write_word(state, 75, 32768);
735 if (!state->current_agc->perform_agc_softsplit) {
736 /* we are using the wbd - so slow AGC startup */
737 dib7000m_write_word(state, 103, 1 << 8); /* force 0 split on WBD and restart AGC */
738 (*agc_state)++;
739 ret = 5;
740 } else {
741 /* default AGC startup */
742 (*agc_state) = 4;
743 /* wait AGC rough lock time */
744 ret = 7;
745 }
746
747 dib7000m_restart_agc(state);
748 break;
749
750 case 2: /* fast split search path after 5sec */
751 dib7000m_write_word(state, 72, cfg_72 | (1 << 4)); /* freeze AGC loop */
752 dib7000m_write_word(state, 103, 2 << 9); /* fast split search 0.25kHz */
753 (*agc_state)++;
754 ret = 14;
755 break;
756
757 case 3: /* split search ended */
Patrick Boettcher01373a52007-07-30 12:49:04 -0300758 agc_split = (u8)dib7000m_read_word(state, 392); /* store the split value for the next time */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300759 dib7000m_write_word(state, 75, dib7000m_read_word(state, 390)); /* set AGC gain start value */
760
761 dib7000m_write_word(state, 72, cfg_72 & ~(1 << 4)); /* std AGC loop */
762 dib7000m_write_word(state, 103, (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
763
764 dib7000m_restart_agc(state);
765
766 dprintk( "SPLIT %p: %hd", demod, agc_split);
767
768 (*agc_state)++;
769 ret = 5;
770 break;
771
772 case 4: /* LNA startup */
773 /* wait AGC accurate lock time */
774 ret = 7;
775
776 if (dib7000m_update_lna(state))
777 // wait only AGC rough lock time
778 ret = 5;
779 else
780 (*agc_state)++;
781 break;
782
783 case 5:
784 dib7000m_agc_soft_split(state);
785
786 if (state->cfg.agc_control)
787 state->cfg.agc_control(&state->demod, 0);
788
789 (*agc_state)++;
790 break;
791
792 default:
793 break;
794 }
795 return ret;
796}
797
798static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_frontend_parameters *ch, u8 seq)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300799{
800 u16 value, est[4];
801
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300802 dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300803
804 /* nfft, guard, qam, alpha */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300805 value = 0;
806 switch (ch->u.ofdm.transmission_mode) {
807 case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
Mauro Carvalho Chehab2e94b532010-12-27 11:55:07 -0300808 case TRANSMISSION_MODE_4K: value |= (2 << 7); break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300809 default:
810 case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
811 }
812 switch (ch->u.ofdm.guard_interval) {
813 case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
814 case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
815 case GUARD_INTERVAL_1_4: value |= (3 << 5); break;
816 default:
817 case GUARD_INTERVAL_1_8: value |= (2 << 5); break;
818 }
819 switch (ch->u.ofdm.constellation) {
820 case QPSK: value |= (0 << 3); break;
821 case QAM_16: value |= (1 << 3); break;
822 default:
823 case QAM_64: value |= (2 << 3); break;
824 }
825 switch (HIERARCHY_1) {
826 case HIERARCHY_2: value |= 2; break;
827 case HIERARCHY_4: value |= 4; break;
828 default:
829 case HIERARCHY_1: value |= 1; break;
830 }
831 dib7000m_write_word(state, 0, value);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300832 dib7000m_write_word(state, 5, (seq << 4));
833
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300834 /* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
835 value = 0;
836 if (1 != 0)
837 value |= (1 << 6);
838 if (ch->u.ofdm.hierarchy_information == 1)
839 value |= (1 << 4);
840 if (1 == 1)
841 value |= 1;
842 switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
843 case FEC_2_3: value |= (2 << 1); break;
844 case FEC_3_4: value |= (3 << 1); break;
845 case FEC_5_6: value |= (5 << 1); break;
846 case FEC_7_8: value |= (7 << 1); break;
847 default:
848 case FEC_1_2: value |= (1 << 1); break;
849 }
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300850 dib7000m_write_word(state, 267 + state->reg_offs, value);
851
852 /* offset loop parameters */
853
854 /* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */
855 dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80);
856
857 /* 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 */
858 dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3));
859
860 /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */
861 dib7000m_write_word(state, 32, (0 << 4) | 0x3);
862
863 /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */
864 dib7000m_write_word(state, 33, (0 << 4) | 0x5);
865
866 /* P_dvsy_sync_wait */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300867 switch (ch->u.ofdm.transmission_mode) {
868 case TRANSMISSION_MODE_8K: value = 256; break;
Mauro Carvalho Chehab2e94b532010-12-27 11:55:07 -0300869 case TRANSMISSION_MODE_4K: value = 128; break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300870 case TRANSMISSION_MODE_2K:
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300871 default: value = 64; break;
872 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300873 switch (ch->u.ofdm.guard_interval) {
874 case GUARD_INTERVAL_1_16: value *= 2; break;
875 case GUARD_INTERVAL_1_8: value *= 4; break;
876 case GUARD_INTERVAL_1_4: value *= 8; break;
877 default:
878 case GUARD_INTERVAL_1_32: value *= 1; break;
879 }
880 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 -0300881
882 /* deactive the possibility of diversity reception if extended interleave - not for 7000MC */
883 /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300884 if (1 == 1 || state->revision > 0x4000)
885 state->div_force_off = 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300886 else
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300887 state->div_force_off = 1;
888 dib7000m_set_diversity_in(&state->demod, state->div_state);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300889
890 /* channel estimation fine configuration */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300891 switch (ch->u.ofdm.constellation) {
892 case QAM_64:
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300893 est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
894 est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
895 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
896 est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */
897 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300898 case QAM_16:
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300899 est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */
900 est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */
901 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
902 est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */
903 break;
904 default:
905 est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */
906 est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */
907 est[2] = 0x0333; /* P_adp_regul_ext 0.1 */
908 est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */
909 break;
910 }
911 for (value = 0; value < 4; value++)
912 dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]);
913
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300914 // set power-up level: autosearch
915 dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD);
916}
917
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300918static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300919{
920 struct dib7000m_state *state = demod->demodulator_priv;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300921 struct dvb_frontend_parameters schan;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300922 int ret = 0;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300923 u32 value, factor;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300924
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300925 schan = *ch;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300926
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300927 schan.u.ofdm.constellation = QAM_64;
928 schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
929 schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
930 schan.u.ofdm.code_rate_HP = FEC_2_3;
931 schan.u.ofdm.code_rate_LP = FEC_3_4;
932 schan.u.ofdm.hierarchy_information = 0;
933
934 dib7000m_set_channel(state, &schan, 7);
935
936 factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth);
937 if (factor >= 5000)
938 factor = 1;
939 else
940 factor = 6;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300941
942 // always use the setting for 8MHz here lock_time for 7,6 MHz are longer
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300943 value = 30 * state->internal_clk * factor;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300944 ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time
945 ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300946 value = 100 * state->internal_clk * factor;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300947 ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time
948 ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300949 value = 500 * state->internal_clk * factor;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300950 ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
951 ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time
952
953 // start search
954 value = dib7000m_read_word(state, 0);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300955 ret |= dib7000m_write_word(state, 0, (u16) (value | (1 << 9)));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300956
957 /* clear n_irq_pending */
958 if (state->revision == 0x4000)
959 dib7000m_write_word(state, 1793, 0);
960 else
961 dib7000m_read_word(state, 537);
962
963 ret |= dib7000m_write_word(state, 0, (u16) value);
964
965 return ret;
966}
967
968static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg)
969{
970 u16 irq_pending = dib7000m_read_word(state, reg);
971
972 if (irq_pending & 0x1) { // failed
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300973 dprintk( "autosearch failed");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300974 return 1;
975 }
976
977 if (irq_pending & 0x2) { // succeeded
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300978 dprintk( "autosearch succeeded");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300979 return 2;
980 }
981 return 0; // still pending
982}
983
984static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod)
985{
986 struct dib7000m_state *state = demod->demodulator_priv;
987 if (state->revision == 0x4000)
988 return dib7000m_autosearch_irq(state, 1793);
989 else
990 return dib7000m_autosearch_irq(state, 537);
991}
992
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300993static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300994{
995 struct dib7000m_state *state = demod->demodulator_priv;
996 int ret = 0;
997 u16 value;
998
999 // we are already tuned - just resuming from suspend
1000 if (ch != NULL)
1001 dib7000m_set_channel(state, ch, 0);
1002 else
1003 return -EINVAL;
1004
1005 // restart demod
1006 ret |= dib7000m_write_word(state, 898, 0x4000);
1007 ret |= dib7000m_write_word(state, 898, 0x0000);
1008 msleep(45);
1009
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001010 dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001011 /* 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 */
1012 ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3));
1013
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001014 // never achieved a lock before - wait for timfreq to update
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001015 if (state->timf == 0)
1016 msleep(200);
1017
1018 //dump_reg(state);
1019 /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
1020 value = (6 << 8) | 0x80;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001021 switch (ch->u.ofdm.transmission_mode) {
1022 case TRANSMISSION_MODE_2K: value |= (7 << 12); break;
Mauro Carvalho Chehab2e94b532010-12-27 11:55:07 -03001023 case TRANSMISSION_MODE_4K: value |= (8 << 12); break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001024 default:
1025 case TRANSMISSION_MODE_8K: value |= (9 << 12); break;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001026 }
1027 ret |= dib7000m_write_word(state, 26, value);
1028
1029 /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
1030 value = (0 << 4);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001031 switch (ch->u.ofdm.transmission_mode) {
1032 case TRANSMISSION_MODE_2K: value |= 0x6; break;
Mauro Carvalho Chehab2e94b532010-12-27 11:55:07 -03001033 case TRANSMISSION_MODE_4K: value |= 0x7; break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001034 default:
1035 case TRANSMISSION_MODE_8K: value |= 0x8; break;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001036 }
1037 ret |= dib7000m_write_word(state, 32, value);
1038
1039 /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
1040 value = (0 << 4);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001041 switch (ch->u.ofdm.transmission_mode) {
1042 case TRANSMISSION_MODE_2K: value |= 0x6; break;
Mauro Carvalho Chehab2e94b532010-12-27 11:55:07 -03001043 case TRANSMISSION_MODE_4K: value |= 0x7; break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001044 default:
1045 case TRANSMISSION_MODE_8K: value |= 0x8; break;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001046 }
1047 ret |= dib7000m_write_word(state, 33, value);
1048
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001049 // we achieved a lock - it's time to update the timf freq
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001050 if ((dib7000m_read_word(state, 535) >> 6) & 0x1)
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001051 dib7000m_update_timf(state);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001052
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001053 dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001054 return ret;
1055}
1056
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001057static int dib7000m_wakeup(struct dvb_frontend *demod)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001058{
1059 struct dib7000m_state *state = demod->demodulator_priv;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001060
1061 dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
1062
1063 if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001064 dprintk( "could not start Slow ADC");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001065
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001066 return 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001067}
1068
1069static int dib7000m_sleep(struct dvb_frontend *demod)
1070{
1071 struct dib7000m_state *st = demod->demodulator_priv;
1072 dib7000m_set_output_mode(st, OUTMODE_HIGH_Z);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001073 dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY);
1074 return dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) |
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001075 dib7000m_set_adc_state(st, DIBX000_ADC_OFF);
1076}
1077
1078static int dib7000m_identify(struct dib7000m_state *state)
1079{
1080 u16 value;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001081
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001082 if ((value = dib7000m_read_word(state, 896)) != 0x01b3) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001083 dprintk( "wrong Vendor ID (0x%x)",value);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001084 return -EREMOTEIO;
1085 }
1086
1087 state->revision = dib7000m_read_word(state, 897);
1088 if (state->revision != 0x4000 &&
1089 state->revision != 0x4001 &&
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001090 state->revision != 0x4002 &&
1091 state->revision != 0x4003) {
1092 dprintk( "wrong Device ID (0x%x)",value);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001093 return -EREMOTEIO;
1094 }
1095
1096 /* protect this driver to be used with 7000PC */
1097 if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001098 dprintk( "this driver does not work with DiB7000PC");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001099 return -EREMOTEIO;
1100 }
1101
1102 switch (state->revision) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001103 case 0x4000: dprintk( "found DiB7000MA/PA/MB/PB"); break;
1104 case 0x4001: state->reg_offs = 1; dprintk( "found DiB7000HC"); break;
1105 case 0x4002: state->reg_offs = 1; dprintk( "found DiB7000MC"); break;
1106 case 0x4003: state->reg_offs = 1; dprintk( "found DiB9000"); break;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001107 }
1108
1109 return 0;
1110}
1111
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001112
1113static int dib7000m_get_frontend(struct dvb_frontend* fe,
1114 struct dvb_frontend_parameters *fep)
1115{
1116 struct dib7000m_state *state = fe->demodulator_priv;
1117 u16 tps = dib7000m_read_word(state,480);
1118
1119 fep->inversion = INVERSION_AUTO;
1120
1121 fep->u.ofdm.bandwidth = state->current_bandwidth;
1122
Patrick Boettcherd92532d2006-10-18 08:35:16 -03001123 switch ((tps >> 8) & 0x3) {
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001124 case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
1125 case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
1126 /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
1127 }
1128
1129 switch (tps & 0x3) {
1130 case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
1131 case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
1132 case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
1133 case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
1134 }
1135
1136 switch ((tps >> 14) & 0x3) {
1137 case 0: fep->u.ofdm.constellation = QPSK; break;
1138 case 1: fep->u.ofdm.constellation = QAM_16; break;
1139 case 2:
1140 default: fep->u.ofdm.constellation = QAM_64; break;
1141 }
1142
1143 /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
1144 /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
1145
1146 fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
1147 switch ((tps >> 5) & 0x7) {
1148 case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
1149 case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
1150 case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
1151 case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
1152 case 7:
1153 default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
1154
1155 }
1156
1157 switch ((tps >> 2) & 0x7) {
1158 case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
1159 case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
1160 case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
1161 case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
1162 case 7:
1163 default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
1164 }
1165
1166 /* native interleaver: (dib7000m_read_word(state, 481) >> 5) & 0x1 */
1167
1168 return 0;
1169}
1170
1171static int dib7000m_set_frontend(struct dvb_frontend* fe,
1172 struct dvb_frontend_parameters *fep)
1173{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001174 struct dib7000m_state *state = fe->demodulator_priv;
Soeren Moch853ea132008-01-25 06:27:06 -03001175 int time, ret;
1176
1177 dib7000m_set_output_mode(state, OUTMODE_HIGH_Z);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001178
1179 state->current_bandwidth = fep->u.ofdm.bandwidth;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001180 dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001181
1182 if (fe->ops.tuner_ops.set_params)
1183 fe->ops.tuner_ops.set_params(fe, fep);
1184
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001185 /* start up the AGC */
1186 state->agc_state = 0;
1187 do {
1188 time = dib7000m_agc_startup(fe, fep);
1189 if (time != -1)
1190 msleep(time);
1191 } while (time != -1);
1192
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001193 if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
1194 fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
1195 fep->u.ofdm.constellation == QAM_AUTO ||
1196 fep->u.ofdm.code_rate_HP == FEC_AUTO) {
1197 int i = 800, found;
1198
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001199 dib7000m_autosearch_start(fe, fep);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001200 do {
1201 msleep(1);
1202 found = dib7000m_autosearch_is_irq(fe);
1203 } while (found == 0 && i--);
1204
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001205 dprintk("autosearch returns: %d",found);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001206 if (found == 0 || found == 1)
1207 return 0; // no channel found
1208
1209 dib7000m_get_frontend(fe, fep);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001210 }
1211
Soeren Moch853ea132008-01-25 06:27:06 -03001212 ret = dib7000m_tune(fe, fep);
1213
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001214 /* make this a config parameter */
1215 dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO);
Soeren Moch853ea132008-01-25 06:27:06 -03001216 return ret;
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001217}
1218
1219static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat)
1220{
1221 struct dib7000m_state *state = fe->demodulator_priv;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001222 u16 lock = dib7000m_read_word(state, 535);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001223
1224 *stat = 0;
1225
1226 if (lock & 0x8000)
1227 *stat |= FE_HAS_SIGNAL;
1228 if (lock & 0x3000)
1229 *stat |= FE_HAS_CARRIER;
1230 if (lock & 0x0100)
1231 *stat |= FE_HAS_VITERBI;
1232 if (lock & 0x0010)
1233 *stat |= FE_HAS_SYNC;
1234 if (lock & 0x0008)
1235 *stat |= FE_HAS_LOCK;
1236
1237 return 0;
1238}
1239
1240static int dib7000m_read_ber(struct dvb_frontend *fe, u32 *ber)
1241{
1242 struct dib7000m_state *state = fe->demodulator_priv;
1243 *ber = (dib7000m_read_word(state, 526) << 16) | dib7000m_read_word(state, 527);
1244 return 0;
1245}
1246
1247static int dib7000m_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
1248{
1249 struct dib7000m_state *state = fe->demodulator_priv;
1250 *unc = dib7000m_read_word(state, 534);
1251 return 0;
1252}
1253
1254static int dib7000m_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
1255{
1256 struct dib7000m_state *state = fe->demodulator_priv;
1257 u16 val = dib7000m_read_word(state, 390);
1258 *strength = 65535 - val;
1259 return 0;
1260}
1261
1262static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr)
1263{
1264 *snr = 0x0000;
1265 return 0;
1266}
1267
1268static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
1269{
1270 tune->min_delay_ms = 1000;
1271 return 0;
1272}
1273
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001274static void dib7000m_release(struct dvb_frontend *demod)
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001275{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001276 struct dib7000m_state *st = demod->demodulator_priv;
1277 dibx000_exit_i2c_master(&st->i2c_master);
1278 kfree(st);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001279}
1280
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001281struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001282{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001283 struct dib7000m_state *st = demod->demodulator_priv;
1284 return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
1285}
1286EXPORT_SYMBOL(dib7000m_get_i2c_master);
1287
Hans Verkuil942648a2008-09-07 08:38:50 -03001288#if 0
1289/* used with some prototype boards */
1290int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods,
Hans Verkuild45b9b82008-09-04 03:33:43 -03001291 u8 default_addr, struct dib7000m_config cfg[])
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001292{
1293 struct dib7000m_state st = { .i2c_adap = i2c };
1294 int k = 0;
1295 u8 new_addr = 0;
1296
1297 for (k = no_of_demods-1; k >= 0; k--) {
1298 st.cfg = cfg[k];
1299
1300 /* designated i2c address */
1301 new_addr = (0x40 + k) << 1;
1302 st.i2c_addr = new_addr;
1303 if (dib7000m_identify(&st) != 0) {
1304 st.i2c_addr = default_addr;
1305 if (dib7000m_identify(&st) != 0) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001306 dprintk("DiB7000M #%d: not identified", k);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001307 return -EIO;
1308 }
1309 }
1310
1311 /* start diversity to pull_down div_str - just for i2c-enumeration */
1312 dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY);
1313
1314 dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output
1315
1316 /* set new i2c address and force divstart */
1317 dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2);
1318
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001319 dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001320 }
1321
1322 for (k = 0; k < no_of_demods; k++) {
1323 st.cfg = cfg[k];
1324 st.i2c_addr = (0x40 + k) << 1;
1325
1326 // unforce divstr
1327 dib7000m_write_word(&st,1794, st.i2c_addr << 2);
1328
1329 /* deactivate div - it was just for i2c-enumeration */
1330 dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z);
1331 }
1332
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001333 return 0;
1334}
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001335EXPORT_SYMBOL(dib7000m_i2c_enumeration);
Hans Verkuil942648a2008-09-07 08:38:50 -03001336#endif
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001337
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001338static struct dvb_frontend_ops dib7000m_ops;
1339struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg)
1340{
1341 struct dvb_frontend *demod;
1342 struct dib7000m_state *st;
1343 st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL);
1344 if (st == NULL)
1345 return NULL;
1346
1347 memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config));
1348 st->i2c_adap = i2c_adap;
1349 st->i2c_addr = i2c_addr;
1350
1351 demod = &st->demod;
1352 demod->demodulator_priv = st;
1353 memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops));
1354
Patrick Boettcher3db78e52007-07-31 08:19:28 -03001355 st->timf_default = cfg->bw->timf;
1356
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001357 if (dib7000m_identify(st) != 0)
1358 goto error;
1359
1360 if (st->revision == 0x4000)
1361 dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr);
1362 else
1363 dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr);
1364
1365 dib7000m_demod_reset(st);
1366
1367 return demod;
1368
1369error:
1370 kfree(st);
1371 return NULL;
1372}
1373EXPORT_SYMBOL(dib7000m_attach);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001374
1375static struct dvb_frontend_ops dib7000m_ops = {
1376 .info = {
1377 .name = "DiBcom 7000MA/MB/PA/PB/MC",
1378 .type = FE_OFDM,
1379 .frequency_min = 44250000,
1380 .frequency_max = 867250000,
1381 .frequency_stepsize = 62500,
1382 .caps = FE_CAN_INVERSION_AUTO |
1383 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1384 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1385 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
1386 FE_CAN_TRANSMISSION_MODE_AUTO |
1387 FE_CAN_GUARD_INTERVAL_AUTO |
1388 FE_CAN_RECOVER |
1389 FE_CAN_HIERARCHY_AUTO,
1390 },
1391
1392 .release = dib7000m_release,
1393
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001394 .init = dib7000m_wakeup,
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001395 .sleep = dib7000m_sleep,
1396
1397 .set_frontend = dib7000m_set_frontend,
1398 .get_tune_settings = dib7000m_fe_get_tune_settings,
1399 .get_frontend = dib7000m_get_frontend,
1400
1401 .read_status = dib7000m_read_status,
1402 .read_ber = dib7000m_read_ber,
1403 .read_signal_strength = dib7000m_read_signal_strength,
1404 .read_snr = dib7000m_read_snr,
1405 .read_ucblocks = dib7000m_read_unc_blocks,
1406};
1407
1408MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
1409MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator");
1410MODULE_LICENSE("GPL");