blob: 113fc1394d5dc2440fea291b9ec37c73e75a4797 [file] [log] [blame]
Patrick Boettchera75763f2006-10-18 08:34:16 -03001/*
2 * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC).
3 *
Patrick Boettcherb6884a12007-07-27 10:08:51 -03004 * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
Patrick Boettchera75763f2006-10-18 08:34:16 -03005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2.
9 */
10#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090011#include <linux/slab.h>
Patrick Boettchera75763f2006-10-18 08:34:16 -030012#include <linux/i2c.h>
13
Olivier Grenieef801962009-09-15 06:46:52 -030014#include "dvb_math.h"
Patrick Boettchera75763f2006-10-18 08:34:16 -030015#include "dvb_frontend.h"
16
17#include "dib7000p.h"
18
19static int debug;
20module_param(debug, int, 0644);
21MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
22
Matt Doran8f6956c2007-07-31 07:09:30 -030023static int buggy_sfn_workaround;
24module_param(buggy_sfn_workaround, int, 0644);
Patrick Boettcher8d999962007-07-31 10:36:06 -030025MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
Matt Doran8f6956c2007-07-31 07:09:30 -030026
Patrick Boettcherb6884a12007-07-27 10:08:51 -030027#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P: "); printk(args); printk("\n"); } } while (0)
Patrick Boettchera75763f2006-10-18 08:34:16 -030028
29struct dib7000p_state {
30 struct dvb_frontend demod;
31 struct dib7000p_config cfg;
32
33 u8 i2c_addr;
34 struct i2c_adapter *i2c_adap;
35
36 struct dibx000_i2c_master i2c_master;
37
38 u16 wbd_ref;
39
Patrick Boettcher904a82e2008-01-25 07:31:58 -030040 u8 current_band;
41 u32 current_bandwidth;
Patrick Boettchera75763f2006-10-18 08:34:16 -030042 struct dibx000_agc_config *current_agc;
43 u32 timf;
44
Patrick Boettcher01373a52007-07-30 12:49:04 -030045 u8 div_force_off : 1;
46 u8 div_state : 1;
47 u16 div_sync_wait;
Patrick Boettcherb6884a12007-07-27 10:08:51 -030048
49 u8 agc_state;
50
Patrick Boettchera75763f2006-10-18 08:34:16 -030051 u16 gpio_dir;
52 u16 gpio_val;
Matt Doran8f6956c2007-07-31 07:09:30 -030053
54 u8 sfn_workaround_active :1;
Patrick Boettchera75763f2006-10-18 08:34:16 -030055};
56
57enum dib7000p_power_mode {
58 DIB7000P_POWER_ALL = 0,
Patrick Boettcherb6884a12007-07-27 10:08:51 -030059 DIB7000P_POWER_ANALOG_ADC,
Patrick Boettchera75763f2006-10-18 08:34:16 -030060 DIB7000P_POWER_INTERFACE_ONLY,
61};
62
63static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
64{
65 u8 wb[2] = { reg >> 8, reg & 0xff };
66 u8 rb[2];
67 struct i2c_msg msg[2] = {
68 { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 },
69 { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
70 };
71
72 if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
Patrick Boettcherb6884a12007-07-27 10:08:51 -030073 dprintk("i2c read error on %d",reg);
Patrick Boettchera75763f2006-10-18 08:34:16 -030074
75 return (rb[0] << 8) | rb[1];
76}
77
78static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
79{
80 u8 b[4] = {
81 (reg >> 8) & 0xff, reg & 0xff,
82 (val >> 8) & 0xff, val & 0xff,
83 };
84 struct i2c_msg msg = {
85 .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
86 };
87 return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
88}
Patrick Boettcherb6884a12007-07-27 10:08:51 -030089static void dib7000p_write_tab(struct dib7000p_state *state, u16 *buf)
90{
91 u16 l = 0, r, *n;
92 n = buf;
93 l = *n++;
94 while (l) {
95 r = *n++;
96
97 do {
98 dib7000p_write_word(state, r, *n++);
99 r++;
100 } while (--l);
101 l = *n++;
102 }
103}
104
Patrick Boettchera75763f2006-10-18 08:34:16 -0300105static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode)
106{
107 int ret = 0;
108 u16 outreg, fifo_threshold, smo_mode;
109
110 outreg = 0;
111 fifo_threshold = 1792;
Olivier Grenieeac1fe12009-09-23 13:41:27 -0300112 smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300113
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300114 dprintk( "setting output mode for demod %p to %d",
Patrick Boettchera75763f2006-10-18 08:34:16 -0300115 &state->demod, mode);
116
117 switch (mode) {
118 case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock
119 outreg = (1 << 10); /* 0x0400 */
120 break;
121 case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock
122 outreg = (1 << 10) | (1 << 6); /* 0x0440 */
123 break;
124 case OUTMODE_MPEG2_SERIAL: // STBs with serial input
125 outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0480 */
126 break;
127 case OUTMODE_DIVERSITY:
128 if (state->cfg.hostbus_diversity)
129 outreg = (1 << 10) | (4 << 6); /* 0x0500 */
130 else
131 outreg = (1 << 11);
132 break;
133 case OUTMODE_MPEG2_FIFO: // e.g. USB feeding
134 smo_mode |= (3 << 1);
135 fifo_threshold = 512;
136 outreg = (1 << 10) | (5 << 6);
137 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300138 case OUTMODE_ANALOG_ADC:
139 outreg = (1 << 10) | (3 << 6);
140 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300141 case OUTMODE_HIGH_Z: // disable
142 outreg = 0;
143 break;
144 default:
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300145 dprintk( "Unhandled output_mode passed to be set for demod %p",&state->demod);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300146 break;
147 }
148
149 if (state->cfg.output_mpeg2_in_188_bytes)
150 smo_mode |= (1 << 5) ;
151
152 ret |= dib7000p_write_word(state, 235, smo_mode);
153 ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */
154 ret |= dib7000p_write_word(state, 1286, outreg); /* P_Div_active */
155
156 return ret;
157}
158
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300159static int dib7000p_set_diversity_in(struct dvb_frontend *demod, int onoff)
160{
161 struct dib7000p_state *state = demod->demodulator_priv;
162
163 if (state->div_force_off) {
164 dprintk( "diversity combination deactivated - forced by COFDM parameters");
165 onoff = 0;
Olivier Grenieeac1fe12009-09-23 13:41:27 -0300166 dib7000p_write_word(state, 207, 0);
167 } else
168 dib7000p_write_word(state, 207, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
169
Patrick Boettcher01373a52007-07-30 12:49:04 -0300170 state->div_state = (u8)onoff;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300171
172 if (onoff) {
173 dib7000p_write_word(state, 204, 6);
174 dib7000p_write_word(state, 205, 16);
175 /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300176 } else {
177 dib7000p_write_word(state, 204, 1);
178 dib7000p_write_word(state, 205, 0);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300179 }
180
181 return 0;
182}
183
Patrick Boettchera75763f2006-10-18 08:34:16 -0300184static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode)
185{
186 /* by default everything is powered off */
187 u16 reg_774 = 0xffff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899 = 0x0003,
188 reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff);
189
190 /* now, depending on the requested mode, we power on */
191 switch (mode) {
192 /* power up everything in the demod */
193 case DIB7000P_POWER_ALL:
194 reg_774 = 0x0000; reg_775 = 0x0000; reg_776 = 0x0; reg_899 = 0x0; reg_1280 &= 0x01ff;
195 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300196
197 case DIB7000P_POWER_ANALOG_ADC:
198 /* dem, cfg, iqc, sad, agc */
199 reg_774 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10) | (1 << 9));
200 /* nud */
201 reg_776 &= ~((1 << 0));
202 /* Dout */
203 reg_1280 &= ~((1 << 11));
204 /* fall through wanted to enable the interfaces */
205
Patrick Boettchera75763f2006-10-18 08:34:16 -0300206 /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */
207 case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */
208 reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10));
209 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300210
Patrick Boettchera75763f2006-10-18 08:34:16 -0300211/* TODO following stuff is just converted from the dib7000-driver - check when is used what */
212 }
213
214 dib7000p_write_word(state, 774, reg_774);
215 dib7000p_write_word(state, 775, reg_775);
216 dib7000p_write_word(state, 776, reg_776);
217 dib7000p_write_word(state, 899, reg_899);
218 dib7000p_write_word(state, 1280, reg_1280);
219
220 return 0;
221}
222
223static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no)
224{
225 u16 reg_908 = dib7000p_read_word(state, 908),
226 reg_909 = dib7000p_read_word(state, 909);
227
228 switch (no) {
229 case DIBX000_SLOW_ADC_ON:
230 reg_909 |= (1 << 1) | (1 << 0);
231 dib7000p_write_word(state, 909, reg_909);
232 reg_909 &= ~(1 << 1);
233 break;
234
235 case DIBX000_SLOW_ADC_OFF:
236 reg_909 |= (1 << 1) | (1 << 0);
237 break;
238
239 case DIBX000_ADC_ON:
240 reg_908 &= 0x0fff;
241 reg_909 &= 0x0003;
242 break;
243
244 case DIBX000_ADC_OFF: // leave the VBG voltage on
245 reg_908 |= (1 << 14) | (1 << 13) | (1 << 12);
246 reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
247 break;
248
249 case DIBX000_VBG_ENABLE:
250 reg_908 &= ~(1 << 15);
251 break;
252
253 case DIBX000_VBG_DISABLE:
254 reg_908 |= (1 << 15);
255 break;
256
257 default:
258 break;
259 }
260
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300261// dprintk( "908: %x, 909: %x\n", reg_908, reg_909);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300262
263 dib7000p_write_word(state, 908, reg_908);
264 dib7000p_write_word(state, 909, reg_909);
265}
266
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300267static int dib7000p_set_bandwidth(struct dib7000p_state *state, u32 bw)
Patrick Boettchera75763f2006-10-18 08:34:16 -0300268{
Patrick Boettchera75763f2006-10-18 08:34:16 -0300269 u32 timf;
270
271 // store the current bandwidth for later use
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300272 state->current_bandwidth = bw;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300273
274 if (state->timf == 0) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300275 dprintk( "using default timf");
Patrick Boettchera75763f2006-10-18 08:34:16 -0300276 timf = state->cfg.bw->timf;
277 } else {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300278 dprintk( "using updated timf");
Patrick Boettchera75763f2006-10-18 08:34:16 -0300279 timf = state->timf;
280 }
281
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300282 timf = timf * (bw / 50) / 160;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300283
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300284 dib7000p_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
285 dib7000p_write_word(state, 24, (u16) ((timf ) & 0xffff));
Patrick Boettchera75763f2006-10-18 08:34:16 -0300286
287 return 0;
288}
289
290static int dib7000p_sad_calib(struct dib7000p_state *state)
291{
292/* internal */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300293// dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth
Patrick Boettchera75763f2006-10-18 08:34:16 -0300294 dib7000p_write_word(state, 73, (0 << 1) | (0 << 0));
295 dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096
296
297 /* do the calibration */
298 dib7000p_write_word(state, 73, (1 << 0));
299 dib7000p_write_word(state, 73, (0 << 0));
300
301 msleep(1);
302
303 return 0;
304}
305
Patrick Boettcher01373a52007-07-30 12:49:04 -0300306int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
307{
308 struct dib7000p_state *state = demod->demodulator_priv;
309 if (value > 4095)
310 value = 4095;
311 state->wbd_ref = value;
312 return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
313}
314
315EXPORT_SYMBOL(dib7000p_set_wbd_ref);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300316static void dib7000p_reset_pll(struct dib7000p_state *state)
317{
318 struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300319 u16 clk_cfg0;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300320
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300321 /* force PLL bypass */
322 clk_cfg0 = (1 << 15) | ((bw->pll_ratio & 0x3f) << 9) |
323 (bw->modulo << 7) | (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) |
324 (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0);
325
326 dib7000p_write_word(state, 900, clk_cfg0);
327
328 /* P_pll_cfg */
Patrick Boettchera75763f2006-10-18 08:34:16 -0300329 dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300330 clk_cfg0 = (bw->pll_bypass << 15) | (clk_cfg0 & 0x7fff);
331 dib7000p_write_word(state, 900, clk_cfg0);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300332
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300333 dib7000p_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff));
334 dib7000p_write_word(state, 19, (u16) ( (bw->internal*1000 ) & 0xffff));
335 dib7000p_write_word(state, 21, (u16) ( (bw->ifreq >> 16) & 0xffff));
336 dib7000p_write_word(state, 22, (u16) ( (bw->ifreq ) & 0xffff));
Patrick Boettchera75763f2006-10-18 08:34:16 -0300337
338 dib7000p_write_word(state, 72, bw->sad_cfg);
339}
340
341static int dib7000p_reset_gpio(struct dib7000p_state *st)
342{
343 /* reset the GPIOs */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300344 dprintk( "gpio dir: %x: val: %x, pwm_pos: %x",st->gpio_dir, st->gpio_val,st->cfg.gpio_pwm_pos);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300345
346 dib7000p_write_word(st, 1029, st->gpio_dir);
347 dib7000p_write_word(st, 1030, st->gpio_val);
348
349 /* TODO 1031 is P_gpio_od */
350
351 dib7000p_write_word(st, 1032, st->cfg.gpio_pwm_pos);
352
353 dib7000p_write_word(st, 1037, st->cfg.pwm_freq_div);
354 return 0;
355}
356
Patrick Boettcher01373a52007-07-30 12:49:04 -0300357static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
358{
359 st->gpio_dir = dib7000p_read_word(st, 1029);
360 st->gpio_dir &= ~(1 << num); /* reset the direction bit */
361 st->gpio_dir |= (dir & 0x1) << num; /* set the new direction */
362 dib7000p_write_word(st, 1029, st->gpio_dir);
363
364 st->gpio_val = dib7000p_read_word(st, 1030);
365 st->gpio_val &= ~(1 << num); /* reset the direction bit */
366 st->gpio_val |= (val & 0x01) << num; /* set the new value */
367 dib7000p_write_word(st, 1030, st->gpio_val);
368
369 return 0;
370}
371
372int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
373{
374 struct dib7000p_state *state = demod->demodulator_priv;
375 return dib7000p_cfg_gpio(state, num, dir, val);
376}
377
378EXPORT_SYMBOL(dib7000p_set_gpio);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300379static u16 dib7000p_defaults[] =
380
381{
382 // auto search configuration
383 3, 2,
384 0x0004,
385 0x1000,
386 0x0814, /* Equal Lock */
387
388 12, 6,
389 0x001b,
390 0x7740,
391 0x005b,
392 0x8d80,
393 0x01c9,
394 0xc380,
395 0x0000,
396 0x0080,
397 0x0000,
398 0x0090,
399 0x0001,
400 0xd4c0,
401
402 1, 26,
403 0x6680, // P_timf_alpha=6, P_corm_alpha=6, P_corm_thres=128 default: 6,4,26
404
405 /* set ADC level to -16 */
406 11, 79,
407 (1 << 13) - 825 - 117,
408 (1 << 13) - 837 - 117,
409 (1 << 13) - 811 - 117,
410 (1 << 13) - 766 - 117,
411 (1 << 13) - 737 - 117,
412 (1 << 13) - 693 - 117,
413 (1 << 13) - 648 - 117,
414 (1 << 13) - 619 - 117,
415 (1 << 13) - 575 - 117,
416 (1 << 13) - 531 - 117,
417 (1 << 13) - 501 - 117,
418
419 1, 142,
420 0x0410, // P_palf_filter_on=1, P_palf_filter_freeze=0, P_palf_alpha_regul=16
421
422 /* disable power smoothing */
423 8, 145,
424 0,
425 0,
426 0,
427 0,
428 0,
429 0,
430 0,
431 0,
432
433 1, 154,
434 1 << 13, // P_fft_freq_dir=1, P_fft_nb_to_cut=0
435
436 1, 168,
437 0x0ccd, // P_pha3_thres, default 0x3000
438
439// 1, 169,
440// 0x0010, // P_cti_use_cpe=0, P_cti_use_prog=0, P_cti_win_len=16, default: 0x0010
441
442 1, 183,
443 0x200f, // P_cspu_regul=512, P_cspu_win_cut=15, default: 0x2005
444
445 5, 187,
446 0x023d, // P_adp_regul_cnt=573, default: 410
447 0x00a4, // P_adp_noise_cnt=
448 0x00a4, // P_adp_regul_ext
449 0x7ff0, // P_adp_noise_ext
450 0x3ccc, // P_adp_fil
451
452 1, 198,
453 0x800, // P_equal_thres_wgn
454
455 1, 222,
456 0x0010, // P_fec_ber_rs_len=2
457
458 1, 235,
459 0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
460
461 2, 901,
462 0x0006, // P_clk_cfg1
463 (3 << 10) | (1 << 6), // P_divclksel=3 P_divbitsel=1
464
465 1, 905,
466 0x2c8e, // Tuner IO bank: max drive (14mA) + divout pads max drive
467
468 0,
469};
470
Patrick Boettchera75763f2006-10-18 08:34:16 -0300471static int dib7000p_demod_reset(struct dib7000p_state *state)
472{
473 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
474
475 dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE);
476
477 /* restart all parts */
478 dib7000p_write_word(state, 770, 0xffff);
479 dib7000p_write_word(state, 771, 0xffff);
480 dib7000p_write_word(state, 772, 0x001f);
481 dib7000p_write_word(state, 898, 0x0003);
482 /* except i2c, sdio, gpio - control interfaces */
483 dib7000p_write_word(state, 1280, 0x01fc - ((1 << 7) | (1 << 6) | (1 << 5)) );
484
485 dib7000p_write_word(state, 770, 0);
486 dib7000p_write_word(state, 771, 0);
487 dib7000p_write_word(state, 772, 0);
488 dib7000p_write_word(state, 898, 0);
489 dib7000p_write_word(state, 1280, 0);
490
491 /* default */
492 dib7000p_reset_pll(state);
493
494 if (dib7000p_reset_gpio(state) != 0)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300495 dprintk( "GPIO reset was not successful.");
Patrick Boettchera75763f2006-10-18 08:34:16 -0300496
497 if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300498 dprintk( "OUTPUT_MODE could not be reset.");
Patrick Boettchera75763f2006-10-18 08:34:16 -0300499
500 /* unforce divstr regardless whether i2c enumeration was done or not */
501 dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1) );
502
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300503 dib7000p_set_bandwidth(state, 8000);
504
505 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
506 dib7000p_sad_calib(state);
507 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
508
509 // P_iqc_alpha_pha, P_iqc_alpha_amp_dcc_alpha, ...
510 if(state->cfg.tuner_is_baseband)
511 dib7000p_write_word(state, 36,0x0755);
512 else
513 dib7000p_write_word(state, 36,0x1f55);
514
515 dib7000p_write_tab(state, dib7000p_defaults);
516
Patrick Boettchera75763f2006-10-18 08:34:16 -0300517 dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
518
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300519
Patrick Boettchera75763f2006-10-18 08:34:16 -0300520 return 0;
521}
522
Patrick Boettchera75763f2006-10-18 08:34:16 -0300523static void dib7000p_pll_clk_cfg(struct dib7000p_state *state)
524{
525 u16 tmp = 0;
526 tmp = dib7000p_read_word(state, 903);
527 dib7000p_write_word(state, 903, (tmp | 0x1)); //pwr-up pll
528 tmp = dib7000p_read_word(state, 900);
529 dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6)); //use High freq clock
530}
531
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300532static void dib7000p_restart_agc(struct dib7000p_state *state)
Patrick Boettchera75763f2006-10-18 08:34:16 -0300533{
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300534 // P_restart_iqc & P_restart_agc
535 dib7000p_write_word(state, 770, (1 << 11) | (1 << 9));
536 dib7000p_write_word(state, 770, 0x0000);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300537}
538
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300539static int dib7000p_update_lna(struct dib7000p_state *state)
Patrick Boettchera75763f2006-10-18 08:34:16 -0300540{
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300541 u16 dyn_gain;
542
543 // when there is no LNA to program return immediatly
544 if (state->cfg.update_lna) {
Patrick Boettcher01373a52007-07-30 12:49:04 -0300545 // read dyn_gain here (because it is demod-dependent and not fe)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300546 dyn_gain = dib7000p_read_word(state, 394);
547 if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
548 dib7000p_restart_agc(state);
549 return 1;
550 }
551 }
552
553 return 0;
554}
555
556static int dib7000p_set_agc_config(struct dib7000p_state *state, u8 band)
557{
558 struct dibx000_agc_config *agc = NULL;
559 int i;
560 if (state->current_band == band && state->current_agc != NULL)
561 return 0;
562 state->current_band = band;
563
564 for (i = 0; i < state->cfg.agc_config_count; i++)
565 if (state->cfg.agc[i].band_caps & band) {
566 agc = &state->cfg.agc[i];
567 break;
568 }
569
570 if (agc == NULL) {
571 dprintk( "no valid AGC configuration found for band 0x%02x",band);
572 return -EINVAL;
573 }
574
575 state->current_agc = agc;
576
577 /* AGC */
578 dib7000p_write_word(state, 75 , agc->setup );
579 dib7000p_write_word(state, 76 , agc->inv_gain );
580 dib7000p_write_word(state, 77 , agc->time_stabiliz );
581 dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock);
582
583 // Demod AGC loop configuration
584 dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp);
585 dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp);
586
587 /* AGC continued */
588 dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d",
589 state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
590
591 if (state->wbd_ref != 0)
592 dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref);
593 else
594 dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref);
595
596 dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
597
598 dib7000p_write_word(state, 107, agc->agc1_max);
599 dib7000p_write_word(state, 108, agc->agc1_min);
600 dib7000p_write_word(state, 109, agc->agc2_max);
601 dib7000p_write_word(state, 110, agc->agc2_min);
602 dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
603 dib7000p_write_word(state, 112, agc->agc1_pt3);
604 dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
605 dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
606 dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
607 return 0;
608}
609
610static int dib7000p_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
611{
612 struct dib7000p_state *state = demod->demodulator_priv;
613 int ret = -1;
614 u8 *agc_state = &state->agc_state;
615 u8 agc_split;
616
617 switch (state->agc_state) {
618 case 0:
619 // set power-up level: interf+analog+AGC
620 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
621 dib7000p_set_adc_state(state, DIBX000_ADC_ON);
622 dib7000p_pll_clk_cfg(state);
623
624 if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0)
625 return -1;
626
627 ret = 7;
628 (*agc_state)++;
629 break;
630
631 case 1:
632 // AGC initialization
633 if (state->cfg.agc_control)
634 state->cfg.agc_control(&state->demod, 1);
635
636 dib7000p_write_word(state, 78, 32768);
637 if (!state->current_agc->perform_agc_softsplit) {
638 /* we are using the wbd - so slow AGC startup */
639 /* force 0 split on WBD and restart AGC */
640 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | (1 << 8));
641 (*agc_state)++;
642 ret = 5;
643 } else {
644 /* default AGC startup */
645 (*agc_state) = 4;
646 /* wait AGC rough lock time */
647 ret = 7;
648 }
649
650 dib7000p_restart_agc(state);
651 break;
652
653 case 2: /* fast split search path after 5sec */
654 dib7000p_write_word(state, 75, state->current_agc->setup | (1 << 4)); /* freeze AGC loop */
655 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (2 << 9) | (0 << 8)); /* fast split search 0.25kHz */
656 (*agc_state)++;
657 ret = 14;
658 break;
659
660 case 3: /* split search ended */
Patrick Boettcher01373a52007-07-30 12:49:04 -0300661 agc_split = (u8)dib7000p_read_word(state, 396); /* store the split value for the next time */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300662 dib7000p_write_word(state, 78, dib7000p_read_word(state, 394)); /* set AGC gain start value */
663
664 dib7000p_write_word(state, 75, state->current_agc->setup); /* std AGC loop */
665 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
666
667 dib7000p_restart_agc(state);
668
669 dprintk( "SPLIT %p: %hd", demod, agc_split);
670
671 (*agc_state)++;
672 ret = 5;
673 break;
674
675 case 4: /* LNA startup */
676 // wait AGC accurate lock time
677 ret = 7;
678
679 if (dib7000p_update_lna(state))
680 // wait only AGC rough lock time
681 ret = 5;
682 else // nothing was done, go to the next state
683 (*agc_state)++;
684 break;
685
686 case 5:
687 if (state->cfg.agc_control)
688 state->cfg.agc_control(&state->demod, 0);
689 (*agc_state)++;
690 break;
691 default:
692 break;
693 }
694 return ret;
695}
696
697static void dib7000p_update_timf(struct dib7000p_state *state)
698{
699 u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428);
700 state->timf = timf * 160 / (state->current_bandwidth / 50);
701 dib7000p_write_word(state, 23, (u16) (timf >> 16));
702 dib7000p_write_word(state, 24, (u16) (timf & 0xffff));
703 dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->cfg.bw->timf);
704
705}
706
707static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_frontend_parameters *ch, u8 seq)
708{
709 u16 value, est[4];
710
711 dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
Patrick Boettchera75763f2006-10-18 08:34:16 -0300712
713 /* nfft, guard, qam, alpha */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300714 value = 0;
715 switch (ch->u.ofdm.transmission_mode) {
716 case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
717 case /* 4K MODE */ 255: value |= (2 << 7); break;
718 default:
719 case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
720 }
721 switch (ch->u.ofdm.guard_interval) {
722 case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
723 case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
724 case GUARD_INTERVAL_1_4: value |= (3 << 5); break;
725 default:
726 case GUARD_INTERVAL_1_8: value |= (2 << 5); break;
727 }
728 switch (ch->u.ofdm.constellation) {
729 case QPSK: value |= (0 << 3); break;
730 case QAM_16: value |= (1 << 3); break;
731 default:
732 case QAM_64: value |= (2 << 3); break;
733 }
734 switch (HIERARCHY_1) {
735 case HIERARCHY_2: value |= 2; break;
736 case HIERARCHY_4: value |= 4; break;
737 default:
738 case HIERARCHY_1: value |= 1; break;
739 }
740 dib7000p_write_word(state, 0, value);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300741 dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */
742
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300743 /* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
744 value = 0;
745 if (1 != 0)
746 value |= (1 << 6);
747 if (ch->u.ofdm.hierarchy_information == 1)
748 value |= (1 << 4);
749 if (1 == 1)
750 value |= 1;
751 switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
752 case FEC_2_3: value |= (2 << 1); break;
753 case FEC_3_4: value |= (3 << 1); break;
754 case FEC_5_6: value |= (5 << 1); break;
755 case FEC_7_8: value |= (7 << 1); break;
756 default:
757 case FEC_1_2: value |= (1 << 1); break;
758 }
759 dib7000p_write_word(state, 208, value);
760
761 /* offset loop parameters */
762 dib7000p_write_word(state, 26, 0x6680); // timf(6xxx)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300763 dib7000p_write_word(state, 32, 0x0003); // pha_off_max(xxx3)
Matt Doran8f6956c2007-07-31 07:09:30 -0300764 dib7000p_write_word(state, 29, 0x1273); // isi
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300765 dib7000p_write_word(state, 33, 0x0005); // sfreq(xxx5)
Patrick Boettchera75763f2006-10-18 08:34:16 -0300766
767 /* P_dvsy_sync_wait */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300768 switch (ch->u.ofdm.transmission_mode) {
769 case TRANSMISSION_MODE_8K: value = 256; break;
770 case /* 4K MODE */ 255: value = 128; break;
771 case TRANSMISSION_MODE_2K:
772 default: value = 64; break;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300773 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300774 switch (ch->u.ofdm.guard_interval) {
775 case GUARD_INTERVAL_1_16: value *= 2; break;
776 case GUARD_INTERVAL_1_8: value *= 4; break;
777 case GUARD_INTERVAL_1_4: value *= 8; break;
778 default:
779 case GUARD_INTERVAL_1_32: value *= 1; break;
780 }
781 state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO
Patrick Boettchera75763f2006-10-18 08:34:16 -0300782
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300783 /* deactive the possibility of diversity reception if extended interleaver */
784 state->div_force_off = !1 && ch->u.ofdm.transmission_mode != TRANSMISSION_MODE_8K;
785 dib7000p_set_diversity_in(&state->demod, state->div_state);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300786
787 /* channel estimation fine configuration */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300788 switch (ch->u.ofdm.constellation) {
789 case QAM_64:
Patrick Boettchera75763f2006-10-18 08:34:16 -0300790 est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
791 est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
792 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
793 est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */
794 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300795 case QAM_16:
Patrick Boettchera75763f2006-10-18 08:34:16 -0300796 est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */
797 est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */
798 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
799 est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */
800 break;
801 default:
802 est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */
803 est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */
804 est[2] = 0x0333; /* P_adp_regul_ext 0.1 */
805 est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */
806 break;
807 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300808 for (value = 0; value < 4; value++)
809 dib7000p_write_word(state, 187 + value, est[value]);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300810}
811
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300812static int dib7000p_autosearch_start(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
Patrick Boettchera75763f2006-10-18 08:34:16 -0300813{
814 struct dib7000p_state *state = demod->demodulator_priv;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300815 struct dvb_frontend_parameters schan;
816 u32 value, factor;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300817
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300818 schan = *ch;
819 schan.u.ofdm.constellation = QAM_64;
820 schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
821 schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
822 schan.u.ofdm.code_rate_HP = FEC_2_3;
823 schan.u.ofdm.code_rate_LP = FEC_3_4;
824 schan.u.ofdm.hierarchy_information = 0;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300825
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300826 dib7000p_set_channel(state, &schan, 7);
827
828 factor = BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth);
829 if (factor >= 5000)
830 factor = 1;
831 else
832 factor = 6;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300833
834 // always use the setting for 8MHz here lock_time for 7,6 MHz are longer
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300835 value = 30 * state->cfg.bw->internal * factor;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300836 dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time
837 dib7000p_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300838 value = 100 * state->cfg.bw->internal * factor;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300839 dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time
840 dib7000p_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300841 value = 500 * state->cfg.bw->internal * factor;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300842 dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
843 dib7000p_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time
844
845 value = dib7000p_read_word(state, 0);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300846 dib7000p_write_word(state, 0, (u16) ((1 << 9) | value));
Patrick Boettchera75763f2006-10-18 08:34:16 -0300847 dib7000p_read_word(state, 1284);
848 dib7000p_write_word(state, 0, (u16) value);
849
850 return 0;
851}
852
853static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod)
854{
855 struct dib7000p_state *state = demod->demodulator_priv;
856 u16 irq_pending = dib7000p_read_word(state, 1284);
857
858 if (irq_pending & 0x1) // failed
859 return 1;
860
861 if (irq_pending & 0x2) // succeeded
862 return 2;
863
864 return 0; // still pending
865}
866
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300867static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 bw)
868{
869 static s16 notch[]={16143, 14402, 12238, 9713, 6902, 3888, 759, -2392};
870 static u8 sine [] ={0, 2, 3, 5, 6, 8, 9, 11, 13, 14, 16, 17, 19, 20, 22,
871 24, 25, 27, 28, 30, 31, 33, 34, 36, 38, 39, 41, 42, 44, 45, 47, 48, 50, 51,
872 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80,
873 82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, 104, 105,
874 107, 108, 109, 111, 112, 114, 115, 117, 118, 119, 121, 122, 123, 125, 126,
875 128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 144, 145, 146,
876 147, 149, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 162, 164, 165,
877 166, 167, 168, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182,
878 183, 184, 185, 186, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
879 199, 200, 201, 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 212,
880 213, 214, 215, 215, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 224,
881 225, 226, 227, 227, 228, 229, 229, 230, 231, 231, 232, 233, 233, 234, 235,
882 235, 236, 237, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 243,
883 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 248, 249, 249, 249,
884 250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 254,
885 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
886 255, 255, 255, 255, 255, 255};
887
888 u32 xtal = state->cfg.bw->xtal_hz / 1000;
Julia Lawall75b697f2009-08-01 16:48:41 -0300889 int f_rel = DIV_ROUND_CLOSEST(rf_khz, xtal) * xtal - rf_khz;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300890 int k;
891 int coef_re[8],coef_im[8];
892 int bw_khz = bw;
893 u32 pha;
894
895 dprintk( "relative position of the Spur: %dk (RF: %dk, XTAL: %dk)", f_rel, rf_khz, xtal);
896
897
898 if (f_rel < -bw_khz/2 || f_rel > bw_khz/2)
899 return;
900
901 bw_khz /= 100;
902
903 dib7000p_write_word(state, 142 ,0x0610);
904
905 for (k = 0; k < 8; k++) {
906 pha = ((f_rel * (k+1) * 112 * 80/bw_khz) /1000) & 0x3ff;
907
908 if (pha==0) {
909 coef_re[k] = 256;
910 coef_im[k] = 0;
911 } else if(pha < 256) {
912 coef_re[k] = sine[256-(pha&0xff)];
913 coef_im[k] = sine[pha&0xff];
914 } else if (pha == 256) {
915 coef_re[k] = 0;
916 coef_im[k] = 256;
917 } else if (pha < 512) {
918 coef_re[k] = -sine[pha&0xff];
919 coef_im[k] = sine[256 - (pha&0xff)];
920 } else if (pha == 512) {
921 coef_re[k] = -256;
922 coef_im[k] = 0;
923 } else if (pha < 768) {
924 coef_re[k] = -sine[256-(pha&0xff)];
925 coef_im[k] = -sine[pha&0xff];
926 } else if (pha == 768) {
927 coef_re[k] = 0;
928 coef_im[k] = -256;
929 } else {
930 coef_re[k] = sine[pha&0xff];
931 coef_im[k] = -sine[256 - (pha&0xff)];
932 }
933
934 coef_re[k] *= notch[k];
935 coef_re[k] += (1<<14);
936 if (coef_re[k] >= (1<<24))
937 coef_re[k] = (1<<24) - 1;
938 coef_re[k] /= (1<<15);
939
940 coef_im[k] *= notch[k];
941 coef_im[k] += (1<<14);
942 if (coef_im[k] >= (1<<24))
943 coef_im[k] = (1<<24)-1;
944 coef_im[k] /= (1<<15);
945
946 dprintk( "PALF COEF: %d re: %d im: %d", k, coef_re[k], coef_im[k]);
947
948 dib7000p_write_word(state, 143, (0 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
949 dib7000p_write_word(state, 144, coef_im[k] & 0x3ff);
950 dib7000p_write_word(state, 143, (1 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
951 }
952 dib7000p_write_word(state,143 ,0);
953}
954
955static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
Patrick Boettchera75763f2006-10-18 08:34:16 -0300956{
957 struct dib7000p_state *state = demod->demodulator_priv;
958 u16 tmp = 0;
959
960 if (ch != NULL)
961 dib7000p_set_channel(state, ch, 0);
962 else
963 return -EINVAL;
964
965 // restart demod
966 dib7000p_write_word(state, 770, 0x4000);
967 dib7000p_write_word(state, 770, 0x0000);
968 msleep(45);
969
970 /* 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 */
Matt Doran8f6956c2007-07-31 07:09:30 -0300971 tmp = (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3);
972 if (state->sfn_workaround_active) {
973 dprintk( "SFN workaround is active");
974 tmp |= (1 << 9);
975 dib7000p_write_word(state, 166, 0x4000); // P_pha3_force_pha_shift
976 } else {
977 dib7000p_write_word(state, 166, 0x0000); // P_pha3_force_pha_shift
978 }
979 dib7000p_write_word(state, 29, tmp);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300980
981 // never achieved a lock with that bandwidth so far - wait for osc-freq to update
982 if (state->timf == 0)
983 msleep(200);
984
985 /* offset loop parameters */
986
987 /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
988 tmp = (6 << 8) | 0x80;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300989 switch (ch->u.ofdm.transmission_mode) {
990 case TRANSMISSION_MODE_2K: tmp |= (7 << 12); break;
991 case /* 4K MODE */ 255: tmp |= (8 << 12); break;
992 default:
993 case TRANSMISSION_MODE_8K: tmp |= (9 << 12); break;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300994 }
995 dib7000p_write_word(state, 26, tmp); /* timf_a(6xxx) */
996
997 /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
998 tmp = (0 << 4);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300999 switch (ch->u.ofdm.transmission_mode) {
1000 case TRANSMISSION_MODE_2K: tmp |= 0x6; break;
1001 case /* 4K MODE */ 255: tmp |= 0x7; break;
1002 default:
1003 case TRANSMISSION_MODE_8K: tmp |= 0x8; break;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001004 }
1005 dib7000p_write_word(state, 32, tmp);
1006
1007 /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
1008 tmp = (0 << 4);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001009 switch (ch->u.ofdm.transmission_mode) {
1010 case TRANSMISSION_MODE_2K: tmp |= 0x6; break;
1011 case /* 4K MODE */ 255: tmp |= 0x7; break;
1012 default:
1013 case TRANSMISSION_MODE_8K: tmp |= 0x8; break;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001014 }
1015 dib7000p_write_word(state, 33, tmp);
1016
1017 tmp = dib7000p_read_word(state,509);
1018 if (!((tmp >> 6) & 0x1)) {
1019 /* restart the fec */
1020 tmp = dib7000p_read_word(state,771);
1021 dib7000p_write_word(state, 771, tmp | (1 << 1));
1022 dib7000p_write_word(state, 771, tmp);
1023 msleep(10);
1024 tmp = dib7000p_read_word(state,509);
1025 }
1026
1027 // we achieved a lock - it's time to update the osc freq
1028 if ((tmp >> 6) & 0x1)
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001029 dib7000p_update_timf(state);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001030
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001031 if (state->cfg.spur_protect)
1032 dib7000p_spur_protect(state, ch->frequency/1000, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
1033
1034 dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
Patrick Boettchera75763f2006-10-18 08:34:16 -03001035 return 0;
1036}
1037
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001038static int dib7000p_wakeup(struct dvb_frontend *demod)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001039{
Patrick Boettchera75763f2006-10-18 08:34:16 -03001040 struct dib7000p_state *state = demod->demodulator_priv;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001041 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
1042 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001043 return 0;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001044}
1045
1046static int dib7000p_sleep(struct dvb_frontend *demod)
1047{
1048 struct dib7000p_state *state = demod->demodulator_priv;
1049 return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
1050}
1051
1052static int dib7000p_identify(struct dib7000p_state *st)
1053{
1054 u16 value;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001055 dprintk( "checking demod on I2C address: %d (%x)",
Patrick Boettchera75763f2006-10-18 08:34:16 -03001056 st->i2c_addr, st->i2c_addr);
1057
1058 if ((value = dib7000p_read_word(st, 768)) != 0x01b3) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001059 dprintk( "wrong Vendor ID (read=0x%x)",value);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001060 return -EREMOTEIO;
1061 }
1062
1063 if ((value = dib7000p_read_word(st, 769)) != 0x4000) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001064 dprintk( "wrong Device ID (%x)",value);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001065 return -EREMOTEIO;
1066 }
1067
1068 return 0;
1069}
1070
1071
1072static int dib7000p_get_frontend(struct dvb_frontend* fe,
1073 struct dvb_frontend_parameters *fep)
1074{
1075 struct dib7000p_state *state = fe->demodulator_priv;
1076 u16 tps = dib7000p_read_word(state,463);
1077
1078 fep->inversion = INVERSION_AUTO;
1079
Patrick Boettcher904a82e2008-01-25 07:31:58 -03001080 fep->u.ofdm.bandwidth = BANDWIDTH_TO_INDEX(state->current_bandwidth);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001081
1082 switch ((tps >> 8) & 0x3) {
1083 case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
1084 case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
1085 /* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
1086 }
1087
1088 switch (tps & 0x3) {
1089 case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
1090 case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
1091 case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
1092 case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
1093 }
1094
1095 switch ((tps >> 14) & 0x3) {
1096 case 0: fep->u.ofdm.constellation = QPSK; break;
1097 case 1: fep->u.ofdm.constellation = QAM_16; break;
1098 case 2:
1099 default: fep->u.ofdm.constellation = QAM_64; break;
1100 }
1101
1102 /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
1103 /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
1104
1105 fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
1106 switch ((tps >> 5) & 0x7) {
1107 case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
1108 case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
1109 case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
1110 case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
1111 case 7:
1112 default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
1113
1114 }
1115
1116 switch ((tps >> 2) & 0x7) {
1117 case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
1118 case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
1119 case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
1120 case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
1121 case 7:
1122 default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
1123 }
1124
1125 /* native interleaver: (dib7000p_read_word(state, 464) >> 5) & 0x1 */
1126
1127 return 0;
1128}
1129
1130static int dib7000p_set_frontend(struct dvb_frontend* fe,
1131 struct dvb_frontend_parameters *fep)
1132{
1133 struct dib7000p_state *state = fe->demodulator_priv;
Soeren Moch853ea132008-01-25 06:27:06 -03001134 int time, ret;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001135
Soeren Moch853ea132008-01-25 06:27:06 -03001136 dib7000p_set_output_mode(state, OUTMODE_HIGH_Z);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001137
Patrick Boettcher904a82e2008-01-25 07:31:58 -03001138 /* maybe the parameter has been changed */
Matt Doran8f6956c2007-07-31 07:09:30 -03001139 state->sfn_workaround_active = buggy_sfn_workaround;
1140
Patrick Boettchera75763f2006-10-18 08:34:16 -03001141 if (fe->ops.tuner_ops.set_params)
1142 fe->ops.tuner_ops.set_params(fe, fep);
1143
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001144 /* start up the AGC */
1145 state->agc_state = 0;
1146 do {
1147 time = dib7000p_agc_startup(fe, fep);
1148 if (time != -1)
1149 msleep(time);
1150 } while (time != -1);
1151
Patrick Boettchera75763f2006-10-18 08:34:16 -03001152 if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
1153 fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
1154 fep->u.ofdm.constellation == QAM_AUTO ||
1155 fep->u.ofdm.code_rate_HP == FEC_AUTO) {
1156 int i = 800, found;
1157
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001158 dib7000p_autosearch_start(fe, fep);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001159 do {
1160 msleep(1);
1161 found = dib7000p_autosearch_is_irq(fe);
1162 } while (found == 0 && i--);
1163
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001164 dprintk("autosearch returns: %d",found);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001165 if (found == 0 || found == 1)
1166 return 0; // no channel found
1167
1168 dib7000p_get_frontend(fe, fep);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001169 }
1170
Soeren Moch853ea132008-01-25 06:27:06 -03001171 ret = dib7000p_tune(fe, fep);
1172
Patrick Boettchera75763f2006-10-18 08:34:16 -03001173 /* make this a config parameter */
Steven Totha38d6e32008-04-22 15:37:01 -03001174 dib7000p_set_output_mode(state, state->cfg.output_mode);
Soeren Moch853ea132008-01-25 06:27:06 -03001175 return ret;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001176}
1177
1178static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat)
1179{
1180 struct dib7000p_state *state = fe->demodulator_priv;
1181 u16 lock = dib7000p_read_word(state, 509);
1182
1183 *stat = 0;
1184
1185 if (lock & 0x8000)
1186 *stat |= FE_HAS_SIGNAL;
1187 if (lock & 0x3000)
1188 *stat |= FE_HAS_CARRIER;
1189 if (lock & 0x0100)
1190 *stat |= FE_HAS_VITERBI;
1191 if (lock & 0x0010)
1192 *stat |= FE_HAS_SYNC;
Olivier Grenieeac1fe12009-09-23 13:41:27 -03001193 if ((lock & 0x0038) == 0x38)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001194 *stat |= FE_HAS_LOCK;
1195
1196 return 0;
1197}
1198
1199static int dib7000p_read_ber(struct dvb_frontend *fe, u32 *ber)
1200{
1201 struct dib7000p_state *state = fe->demodulator_priv;
1202 *ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501);
1203 return 0;
1204}
1205
1206static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
1207{
1208 struct dib7000p_state *state = fe->demodulator_priv;
1209 *unc = dib7000p_read_word(state, 506);
1210 return 0;
1211}
1212
1213static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
1214{
1215 struct dib7000p_state *state = fe->demodulator_priv;
1216 u16 val = dib7000p_read_word(state, 394);
1217 *strength = 65535 - val;
1218 return 0;
1219}
1220
1221static int dib7000p_read_snr(struct dvb_frontend* fe, u16 *snr)
1222{
Olivier Grenieef801962009-09-15 06:46:52 -03001223 struct dib7000p_state *state = fe->demodulator_priv;
1224 u16 val;
1225 s32 signal_mant, signal_exp, noise_mant, noise_exp;
1226 u32 result = 0;
1227
1228 val = dib7000p_read_word(state, 479);
1229 noise_mant = (val >> 4) & 0xff;
1230 noise_exp = ((val & 0xf) << 2);
1231 val = dib7000p_read_word(state, 480);
1232 noise_exp += ((val >> 14) & 0x3);
1233 if ((noise_exp & 0x20) != 0)
1234 noise_exp -= 0x40;
1235
1236 signal_mant = (val >> 6) & 0xFF;
1237 signal_exp = (val & 0x3F);
1238 if ((signal_exp & 0x20) != 0)
1239 signal_exp -= 0x40;
1240
1241 if (signal_mant != 0)
1242 result = intlog10(2) * 10 * signal_exp + 10 *
1243 intlog10(signal_mant);
1244 else
1245 result = intlog10(2) * 10 * signal_exp - 100;
1246
1247 if (noise_mant != 0)
1248 result -= intlog10(2) * 10 * noise_exp + 10 *
1249 intlog10(noise_mant);
1250 else
1251 result -= intlog10(2) * 10 * noise_exp - 100;
1252
1253 *snr = result / ((1 << 24) / 10);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001254 return 0;
1255}
1256
1257static int dib7000p_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
1258{
1259 tune->min_delay_ms = 1000;
1260 return 0;
1261}
1262
1263static void dib7000p_release(struct dvb_frontend *demod)
1264{
1265 struct dib7000p_state *st = demod->demodulator_priv;
1266 dibx000_exit_i2c_master(&st->i2c_master);
1267 kfree(st);
1268}
1269
1270int dib7000pc_detection(struct i2c_adapter *i2c_adap)
1271{
1272 u8 tx[2], rx[2];
1273 struct i2c_msg msg[2] = {
1274 { .addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2 },
1275 { .addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2 },
1276 };
1277
1278 tx[0] = 0x03;
1279 tx[1] = 0x00;
1280
1281 if (i2c_transfer(i2c_adap, msg, 2) == 2)
1282 if (rx[0] == 0x01 && rx[1] == 0xb3) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001283 dprintk("-D- DiB7000PC detected");
Patrick Boettchera75763f2006-10-18 08:34:16 -03001284 return 1;
1285 }
1286
1287 msg[0].addr = msg[1].addr = 0x40;
1288
1289 if (i2c_transfer(i2c_adap, msg, 2) == 2)
1290 if (rx[0] == 0x01 && rx[1] == 0xb3) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001291 dprintk("-D- DiB7000PC detected");
Patrick Boettchera75763f2006-10-18 08:34:16 -03001292 return 1;
1293 }
1294
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001295 dprintk("-D- DiB7000PC not detected");
Patrick Boettchera75763f2006-10-18 08:34:16 -03001296 return 0;
1297}
1298EXPORT_SYMBOL(dib7000pc_detection);
1299
1300struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
1301{
1302 struct dib7000p_state *st = demod->demodulator_priv;
1303 return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
1304}
1305EXPORT_SYMBOL(dib7000p_get_i2c_master);
1306
Olivier Grenief8731f42009-09-18 04:08:43 -03001307int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
1308{
1309 struct dib7000p_state *state = fe->demodulator_priv;
1310 u16 val = dib7000p_read_word(state, 235) & 0xffef;
1311 val |= (onoff & 0x1) << 4;
1312 dprintk("PID filter enabled %d", onoff);
1313 return dib7000p_write_word(state, 235, val);
1314}
1315EXPORT_SYMBOL(dib7000p_pid_filter_ctrl);
1316
1317int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
1318{
1319 struct dib7000p_state *state = fe->demodulator_priv;
1320 dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
1321 return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0);
1322}
1323EXPORT_SYMBOL(dib7000p_pid_filter);
1324
Patrick Boettchera75763f2006-10-18 08:34:16 -03001325int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
1326{
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001327 struct dib7000p_state *dpst;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001328 int k = 0;
1329 u8 new_addr = 0;
1330
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001331 dpst = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
1332 if (!dpst)
1333 return -ENODEV;
1334
1335 dpst->i2c_adap = i2c;
1336
Patrick Boettchera75763f2006-10-18 08:34:16 -03001337 for (k = no_of_demods-1; k >= 0; k--) {
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001338 dpst->cfg = cfg[k];
Patrick Boettchera75763f2006-10-18 08:34:16 -03001339
1340 /* designated i2c address */
1341 new_addr = (0x40 + k) << 1;
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001342 dpst->i2c_addr = new_addr;
1343 dib7000p_write_word(dpst, 1287, 0x0003); /* sram lead in, rdy */
1344 if (dib7000p_identify(dpst) != 0) {
1345 dpst->i2c_addr = default_addr;
1346 dib7000p_write_word(dpst, 1287, 0x0003); /* sram lead in, rdy */
1347 if (dib7000p_identify(dpst) != 0) {
Patrick Boettchera75763f2006-10-18 08:34:16 -03001348 dprintk("DiB7000P #%d: not identified\n", k);
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001349 kfree(dpst);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001350 return -EIO;
1351 }
1352 }
1353
1354 /* start diversity to pull_down div_str - just for i2c-enumeration */
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001355 dib7000p_set_output_mode(dpst, OUTMODE_DIVERSITY);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001356
1357 /* set new i2c address and force divstart */
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001358 dib7000p_write_word(dpst, 1285, (new_addr << 2) | 0x2);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001359
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001360 dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001361 }
1362
1363 for (k = 0; k < no_of_demods; k++) {
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001364 dpst->cfg = cfg[k];
1365 dpst->i2c_addr = (0x40 + k) << 1;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001366
1367 // unforce divstr
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001368 dib7000p_write_word(dpst, 1285, dpst->i2c_addr << 2);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001369
1370 /* deactivate div - it was just for i2c-enumeration */
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001371 dib7000p_set_output_mode(dpst, OUTMODE_HIGH_Z);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001372 }
1373
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001374 kfree(dpst);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001375 return 0;
1376}
1377EXPORT_SYMBOL(dib7000p_i2c_enumeration);
1378
1379static struct dvb_frontend_ops dib7000p_ops;
1380struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
1381{
1382 struct dvb_frontend *demod;
1383 struct dib7000p_state *st;
1384 st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
1385 if (st == NULL)
1386 return NULL;
1387
1388 memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config));
1389 st->i2c_adap = i2c_adap;
1390 st->i2c_addr = i2c_addr;
1391 st->gpio_val = cfg->gpio_val;
1392 st->gpio_dir = cfg->gpio_dir;
1393
Steven Totha38d6e32008-04-22 15:37:01 -03001394 /* Ensure the output mode remains at the previous default if it's
1395 * not specifically set by the caller.
1396 */
Anton Blanchard8d798982008-08-09 12:23:15 -03001397 if ((st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) &&
1398 (st->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
Steven Totha38d6e32008-04-22 15:37:01 -03001399 st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
1400
Patrick Boettchera75763f2006-10-18 08:34:16 -03001401 demod = &st->demod;
1402 demod->demodulator_priv = st;
1403 memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
1404
Olivier Grenieeac1fe12009-09-23 13:41:27 -03001405 dib7000p_write_word(st, 1287, 0x0003); /* sram lead in, rdy */
1406
Patrick Boettchera75763f2006-10-18 08:34:16 -03001407 if (dib7000p_identify(st) != 0)
1408 goto error;
1409
Martin Samek7646b9d2009-09-30 22:59:09 -03001410 /* FIXME: make sure the dev.parent field is initialized, or else
1411 request_firmware() will hit an OOPS (this should be moved somewhere
1412 more common) */
1413 st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
1414
Patrick Boettchera75763f2006-10-18 08:34:16 -03001415 dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
1416
1417 dib7000p_demod_reset(st);
1418
1419 return demod;
1420
1421error:
1422 kfree(st);
1423 return NULL;
1424}
1425EXPORT_SYMBOL(dib7000p_attach);
1426
1427static struct dvb_frontend_ops dib7000p_ops = {
1428 .info = {
1429 .name = "DiBcom 7000PC",
1430 .type = FE_OFDM,
1431 .frequency_min = 44250000,
1432 .frequency_max = 867250000,
1433 .frequency_stepsize = 62500,
1434 .caps = FE_CAN_INVERSION_AUTO |
1435 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1436 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1437 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
1438 FE_CAN_TRANSMISSION_MODE_AUTO |
1439 FE_CAN_GUARD_INTERVAL_AUTO |
1440 FE_CAN_RECOVER |
1441 FE_CAN_HIERARCHY_AUTO,
1442 },
1443
1444 .release = dib7000p_release,
1445
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001446 .init = dib7000p_wakeup,
Patrick Boettchera75763f2006-10-18 08:34:16 -03001447 .sleep = dib7000p_sleep,
1448
1449 .set_frontend = dib7000p_set_frontend,
1450 .get_tune_settings = dib7000p_fe_get_tune_settings,
1451 .get_frontend = dib7000p_get_frontend,
1452
1453 .read_status = dib7000p_read_status,
1454 .read_ber = dib7000p_read_ber,
1455 .read_signal_strength = dib7000p_read_signal_strength,
1456 .read_snr = dib7000p_read_snr,
1457 .read_ucblocks = dib7000p_read_unc_blocks,
1458};
1459
1460MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
1461MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator");
1462MODULE_LICENSE("GPL");