blob: dbb76d75c932fecb36784a62be7451a3d63fb4c8 [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>
Patrick Boettcher79fcce32011-08-03 12:08:21 -030014#include <linux/mutex.h>
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020015
16#include "dvb_frontend.h"
17
18#include "dib7000m.h"
19
20static int debug;
21module_param(debug, int, 0644);
22MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
23
Patrick Boettcherb6884a12007-07-27 10:08:51 -030024#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M: "); printk(args); printk("\n"); } } while (0)
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020025
26struct dib7000m_state {
27 struct dvb_frontend demod;
28 struct dib7000m_config cfg;
29
30 u8 i2c_addr;
31 struct i2c_adapter *i2c_adap;
32
33 struct dibx000_i2c_master i2c_master;
34
35/* offset is 1 in case of the 7000MC */
36 u8 reg_offs;
37
38 u16 wbd_ref;
39
40 u8 current_band;
41 fe_bandwidth_t current_bandwidth;
42 struct dibx000_agc_config *current_agc;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -030043 u32 timf;
Patrick Boettcherb6884a12007-07-27 10:08:51 -030044 u32 timf_default;
45 u32 internal_clk;
46
Patrick Boettcher01373a52007-07-30 12:49:04 -030047 u8 div_force_off : 1;
48 u8 div_state : 1;
49 u16 div_sync_wait;
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020050
51 u16 revision;
Patrick Boettcherb6884a12007-07-27 10:08:51 -030052
53 u8 agc_state;
Olivier Grenie5a0deee2011-05-03 12:27:33 -030054
55 /* for the I2C transfer */
56 struct i2c_msg msg[2];
57 u8 i2c_write_buffer[4];
58 u8 i2c_read_buffer[2];
Patrick Boettcher79fcce32011-08-03 12:08:21 -030059 struct mutex i2c_buffer_lock;
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020060};
61
Patrick Boettcher69ea31e2006-10-17 18:28:14 -030062enum dib7000m_power_mode {
63 DIB7000M_POWER_ALL = 0,
64
65 DIB7000M_POWER_NO,
66 DIB7000M_POWER_INTERF_ANALOG_AGC,
67 DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD,
68 DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD,
69 DIB7000M_POWER_INTERFACE_ONLY,
70};
71
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020072static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
73{
Patrick Boettcher79fcce32011-08-03 12:08:21 -030074 u16 ret;
75
76 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
77 dprintk("could not acquire lock");
78 return 0;
79 }
80
Olivier Grenie5a0deee2011-05-03 12:27:33 -030081 state->i2c_write_buffer[0] = (reg >> 8) | 0x80;
82 state->i2c_write_buffer[1] = reg & 0xff;
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020083
Olivier Grenie5a0deee2011-05-03 12:27:33 -030084 memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
85 state->msg[0].addr = state->i2c_addr >> 1;
86 state->msg[0].flags = 0;
87 state->msg[0].buf = state->i2c_write_buffer;
88 state->msg[0].len = 2;
89 state->msg[1].addr = state->i2c_addr >> 1;
90 state->msg[1].flags = I2C_M_RD;
91 state->msg[1].buf = state->i2c_read_buffer;
92 state->msg[1].len = 2;
93
94 if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
Patrick Boettcherb6884a12007-07-27 10:08:51 -030095 dprintk("i2c read error on %d",reg);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -020096
Patrick Boettcher79fcce32011-08-03 12:08:21 -030097 ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
98 mutex_unlock(&state->i2c_buffer_lock);
99
100 return ret;
Patrick Boettcher91bb9be2006-12-02 21:15:51 -0200101}
102
Patrick Boettcher91bb9be2006-12-02 21:15:51 -0200103static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
104{
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300105 int ret;
106
107 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
108 dprintk("could not acquire lock");
109 return -EINVAL;
110 }
111
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300112 state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
113 state->i2c_write_buffer[1] = reg & 0xff;
114 state->i2c_write_buffer[2] = (val >> 8) & 0xff;
115 state->i2c_write_buffer[3] = val & 0xff;
116
117 memset(&state->msg[0], 0, sizeof(struct i2c_msg));
118 state->msg[0].addr = state->i2c_addr >> 1;
119 state->msg[0].flags = 0;
120 state->msg[0].buf = state->i2c_write_buffer;
121 state->msg[0].len = 4;
122
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300123 ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
124 -EREMOTEIO : 0);
125 mutex_unlock(&state->i2c_buffer_lock);
126 return ret;
Patrick Boettcher91bb9be2006-12-02 21:15:51 -0200127}
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300128static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
129{
130 u16 l = 0, r, *n;
131 n = buf;
132 l = *n++;
133 while (l) {
134 r = *n++;
135
136 if (state->reg_offs && (r >= 112 && r <= 331)) // compensate for 7000MC
137 r++;
138
139 do {
140 dib7000m_write_word(state, r, *n++);
141 r++;
142 } while (--l);
143 l = *n++;
144 }
145}
146
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300147static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode)
148{
149 int ret = 0;
150 u16 outreg, fifo_threshold, smo_mode,
151 sram = 0x0005; /* by default SRAM output is disabled */
152
153 outreg = 0;
154 fifo_threshold = 1792;
155 smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1);
156
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300157 dprintk( "setting output mode for demod %p to %d", &state->demod, mode);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300158
159 switch (mode) {
160 case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock
161 outreg = (1 << 10); /* 0x0400 */
162 break;
163 case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock
164 outreg = (1 << 10) | (1 << 6); /* 0x0440 */
165 break;
166 case OUTMODE_MPEG2_SERIAL: // STBs with serial input
167 outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */
168 break;
169 case OUTMODE_DIVERSITY:
170 if (state->cfg.hostbus_diversity)
171 outreg = (1 << 10) | (4 << 6); /* 0x0500 */
172 else
173 sram |= 0x0c00;
174 break;
175 case OUTMODE_MPEG2_FIFO: // e.g. USB feeding
176 smo_mode |= (3 << 1);
177 fifo_threshold = 512;
178 outreg = (1 << 10) | (5 << 6);
179 break;
180 case OUTMODE_HIGH_Z: // disable
181 outreg = 0;
182 break;
183 default:
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300184 dprintk( "Unhandled output_mode passed to be set for demod %p",&state->demod);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300185 break;
186 }
187
188 if (state->cfg.output_mpeg2_in_188_bytes)
189 smo_mode |= (1 << 5) ;
190
191 ret |= dib7000m_write_word(state, 294 + state->reg_offs, smo_mode);
192 ret |= dib7000m_write_word(state, 295 + state->reg_offs, fifo_threshold); /* synchronous fread */
193 ret |= dib7000m_write_word(state, 1795, outreg);
194 ret |= dib7000m_write_word(state, 1805, sram);
195
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300196 if (state->revision == 0x4003) {
197 u16 clk_cfg1 = dib7000m_read_word(state, 909) & 0xfffd;
198 if (mode == OUTMODE_DIVERSITY)
199 clk_cfg1 |= (1 << 1); // P_O_CLK_en
200 dib7000m_write_word(state, 909, clk_cfg1);
201 }
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300202 return ret;
203}
204
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300205static void dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300206{
207 /* by default everything is going to be powered off */
208 u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906 = 0x3fff;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300209 u8 offset = 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300210
211 /* now, depending on the requested mode, we power on */
212 switch (mode) {
213 /* power up everything in the demod */
214 case DIB7000M_POWER_ALL:
215 reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000;
216 break;
217
218 /* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */
219 case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */
220 reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2));
221 break;
222
223 case DIB7000M_POWER_INTERF_ANALOG_AGC:
224 reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10));
225 reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2));
226 reg_906 &= ~((1 << 0));
227 break;
228
229 case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD:
230 reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000;
231 break;
232
233 case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD:
234 reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000;
235 break;
236 case DIB7000M_POWER_NO:
237 break;
238 }
239
240 /* always power down unused parts */
241 if (!state->cfg.mobile_mode)
242 reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1);
243
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300244 /* P_sdio_select_clk = 0 on MC and after*/
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300245 if (state->revision != 0x4000)
246 reg_906 <<= 1;
247
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300248 if (state->revision == 0x4003)
249 offset = 1;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300250
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300251 dib7000m_write_word(state, 903 + offset, reg_903);
252 dib7000m_write_word(state, 904 + offset, reg_904);
253 dib7000m_write_word(state, 905 + offset, reg_905);
254 dib7000m_write_word(state, 906 + offset, reg_906);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300255}
256
257static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no)
258{
259 int ret = 0;
260 u16 reg_913 = dib7000m_read_word(state, 913),
261 reg_914 = dib7000m_read_word(state, 914);
262
263 switch (no) {
264 case DIBX000_SLOW_ADC_ON:
265 reg_914 |= (1 << 1) | (1 << 0);
266 ret |= dib7000m_write_word(state, 914, reg_914);
267 reg_914 &= ~(1 << 1);
268 break;
269
270 case DIBX000_SLOW_ADC_OFF:
271 reg_914 |= (1 << 1) | (1 << 0);
272 break;
273
274 case DIBX000_ADC_ON:
275 if (state->revision == 0x4000) { // workaround for PA/MA
276 // power-up ADC
277 dib7000m_write_word(state, 913, 0);
278 dib7000m_write_word(state, 914, reg_914 & 0x3);
279 // power-down bandgag
280 dib7000m_write_word(state, 913, (1 << 15));
281 dib7000m_write_word(state, 914, reg_914 & 0x3);
282 }
283
284 reg_913 &= 0x0fff;
285 reg_914 &= 0x0003;
286 break;
287
288 case DIBX000_ADC_OFF: // leave the VBG voltage on
289 reg_913 |= (1 << 14) | (1 << 13) | (1 << 12);
290 reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
291 break;
292
293 case DIBX000_VBG_ENABLE:
294 reg_913 &= ~(1 << 15);
295 break;
296
297 case DIBX000_VBG_DISABLE:
298 reg_913 |= (1 << 15);
299 break;
300
301 default:
302 break;
303 }
304
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300305// dprintk( "913: %x, 914: %x", reg_913, reg_914);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300306 ret |= dib7000m_write_word(state, 913, reg_913);
307 ret |= dib7000m_write_word(state, 914, reg_914);
308
309 return ret;
310}
311
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300312static int dib7000m_set_bandwidth(struct dib7000m_state *state, u32 bw)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300313{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300314 u32 timf;
315
316 // store the current bandwidth for later use
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300317 state->current_bandwidth = bw;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300318
319 if (state->timf == 0) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300320 dprintk( "using default timf");
321 timf = state->timf_default;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300322 } else {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300323 dprintk( "using updated timf");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300324 timf = state->timf;
325 }
326
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300327 timf = timf * (bw / 50) / 160;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300328
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300329 dib7000m_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
330 dib7000m_write_word(state, 24, (u16) ((timf ) & 0xffff));
331
332 return 0;
333}
334
335static int dib7000m_set_diversity_in(struct dvb_frontend *demod, int onoff)
336{
337 struct dib7000m_state *state = demod->demodulator_priv;
338
339 if (state->div_force_off) {
340 dprintk( "diversity combination deactivated - forced by COFDM parameters");
341 onoff = 0;
342 }
Patrick Boettcher01373a52007-07-30 12:49:04 -0300343 state->div_state = (u8)onoff;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300344
345 if (onoff) {
346 dib7000m_write_word(state, 263 + state->reg_offs, 6);
347 dib7000m_write_word(state, 264 + state->reg_offs, 6);
348 dib7000m_write_word(state, 266 + state->reg_offs, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
349 } else {
350 dib7000m_write_word(state, 263 + state->reg_offs, 1);
351 dib7000m_write_word(state, 264 + state->reg_offs, 0);
352 dib7000m_write_word(state, 266 + state->reg_offs, 0);
353 }
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300354
355 return 0;
356}
357
358static int dib7000m_sad_calib(struct dib7000m_state *state)
359{
360
361/* internal */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300362// 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 -0300363 dib7000m_write_word(state, 929, (0 << 1) | (0 << 0));
364 dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096
365
366 /* do the calibration */
367 dib7000m_write_word(state, 929, (1 << 0));
368 dib7000m_write_word(state, 929, (0 << 0));
369
370 msleep(1);
371
372 return 0;
373}
374
375static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw)
376{
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300377 dib7000m_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff));
378 dib7000m_write_word(state, 19, (u16) ( (bw->internal*1000) & 0xffff));
379 dib7000m_write_word(state, 21, (u16) ( (bw->ifreq >> 16) & 0xffff));
380 dib7000m_write_word(state, 22, (u16) ( bw->ifreq & 0xffff));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300381
382 dib7000m_write_word(state, 928, bw->sad_cfg);
383}
384
385static void dib7000m_reset_pll(struct dib7000m_state *state)
386{
387 const struct dibx000_bandwidth_config *bw = state->cfg.bw;
388 u16 reg_907,reg_910;
389
390 /* default */
391 reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) |
392 (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) |
393 (bw->enable_refdiv << 1) | (0 << 0);
394 reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset;
395
396 // for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value)
397 // this is only working only for 30 MHz crystals
398 if (!state->cfg.quartz_direct) {
399 reg_910 |= (1 << 5); // forcing the predivider to 1
400
401 // if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2)
402 if(state->cfg.input_clk_is_div_2)
403 reg_907 |= (16 << 9);
404 else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary
405 reg_907 |= (8 << 9);
406 } else {
407 reg_907 |= (bw->pll_ratio & 0x3f) << 9;
408 reg_910 |= (bw->pll_prediv << 5);
409 }
410
411 dib7000m_write_word(state, 910, reg_910); // pll cfg
412 dib7000m_write_word(state, 907, reg_907); // clk cfg0
413 dib7000m_write_word(state, 908, 0x0006); // clk_cfg1
414
415 dib7000m_reset_pll_common(state, bw);
416}
417
418static void dib7000mc_reset_pll(struct dib7000m_state *state)
419{
420 const struct dibx000_bandwidth_config *bw = state->cfg.bw;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300421 u16 clk_cfg1;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300422
423 // clk_cfg0
424 dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0));
425
426 // clk_cfg1
427 //dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) |
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300428 clk_cfg1 = (0 << 14) | (3 << 12) |(0 << 11) |
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300429 (bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) |
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300430 (1 << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0);
431 dib7000m_write_word(state, 908, clk_cfg1);
432 clk_cfg1 = (clk_cfg1 & 0xfff7) | (bw->pll_bypass << 3);
433 dib7000m_write_word(state, 908, clk_cfg1);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300434
435 // smpl_cfg
436 dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7));
437
438 dib7000m_reset_pll_common(state, bw);
439}
440
441static int dib7000m_reset_gpio(struct dib7000m_state *st)
442{
443 /* reset the GPIOs */
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300444 dib7000m_write_word(st, 773, st->cfg.gpio_dir);
445 dib7000m_write_word(st, 774, st->cfg.gpio_val);
446
447 /* TODO 782 is P_gpio_od */
448
449 dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos);
450
451 dib7000m_write_word(st, 780, st->cfg.pwm_freq_div);
452 return 0;
453}
454
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300455static u16 dib7000m_defaults_common[] =
456
457{
458 // auto search configuration
459 3, 2,
460 0x0004,
461 0x1000,
462 0x0814,
463
464 12, 6,
465 0x001b,
466 0x7740,
467 0x005b,
468 0x8d80,
469 0x01c9,
470 0xc380,
471 0x0000,
472 0x0080,
473 0x0000,
474 0x0090,
475 0x0001,
476 0xd4c0,
477
478 1, 26,
479 0x6680, // P_corm_thres Lock algorithms configuration
480
481 1, 170,
482 0x0410, // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on
483
484 8, 173,
485 0,
486 0,
487 0,
488 0,
489 0,
490 0,
491 0,
492 0,
493
494 1, 182,
495 8192, // P_fft_nb_to_cut
496
497 2, 195,
498 0x0ccd, // P_pha3_thres
499 0, // P_cti_use_cpe, P_cti_use_prog
500
501 1, 205,
502 0x200f, // P_cspu_regul, P_cspu_win_cut
503
504 5, 214,
505 0x023d, // P_adp_regul_cnt
506 0x00a4, // P_adp_noise_cnt
507 0x00a4, // P_adp_regul_ext
508 0x7ff0, // P_adp_noise_ext
509 0x3ccc, // P_adp_fil
510
511 1, 226,
512 0, // P_2d_byp_ti_num
513
514 1, 255,
515 0x800, // P_equal_thres_wgn
516
517 1, 263,
518 0x0001,
519
520 1, 281,
521 0x0010, // P_fec_*
522
523 1, 294,
524 0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
525
526 0
527};
528
529static u16 dib7000m_defaults[] =
530
531{
532 /* set ADC level to -16 */
533 11, 76,
534 (1 << 13) - 825 - 117,
535 (1 << 13) - 837 - 117,
536 (1 << 13) - 811 - 117,
537 (1 << 13) - 766 - 117,
538 (1 << 13) - 737 - 117,
539 (1 << 13) - 693 - 117,
540 (1 << 13) - 648 - 117,
541 (1 << 13) - 619 - 117,
542 (1 << 13) - 575 - 117,
543 (1 << 13) - 531 - 117,
544 (1 << 13) - 501 - 117,
545
546 // Tuner IO bank: max drive (14mA)
547 1, 912,
548 0x2c8a,
549
550 1, 1817,
551 1,
552
553 0,
554};
555
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300556static int dib7000m_demod_reset(struct dib7000m_state *state)
557{
558 dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
559
560 /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
561 dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE);
562
563 /* restart all parts */
564 dib7000m_write_word(state, 898, 0xffff);
565 dib7000m_write_word(state, 899, 0xffff);
566 dib7000m_write_word(state, 900, 0xff0f);
567 dib7000m_write_word(state, 901, 0xfffc);
568
569 dib7000m_write_word(state, 898, 0);
570 dib7000m_write_word(state, 899, 0);
571 dib7000m_write_word(state, 900, 0);
572 dib7000m_write_word(state, 901, 0);
573
574 if (state->revision == 0x4000)
575 dib7000m_reset_pll(state);
576 else
577 dib7000mc_reset_pll(state);
578
579 if (dib7000m_reset_gpio(state) != 0)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300580 dprintk( "GPIO reset was not successful.");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300581
582 if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300583 dprintk( "OUTPUT_MODE could not be reset.");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300584
585 /* unforce divstr regardless whether i2c enumeration was done or not */
586 dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) );
587
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300588 dib7000m_set_bandwidth(state, 8000);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300589
590 dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON);
591 dib7000m_sad_calib(state);
592 dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
593
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300594 if (state->cfg.dvbt_mode)
595 dib7000m_write_word(state, 1796, 0x0); // select DVB-T output
596
597 if (state->cfg.mobile_mode)
598 dib7000m_write_word(state, 261 + state->reg_offs, 2);
599 else
600 dib7000m_write_word(state, 224 + state->reg_offs, 1);
601
602 // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ...
603 if(state->cfg.tuner_is_baseband)
604 dib7000m_write_word(state, 36, 0x0755);
605 else
606 dib7000m_write_word(state, 36, 0x1f55);
607
608 // P_divclksel=3 P_divbitsel=1
609 if (state->revision == 0x4000)
610 dib7000m_write_word(state, 909, (3 << 10) | (1 << 6));
611 else
612 dib7000m_write_word(state, 909, (3 << 4) | 1);
613
614 dib7000m_write_tab(state, dib7000m_defaults_common);
615 dib7000m_write_tab(state, dib7000m_defaults);
616
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300617 dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY);
618
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300619 state->internal_clk = state->cfg.bw->internal;
620
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300621 return 0;
622}
623
624static void dib7000m_restart_agc(struct dib7000m_state *state)
625{
626 // P_restart_iqc & P_restart_agc
627 dib7000m_write_word(state, 898, 0x0c00);
628 dib7000m_write_word(state, 898, 0x0000);
629}
630
631static int dib7000m_agc_soft_split(struct dib7000m_state *state)
632{
633 u16 agc,split_offset;
634
635 if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
636 return 0;
637
638 // n_agc_global
639 agc = dib7000m_read_word(state, 390);
640
641 if (agc > state->current_agc->split.min_thres)
642 split_offset = state->current_agc->split.min;
643 else if (agc < state->current_agc->split.max_thres)
644 split_offset = state->current_agc->split.max;
645 else
646 split_offset = state->current_agc->split.max *
647 (agc - state->current_agc->split.min_thres) /
648 (state->current_agc->split.max_thres - state->current_agc->split.min_thres);
649
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300650 dprintk( "AGC split_offset: %d",split_offset);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300651
652 // P_agc_force_split and P_agc_split_offset
653 return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset);
654}
655
656static int dib7000m_update_lna(struct dib7000m_state *state)
657{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300658 u16 dyn_gain;
659
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300660 if (state->cfg.update_lna) {
Patrick Boettcher01373a52007-07-30 12:49:04 -0300661 // read dyn_gain here (because it is demod-dependent and not fe)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300662 dyn_gain = dib7000m_read_word(state, 390);
663
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300664 if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
665 dib7000m_restart_agc(state);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300666 return 1;
667 }
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300668 }
669 return 0;
670}
671
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300672static int dib7000m_set_agc_config(struct dib7000m_state *state, u8 band)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300673{
674 struct dibx000_agc_config *agc = NULL;
675 int i;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300676 if (state->current_band == band && state->current_agc != NULL)
677 return 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300678 state->current_band = band;
679
680 for (i = 0; i < state->cfg.agc_config_count; i++)
681 if (state->cfg.agc[i].band_caps & band) {
682 agc = &state->cfg.agc[i];
683 break;
684 }
685
686 if (agc == NULL) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300687 dprintk( "no valid AGC configuration found for band 0x%02x",band);
688 return -EINVAL;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300689 }
690
691 state->current_agc = agc;
692
693 /* AGC */
694 dib7000m_write_word(state, 72 , agc->setup);
695 dib7000m_write_word(state, 73 , agc->inv_gain);
696 dib7000m_write_word(state, 74 , agc->time_stabiliz);
697 dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock);
698
699 // Demod AGC loop configuration
700 dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp);
701 dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp);
702
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300703 dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d",
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300704 state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
705
706 /* AGC continued */
707 if (state->wbd_ref != 0)
708 dib7000m_write_word(state, 102, state->wbd_ref);
709 else // use default
710 dib7000m_write_word(state, 102, agc->wbd_ref);
711
712 dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) );
713 dib7000m_write_word(state, 104, agc->agc1_max);
714 dib7000m_write_word(state, 105, agc->agc1_min);
715 dib7000m_write_word(state, 106, agc->agc2_max);
716 dib7000m_write_word(state, 107, agc->agc2_min);
717 dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 );
718 dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
719 dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
720 dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
721
722 if (state->revision > 0x4000) { // settings for the MC
723 dib7000m_write_word(state, 71, agc->agc1_pt3);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300724// dprintk( "929: %x %d %d",
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300725// (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel);
726 dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2));
727 } else {
728 // wrong default values
729 u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 };
730 for (i = 0; i < 9; i++)
731 dib7000m_write_word(state, 88 + i, b[i]);
732 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300733 return 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300734}
735
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300736static void dib7000m_update_timf(struct dib7000m_state *state)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300737{
738 u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300739 state->timf = timf * 160 / (state->current_bandwidth / 50);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300740 dib7000m_write_word(state, 23, (u16) (timf >> 16));
741 dib7000m_write_word(state, 24, (u16) (timf & 0xffff));
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300742 dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->timf_default);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300743}
744
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300745static int dib7000m_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
746{
747 struct dib7000m_state *state = demod->demodulator_priv;
748 u16 cfg_72 = dib7000m_read_word(state, 72);
749 int ret = -1;
750 u8 *agc_state = &state->agc_state;
751 u8 agc_split;
752
753 switch (state->agc_state) {
754 case 0:
755 // set power-up level: interf+analog+AGC
756 dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC);
757 dib7000m_set_adc_state(state, DIBX000_ADC_ON);
758
759 if (dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0)
760 return -1;
761
762 ret = 7; /* ADC power up */
763 (*agc_state)++;
764 break;
765
766 case 1:
767 /* AGC initialization */
768 if (state->cfg.agc_control)
769 state->cfg.agc_control(&state->demod, 1);
770
771 dib7000m_write_word(state, 75, 32768);
772 if (!state->current_agc->perform_agc_softsplit) {
773 /* we are using the wbd - so slow AGC startup */
774 dib7000m_write_word(state, 103, 1 << 8); /* force 0 split on WBD and restart AGC */
775 (*agc_state)++;
776 ret = 5;
777 } else {
778 /* default AGC startup */
779 (*agc_state) = 4;
780 /* wait AGC rough lock time */
781 ret = 7;
782 }
783
784 dib7000m_restart_agc(state);
785 break;
786
787 case 2: /* fast split search path after 5sec */
788 dib7000m_write_word(state, 72, cfg_72 | (1 << 4)); /* freeze AGC loop */
789 dib7000m_write_word(state, 103, 2 << 9); /* fast split search 0.25kHz */
790 (*agc_state)++;
791 ret = 14;
792 break;
793
794 case 3: /* split search ended */
Patrick Boettcher01373a52007-07-30 12:49:04 -0300795 agc_split = (u8)dib7000m_read_word(state, 392); /* store the split value for the next time */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300796 dib7000m_write_word(state, 75, dib7000m_read_word(state, 390)); /* set AGC gain start value */
797
798 dib7000m_write_word(state, 72, cfg_72 & ~(1 << 4)); /* std AGC loop */
799 dib7000m_write_word(state, 103, (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
800
801 dib7000m_restart_agc(state);
802
803 dprintk( "SPLIT %p: %hd", demod, agc_split);
804
805 (*agc_state)++;
806 ret = 5;
807 break;
808
809 case 4: /* LNA startup */
810 /* wait AGC accurate lock time */
811 ret = 7;
812
813 if (dib7000m_update_lna(state))
814 // wait only AGC rough lock time
815 ret = 5;
816 else
817 (*agc_state)++;
818 break;
819
820 case 5:
821 dib7000m_agc_soft_split(state);
822
823 if (state->cfg.agc_control)
824 state->cfg.agc_control(&state->demod, 0);
825
826 (*agc_state)++;
827 break;
828
829 default:
830 break;
831 }
832 return ret;
833}
834
835static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_frontend_parameters *ch, u8 seq)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300836{
837 u16 value, est[4];
838
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300839 dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300840
841 /* nfft, guard, qam, alpha */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300842 value = 0;
843 switch (ch->u.ofdm.transmission_mode) {
844 case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
Mauro Carvalho Chehab2e94b532010-12-27 11:55:07 -0300845 case TRANSMISSION_MODE_4K: value |= (2 << 7); break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300846 default:
847 case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
848 }
849 switch (ch->u.ofdm.guard_interval) {
850 case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
851 case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
852 case GUARD_INTERVAL_1_4: value |= (3 << 5); break;
853 default:
854 case GUARD_INTERVAL_1_8: value |= (2 << 5); break;
855 }
856 switch (ch->u.ofdm.constellation) {
857 case QPSK: value |= (0 << 3); break;
858 case QAM_16: value |= (1 << 3); break;
859 default:
860 case QAM_64: value |= (2 << 3); break;
861 }
862 switch (HIERARCHY_1) {
863 case HIERARCHY_2: value |= 2; break;
864 case HIERARCHY_4: value |= 4; break;
865 default:
866 case HIERARCHY_1: value |= 1; break;
867 }
868 dib7000m_write_word(state, 0, value);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300869 dib7000m_write_word(state, 5, (seq << 4));
870
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300871 /* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
872 value = 0;
873 if (1 != 0)
874 value |= (1 << 6);
875 if (ch->u.ofdm.hierarchy_information == 1)
876 value |= (1 << 4);
877 if (1 == 1)
878 value |= 1;
879 switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
880 case FEC_2_3: value |= (2 << 1); break;
881 case FEC_3_4: value |= (3 << 1); break;
882 case FEC_5_6: value |= (5 << 1); break;
883 case FEC_7_8: value |= (7 << 1); break;
884 default:
885 case FEC_1_2: value |= (1 << 1); break;
886 }
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300887 dib7000m_write_word(state, 267 + state->reg_offs, value);
888
889 /* offset loop parameters */
890
891 /* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */
892 dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80);
893
894 /* 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 */
895 dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3));
896
897 /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */
898 dib7000m_write_word(state, 32, (0 << 4) | 0x3);
899
900 /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */
901 dib7000m_write_word(state, 33, (0 << 4) | 0x5);
902
903 /* P_dvsy_sync_wait */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300904 switch (ch->u.ofdm.transmission_mode) {
905 case TRANSMISSION_MODE_8K: value = 256; break;
Mauro Carvalho Chehab2e94b532010-12-27 11:55:07 -0300906 case TRANSMISSION_MODE_4K: value = 128; break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300907 case TRANSMISSION_MODE_2K:
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300908 default: value = 64; break;
909 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300910 switch (ch->u.ofdm.guard_interval) {
911 case GUARD_INTERVAL_1_16: value *= 2; break;
912 case GUARD_INTERVAL_1_8: value *= 4; break;
913 case GUARD_INTERVAL_1_4: value *= 8; break;
914 default:
915 case GUARD_INTERVAL_1_32: value *= 1; break;
916 }
917 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 -0300918
919 /* deactive the possibility of diversity reception if extended interleave - not for 7000MC */
920 /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300921 if (1 == 1 || state->revision > 0x4000)
922 state->div_force_off = 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300923 else
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300924 state->div_force_off = 1;
925 dib7000m_set_diversity_in(&state->demod, state->div_state);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300926
927 /* channel estimation fine configuration */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300928 switch (ch->u.ofdm.constellation) {
929 case QAM_64:
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300930 est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
931 est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
932 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
933 est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */
934 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300935 case QAM_16:
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300936 est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */
937 est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */
938 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
939 est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */
940 break;
941 default:
942 est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */
943 est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */
944 est[2] = 0x0333; /* P_adp_regul_ext 0.1 */
945 est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */
946 break;
947 }
948 for (value = 0; value < 4; value++)
949 dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]);
950
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300951 // set power-up level: autosearch
952 dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD);
953}
954
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300955static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300956{
957 struct dib7000m_state *state = demod->demodulator_priv;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300958 struct dvb_frontend_parameters schan;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300959 int ret = 0;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300960 u32 value, factor;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300961
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300962 schan = *ch;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300963
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300964 schan.u.ofdm.constellation = QAM_64;
965 schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
966 schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
967 schan.u.ofdm.code_rate_HP = FEC_2_3;
968 schan.u.ofdm.code_rate_LP = FEC_3_4;
969 schan.u.ofdm.hierarchy_information = 0;
970
971 dib7000m_set_channel(state, &schan, 7);
972
973 factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth);
974 if (factor >= 5000)
975 factor = 1;
976 else
977 factor = 6;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300978
979 // always use the setting for 8MHz here lock_time for 7,6 MHz are longer
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300980 value = 30 * state->internal_clk * factor;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300981 ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time
982 ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300983 value = 100 * state->internal_clk * factor;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300984 ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time
985 ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300986 value = 500 * state->internal_clk * factor;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300987 ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
988 ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time
989
990 // start search
991 value = dib7000m_read_word(state, 0);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300992 ret |= dib7000m_write_word(state, 0, (u16) (value | (1 << 9)));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -0300993
994 /* clear n_irq_pending */
995 if (state->revision == 0x4000)
996 dib7000m_write_word(state, 1793, 0);
997 else
998 dib7000m_read_word(state, 537);
999
1000 ret |= dib7000m_write_word(state, 0, (u16) value);
1001
1002 return ret;
1003}
1004
1005static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg)
1006{
1007 u16 irq_pending = dib7000m_read_word(state, reg);
1008
1009 if (irq_pending & 0x1) { // failed
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001010 dprintk( "autosearch failed");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001011 return 1;
1012 }
1013
1014 if (irq_pending & 0x2) { // succeeded
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001015 dprintk( "autosearch succeeded");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001016 return 2;
1017 }
1018 return 0; // still pending
1019}
1020
1021static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod)
1022{
1023 struct dib7000m_state *state = demod->demodulator_priv;
1024 if (state->revision == 0x4000)
1025 return dib7000m_autosearch_irq(state, 1793);
1026 else
1027 return dib7000m_autosearch_irq(state, 537);
1028}
1029
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001030static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001031{
1032 struct dib7000m_state *state = demod->demodulator_priv;
1033 int ret = 0;
1034 u16 value;
1035
1036 // we are already tuned - just resuming from suspend
1037 if (ch != NULL)
1038 dib7000m_set_channel(state, ch, 0);
1039 else
1040 return -EINVAL;
1041
1042 // restart demod
1043 ret |= dib7000m_write_word(state, 898, 0x4000);
1044 ret |= dib7000m_write_word(state, 898, 0x0000);
1045 msleep(45);
1046
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001047 dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001048 /* 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 */
1049 ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3));
1050
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001051 // never achieved a lock before - wait for timfreq to update
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001052 if (state->timf == 0)
1053 msleep(200);
1054
1055 //dump_reg(state);
1056 /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
1057 value = (6 << 8) | 0x80;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001058 switch (ch->u.ofdm.transmission_mode) {
1059 case TRANSMISSION_MODE_2K: value |= (7 << 12); break;
Mauro Carvalho Chehab2e94b532010-12-27 11:55:07 -03001060 case TRANSMISSION_MODE_4K: value |= (8 << 12); break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001061 default:
1062 case TRANSMISSION_MODE_8K: value |= (9 << 12); break;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001063 }
1064 ret |= dib7000m_write_word(state, 26, value);
1065
1066 /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
1067 value = (0 << 4);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001068 switch (ch->u.ofdm.transmission_mode) {
1069 case TRANSMISSION_MODE_2K: value |= 0x6; break;
Mauro Carvalho Chehab2e94b532010-12-27 11:55:07 -03001070 case TRANSMISSION_MODE_4K: value |= 0x7; break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001071 default:
1072 case TRANSMISSION_MODE_8K: value |= 0x8; break;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001073 }
1074 ret |= dib7000m_write_word(state, 32, value);
1075
1076 /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
1077 value = (0 << 4);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001078 switch (ch->u.ofdm.transmission_mode) {
1079 case TRANSMISSION_MODE_2K: value |= 0x6; break;
Mauro Carvalho Chehab2e94b532010-12-27 11:55:07 -03001080 case TRANSMISSION_MODE_4K: value |= 0x7; break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001081 default:
1082 case TRANSMISSION_MODE_8K: value |= 0x8; break;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001083 }
1084 ret |= dib7000m_write_word(state, 33, value);
1085
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001086 // we achieved a lock - it's time to update the timf freq
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001087 if ((dib7000m_read_word(state, 535) >> 6) & 0x1)
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001088 dib7000m_update_timf(state);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001089
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001090 dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001091 return ret;
1092}
1093
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001094static int dib7000m_wakeup(struct dvb_frontend *demod)
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001095{
1096 struct dib7000m_state *state = demod->demodulator_priv;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001097
1098 dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
1099
1100 if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001101 dprintk( "could not start Slow ADC");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001102
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001103 return 0;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001104}
1105
1106static int dib7000m_sleep(struct dvb_frontend *demod)
1107{
1108 struct dib7000m_state *st = demod->demodulator_priv;
1109 dib7000m_set_output_mode(st, OUTMODE_HIGH_Z);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001110 dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY);
1111 return dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) |
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001112 dib7000m_set_adc_state(st, DIBX000_ADC_OFF);
1113}
1114
1115static int dib7000m_identify(struct dib7000m_state *state)
1116{
1117 u16 value;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001118
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001119 if ((value = dib7000m_read_word(state, 896)) != 0x01b3) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001120 dprintk( "wrong Vendor ID (0x%x)",value);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001121 return -EREMOTEIO;
1122 }
1123
1124 state->revision = dib7000m_read_word(state, 897);
1125 if (state->revision != 0x4000 &&
1126 state->revision != 0x4001 &&
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001127 state->revision != 0x4002 &&
1128 state->revision != 0x4003) {
1129 dprintk( "wrong Device ID (0x%x)",value);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001130 return -EREMOTEIO;
1131 }
1132
1133 /* protect this driver to be used with 7000PC */
1134 if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001135 dprintk( "this driver does not work with DiB7000PC");
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001136 return -EREMOTEIO;
1137 }
1138
1139 switch (state->revision) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001140 case 0x4000: dprintk( "found DiB7000MA/PA/MB/PB"); break;
1141 case 0x4001: state->reg_offs = 1; dprintk( "found DiB7000HC"); break;
1142 case 0x4002: state->reg_offs = 1; dprintk( "found DiB7000MC"); break;
1143 case 0x4003: state->reg_offs = 1; dprintk( "found DiB9000"); break;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001144 }
1145
1146 return 0;
1147}
1148
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001149
1150static int dib7000m_get_frontend(struct dvb_frontend* fe,
1151 struct dvb_frontend_parameters *fep)
1152{
1153 struct dib7000m_state *state = fe->demodulator_priv;
1154 u16 tps = dib7000m_read_word(state,480);
1155
1156 fep->inversion = INVERSION_AUTO;
1157
1158 fep->u.ofdm.bandwidth = state->current_bandwidth;
1159
Patrick Boettcherd92532d2006-10-18 08:35:16 -03001160 switch ((tps >> 8) & 0x3) {
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001161 case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
1162 case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
1163 /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
1164 }
1165
1166 switch (tps & 0x3) {
1167 case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
1168 case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
1169 case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
1170 case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
1171 }
1172
1173 switch ((tps >> 14) & 0x3) {
1174 case 0: fep->u.ofdm.constellation = QPSK; break;
1175 case 1: fep->u.ofdm.constellation = QAM_16; break;
1176 case 2:
1177 default: fep->u.ofdm.constellation = QAM_64; break;
1178 }
1179
1180 /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
1181 /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
1182
1183 fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
1184 switch ((tps >> 5) & 0x7) {
1185 case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
1186 case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
1187 case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
1188 case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
1189 case 7:
1190 default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
1191
1192 }
1193
1194 switch ((tps >> 2) & 0x7) {
1195 case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
1196 case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
1197 case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
1198 case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
1199 case 7:
1200 default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
1201 }
1202
1203 /* native interleaver: (dib7000m_read_word(state, 481) >> 5) & 0x1 */
1204
1205 return 0;
1206}
1207
1208static int dib7000m_set_frontend(struct dvb_frontend* fe,
1209 struct dvb_frontend_parameters *fep)
1210{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001211 struct dib7000m_state *state = fe->demodulator_priv;
Soeren Moch853ea132008-01-25 06:27:06 -03001212 int time, ret;
1213
1214 dib7000m_set_output_mode(state, OUTMODE_HIGH_Z);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001215
1216 state->current_bandwidth = fep->u.ofdm.bandwidth;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001217 dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001218
1219 if (fe->ops.tuner_ops.set_params)
1220 fe->ops.tuner_ops.set_params(fe, fep);
1221
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001222 /* start up the AGC */
1223 state->agc_state = 0;
1224 do {
1225 time = dib7000m_agc_startup(fe, fep);
1226 if (time != -1)
1227 msleep(time);
1228 } while (time != -1);
1229
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001230 if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
1231 fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
1232 fep->u.ofdm.constellation == QAM_AUTO ||
1233 fep->u.ofdm.code_rate_HP == FEC_AUTO) {
1234 int i = 800, found;
1235
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001236 dib7000m_autosearch_start(fe, fep);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001237 do {
1238 msleep(1);
1239 found = dib7000m_autosearch_is_irq(fe);
1240 } while (found == 0 && i--);
1241
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001242 dprintk("autosearch returns: %d",found);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001243 if (found == 0 || found == 1)
1244 return 0; // no channel found
1245
1246 dib7000m_get_frontend(fe, fep);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001247 }
1248
Soeren Moch853ea132008-01-25 06:27:06 -03001249 ret = dib7000m_tune(fe, fep);
1250
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001251 /* make this a config parameter */
1252 dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO);
Soeren Moch853ea132008-01-25 06:27:06 -03001253 return ret;
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001254}
1255
1256static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat)
1257{
1258 struct dib7000m_state *state = fe->demodulator_priv;
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001259 u16 lock = dib7000m_read_word(state, 535);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001260
1261 *stat = 0;
1262
1263 if (lock & 0x8000)
1264 *stat |= FE_HAS_SIGNAL;
1265 if (lock & 0x3000)
1266 *stat |= FE_HAS_CARRIER;
1267 if (lock & 0x0100)
1268 *stat |= FE_HAS_VITERBI;
1269 if (lock & 0x0010)
1270 *stat |= FE_HAS_SYNC;
1271 if (lock & 0x0008)
1272 *stat |= FE_HAS_LOCK;
1273
1274 return 0;
1275}
1276
1277static int dib7000m_read_ber(struct dvb_frontend *fe, u32 *ber)
1278{
1279 struct dib7000m_state *state = fe->demodulator_priv;
1280 *ber = (dib7000m_read_word(state, 526) << 16) | dib7000m_read_word(state, 527);
1281 return 0;
1282}
1283
1284static int dib7000m_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
1285{
1286 struct dib7000m_state *state = fe->demodulator_priv;
1287 *unc = dib7000m_read_word(state, 534);
1288 return 0;
1289}
1290
1291static int dib7000m_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
1292{
1293 struct dib7000m_state *state = fe->demodulator_priv;
1294 u16 val = dib7000m_read_word(state, 390);
1295 *strength = 65535 - val;
1296 return 0;
1297}
1298
1299static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr)
1300{
1301 *snr = 0x0000;
1302 return 0;
1303}
1304
1305static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
1306{
1307 tune->min_delay_ms = 1000;
1308 return 0;
1309}
1310
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001311static void dib7000m_release(struct dvb_frontend *demod)
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001312{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001313 struct dib7000m_state *st = demod->demodulator_priv;
1314 dibx000_exit_i2c_master(&st->i2c_master);
1315 kfree(st);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001316}
1317
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001318struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001319{
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001320 struct dib7000m_state *st = demod->demodulator_priv;
1321 return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
1322}
1323EXPORT_SYMBOL(dib7000m_get_i2c_master);
1324
Olivier Greniee192a7c2011-01-14 13:58:59 -03001325int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
1326{
1327 struct dib7000m_state *state = fe->demodulator_priv;
1328 u16 val = dib7000m_read_word(state, 294 + state->reg_offs) & 0xffef;
1329 val |= (onoff & 0x1) << 4;
1330 dprintk("PID filter enabled %d", onoff);
1331 return dib7000m_write_word(state, 294 + state->reg_offs, val);
1332}
1333EXPORT_SYMBOL(dib7000m_pid_filter_ctrl);
1334
1335int dib7000m_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
1336{
1337 struct dib7000m_state *state = fe->demodulator_priv;
1338 dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
1339 return dib7000m_write_word(state, 300 + state->reg_offs + id,
1340 onoff ? (1 << 13) | pid : 0);
1341}
1342EXPORT_SYMBOL(dib7000m_pid_filter);
1343
Hans Verkuil942648a2008-09-07 08:38:50 -03001344#if 0
1345/* used with some prototype boards */
1346int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods,
Hans Verkuild45b9b82008-09-04 03:33:43 -03001347 u8 default_addr, struct dib7000m_config cfg[])
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001348{
1349 struct dib7000m_state st = { .i2c_adap = i2c };
1350 int k = 0;
1351 u8 new_addr = 0;
1352
1353 for (k = no_of_demods-1; k >= 0; k--) {
1354 st.cfg = cfg[k];
1355
1356 /* designated i2c address */
1357 new_addr = (0x40 + k) << 1;
1358 st.i2c_addr = new_addr;
1359 if (dib7000m_identify(&st) != 0) {
1360 st.i2c_addr = default_addr;
1361 if (dib7000m_identify(&st) != 0) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001362 dprintk("DiB7000M #%d: not identified", k);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001363 return -EIO;
1364 }
1365 }
1366
1367 /* start diversity to pull_down div_str - just for i2c-enumeration */
1368 dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY);
1369
1370 dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output
1371
1372 /* set new i2c address and force divstart */
1373 dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2);
1374
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001375 dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001376 }
1377
1378 for (k = 0; k < no_of_demods; k++) {
1379 st.cfg = cfg[k];
1380 st.i2c_addr = (0x40 + k) << 1;
1381
1382 // unforce divstr
1383 dib7000m_write_word(&st,1794, st.i2c_addr << 2);
1384
1385 /* deactivate div - it was just for i2c-enumeration */
1386 dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z);
1387 }
1388
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001389 return 0;
1390}
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001391EXPORT_SYMBOL(dib7000m_i2c_enumeration);
Hans Verkuil942648a2008-09-07 08:38:50 -03001392#endif
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001393
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001394static struct dvb_frontend_ops dib7000m_ops;
1395struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg)
1396{
1397 struct dvb_frontend *demod;
1398 struct dib7000m_state *st;
1399 st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL);
1400 if (st == NULL)
1401 return NULL;
1402
1403 memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config));
1404 st->i2c_adap = i2c_adap;
1405 st->i2c_addr = i2c_addr;
1406
1407 demod = &st->demod;
1408 demod->demodulator_priv = st;
1409 memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops));
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001410 mutex_init(&st->i2c_buffer_lock);
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001411
Patrick Boettcher3db78e52007-07-31 08:19:28 -03001412 st->timf_default = cfg->bw->timf;
1413
Patrick Boettcher69ea31e2006-10-17 18:28:14 -03001414 if (dib7000m_identify(st) != 0)
1415 goto error;
1416
1417 if (st->revision == 0x4000)
1418 dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr);
1419 else
1420 dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr);
1421
1422 dib7000m_demod_reset(st);
1423
1424 return demod;
1425
1426error:
1427 kfree(st);
1428 return NULL;
1429}
1430EXPORT_SYMBOL(dib7000m_attach);
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001431
1432static struct dvb_frontend_ops dib7000m_ops = {
1433 .info = {
1434 .name = "DiBcom 7000MA/MB/PA/PB/MC",
1435 .type = FE_OFDM,
1436 .frequency_min = 44250000,
1437 .frequency_max = 867250000,
1438 .frequency_stepsize = 62500,
1439 .caps = FE_CAN_INVERSION_AUTO |
1440 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1441 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1442 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
1443 FE_CAN_TRANSMISSION_MODE_AUTO |
1444 FE_CAN_GUARD_INTERVAL_AUTO |
1445 FE_CAN_RECOVER |
1446 FE_CAN_HIERARCHY_AUTO,
1447 },
1448
1449 .release = dib7000m_release,
1450
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001451 .init = dib7000m_wakeup,
Patrick Boettcher91bb9be2006-12-02 21:15:51 -02001452 .sleep = dib7000m_sleep,
1453
1454 .set_frontend = dib7000m_set_frontend,
1455 .get_tune_settings = dib7000m_fe_get_tune_settings,
1456 .get_frontend = dib7000m_get_frontend,
1457
1458 .read_status = dib7000m_read_status,
1459 .read_ber = dib7000m_read_ber,
1460 .read_signal_strength = dib7000m_read_signal_strength,
1461 .read_snr = dib7000m_read_snr,
1462 .read_ucblocks = dib7000m_read_unc_blocks,
1463};
1464
1465MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
1466MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator");
1467MODULE_LICENSE("GPL");