blob: 79cb1c20df24e7aece91b3f7e900efb7e13d1c57 [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;
Olivier Grenie5a0deee2011-05-03 12:27:33 -030053
54 /* for the I2C transfer */
55 struct i2c_msg msg[2];
56 u8 i2c_write_buffer[4];
57 u8 i2c_read_buffer[2];
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020058};
59
Patrick Boettcher69ea31e2006-10-17 18:28:14 -030060enum dib7000m_power_mode {
61 DIB7000M_POWER_ALL = 0,
62
63 DIB7000M_POWER_NO,
64 DIB7000M_POWER_INTERF_ANALOG_AGC,
65 DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD,
66 DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD,
67 DIB7000M_POWER_INTERFACE_ONLY,
68};
69
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020070static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
71{
Olivier Grenie5a0deee2011-05-03 12:27:33 -030072 state->i2c_write_buffer[0] = (reg >> 8) | 0x80;
73 state->i2c_write_buffer[1] = reg & 0xff;
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020074
Olivier Grenie5a0deee2011-05-03 12:27:33 -030075 memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
76 state->msg[0].addr = state->i2c_addr >> 1;
77 state->msg[0].flags = 0;
78 state->msg[0].buf = state->i2c_write_buffer;
79 state->msg[0].len = 2;
80 state->msg[1].addr = state->i2c_addr >> 1;
81 state->msg[1].flags = I2C_M_RD;
82 state->msg[1].buf = state->i2c_read_buffer;
83 state->msg[1].len = 2;
84
85 if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
Patrick Boettcherb6884a12007-07-27 10:08:51 -030086 dprintk("i2c read error on %d",reg);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020087
Olivier Grenie5a0deee2011-05-03 12:27:33 -030088 return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020089}
90
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020091static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
92{
Olivier Grenie5a0deee2011-05-03 12:27:33 -030093 state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
94 state->i2c_write_buffer[1] = reg & 0xff;
95 state->i2c_write_buffer[2] = (val >> 8) & 0xff;
96 state->i2c_write_buffer[3] = val & 0xff;
97
98 memset(&state->msg[0], 0, sizeof(struct i2c_msg));
99 state->msg[0].addr = state->i2c_addr >> 1;
100 state->msg[0].flags = 0;
101 state->msg[0].buf = state->i2c_write_buffer;
102 state->msg[0].len = 4;
103
104 return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
Patrick Boettcher91bb9be2006-12-02 21:15:51 -0200105}
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300106static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
107{
108 u16 l = 0, r, *n;
109 n = buf;
110 l = *n++;
111 while (l) {
112 r = *n++;
113
114 if (state->reg_offs && (r >= 112 && r <= 331)) // compensate for 7000MC
115 r++;
116
117 do {
118 dib7000m_write_word(state, r, *n++);
119 r++;
120 } while (--l);
121 l = *n++;
122 }
123}
124
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300125static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode)
126{
127 int ret = 0;
128 u16 outreg, fifo_threshold, smo_mode,
129 sram = 0x0005; /* by default SRAM output is disabled */
130
131 outreg = 0;
132 fifo_threshold = 1792;
133 smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1);
134
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300135 dprintk( "setting output mode for demod %p to %d", &state->demod, mode);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300136
137 switch (mode) {
138 case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock
139 outreg = (1 << 10); /* 0x0400 */
140 break;
141 case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock
142 outreg = (1 << 10) | (1 << 6); /* 0x0440 */
143 break;
144 case OUTMODE_MPEG2_SERIAL: // STBs with serial input
145 outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */
146 break;
147 case OUTMODE_DIVERSITY:
148 if (state->cfg.hostbus_diversity)
149 outreg = (1 << 10) | (4 << 6); /* 0x0500 */
150 else
151 sram |= 0x0c00;
152 break;
153 case OUTMODE_MPEG2_FIFO: // e.g. USB feeding
154 smo_mode |= (3 << 1);
155 fifo_threshold = 512;
156 outreg = (1 << 10) | (5 << 6);
157 break;
158 case OUTMODE_HIGH_Z: // disable
159 outreg = 0;
160 break;
161 default:
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300162 dprintk( "Unhandled output_mode passed to be set for demod %p",&state->demod);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300163 break;
164 }
165
166 if (state->cfg.output_mpeg2_in_188_bytes)
167 smo_mode |= (1 << 5) ;
168
169 ret |= dib7000m_write_word(state, 294 + state->reg_offs, smo_mode);
170 ret |= dib7000m_write_word(state, 295 + state->reg_offs, fifo_threshold); /* synchronous fread */
171 ret |= dib7000m_write_word(state, 1795, outreg);
172 ret |= dib7000m_write_word(state, 1805, sram);
173
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300174 if (state->revision == 0x4003) {
175 u16 clk_cfg1 = dib7000m_read_word(state, 909) & 0xfffd;
176 if (mode == OUTMODE_DIVERSITY)
177 clk_cfg1 |= (1 << 1); // P_O_CLK_en
178 dib7000m_write_word(state, 909, clk_cfg1);
179 }
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300180 return ret;
181}
182
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300183static void dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300184{
185 /* by default everything is going to be powered off */
186 u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906 = 0x3fff;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300187 u8 offset = 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300188
189 /* now, depending on the requested mode, we power on */
190 switch (mode) {
191 /* power up everything in the demod */
192 case DIB7000M_POWER_ALL:
193 reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000;
194 break;
195
196 /* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */
197 case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */
198 reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2));
199 break;
200
201 case DIB7000M_POWER_INTERF_ANALOG_AGC:
202 reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10));
203 reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2));
204 reg_906 &= ~((1 << 0));
205 break;
206
207 case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD:
208 reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000;
209 break;
210
211 case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD:
212 reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000;
213 break;
214 case DIB7000M_POWER_NO:
215 break;
216 }
217
218 /* always power down unused parts */
219 if (!state->cfg.mobile_mode)
220 reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1);
221
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300222 /* P_sdio_select_clk = 0 on MC and after*/
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300223 if (state->revision != 0x4000)
224 reg_906 <<= 1;
225
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300226 if (state->revision == 0x4003)
227 offset = 1;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300228
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300229 dib7000m_write_word(state, 903 + offset, reg_903);
230 dib7000m_write_word(state, 904 + offset, reg_904);
231 dib7000m_write_word(state, 905 + offset, reg_905);
232 dib7000m_write_word(state, 906 + offset, reg_906);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300233}
234
235static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no)
236{
237 int ret = 0;
238 u16 reg_913 = dib7000m_read_word(state, 913),
239 reg_914 = dib7000m_read_word(state, 914);
240
241 switch (no) {
242 case DIBX000_SLOW_ADC_ON:
243 reg_914 |= (1 << 1) | (1 << 0);
244 ret |= dib7000m_write_word(state, 914, reg_914);
245 reg_914 &= ~(1 << 1);
246 break;
247
248 case DIBX000_SLOW_ADC_OFF:
249 reg_914 |= (1 << 1) | (1 << 0);
250 break;
251
252 case DIBX000_ADC_ON:
253 if (state->revision == 0x4000) { // workaround for PA/MA
254 // power-up ADC
255 dib7000m_write_word(state, 913, 0);
256 dib7000m_write_word(state, 914, reg_914 & 0x3);
257 // power-down bandgag
258 dib7000m_write_word(state, 913, (1 << 15));
259 dib7000m_write_word(state, 914, reg_914 & 0x3);
260 }
261
262 reg_913 &= 0x0fff;
263 reg_914 &= 0x0003;
264 break;
265
266 case DIBX000_ADC_OFF: // leave the VBG voltage on
267 reg_913 |= (1 << 14) | (1 << 13) | (1 << 12);
268 reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
269 break;
270
271 case DIBX000_VBG_ENABLE:
272 reg_913 &= ~(1 << 15);
273 break;
274
275 case DIBX000_VBG_DISABLE:
276 reg_913 |= (1 << 15);
277 break;
278
279 default:
280 break;
281 }
282
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300283// dprintk( "913: %x, 914: %x", reg_913, reg_914);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300284 ret |= dib7000m_write_word(state, 913, reg_913);
285 ret |= dib7000m_write_word(state, 914, reg_914);
286
287 return ret;
288}
289
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300290static int dib7000m_set_bandwidth(struct dib7000m_state *state, u32 bw)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300291{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300292 u32 timf;
293
294 // store the current bandwidth for later use
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300295 state->current_bandwidth = bw;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300296
297 if (state->timf == 0) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300298 dprintk( "using default timf");
299 timf = state->timf_default;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300300 } else {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300301 dprintk( "using updated timf");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300302 timf = state->timf;
303 }
304
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300305 timf = timf * (bw / 50) / 160;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300306
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300307 dib7000m_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
308 dib7000m_write_word(state, 24, (u16) ((timf ) & 0xffff));
309
310 return 0;
311}
312
313static int dib7000m_set_diversity_in(struct dvb_frontend *demod, int onoff)
314{
315 struct dib7000m_state *state = demod->demodulator_priv;
316
317 if (state->div_force_off) {
318 dprintk( "diversity combination deactivated - forced by COFDM parameters");
319 onoff = 0;
320 }
Patrick Boettcher01373a52007-07-30 12:49:04 -0300321 state->div_state = (u8)onoff;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300322
323 if (onoff) {
324 dib7000m_write_word(state, 263 + state->reg_offs, 6);
325 dib7000m_write_word(state, 264 + state->reg_offs, 6);
326 dib7000m_write_word(state, 266 + state->reg_offs, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
327 } else {
328 dib7000m_write_word(state, 263 + state->reg_offs, 1);
329 dib7000m_write_word(state, 264 + state->reg_offs, 0);
330 dib7000m_write_word(state, 266 + state->reg_offs, 0);
331 }
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300332
333 return 0;
334}
335
336static int dib7000m_sad_calib(struct dib7000m_state *state)
337{
338
339/* internal */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300340// 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 -0300341 dib7000m_write_word(state, 929, (0 << 1) | (0 << 0));
342 dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096
343
344 /* do the calibration */
345 dib7000m_write_word(state, 929, (1 << 0));
346 dib7000m_write_word(state, 929, (0 << 0));
347
348 msleep(1);
349
350 return 0;
351}
352
353static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw)
354{
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300355 dib7000m_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff));
356 dib7000m_write_word(state, 19, (u16) ( (bw->internal*1000) & 0xffff));
357 dib7000m_write_word(state, 21, (u16) ( (bw->ifreq >> 16) & 0xffff));
358 dib7000m_write_word(state, 22, (u16) ( bw->ifreq & 0xffff));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300359
360 dib7000m_write_word(state, 928, bw->sad_cfg);
361}
362
363static void dib7000m_reset_pll(struct dib7000m_state *state)
364{
365 const struct dibx000_bandwidth_config *bw = state->cfg.bw;
366 u16 reg_907,reg_910;
367
368 /* default */
369 reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) |
370 (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) |
371 (bw->enable_refdiv << 1) | (0 << 0);
372 reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset;
373
374 // for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value)
375 // this is only working only for 30 MHz crystals
376 if (!state->cfg.quartz_direct) {
377 reg_910 |= (1 << 5); // forcing the predivider to 1
378
379 // if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2)
380 if(state->cfg.input_clk_is_div_2)
381 reg_907 |= (16 << 9);
382 else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary
383 reg_907 |= (8 << 9);
384 } else {
385 reg_907 |= (bw->pll_ratio & 0x3f) << 9;
386 reg_910 |= (bw->pll_prediv << 5);
387 }
388
389 dib7000m_write_word(state, 910, reg_910); // pll cfg
390 dib7000m_write_word(state, 907, reg_907); // clk cfg0
391 dib7000m_write_word(state, 908, 0x0006); // clk_cfg1
392
393 dib7000m_reset_pll_common(state, bw);
394}
395
396static void dib7000mc_reset_pll(struct dib7000m_state *state)
397{
398 const struct dibx000_bandwidth_config *bw = state->cfg.bw;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300399 u16 clk_cfg1;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300400
401 // clk_cfg0
402 dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0));
403
404 // clk_cfg1
405 //dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) |
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300406 clk_cfg1 = (0 << 14) | (3 << 12) |(0 << 11) |
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300407 (bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) |
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300408 (1 << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0);
409 dib7000m_write_word(state, 908, clk_cfg1);
410 clk_cfg1 = (clk_cfg1 & 0xfff7) | (bw->pll_bypass << 3);
411 dib7000m_write_word(state, 908, clk_cfg1);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300412
413 // smpl_cfg
414 dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7));
415
416 dib7000m_reset_pll_common(state, bw);
417}
418
419static int dib7000m_reset_gpio(struct dib7000m_state *st)
420{
421 /* reset the GPIOs */
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300422 dib7000m_write_word(st, 773, st->cfg.gpio_dir);
423 dib7000m_write_word(st, 774, st->cfg.gpio_val);
424
425 /* TODO 782 is P_gpio_od */
426
427 dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos);
428
429 dib7000m_write_word(st, 780, st->cfg.pwm_freq_div);
430 return 0;
431}
432
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300433static u16 dib7000m_defaults_common[] =
434
435{
436 // auto search configuration
437 3, 2,
438 0x0004,
439 0x1000,
440 0x0814,
441
442 12, 6,
443 0x001b,
444 0x7740,
445 0x005b,
446 0x8d80,
447 0x01c9,
448 0xc380,
449 0x0000,
450 0x0080,
451 0x0000,
452 0x0090,
453 0x0001,
454 0xd4c0,
455
456 1, 26,
457 0x6680, // P_corm_thres Lock algorithms configuration
458
459 1, 170,
460 0x0410, // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on
461
462 8, 173,
463 0,
464 0,
465 0,
466 0,
467 0,
468 0,
469 0,
470 0,
471
472 1, 182,
473 8192, // P_fft_nb_to_cut
474
475 2, 195,
476 0x0ccd, // P_pha3_thres
477 0, // P_cti_use_cpe, P_cti_use_prog
478
479 1, 205,
480 0x200f, // P_cspu_regul, P_cspu_win_cut
481
482 5, 214,
483 0x023d, // P_adp_regul_cnt
484 0x00a4, // P_adp_noise_cnt
485 0x00a4, // P_adp_regul_ext
486 0x7ff0, // P_adp_noise_ext
487 0x3ccc, // P_adp_fil
488
489 1, 226,
490 0, // P_2d_byp_ti_num
491
492 1, 255,
493 0x800, // P_equal_thres_wgn
494
495 1, 263,
496 0x0001,
497
498 1, 281,
499 0x0010, // P_fec_*
500
501 1, 294,
502 0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
503
504 0
505};
506
507static u16 dib7000m_defaults[] =
508
509{
510 /* set ADC level to -16 */
511 11, 76,
512 (1 << 13) - 825 - 117,
513 (1 << 13) - 837 - 117,
514 (1 << 13) - 811 - 117,
515 (1 << 13) - 766 - 117,
516 (1 << 13) - 737 - 117,
517 (1 << 13) - 693 - 117,
518 (1 << 13) - 648 - 117,
519 (1 << 13) - 619 - 117,
520 (1 << 13) - 575 - 117,
521 (1 << 13) - 531 - 117,
522 (1 << 13) - 501 - 117,
523
524 // Tuner IO bank: max drive (14mA)
525 1, 912,
526 0x2c8a,
527
528 1, 1817,
529 1,
530
531 0,
532};
533
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300534static int dib7000m_demod_reset(struct dib7000m_state *state)
535{
536 dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
537
538 /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
539 dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE);
540
541 /* restart all parts */
542 dib7000m_write_word(state, 898, 0xffff);
543 dib7000m_write_word(state, 899, 0xffff);
544 dib7000m_write_word(state, 900, 0xff0f);
545 dib7000m_write_word(state, 901, 0xfffc);
546
547 dib7000m_write_word(state, 898, 0);
548 dib7000m_write_word(state, 899, 0);
549 dib7000m_write_word(state, 900, 0);
550 dib7000m_write_word(state, 901, 0);
551
552 if (state->revision == 0x4000)
553 dib7000m_reset_pll(state);
554 else
555 dib7000mc_reset_pll(state);
556
557 if (dib7000m_reset_gpio(state) != 0)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300558 dprintk( "GPIO reset was not successful.");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300559
560 if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300561 dprintk( "OUTPUT_MODE could not be reset.");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300562
563 /* unforce divstr regardless whether i2c enumeration was done or not */
564 dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) );
565
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300566 dib7000m_set_bandwidth(state, 8000);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300567
568 dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON);
569 dib7000m_sad_calib(state);
570 dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
571
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300572 if (state->cfg.dvbt_mode)
573 dib7000m_write_word(state, 1796, 0x0); // select DVB-T output
574
575 if (state->cfg.mobile_mode)
576 dib7000m_write_word(state, 261 + state->reg_offs, 2);
577 else
578 dib7000m_write_word(state, 224 + state->reg_offs, 1);
579
580 // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ...
581 if(state->cfg.tuner_is_baseband)
582 dib7000m_write_word(state, 36, 0x0755);
583 else
584 dib7000m_write_word(state, 36, 0x1f55);
585
586 // P_divclksel=3 P_divbitsel=1
587 if (state->revision == 0x4000)
588 dib7000m_write_word(state, 909, (3 << 10) | (1 << 6));
589 else
590 dib7000m_write_word(state, 909, (3 << 4) | 1);
591
592 dib7000m_write_tab(state, dib7000m_defaults_common);
593 dib7000m_write_tab(state, dib7000m_defaults);
594
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300595 dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY);
596
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300597 state->internal_clk = state->cfg.bw->internal;
598
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300599 return 0;
600}
601
602static void dib7000m_restart_agc(struct dib7000m_state *state)
603{
604 // P_restart_iqc & P_restart_agc
605 dib7000m_write_word(state, 898, 0x0c00);
606 dib7000m_write_word(state, 898, 0x0000);
607}
608
609static int dib7000m_agc_soft_split(struct dib7000m_state *state)
610{
611 u16 agc,split_offset;
612
613 if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
614 return 0;
615
616 // n_agc_global
617 agc = dib7000m_read_word(state, 390);
618
619 if (agc > state->current_agc->split.min_thres)
620 split_offset = state->current_agc->split.min;
621 else if (agc < state->current_agc->split.max_thres)
622 split_offset = state->current_agc->split.max;
623 else
624 split_offset = state->current_agc->split.max *
625 (agc - state->current_agc->split.min_thres) /
626 (state->current_agc->split.max_thres - state->current_agc->split.min_thres);
627
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300628 dprintk( "AGC split_offset: %d",split_offset);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300629
630 // P_agc_force_split and P_agc_split_offset
631 return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset);
632}
633
634static int dib7000m_update_lna(struct dib7000m_state *state)
635{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300636 u16 dyn_gain;
637
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300638 if (state->cfg.update_lna) {
Patrick Boettcher01373a52007-07-30 12:49:04 -0300639 // read dyn_gain here (because it is demod-dependent and not fe)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300640 dyn_gain = dib7000m_read_word(state, 390);
641
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300642 if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
643 dib7000m_restart_agc(state);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300644 return 1;
645 }
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300646 }
647 return 0;
648}
649
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300650static int dib7000m_set_agc_config(struct dib7000m_state *state, u8 band)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300651{
652 struct dibx000_agc_config *agc = NULL;
653 int i;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300654 if (state->current_band == band && state->current_agc != NULL)
655 return 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300656 state->current_band = band;
657
658 for (i = 0; i < state->cfg.agc_config_count; i++)
659 if (state->cfg.agc[i].band_caps & band) {
660 agc = &state->cfg.agc[i];
661 break;
662 }
663
664 if (agc == NULL) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300665 dprintk( "no valid AGC configuration found for band 0x%02x",band);
666 return -EINVAL;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300667 }
668
669 state->current_agc = agc;
670
671 /* AGC */
672 dib7000m_write_word(state, 72 , agc->setup);
673 dib7000m_write_word(state, 73 , agc->inv_gain);
674 dib7000m_write_word(state, 74 , agc->time_stabiliz);
675 dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock);
676
677 // Demod AGC loop configuration
678 dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp);
679 dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp);
680
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300681 dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d",
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300682 state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
683
684 /* AGC continued */
685 if (state->wbd_ref != 0)
686 dib7000m_write_word(state, 102, state->wbd_ref);
687 else // use default
688 dib7000m_write_word(state, 102, agc->wbd_ref);
689
690 dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) );
691 dib7000m_write_word(state, 104, agc->agc1_max);
692 dib7000m_write_word(state, 105, agc->agc1_min);
693 dib7000m_write_word(state, 106, agc->agc2_max);
694 dib7000m_write_word(state, 107, agc->agc2_min);
695 dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 );
696 dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
697 dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
698 dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
699
700 if (state->revision > 0x4000) { // settings for the MC
701 dib7000m_write_word(state, 71, agc->agc1_pt3);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300702// dprintk( "929: %x %d %d",
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300703// (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel);
704 dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2));
705 } else {
706 // wrong default values
707 u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 };
708 for (i = 0; i < 9; i++)
709 dib7000m_write_word(state, 88 + i, b[i]);
710 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300711 return 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300712}
713
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300714static void dib7000m_update_timf(struct dib7000m_state *state)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300715{
716 u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300717 state->timf = timf * 160 / (state->current_bandwidth / 50);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300718 dib7000m_write_word(state, 23, (u16) (timf >> 16));
719 dib7000m_write_word(state, 24, (u16) (timf & 0xffff));
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300720 dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->timf_default);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300721}
722
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300723static int dib7000m_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
724{
725 struct dib7000m_state *state = demod->demodulator_priv;
726 u16 cfg_72 = dib7000m_read_word(state, 72);
727 int ret = -1;
728 u8 *agc_state = &state->agc_state;
729 u8 agc_split;
730
731 switch (state->agc_state) {
732 case 0:
733 // set power-up level: interf+analog+AGC
734 dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC);
735 dib7000m_set_adc_state(state, DIBX000_ADC_ON);
736
737 if (dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0)
738 return -1;
739
740 ret = 7; /* ADC power up */
741 (*agc_state)++;
742 break;
743
744 case 1:
745 /* AGC initialization */
746 if (state->cfg.agc_control)
747 state->cfg.agc_control(&state->demod, 1);
748
749 dib7000m_write_word(state, 75, 32768);
750 if (!state->current_agc->perform_agc_softsplit) {
751 /* we are using the wbd - so slow AGC startup */
752 dib7000m_write_word(state, 103, 1 << 8); /* force 0 split on WBD and restart AGC */
753 (*agc_state)++;
754 ret = 5;
755 } else {
756 /* default AGC startup */
757 (*agc_state) = 4;
758 /* wait AGC rough lock time */
759 ret = 7;
760 }
761
762 dib7000m_restart_agc(state);
763 break;
764
765 case 2: /* fast split search path after 5sec */
766 dib7000m_write_word(state, 72, cfg_72 | (1 << 4)); /* freeze AGC loop */
767 dib7000m_write_word(state, 103, 2 << 9); /* fast split search 0.25kHz */
768 (*agc_state)++;
769 ret = 14;
770 break;
771
772 case 3: /* split search ended */
Patrick Boettcher01373a52007-07-30 12:49:04 -0300773 agc_split = (u8)dib7000m_read_word(state, 392); /* store the split value for the next time */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300774 dib7000m_write_word(state, 75, dib7000m_read_word(state, 390)); /* set AGC gain start value */
775
776 dib7000m_write_word(state, 72, cfg_72 & ~(1 << 4)); /* std AGC loop */
777 dib7000m_write_word(state, 103, (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
778
779 dib7000m_restart_agc(state);
780
781 dprintk( "SPLIT %p: %hd", demod, agc_split);
782
783 (*agc_state)++;
784 ret = 5;
785 break;
786
787 case 4: /* LNA startup */
788 /* wait AGC accurate lock time */
789 ret = 7;
790
791 if (dib7000m_update_lna(state))
792 // wait only AGC rough lock time
793 ret = 5;
794 else
795 (*agc_state)++;
796 break;
797
798 case 5:
799 dib7000m_agc_soft_split(state);
800
801 if (state->cfg.agc_control)
802 state->cfg.agc_control(&state->demod, 0);
803
804 (*agc_state)++;
805 break;
806
807 default:
808 break;
809 }
810 return ret;
811}
812
813static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_frontend_parameters *ch, u8 seq)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300814{
815 u16 value, est[4];
816
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300817 dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300818
819 /* nfft, guard, qam, alpha */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300820 value = 0;
821 switch (ch->u.ofdm.transmission_mode) {
822 case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
Mauro Carvalho Chehab2e94b532010-12-27 11:55:07 -0300823 case TRANSMISSION_MODE_4K: value |= (2 << 7); break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300824 default:
825 case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
826 }
827 switch (ch->u.ofdm.guard_interval) {
828 case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
829 case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
830 case GUARD_INTERVAL_1_4: value |= (3 << 5); break;
831 default:
832 case GUARD_INTERVAL_1_8: value |= (2 << 5); break;
833 }
834 switch (ch->u.ofdm.constellation) {
835 case QPSK: value |= (0 << 3); break;
836 case QAM_16: value |= (1 << 3); break;
837 default:
838 case QAM_64: value |= (2 << 3); break;
839 }
840 switch (HIERARCHY_1) {
841 case HIERARCHY_2: value |= 2; break;
842 case HIERARCHY_4: value |= 4; break;
843 default:
844 case HIERARCHY_1: value |= 1; break;
845 }
846 dib7000m_write_word(state, 0, value);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300847 dib7000m_write_word(state, 5, (seq << 4));
848
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300849 /* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
850 value = 0;
851 if (1 != 0)
852 value |= (1 << 6);
853 if (ch->u.ofdm.hierarchy_information == 1)
854 value |= (1 << 4);
855 if (1 == 1)
856 value |= 1;
857 switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
858 case FEC_2_3: value |= (2 << 1); break;
859 case FEC_3_4: value |= (3 << 1); break;
860 case FEC_5_6: value |= (5 << 1); break;
861 case FEC_7_8: value |= (7 << 1); break;
862 default:
863 case FEC_1_2: value |= (1 << 1); break;
864 }
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300865 dib7000m_write_word(state, 267 + state->reg_offs, value);
866
867 /* offset loop parameters */
868
869 /* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */
870 dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80);
871
872 /* 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 */
873 dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3));
874
875 /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */
876 dib7000m_write_word(state, 32, (0 << 4) | 0x3);
877
878 /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */
879 dib7000m_write_word(state, 33, (0 << 4) | 0x5);
880
881 /* P_dvsy_sync_wait */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300882 switch (ch->u.ofdm.transmission_mode) {
883 case TRANSMISSION_MODE_8K: value = 256; break;
Mauro Carvalho Chehab2e94b532010-12-27 11:55:07 -0300884 case TRANSMISSION_MODE_4K: value = 128; break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300885 case TRANSMISSION_MODE_2K:
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300886 default: value = 64; break;
887 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300888 switch (ch->u.ofdm.guard_interval) {
889 case GUARD_INTERVAL_1_16: value *= 2; break;
890 case GUARD_INTERVAL_1_8: value *= 4; break;
891 case GUARD_INTERVAL_1_4: value *= 8; break;
892 default:
893 case GUARD_INTERVAL_1_32: value *= 1; break;
894 }
895 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 -0300896
897 /* deactive the possibility of diversity reception if extended interleave - not for 7000MC */
898 /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300899 if (1 == 1 || state->revision > 0x4000)
900 state->div_force_off = 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300901 else
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300902 state->div_force_off = 1;
903 dib7000m_set_diversity_in(&state->demod, state->div_state);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300904
905 /* channel estimation fine configuration */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300906 switch (ch->u.ofdm.constellation) {
907 case QAM_64:
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300908 est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
909 est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
910 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
911 est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */
912 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300913 case QAM_16:
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300914 est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */
915 est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */
916 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
917 est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */
918 break;
919 default:
920 est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */
921 est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */
922 est[2] = 0x0333; /* P_adp_regul_ext 0.1 */
923 est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */
924 break;
925 }
926 for (value = 0; value < 4; value++)
927 dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]);
928
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300929 // set power-up level: autosearch
930 dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD);
931}
932
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300933static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300934{
935 struct dib7000m_state *state = demod->demodulator_priv;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300936 struct dvb_frontend_parameters schan;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300937 int ret = 0;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300938 u32 value, factor;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300939
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300940 schan = *ch;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300941
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300942 schan.u.ofdm.constellation = QAM_64;
943 schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
944 schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
945 schan.u.ofdm.code_rate_HP = FEC_2_3;
946 schan.u.ofdm.code_rate_LP = FEC_3_4;
947 schan.u.ofdm.hierarchy_information = 0;
948
949 dib7000m_set_channel(state, &schan, 7);
950
951 factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth);
952 if (factor >= 5000)
953 factor = 1;
954 else
955 factor = 6;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300956
957 // always use the setting for 8MHz here lock_time for 7,6 MHz are longer
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300958 value = 30 * state->internal_clk * factor;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300959 ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time
960 ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300961 value = 100 * state->internal_clk * factor;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300962 ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time
963 ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300964 value = 500 * state->internal_clk * factor;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300965 ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
966 ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time
967
968 // start search
969 value = dib7000m_read_word(state, 0);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300970 ret |= dib7000m_write_word(state, 0, (u16) (value | (1 << 9)));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300971
972 /* clear n_irq_pending */
973 if (state->revision == 0x4000)
974 dib7000m_write_word(state, 1793, 0);
975 else
976 dib7000m_read_word(state, 537);
977
978 ret |= dib7000m_write_word(state, 0, (u16) value);
979
980 return ret;
981}
982
983static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg)
984{
985 u16 irq_pending = dib7000m_read_word(state, reg);
986
987 if (irq_pending & 0x1) { // failed
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300988 dprintk( "autosearch failed");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300989 return 1;
990 }
991
992 if (irq_pending & 0x2) { // succeeded
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300993 dprintk( "autosearch succeeded");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300994 return 2;
995 }
996 return 0; // still pending
997}
998
999static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod)
1000{
1001 struct dib7000m_state *state = demod->demodulator_priv;
1002 if (state->revision == 0x4000)
1003 return dib7000m_autosearch_irq(state, 1793);
1004 else
1005 return dib7000m_autosearch_irq(state, 537);
1006}
1007
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001008static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001009{
1010 struct dib7000m_state *state = demod->demodulator_priv;
1011 int ret = 0;
1012 u16 value;
1013
1014 // we are already tuned - just resuming from suspend
1015 if (ch != NULL)
1016 dib7000m_set_channel(state, ch, 0);
1017 else
1018 return -EINVAL;
1019
1020 // restart demod
1021 ret |= dib7000m_write_word(state, 898, 0x4000);
1022 ret |= dib7000m_write_word(state, 898, 0x0000);
1023 msleep(45);
1024
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001025 dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001026 /* 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 */
1027 ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3));
1028
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001029 // never achieved a lock before - wait for timfreq to update
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001030 if (state->timf == 0)
1031 msleep(200);
1032
1033 //dump_reg(state);
1034 /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
1035 value = (6 << 8) | 0x80;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001036 switch (ch->u.ofdm.transmission_mode) {
1037 case TRANSMISSION_MODE_2K: value |= (7 << 12); break;
Mauro Carvalho Chehab2e94b532010-12-27 11:55:07 -03001038 case TRANSMISSION_MODE_4K: value |= (8 << 12); break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001039 default:
1040 case TRANSMISSION_MODE_8K: value |= (9 << 12); break;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001041 }
1042 ret |= dib7000m_write_word(state, 26, value);
1043
1044 /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
1045 value = (0 << 4);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001046 switch (ch->u.ofdm.transmission_mode) {
1047 case TRANSMISSION_MODE_2K: value |= 0x6; break;
Mauro Carvalho Chehab2e94b532010-12-27 11:55:07 -03001048 case TRANSMISSION_MODE_4K: value |= 0x7; break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001049 default:
1050 case TRANSMISSION_MODE_8K: value |= 0x8; break;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001051 }
1052 ret |= dib7000m_write_word(state, 32, value);
1053
1054 /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
1055 value = (0 << 4);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001056 switch (ch->u.ofdm.transmission_mode) {
1057 case TRANSMISSION_MODE_2K: value |= 0x6; break;
Mauro Carvalho Chehab2e94b532010-12-27 11:55:07 -03001058 case TRANSMISSION_MODE_4K: value |= 0x7; break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001059 default:
1060 case TRANSMISSION_MODE_8K: value |= 0x8; break;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001061 }
1062 ret |= dib7000m_write_word(state, 33, value);
1063
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001064 // we achieved a lock - it's time to update the timf freq
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001065 if ((dib7000m_read_word(state, 535) >> 6) & 0x1)
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001066 dib7000m_update_timf(state);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001067
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001068 dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001069 return ret;
1070}
1071
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001072static int dib7000m_wakeup(struct dvb_frontend *demod)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001073{
1074 struct dib7000m_state *state = demod->demodulator_priv;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001075
1076 dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
1077
1078 if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001079 dprintk( "could not start Slow ADC");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001080
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001081 return 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001082}
1083
1084static int dib7000m_sleep(struct dvb_frontend *demod)
1085{
1086 struct dib7000m_state *st = demod->demodulator_priv;
1087 dib7000m_set_output_mode(st, OUTMODE_HIGH_Z);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001088 dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY);
1089 return dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) |
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001090 dib7000m_set_adc_state(st, DIBX000_ADC_OFF);
1091}
1092
1093static int dib7000m_identify(struct dib7000m_state *state)
1094{
1095 u16 value;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001096
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001097 if ((value = dib7000m_read_word(state, 896)) != 0x01b3) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001098 dprintk( "wrong Vendor ID (0x%x)",value);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001099 return -EREMOTEIO;
1100 }
1101
1102 state->revision = dib7000m_read_word(state, 897);
1103 if (state->revision != 0x4000 &&
1104 state->revision != 0x4001 &&
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001105 state->revision != 0x4002 &&
1106 state->revision != 0x4003) {
1107 dprintk( "wrong Device ID (0x%x)",value);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001108 return -EREMOTEIO;
1109 }
1110
1111 /* protect this driver to be used with 7000PC */
1112 if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001113 dprintk( "this driver does not work with DiB7000PC");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001114 return -EREMOTEIO;
1115 }
1116
1117 switch (state->revision) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001118 case 0x4000: dprintk( "found DiB7000MA/PA/MB/PB"); break;
1119 case 0x4001: state->reg_offs = 1; dprintk( "found DiB7000HC"); break;
1120 case 0x4002: state->reg_offs = 1; dprintk( "found DiB7000MC"); break;
1121 case 0x4003: state->reg_offs = 1; dprintk( "found DiB9000"); break;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001122 }
1123
1124 return 0;
1125}
1126
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001127
1128static int dib7000m_get_frontend(struct dvb_frontend* fe,
1129 struct dvb_frontend_parameters *fep)
1130{
1131 struct dib7000m_state *state = fe->demodulator_priv;
1132 u16 tps = dib7000m_read_word(state,480);
1133
1134 fep->inversion = INVERSION_AUTO;
1135
1136 fep->u.ofdm.bandwidth = state->current_bandwidth;
1137
Patrick Boettcherd92532d2006-10-18 08:35:16 -03001138 switch ((tps >> 8) & 0x3) {
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001139 case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
1140 case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
1141 /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
1142 }
1143
1144 switch (tps & 0x3) {
1145 case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
1146 case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
1147 case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
1148 case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
1149 }
1150
1151 switch ((tps >> 14) & 0x3) {
1152 case 0: fep->u.ofdm.constellation = QPSK; break;
1153 case 1: fep->u.ofdm.constellation = QAM_16; break;
1154 case 2:
1155 default: fep->u.ofdm.constellation = QAM_64; break;
1156 }
1157
1158 /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
1159 /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
1160
1161 fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
1162 switch ((tps >> 5) & 0x7) {
1163 case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
1164 case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
1165 case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
1166 case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
1167 case 7:
1168 default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
1169
1170 }
1171
1172 switch ((tps >> 2) & 0x7) {
1173 case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
1174 case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
1175 case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
1176 case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
1177 case 7:
1178 default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
1179 }
1180
1181 /* native interleaver: (dib7000m_read_word(state, 481) >> 5) & 0x1 */
1182
1183 return 0;
1184}
1185
1186static int dib7000m_set_frontend(struct dvb_frontend* fe,
1187 struct dvb_frontend_parameters *fep)
1188{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001189 struct dib7000m_state *state = fe->demodulator_priv;
Soeren Moch853ea132008-01-25 06:27:06 -03001190 int time, ret;
1191
1192 dib7000m_set_output_mode(state, OUTMODE_HIGH_Z);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001193
1194 state->current_bandwidth = fep->u.ofdm.bandwidth;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001195 dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001196
1197 if (fe->ops.tuner_ops.set_params)
1198 fe->ops.tuner_ops.set_params(fe, fep);
1199
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001200 /* start up the AGC */
1201 state->agc_state = 0;
1202 do {
1203 time = dib7000m_agc_startup(fe, fep);
1204 if (time != -1)
1205 msleep(time);
1206 } while (time != -1);
1207
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001208 if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
1209 fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
1210 fep->u.ofdm.constellation == QAM_AUTO ||
1211 fep->u.ofdm.code_rate_HP == FEC_AUTO) {
1212 int i = 800, found;
1213
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001214 dib7000m_autosearch_start(fe, fep);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001215 do {
1216 msleep(1);
1217 found = dib7000m_autosearch_is_irq(fe);
1218 } while (found == 0 && i--);
1219
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001220 dprintk("autosearch returns: %d",found);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001221 if (found == 0 || found == 1)
1222 return 0; // no channel found
1223
1224 dib7000m_get_frontend(fe, fep);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001225 }
1226
Soeren Moch853ea132008-01-25 06:27:06 -03001227 ret = dib7000m_tune(fe, fep);
1228
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001229 /* make this a config parameter */
1230 dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO);
Soeren Moch853ea132008-01-25 06:27:06 -03001231 return ret;
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001232}
1233
1234static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat)
1235{
1236 struct dib7000m_state *state = fe->demodulator_priv;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001237 u16 lock = dib7000m_read_word(state, 535);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001238
1239 *stat = 0;
1240
1241 if (lock & 0x8000)
1242 *stat |= FE_HAS_SIGNAL;
1243 if (lock & 0x3000)
1244 *stat |= FE_HAS_CARRIER;
1245 if (lock & 0x0100)
1246 *stat |= FE_HAS_VITERBI;
1247 if (lock & 0x0010)
1248 *stat |= FE_HAS_SYNC;
1249 if (lock & 0x0008)
1250 *stat |= FE_HAS_LOCK;
1251
1252 return 0;
1253}
1254
1255static int dib7000m_read_ber(struct dvb_frontend *fe, u32 *ber)
1256{
1257 struct dib7000m_state *state = fe->demodulator_priv;
1258 *ber = (dib7000m_read_word(state, 526) << 16) | dib7000m_read_word(state, 527);
1259 return 0;
1260}
1261
1262static int dib7000m_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
1263{
1264 struct dib7000m_state *state = fe->demodulator_priv;
1265 *unc = dib7000m_read_word(state, 534);
1266 return 0;
1267}
1268
1269static int dib7000m_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
1270{
1271 struct dib7000m_state *state = fe->demodulator_priv;
1272 u16 val = dib7000m_read_word(state, 390);
1273 *strength = 65535 - val;
1274 return 0;
1275}
1276
1277static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr)
1278{
1279 *snr = 0x0000;
1280 return 0;
1281}
1282
1283static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
1284{
1285 tune->min_delay_ms = 1000;
1286 return 0;
1287}
1288
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001289static void dib7000m_release(struct dvb_frontend *demod)
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001290{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001291 struct dib7000m_state *st = demod->demodulator_priv;
1292 dibx000_exit_i2c_master(&st->i2c_master);
1293 kfree(st);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001294}
1295
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001296struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001297{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001298 struct dib7000m_state *st = demod->demodulator_priv;
1299 return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
1300}
1301EXPORT_SYMBOL(dib7000m_get_i2c_master);
1302
Olivier Greniee192a7c2011-01-14 13:58:59 -03001303int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
1304{
1305 struct dib7000m_state *state = fe->demodulator_priv;
1306 u16 val = dib7000m_read_word(state, 294 + state->reg_offs) & 0xffef;
1307 val |= (onoff & 0x1) << 4;
1308 dprintk("PID filter enabled %d", onoff);
1309 return dib7000m_write_word(state, 294 + state->reg_offs, val);
1310}
1311EXPORT_SYMBOL(dib7000m_pid_filter_ctrl);
1312
1313int dib7000m_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
1314{
1315 struct dib7000m_state *state = fe->demodulator_priv;
1316 dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
1317 return dib7000m_write_word(state, 300 + state->reg_offs + id,
1318 onoff ? (1 << 13) | pid : 0);
1319}
1320EXPORT_SYMBOL(dib7000m_pid_filter);
1321
Hans Verkuil942648a2008-09-07 08:38:50 -03001322#if 0
1323/* used with some prototype boards */
1324int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods,
Hans Verkuild45b9b82008-09-04 03:33:43 -03001325 u8 default_addr, struct dib7000m_config cfg[])
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001326{
1327 struct dib7000m_state st = { .i2c_adap = i2c };
1328 int k = 0;
1329 u8 new_addr = 0;
1330
1331 for (k = no_of_demods-1; k >= 0; k--) {
1332 st.cfg = cfg[k];
1333
1334 /* designated i2c address */
1335 new_addr = (0x40 + k) << 1;
1336 st.i2c_addr = new_addr;
1337 if (dib7000m_identify(&st) != 0) {
1338 st.i2c_addr = default_addr;
1339 if (dib7000m_identify(&st) != 0) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001340 dprintk("DiB7000M #%d: not identified", k);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001341 return -EIO;
1342 }
1343 }
1344
1345 /* start diversity to pull_down div_str - just for i2c-enumeration */
1346 dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY);
1347
1348 dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output
1349
1350 /* set new i2c address and force divstart */
1351 dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2);
1352
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001353 dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001354 }
1355
1356 for (k = 0; k < no_of_demods; k++) {
1357 st.cfg = cfg[k];
1358 st.i2c_addr = (0x40 + k) << 1;
1359
1360 // unforce divstr
1361 dib7000m_write_word(&st,1794, st.i2c_addr << 2);
1362
1363 /* deactivate div - it was just for i2c-enumeration */
1364 dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z);
1365 }
1366
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001367 return 0;
1368}
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001369EXPORT_SYMBOL(dib7000m_i2c_enumeration);
Hans Verkuil942648a2008-09-07 08:38:50 -03001370#endif
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001371
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001372static struct dvb_frontend_ops dib7000m_ops;
1373struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg)
1374{
1375 struct dvb_frontend *demod;
1376 struct dib7000m_state *st;
1377 st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL);
1378 if (st == NULL)
1379 return NULL;
1380
1381 memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config));
1382 st->i2c_adap = i2c_adap;
1383 st->i2c_addr = i2c_addr;
1384
1385 demod = &st->demod;
1386 demod->demodulator_priv = st;
1387 memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops));
1388
Patrick Boettcher3db78e52007-07-31 08:19:28 -03001389 st->timf_default = cfg->bw->timf;
1390
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001391 if (dib7000m_identify(st) != 0)
1392 goto error;
1393
1394 if (st->revision == 0x4000)
1395 dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr);
1396 else
1397 dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr);
1398
1399 dib7000m_demod_reset(st);
1400
1401 return demod;
1402
1403error:
1404 kfree(st);
1405 return NULL;
1406}
1407EXPORT_SYMBOL(dib7000m_attach);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001408
1409static struct dvb_frontend_ops dib7000m_ops = {
1410 .info = {
1411 .name = "DiBcom 7000MA/MB/PA/PB/MC",
1412 .type = FE_OFDM,
1413 .frequency_min = 44250000,
1414 .frequency_max = 867250000,
1415 .frequency_stepsize = 62500,
1416 .caps = FE_CAN_INVERSION_AUTO |
1417 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1418 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1419 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
1420 FE_CAN_TRANSMISSION_MODE_AUTO |
1421 FE_CAN_GUARD_INTERVAL_AUTO |
1422 FE_CAN_RECOVER |
1423 FE_CAN_HIERARCHY_AUTO,
1424 },
1425
1426 .release = dib7000m_release,
1427
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001428 .init = dib7000m_wakeup,
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001429 .sleep = dib7000m_sleep,
1430
1431 .set_frontend = dib7000m_set_frontend,
1432 .get_tune_settings = dib7000m_fe_get_tune_settings,
1433 .get_frontend = dib7000m_get_frontend,
1434
1435 .read_status = dib7000m_read_status,
1436 .read_ber = dib7000m_read_ber,
1437 .read_signal_strength = dib7000m_read_signal_strength,
1438 .read_snr = dib7000m_read_snr,
1439 .read_ucblocks = dib7000m_read_unc_blocks,
1440};
1441
1442MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
1443MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator");
1444MODULE_LICENSE("GPL");