]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/media/dvb-frontends/dib7000p.c
[media] dvb: Get rid of typedev usage for enums
[mirror_ubuntu-artful-kernel.git] / drivers / media / dvb-frontends / dib7000p.c
CommitLineData
a75763ff
PB
1/*
2 * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC).
3 *
b6884a17 4 * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
a75763ff
PB
5 *
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>
5a0e3ad6 11#include <linux/slab.h>
a75763ff 12#include <linux/i2c.h>
79fcce32 13#include <linux/mutex.h>
041ad449 14#include <asm/div64.h>
a75763ff 15
ef801964 16#include "dvb_math.h"
a75763ff
PB
17#include "dvb_frontend.h"
18
19#include "dib7000p.h"
20
21static int debug;
22module_param(debug, int, 0644);
23MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
24
8f6956c7
MD
25static int buggy_sfn_workaround;
26module_param(buggy_sfn_workaround, int, 0644);
8d99996b 27MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
8f6956c7 28
b6884a17 29#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P: "); printk(args); printk("\n"); } } while (0)
a75763ff 30
713d54a8
OG
31struct i2c_device {
32 struct i2c_adapter *i2c_adap;
33 u8 i2c_addr;
34};
35
a75763ff
PB
36struct dib7000p_state {
37 struct dvb_frontend demod;
713d54a8 38 struct dib7000p_config cfg;
a75763ff
PB
39
40 u8 i2c_addr;
713d54a8 41 struct i2c_adapter *i2c_adap;
a75763ff
PB
42
43 struct dibx000_i2c_master i2c_master;
44
45 u16 wbd_ref;
46
713d54a8 47 u8 current_band;
904a82e3 48 u32 current_bandwidth;
a75763ff
PB
49 struct dibx000_agc_config *current_agc;
50 u32 timf;
51
713d54a8
OG
52 u8 div_force_off:1;
53 u8 div_state:1;
01373a5c 54 u16 div_sync_wait;
b6884a17
PB
55
56 u8 agc_state;
57
a75763ff
PB
58 u16 gpio_dir;
59 u16 gpio_val;
8f6956c7 60
713d54a8
OG
61 u8 sfn_workaround_active:1;
62
63#define SOC7090 0x7090
64 u16 version;
65
66 u16 tuner_enable;
67 struct i2c_adapter dib7090_tuner_adap;
5a0deeed
OG
68
69 /* for the I2C transfer */
70 struct i2c_msg msg[2];
71 u8 i2c_write_buffer[4];
72 u8 i2c_read_buffer[2];
79fcce32 73 struct mutex i2c_buffer_lock;
2e802861
OG
74
75 u8 input_mode_mpeg;
041ad449
MCC
76
77 /* for DVBv5 stats */
78 s64 old_ucb;
79 unsigned long per_jiffies_stats;
80 unsigned long ber_jiffies_stats;
81 unsigned long get_stats_time;
a75763ff
PB
82};
83
84enum dib7000p_power_mode {
85 DIB7000P_POWER_ALL = 0,
b6884a17 86 DIB7000P_POWER_ANALOG_ADC,
a75763ff
PB
87 DIB7000P_POWER_INTERFACE_ONLY,
88};
89
2e802861 90/* dib7090 specific fonctions */
713d54a8
OG
91static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode);
92static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff);
2e802861
OG
93static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode);
94static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode);
713d54a8 95
a75763ff
PB
96static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
97{
79fcce32
PB
98 u16 ret;
99
100 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
101 dprintk("could not acquire lock");
102 return 0;
103 }
104
5a0deeed
OG
105 state->i2c_write_buffer[0] = reg >> 8;
106 state->i2c_write_buffer[1] = reg & 0xff;
107
108 memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
109 state->msg[0].addr = state->i2c_addr >> 1;
110 state->msg[0].flags = 0;
111 state->msg[0].buf = state->i2c_write_buffer;
112 state->msg[0].len = 2;
113 state->msg[1].addr = state->i2c_addr >> 1;
114 state->msg[1].flags = I2C_M_RD;
115 state->msg[1].buf = state->i2c_read_buffer;
116 state->msg[1].len = 2;
117
118 if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
713d54a8 119 dprintk("i2c read error on %d", reg);
a75763ff 120
79fcce32
PB
121 ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
122 mutex_unlock(&state->i2c_buffer_lock);
123 return ret;
a75763ff
PB
124}
125
126static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
127{
79fcce32
PB
128 int ret;
129
130 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
131 dprintk("could not acquire lock");
132 return -EINVAL;
133 }
134
5a0deeed
OG
135 state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
136 state->i2c_write_buffer[1] = reg & 0xff;
137 state->i2c_write_buffer[2] = (val >> 8) & 0xff;
138 state->i2c_write_buffer[3] = val & 0xff;
139
140 memset(&state->msg[0], 0, sizeof(struct i2c_msg));
141 state->msg[0].addr = state->i2c_addr >> 1;
142 state->msg[0].flags = 0;
143 state->msg[0].buf = state->i2c_write_buffer;
144 state->msg[0].len = 4;
145
79fcce32
PB
146 ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
147 -EREMOTEIO : 0);
148 mutex_unlock(&state->i2c_buffer_lock);
149 return ret;
a75763ff 150}
713d54a8
OG
151
152static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
b6884a17
PB
153{
154 u16 l = 0, r, *n;
155 n = buf;
156 l = *n++;
157 while (l) {
158 r = *n++;
159
160 do {
161 dib7000p_write_word(state, r, *n++);
162 r++;
163 } while (--l);
164 l = *n++;
165 }
166}
167
a75763ff
PB
168static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode)
169{
713d54a8 170 int ret = 0;
a75763ff
PB
171 u16 outreg, fifo_threshold, smo_mode;
172
173 outreg = 0;
174 fifo_threshold = 1792;
eac1fe10 175 smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1);
a75763ff 176
713d54a8 177 dprintk("setting output mode for demod %p to %d", &state->demod, mode);
a75763ff
PB
178
179 switch (mode) {
b4d6046e 180 case OUTMODE_MPEG2_PAR_GATED_CLK:
713d54a8
OG
181 outreg = (1 << 10); /* 0x0400 */
182 break;
b4d6046e 183 case OUTMODE_MPEG2_PAR_CONT_CLK:
713d54a8
OG
184 outreg = (1 << 10) | (1 << 6); /* 0x0440 */
185 break;
b4d6046e 186 case OUTMODE_MPEG2_SERIAL:
713d54a8
OG
187 outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0480 */
188 break;
189 case OUTMODE_DIVERSITY:
190 if (state->cfg.hostbus_diversity)
191 outreg = (1 << 10) | (4 << 6); /* 0x0500 */
192 else
193 outreg = (1 << 11);
194 break;
b4d6046e 195 case OUTMODE_MPEG2_FIFO:
713d54a8
OG
196 smo_mode |= (3 << 1);
197 fifo_threshold = 512;
198 outreg = (1 << 10) | (5 << 6);
199 break;
200 case OUTMODE_ANALOG_ADC:
201 outreg = (1 << 10) | (3 << 6);
202 break;
b4d6046e 203 case OUTMODE_HIGH_Z:
713d54a8
OG
204 outreg = 0;
205 break;
206 default:
207 dprintk("Unhandled output_mode passed to be set for demod %p", &state->demod);
208 break;
a75763ff
PB
209 }
210
211 if (state->cfg.output_mpeg2_in_188_bytes)
713d54a8 212 smo_mode |= (1 << 5);
a75763ff 213
713d54a8
OG
214 ret |= dib7000p_write_word(state, 235, smo_mode);
215 ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */
216 if (state->version != SOC7090)
217 ret |= dib7000p_write_word(state, 1286, outreg); /* P_Div_active */
a75763ff
PB
218
219 return ret;
220}
221
b6884a17
PB
222static int dib7000p_set_diversity_in(struct dvb_frontend *demod, int onoff)
223{
224 struct dib7000p_state *state = demod->demodulator_priv;
225
226 if (state->div_force_off) {
713d54a8 227 dprintk("diversity combination deactivated - forced by COFDM parameters");
b6884a17 228 onoff = 0;
eac1fe10
OG
229 dib7000p_write_word(state, 207, 0);
230 } else
231 dib7000p_write_word(state, 207, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
232
713d54a8 233 state->div_state = (u8) onoff;
b6884a17
PB
234
235 if (onoff) {
236 dib7000p_write_word(state, 204, 6);
237 dib7000p_write_word(state, 205, 16);
238 /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
b6884a17
PB
239 } else {
240 dib7000p_write_word(state, 204, 1);
241 dib7000p_write_word(state, 205, 0);
b6884a17
PB
242 }
243
244 return 0;
245}
246
a75763ff
PB
247static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode)
248{
249 /* by default everything is powered off */
713d54a8 250 u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899 = 0x0003, reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff);
a75763ff
PB
251
252 /* now, depending on the requested mode, we power on */
253 switch (mode) {
254 /* power up everything in the demod */
713d54a8
OG
255 case DIB7000P_POWER_ALL:
256 reg_774 = 0x0000;
257 reg_775 = 0x0000;
258 reg_776 = 0x0;
259 reg_899 = 0x0;
260 if (state->version == SOC7090)
261 reg_1280 &= 0x001f;
262 else
263 reg_1280 &= 0x01ff;
264 break;
265
266 case DIB7000P_POWER_ANALOG_ADC:
267 /* dem, cfg, iqc, sad, agc */
268 reg_774 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10) | (1 << 9));
269 /* nud */
270 reg_776 &= ~((1 << 0));
271 /* Dout */
272 if (state->version != SOC7090)
b6884a17 273 reg_1280 &= ~((1 << 11));
713d54a8
OG
274 reg_1280 &= ~(1 << 6);
275 /* fall through wanted to enable the interfaces */
b6884a17 276
a75763ff 277 /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */
713d54a8
OG
278 case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */
279 if (state->version == SOC7090)
280 reg_1280 &= ~((1 << 7) | (1 << 5));
281 else
a75763ff 282 reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10));
713d54a8 283 break;
b6884a17 284
a75763ff
PB
285/* TODO following stuff is just converted from the dib7000-driver - check when is used what */
286 }
287
713d54a8
OG
288 dib7000p_write_word(state, 774, reg_774);
289 dib7000p_write_word(state, 775, reg_775);
290 dib7000p_write_word(state, 776, reg_776);
a75763ff 291 dib7000p_write_word(state, 1280, reg_1280);
2e802861
OG
292 if (state->version != SOC7090)
293 dib7000p_write_word(state, 899, reg_899);
a75763ff
PB
294
295 return 0;
296}
297
298static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no)
299{
2e802861 300 u16 reg_908 = 0, reg_909 = 0;
713d54a8 301 u16 reg;
a75763ff 302
2e802861
OG
303 if (state->version != SOC7090) {
304 reg_908 = dib7000p_read_word(state, 908);
305 reg_909 = dib7000p_read_word(state, 909);
306 }
307
a75763ff 308 switch (no) {
713d54a8
OG
309 case DIBX000_SLOW_ADC_ON:
310 if (state->version == SOC7090) {
311 reg = dib7000p_read_word(state, 1925);
312
313 dib7000p_write_word(state, 1925, reg | (1 << 4) | (1 << 2)); /* en_slowAdc = 1 & reset_sladc = 1 */
314
315 reg = dib7000p_read_word(state, 1925); /* read acces to make it works... strange ... */
316 msleep(200);
317 dib7000p_write_word(state, 1925, reg & ~(1 << 4)); /* en_slowAdc = 1 & reset_sladc = 0 */
318
319 reg = dib7000p_read_word(state, 72) & ~((0x3 << 14) | (0x3 << 12));
320 dib7000p_write_word(state, 72, reg | (1 << 14) | (3 << 12) | 524); /* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ; (Vin2 = Vcm) */
321 } else {
a75763ff
PB
322 reg_909 |= (1 << 1) | (1 << 0);
323 dib7000p_write_word(state, 909, reg_909);
324 reg_909 &= ~(1 << 1);
713d54a8
OG
325 }
326 break;
a75763ff 327
713d54a8
OG
328 case DIBX000_SLOW_ADC_OFF:
329 if (state->version == SOC7090) {
330 reg = dib7000p_read_word(state, 1925);
331 dib7000p_write_word(state, 1925, (reg & ~(1 << 2)) | (1 << 4)); /* reset_sladc = 1 en_slowAdc = 0 */
332 } else
333 reg_909 |= (1 << 1) | (1 << 0);
334 break;
a75763ff 335
713d54a8
OG
336 case DIBX000_ADC_ON:
337 reg_908 &= 0x0fff;
338 reg_909 &= 0x0003;
339 break;
a75763ff 340
b4d6046e 341 case DIBX000_ADC_OFF:
713d54a8
OG
342 reg_908 |= (1 << 14) | (1 << 13) | (1 << 12);
343 reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
344 break;
a75763ff 345
713d54a8
OG
346 case DIBX000_VBG_ENABLE:
347 reg_908 &= ~(1 << 15);
348 break;
a75763ff 349
713d54a8
OG
350 case DIBX000_VBG_DISABLE:
351 reg_908 |= (1 << 15);
352 break;
a75763ff 353
713d54a8
OG
354 default:
355 break;
a75763ff
PB
356 }
357
b6884a17 358// dprintk( "908: %x, 909: %x\n", reg_908, reg_909);
a75763ff 359
970d14c6 360 reg_909 |= (state->cfg.disable_sample_and_hold & 1) << 4;
90e12cec
OG
361 reg_908 |= (state->cfg.enable_current_mirror & 1) << 7;
362
2e802861
OG
363 if (state->version != SOC7090) {
364 dib7000p_write_word(state, 908, reg_908);
365 dib7000p_write_word(state, 909, reg_909);
366 }
a75763ff
PB
367}
368
b6884a17 369static int dib7000p_set_bandwidth(struct dib7000p_state *state, u32 bw)
a75763ff 370{
a75763ff
PB
371 u32 timf;
372
373 // store the current bandwidth for later use
b6884a17 374 state->current_bandwidth = bw;
a75763ff
PB
375
376 if (state->timf == 0) {
713d54a8 377 dprintk("using default timf");
a75763ff
PB
378 timf = state->cfg.bw->timf;
379 } else {
713d54a8 380 dprintk("using updated timf");
a75763ff
PB
381 timf = state->timf;
382 }
383
b6884a17 384 timf = timf * (bw / 50) / 160;
a75763ff 385
b6884a17 386 dib7000p_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
713d54a8 387 dib7000p_write_word(state, 24, (u16) ((timf) & 0xffff));
a75763ff
PB
388
389 return 0;
390}
391
392static int dib7000p_sad_calib(struct dib7000p_state *state)
393{
394/* internal */
a75763ff 395 dib7000p_write_word(state, 73, (0 << 1) | (0 << 0));
713d54a8
OG
396
397 if (state->version == SOC7090)
b4d6046e 398 dib7000p_write_word(state, 74, 2048);
713d54a8 399 else
b4d6046e 400 dib7000p_write_word(state, 74, 776);
a75763ff
PB
401
402 /* do the calibration */
403 dib7000p_write_word(state, 73, (1 << 0));
404 dib7000p_write_word(state, 73, (0 << 0));
405
406 msleep(1);
407
408 return 0;
409}
410
8abe4a0a 411static int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
01373a5c
PB
412{
413 struct dib7000p_state *state = demod->demodulator_priv;
414 if (value > 4095)
415 value = 4095;
416 state->wbd_ref = value;
417 return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
418}
713d54a8 419
8abe4a0a 420static int dib7000p_get_agc_values(struct dvb_frontend *fe,
6724a2f4
OG
421 u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
422{
423 struct dib7000p_state *state = fe->demodulator_priv;
424
425 if (agc_global != NULL)
426 *agc_global = dib7000p_read_word(state, 394);
427 if (agc1 != NULL)
428 *agc1 = dib7000p_read_word(state, 392);
429 if (agc2 != NULL)
430 *agc2 = dib7000p_read_word(state, 393);
431 if (wbd != NULL)
432 *wbd = dib7000p_read_word(state, 397);
433
434 return 0;
435}
6724a2f4 436
8abe4a0a 437static int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
6fe1099c
OG
438{
439 struct dib7000p_state *state = fe->demodulator_priv;
440 return dib7000p_write_word(state, 108, v);
441}
6fe1099c 442
a75763ff
PB
443static void dib7000p_reset_pll(struct dib7000p_state *state)
444{
445 struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
b6884a17
PB
446 u16 clk_cfg0;
447
713d54a8
OG
448 if (state->version == SOC7090) {
449 dib7000p_write_word(state, 1856, (!bw->pll_reset << 13) | (bw->pll_range << 12) | (bw->pll_ratio << 6) | (bw->pll_prediv));
a75763ff 450
b4d6046e
OG
451 while (((dib7000p_read_word(state, 1856) >> 15) & 0x1) != 1)
452 ;
713d54a8
OG
453
454 dib7000p_write_word(state, 1857, dib7000p_read_word(state, 1857) | (!bw->pll_bypass << 15));
455 } else {
456 /* force PLL bypass */
457 clk_cfg0 = (1 << 15) | ((bw->pll_ratio & 0x3f) << 9) |
458 (bw->modulo << 7) | (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0);
b6884a17 459
713d54a8
OG
460 dib7000p_write_word(state, 900, clk_cfg0);
461
462 /* P_pll_cfg */
463 dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset);
464 clk_cfg0 = (bw->pll_bypass << 15) | (clk_cfg0 & 0x7fff);
465 dib7000p_write_word(state, 900, clk_cfg0);
466 }
a75763ff 467
713d54a8
OG
468 dib7000p_write_word(state, 18, (u16) (((bw->internal * 1000) >> 16) & 0xffff));
469 dib7000p_write_word(state, 19, (u16) ((bw->internal * 1000) & 0xffff));
470 dib7000p_write_word(state, 21, (u16) ((bw->ifreq >> 16) & 0xffff));
471 dib7000p_write_word(state, 22, (u16) ((bw->ifreq) & 0xffff));
a75763ff
PB
472
473 dib7000p_write_word(state, 72, bw->sad_cfg);
474}
475
713d54a8
OG
476static u32 dib7000p_get_internal_freq(struct dib7000p_state *state)
477{
478 u32 internal = (u32) dib7000p_read_word(state, 18) << 16;
479 internal |= (u32) dib7000p_read_word(state, 19);
480 internal /= 1000;
481
482 return internal;
483}
484
8abe4a0a 485static int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
713d54a8
OG
486{
487 struct dib7000p_state *state = fe->demodulator_priv;
488 u16 reg_1857, reg_1856 = dib7000p_read_word(state, 1856);
489 u8 loopdiv, prediv;
490 u32 internal, xtal;
491
492 /* get back old values */
493 prediv = reg_1856 & 0x3f;
494 loopdiv = (reg_1856 >> 6) & 0x3f;
495
496 if ((bw != NULL) && (bw->pll_prediv != prediv || bw->pll_ratio != loopdiv)) {
497 dprintk("Updating pll (prediv: old = %d new = %d ; loopdiv : old = %d new = %d)", prediv, bw->pll_prediv, loopdiv, bw->pll_ratio);
498 reg_1856 &= 0xf000;
499 reg_1857 = dib7000p_read_word(state, 1857);
b4d6046e 500 dib7000p_write_word(state, 1857, reg_1857 & ~(1 << 15));
713d54a8
OG
501
502 dib7000p_write_word(state, 1856, reg_1856 | ((bw->pll_ratio & 0x3f) << 6) | (bw->pll_prediv & 0x3f));
503
504 /* write new system clk into P_sec_len */
505 internal = dib7000p_get_internal_freq(state);
506 xtal = (internal / loopdiv) * prediv;
507 internal = 1000 * (xtal / bw->pll_prediv) * bw->pll_ratio; /* new internal */
508 dib7000p_write_word(state, 18, (u16) ((internal >> 16) & 0xffff));
509 dib7000p_write_word(state, 19, (u16) (internal & 0xffff));
510
b4d6046e 511 dib7000p_write_word(state, 1857, reg_1857 | (1 << 15));
713d54a8 512
b4d6046e 513 while (((dib7000p_read_word(state, 1856) >> 15) & 0x1) != 1)
713d54a8 514 dprintk("Waiting for PLL to lock");
713d54a8
OG
515
516 return 0;
517 }
518 return -EIO;
519}
713d54a8 520
a75763ff
PB
521static int dib7000p_reset_gpio(struct dib7000p_state *st)
522{
523 /* reset the GPIOs */
713d54a8 524 dprintk("gpio dir: %x: val: %x, pwm_pos: %x", st->gpio_dir, st->gpio_val, st->cfg.gpio_pwm_pos);
a75763ff
PB
525
526 dib7000p_write_word(st, 1029, st->gpio_dir);
527 dib7000p_write_word(st, 1030, st->gpio_val);
528
529 /* TODO 1031 is P_gpio_od */
530
531 dib7000p_write_word(st, 1032, st->cfg.gpio_pwm_pos);
532
533 dib7000p_write_word(st, 1037, st->cfg.pwm_freq_div);
534 return 0;
535}
536
01373a5c
PB
537static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
538{
539 st->gpio_dir = dib7000p_read_word(st, 1029);
713d54a8
OG
540 st->gpio_dir &= ~(1 << num); /* reset the direction bit */
541 st->gpio_dir |= (dir & 0x1) << num; /* set the new direction */
01373a5c
PB
542 dib7000p_write_word(st, 1029, st->gpio_dir);
543
544 st->gpio_val = dib7000p_read_word(st, 1030);
713d54a8
OG
545 st->gpio_val &= ~(1 << num); /* reset the direction bit */
546 st->gpio_val |= (val & 0x01) << num; /* set the new value */
01373a5c
PB
547 dib7000p_write_word(st, 1030, st->gpio_val);
548
549 return 0;
550}
551
8abe4a0a 552static int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
01373a5c
PB
553{
554 struct dib7000p_state *state = demod->demodulator_priv;
555 return dib7000p_cfg_gpio(state, num, dir, val);
556}
b6884a17 557
713d54a8 558static u16 dib7000p_defaults[] = {
b6884a17
PB
559 // auto search configuration
560 3, 2,
713d54a8 561 0x0004,
2e802861 562 (1<<3)|(1<<11)|(1<<12)|(1<<13),
713d54a8 563 0x0814, /* Equal Lock */
b6884a17
PB
564
565 12, 6,
713d54a8
OG
566 0x001b,
567 0x7740,
568 0x005b,
569 0x8d80,
570 0x01c9,
571 0xc380,
572 0x0000,
573 0x0080,
574 0x0000,
575 0x0090,
576 0x0001,
577 0xd4c0,
b6884a17
PB
578
579 1, 26,
b4d6046e 580 0x6680,
b6884a17
PB
581
582 /* set ADC level to -16 */
583 11, 79,
713d54a8
OG
584 (1 << 13) - 825 - 117,
585 (1 << 13) - 837 - 117,
586 (1 << 13) - 811 - 117,
587 (1 << 13) - 766 - 117,
588 (1 << 13) - 737 - 117,
589 (1 << 13) - 693 - 117,
590 (1 << 13) - 648 - 117,
591 (1 << 13) - 619 - 117,
592 (1 << 13) - 575 - 117,
593 (1 << 13) - 531 - 117,
594 (1 << 13) - 501 - 117,
b6884a17
PB
595
596 1, 142,
b4d6046e 597 0x0410,
b6884a17
PB
598
599 /* disable power smoothing */
600 8, 145,
713d54a8
OG
601 0,
602 0,
603 0,
604 0,
605 0,
606 0,
607 0,
608 0,
b6884a17
PB
609
610 1, 154,
b4d6046e 611 1 << 13,
b6884a17
PB
612
613 1, 168,
b4d6046e 614 0x0ccd,
b6884a17
PB
615
616 1, 183,
b4d6046e 617 0x200f,
713d54a8
OG
618
619 1, 212,
b4d6046e 620 0x169,
b6884a17
PB
621
622 5, 187,
b4d6046e
OG
623 0x023d,
624 0x00a4,
625 0x00a4,
626 0x7ff0,
627 0x3ccc,
b6884a17
PB
628
629 1, 198,
b4d6046e 630 0x800,
b6884a17
PB
631
632 1, 222,
b4d6046e 633 0x0010,
b6884a17
PB
634
635 1, 235,
b4d6046e 636 0x0062,
b6884a17 637
b6884a17
PB
638 0,
639};
640
041ad449
MCC
641static void dib7000p_reset_stats(struct dvb_frontend *fe);
642
a75763ff
PB
643static int dib7000p_demod_reset(struct dib7000p_state *state)
644{
645 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
646
713d54a8
OG
647 if (state->version == SOC7090)
648 dibx000_reset_i2c_master(&state->i2c_master);
649
a75763ff
PB
650 dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE);
651
652 /* restart all parts */
713d54a8
OG
653 dib7000p_write_word(state, 770, 0xffff);
654 dib7000p_write_word(state, 771, 0xffff);
655 dib7000p_write_word(state, 772, 0x001f);
713d54a8
OG
656 dib7000p_write_word(state, 1280, 0x001f - ((1 << 4) | (1 << 3)));
657
658 dib7000p_write_word(state, 770, 0);
659 dib7000p_write_word(state, 771, 0);
660 dib7000p_write_word(state, 772, 0);
a75763ff
PB
661 dib7000p_write_word(state, 1280, 0);
662
2e802861
OG
663 if (state->version != SOC7090) {
664 dib7000p_write_word(state, 898, 0x0003);
665 dib7000p_write_word(state, 898, 0);
666 }
667
a75763ff
PB
668 /* default */
669 dib7000p_reset_pll(state);
670
671 if (dib7000p_reset_gpio(state) != 0)
713d54a8 672 dprintk("GPIO reset was not successful.");
a75763ff 673
713d54a8
OG
674 if (state->version == SOC7090) {
675 dib7000p_write_word(state, 899, 0);
a75763ff 676
713d54a8
OG
677 /* impulse noise */
678 dib7000p_write_word(state, 42, (1<<5) | 3); /* P_iqc_thsat_ipc = 1 ; P_iqc_win2 = 3 */
679 dib7000p_write_word(state, 43, 0x2d4); /*-300 fag P_iqc_dect_min = -280 */
680 dib7000p_write_word(state, 44, 300); /* 300 fag P_iqc_dect_min = +280 */
2e802861 681 dib7000p_write_word(state, 273, (0<<6) | 30);
713d54a8
OG
682 }
683 if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
684 dprintk("OUTPUT_MODE could not be reset.");
b6884a17
PB
685
686 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
687 dib7000p_sad_calib(state);
688 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
689
713d54a8
OG
690 /* unforce divstr regardless whether i2c enumeration was done or not */
691 dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1));
692
693 dib7000p_set_bandwidth(state, 8000);
694
b4d6046e 695 if (state->version == SOC7090) {
2e802861 696 dib7000p_write_word(state, 36, 0x0755);/* P_iqc_impnc_on =1 & P_iqc_corr_inh = 1 for impulsive noise */
b4d6046e 697 } else {
713d54a8
OG
698 if (state->cfg.tuner_is_baseband)
699 dib7000p_write_word(state, 36, 0x0755);
700 else
701 dib7000p_write_word(state, 36, 0x1f55);
702 }
b6884a17
PB
703
704 dib7000p_write_tab(state, dib7000p_defaults);
2e802861
OG
705 if (state->version != SOC7090) {
706 dib7000p_write_word(state, 901, 0x0006);
707 dib7000p_write_word(state, 902, (3 << 10) | (1 << 6));
708 dib7000p_write_word(state, 905, 0x2c8e);
709 }
b6884a17 710
a75763ff
PB
711 dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
712
713 return 0;
714}
715
b6884a17
PB
716static void dib7000p_pll_clk_cfg(struct dib7000p_state *state)
717{
718 u16 tmp = 0;
719 tmp = dib7000p_read_word(state, 903);
b4d6046e 720 dib7000p_write_word(state, 903, (tmp | 0x1));
b6884a17 721 tmp = dib7000p_read_word(state, 900);
b4d6046e 722 dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6));
b6884a17
PB
723}
724
a75763ff
PB
725static void dib7000p_restart_agc(struct dib7000p_state *state)
726{
727 // P_restart_iqc & P_restart_agc
b6884a17 728 dib7000p_write_word(state, 770, (1 << 11) | (1 << 9));
a75763ff
PB
729 dib7000p_write_word(state, 770, 0x0000);
730}
731
b6884a17 732static int dib7000p_update_lna(struct dib7000p_state *state)
a75763ff 733{
a75763ff
PB
734 u16 dyn_gain;
735
b6884a17 736 if (state->cfg.update_lna) {
a75763ff 737 dyn_gain = dib7000p_read_word(state, 394);
b4d6046e 738 if (state->cfg.update_lna(&state->demod, dyn_gain)) {
a75763ff 739 dib7000p_restart_agc(state);
b6884a17
PB
740 return 1;
741 }
742 }
743
744 return 0;
745}
746
747static int dib7000p_set_agc_config(struct dib7000p_state *state, u8 band)
748{
749 struct dibx000_agc_config *agc = NULL;
750 int i;
751 if (state->current_band == band && state->current_agc != NULL)
752 return 0;
753 state->current_band = band;
754
755 for (i = 0; i < state->cfg.agc_config_count; i++)
756 if (state->cfg.agc[i].band_caps & band) {
757 agc = &state->cfg.agc[i];
a75763ff 758 break;
b6884a17
PB
759 }
760
761 if (agc == NULL) {
713d54a8 762 dprintk("no valid AGC configuration found for band 0x%02x", band);
b6884a17 763 return -EINVAL;
a75763ff 764 }
b6884a17
PB
765
766 state->current_agc = agc;
767
768 /* AGC */
713d54a8
OG
769 dib7000p_write_word(state, 75, agc->setup);
770 dib7000p_write_word(state, 76, agc->inv_gain);
771 dib7000p_write_word(state, 77, agc->time_stabiliz);
b6884a17
PB
772 dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock);
773
774 // Demod AGC loop configuration
775 dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp);
713d54a8 776 dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp);
b6884a17
PB
777
778 /* AGC continued */
713d54a8 779 dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d",
b6884a17
PB
780 state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
781
782 if (state->wbd_ref != 0)
783 dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref);
784 else
785 dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref);
786
787 dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
788
713d54a8
OG
789 dib7000p_write_word(state, 107, agc->agc1_max);
790 dib7000p_write_word(state, 108, agc->agc1_min);
791 dib7000p_write_word(state, 109, agc->agc2_max);
792 dib7000p_write_word(state, 110, agc->agc2_min);
793 dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
794 dib7000p_write_word(state, 112, agc->agc1_pt3);
b6884a17 795 dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
713d54a8 796 dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
b6884a17
PB
797 dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
798 return 0;
a75763ff
PB
799}
800
713d54a8
OG
801static void dib7000p_set_dds(struct dib7000p_state *state, s32 offset_khz)
802{
803 u32 internal = dib7000p_get_internal_freq(state);
804 s32 unit_khz_dds_val = 67108864 / (internal); /* 2**26 / Fsampling is the unit 1KHz offset */
805 u32 abs_offset_khz = ABS(offset_khz);
806 u32 dds = state->cfg.bw->ifreq & 0x1ffffff;
807 u8 invert = !!(state->cfg.bw->ifreq & (1 << 25));
808
809 dprintk("setting a frequency offset of %dkHz internal freq = %d invert = %d", offset_khz, internal, invert);
810
811 if (offset_khz < 0)
812 unit_khz_dds_val *= -1;
813
814 /* IF tuner */
815 if (invert)
816 dds -= (abs_offset_khz * unit_khz_dds_val); /* /100 because of /100 on the unit_khz_dds_val line calc for better accuracy */
817 else
818 dds += (abs_offset_khz * unit_khz_dds_val);
819
820 if (abs_offset_khz <= (internal / 2)) { /* Max dds offset is the half of the demod freq */
821 dib7000p_write_word(state, 21, (u16) (((dds >> 16) & 0x1ff) | (0 << 10) | (invert << 9)));
822 dib7000p_write_word(state, 22, (u16) (dds & 0xffff));
823 }
824}
825
c1f814f4 826static int dib7000p_agc_startup(struct dvb_frontend *demod)
a75763ff 827{
c1f814f4 828 struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
b6884a17
PB
829 struct dib7000p_state *state = demod->demodulator_priv;
830 int ret = -1;
831 u8 *agc_state = &state->agc_state;
832 u8 agc_split;
713d54a8
OG
833 u16 reg;
834 u32 upd_demod_gain_period = 0x1000;
6fe1099c 835 s32 frequency_offset = 0;
b6884a17
PB
836
837 switch (state->agc_state) {
713d54a8 838 case 0:
713d54a8
OG
839 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
840 if (state->version == SOC7090) {
841 reg = dib7000p_read_word(state, 0x79b) & 0xff00;
842 dib7000p_write_word(state, 0x79a, upd_demod_gain_period & 0xFFFF); /* lsb */
b4d6046e 843 dib7000p_write_word(state, 0x79b, reg | (1 << 14) | ((upd_demod_gain_period >> 16) & 0xFF));
713d54a8
OG
844
845 /* enable adc i & q */
846 reg = dib7000p_read_word(state, 0x780);
847 dib7000p_write_word(state, 0x780, (reg | (0x3)) & (~(1 << 7)));
848 } else {
b6884a17
PB
849 dib7000p_set_adc_state(state, DIBX000_ADC_ON);
850 dib7000p_pll_clk_cfg(state);
713d54a8 851 }
b6884a17 852
713d54a8
OG
853 if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency / 1000)) != 0)
854 return -1;
b6884a17 855
6fe1099c
OG
856 if (demod->ops.tuner_ops.get_frequency) {
857 u32 frequency_tuner;
858
859 demod->ops.tuner_ops.get_frequency(demod, &frequency_tuner);
860 frequency_offset = (s32)frequency_tuner / 1000 - ch->frequency / 1000;
861 }
862
863 dib7000p_set_dds(state, frequency_offset);
713d54a8
OG
864 ret = 7;
865 (*agc_state)++;
866 break;
b6884a17 867
713d54a8 868 case 1:
713d54a8
OG
869 if (state->cfg.agc_control)
870 state->cfg.agc_control(&state->demod, 1);
b6884a17 871
713d54a8
OG
872 dib7000p_write_word(state, 78, 32768);
873 if (!state->current_agc->perform_agc_softsplit) {
874 /* we are using the wbd - so slow AGC startup */
875 /* force 0 split on WBD and restart AGC */
876 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | (1 << 8));
b6884a17 877 (*agc_state)++;
713d54a8
OG
878 ret = 5;
879 } else {
880 /* default AGC startup */
881 (*agc_state) = 4;
882 /* wait AGC rough lock time */
883 ret = 7;
884 }
b6884a17 885
713d54a8
OG
886 dib7000p_restart_agc(state);
887 break;
b6884a17 888
713d54a8
OG
889 case 2: /* fast split search path after 5sec */
890 dib7000p_write_word(state, 75, state->current_agc->setup | (1 << 4)); /* freeze AGC loop */
891 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (2 << 9) | (0 << 8)); /* fast split search 0.25kHz */
892 (*agc_state)++;
893 ret = 14;
894 break;
b6884a17 895
713d54a8
OG
896 case 3: /* split search ended */
897 agc_split = (u8) dib7000p_read_word(state, 396); /* store the split value for the next time */
898 dib7000p_write_word(state, 78, dib7000p_read_word(state, 394)); /* set AGC gain start value */
b6884a17 899
713d54a8
OG
900 dib7000p_write_word(state, 75, state->current_agc->setup); /* std AGC loop */
901 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
b6884a17 902
713d54a8 903 dib7000p_restart_agc(state);
b6884a17 904
713d54a8 905 dprintk("SPLIT %p: %hd", demod, agc_split);
b6884a17 906
713d54a8
OG
907 (*agc_state)++;
908 ret = 5;
909 break;
b6884a17 910
713d54a8 911 case 4: /* LNA startup */
713d54a8
OG
912 ret = 7;
913
914 if (dib7000p_update_lna(state))
713d54a8 915 ret = 5;
b4d6046e 916 else
b6884a17 917 (*agc_state)++;
713d54a8
OG
918 break;
919
920 case 5:
921 if (state->cfg.agc_control)
922 state->cfg.agc_control(&state->demod, 0);
923 (*agc_state)++;
924 break;
925 default:
926 break;
b6884a17
PB
927 }
928 return ret;
a75763ff
PB
929}
930
b6884a17 931static void dib7000p_update_timf(struct dib7000p_state *state)
a75763ff
PB
932{
933 u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428);
b6884a17 934 state->timf = timf * 160 / (state->current_bandwidth / 50);
a75763ff
PB
935 dib7000p_write_word(state, 23, (u16) (timf >> 16));
936 dib7000p_write_word(state, 24, (u16) (timf & 0xffff));
713d54a8
OG
937 dprintk("updated timf_frequency: %d (default: %d)", state->timf, state->cfg.bw->timf);
938
939}
b6884a17 940
8abe4a0a 941static u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
713d54a8
OG
942{
943 struct dib7000p_state *state = fe->demodulator_priv;
944 switch (op) {
945 case DEMOD_TIMF_SET:
946 state->timf = timf;
947 break;
948 case DEMOD_TIMF_UPDATE:
949 dib7000p_update_timf(state);
950 break;
951 case DEMOD_TIMF_GET:
952 break;
953 }
954 dib7000p_set_bandwidth(state, state->current_bandwidth);
955 return state->timf;
a75763ff
PB
956}
957
c1f814f4
MCC
958static void dib7000p_set_channel(struct dib7000p_state *state,
959 struct dtv_frontend_properties *ch, u8 seq)
a75763ff 960{
b6884a17
PB
961 u16 value, est[4];
962
c1f814f4 963 dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
a75763ff
PB
964
965 /* nfft, guard, qam, alpha */
b6884a17 966 value = 0;
c1f814f4 967 switch (ch->transmission_mode) {
713d54a8
OG
968 case TRANSMISSION_MODE_2K:
969 value |= (0 << 7);
970 break;
46f7296a 971 case TRANSMISSION_MODE_4K:
713d54a8
OG
972 value |= (2 << 7);
973 break;
974 default:
975 case TRANSMISSION_MODE_8K:
976 value |= (1 << 7);
977 break;
b6884a17 978 }
c1f814f4 979 switch (ch->guard_interval) {
713d54a8
OG
980 case GUARD_INTERVAL_1_32:
981 value |= (0 << 5);
982 break;
983 case GUARD_INTERVAL_1_16:
984 value |= (1 << 5);
985 break;
986 case GUARD_INTERVAL_1_4:
987 value |= (3 << 5);
988 break;
989 default:
990 case GUARD_INTERVAL_1_8:
991 value |= (2 << 5);
992 break;
b6884a17 993 }
c1f814f4 994 switch (ch->modulation) {
713d54a8
OG
995 case QPSK:
996 value |= (0 << 3);
997 break;
998 case QAM_16:
999 value |= (1 << 3);
1000 break;
1001 default:
1002 case QAM_64:
1003 value |= (2 << 3);
1004 break;
b6884a17
PB
1005 }
1006 switch (HIERARCHY_1) {
713d54a8
OG
1007 case HIERARCHY_2:
1008 value |= 2;
1009 break;
1010 case HIERARCHY_4:
1011 value |= 4;
1012 break;
1013 default:
1014 case HIERARCHY_1:
1015 value |= 1;
1016 break;
b6884a17
PB
1017 }
1018 dib7000p_write_word(state, 0, value);
713d54a8 1019 dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */
a75763ff 1020
b6884a17
PB
1021 /* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
1022 value = 0;
1023 if (1 != 0)
1024 value |= (1 << 6);
c1f814f4 1025 if (ch->hierarchy == 1)
b6884a17
PB
1026 value |= (1 << 4);
1027 if (1 == 1)
1028 value |= 1;
c1f814f4 1029 switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
713d54a8
OG
1030 case FEC_2_3:
1031 value |= (2 << 1);
1032 break;
1033 case FEC_3_4:
1034 value |= (3 << 1);
1035 break;
1036 case FEC_5_6:
1037 value |= (5 << 1);
1038 break;
1039 case FEC_7_8:
1040 value |= (7 << 1);
1041 break;
1042 default:
1043 case FEC_1_2:
1044 value |= (1 << 1);
1045 break;
b6884a17
PB
1046 }
1047 dib7000p_write_word(state, 208, value);
1048
1049 /* offset loop parameters */
b4d6046e
OG
1050 dib7000p_write_word(state, 26, 0x6680);
1051 dib7000p_write_word(state, 32, 0x0003);
1052 dib7000p_write_word(state, 29, 0x1273);
1053 dib7000p_write_word(state, 33, 0x0005);
a75763ff
PB
1054
1055 /* P_dvsy_sync_wait */
c1f814f4 1056 switch (ch->transmission_mode) {
713d54a8
OG
1057 case TRANSMISSION_MODE_8K:
1058 value = 256;
1059 break;
1060 case TRANSMISSION_MODE_4K:
1061 value = 128;
1062 break;
1063 case TRANSMISSION_MODE_2K:
1064 default:
1065 value = 64;
1066 break;
a75763ff 1067 }
c1f814f4 1068 switch (ch->guard_interval) {
713d54a8
OG
1069 case GUARD_INTERVAL_1_16:
1070 value *= 2;
1071 break;
1072 case GUARD_INTERVAL_1_8:
1073 value *= 4;
1074 break;
1075 case GUARD_INTERVAL_1_4:
1076 value *= 8;
1077 break;
1078 default:
1079 case GUARD_INTERVAL_1_32:
1080 value *= 1;
1081 break;
b6884a17 1082 }
970d14c6 1083 if (state->cfg.diversity_delay == 0)
b4d6046e 1084 state->div_sync_wait = (value * 3) / 2 + 48;
970d14c6 1085 else
b4d6046e 1086 state->div_sync_wait = (value * 3) / 2 + state->cfg.diversity_delay;
a75763ff 1087
b6884a17 1088 /* deactive the possibility of diversity reception if extended interleaver */
c1f814f4 1089 state->div_force_off = !1 && ch->transmission_mode != TRANSMISSION_MODE_8K;
b6884a17 1090 dib7000p_set_diversity_in(&state->demod, state->div_state);
a75763ff
PB
1091
1092 /* channel estimation fine configuration */
c1f814f4 1093 switch (ch->modulation) {
713d54a8
OG
1094 case QAM_64:
1095 est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
1096 est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
1097 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
1098 est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */
1099 break;
1100 case QAM_16:
1101 est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */
1102 est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */
1103 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
1104 est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */
1105 break;
1106 default:
1107 est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */
1108 est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */
1109 est[2] = 0x0333; /* P_adp_regul_ext 0.1 */
1110 est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */
1111 break;
a75763ff 1112 }
b6884a17
PB
1113 for (value = 0; value < 4; value++)
1114 dib7000p_write_word(state, 187 + value, est[value]);
a75763ff
PB
1115}
1116
c1f814f4 1117static int dib7000p_autosearch_start(struct dvb_frontend *demod)
a75763ff 1118{
c1f814f4 1119 struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
a75763ff 1120 struct dib7000p_state *state = demod->demodulator_priv;
c1f814f4 1121 struct dtv_frontend_properties schan;
b6884a17 1122 u32 value, factor;
713d54a8 1123 u32 internal = dib7000p_get_internal_freq(state);
b6884a17
PB
1124
1125 schan = *ch;
c1f814f4
MCC
1126 schan.modulation = QAM_64;
1127 schan.guard_interval = GUARD_INTERVAL_1_32;
1128 schan.transmission_mode = TRANSMISSION_MODE_8K;
1129 schan.code_rate_HP = FEC_2_3;
1130 schan.code_rate_LP = FEC_3_4;
1131 schan.hierarchy = 0;
b6884a17
PB
1132
1133 dib7000p_set_channel(state, &schan, 7);
1134
c1f814f4 1135 factor = BANDWIDTH_TO_KHZ(ch->bandwidth_hz);
2e802861
OG
1136 if (factor >= 5000) {
1137 if (state->version == SOC7090)
1138 factor = 2;
1139 else
1140 factor = 1;
1141 } else
b6884a17 1142 factor = 6;
a75763ff 1143
713d54a8 1144 value = 30 * internal * factor;
b4d6046e
OG
1145 dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff));
1146 dib7000p_write_word(state, 7, (u16) (value & 0xffff));
713d54a8 1147 value = 100 * internal * factor;
b4d6046e
OG
1148 dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff));
1149 dib7000p_write_word(state, 9, (u16) (value & 0xffff));
713d54a8 1150 value = 500 * internal * factor;
b4d6046e
OG
1151 dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff));
1152 dib7000p_write_word(state, 11, (u16) (value & 0xffff));
a75763ff
PB
1153
1154 value = dib7000p_read_word(state, 0);
b6884a17 1155 dib7000p_write_word(state, 0, (u16) ((1 << 9) | value));
a75763ff
PB
1156 dib7000p_read_word(state, 1284);
1157 dib7000p_write_word(state, 0, (u16) value);
1158
1159 return 0;
1160}
1161
1162static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod)
1163{
1164 struct dib7000p_state *state = demod->demodulator_priv;
1165 u16 irq_pending = dib7000p_read_word(state, 1284);
1166
b4d6046e 1167 if (irq_pending & 0x1)
a75763ff
PB
1168 return 1;
1169
b4d6046e 1170 if (irq_pending & 0x2)
a75763ff
PB
1171 return 2;
1172
b4d6046e 1173 return 0;
a75763ff
PB
1174}
1175
b6884a17
PB
1176static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 bw)
1177{
713d54a8
OG
1178 static s16 notch[] = { 16143, 14402, 12238, 9713, 6902, 3888, 759, -2392 };
1179 static u8 sine[] = { 0, 2, 3, 5, 6, 8, 9, 11, 13, 14, 16, 17, 19, 20, 22,
1180 24, 25, 27, 28, 30, 31, 33, 34, 36, 38, 39, 41, 42, 44, 45, 47, 48, 50, 51,
1181 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80,
1182 82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, 104, 105,
1183 107, 108, 109, 111, 112, 114, 115, 117, 118, 119, 121, 122, 123, 125, 126,
1184 128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 144, 145, 146,
1185 147, 149, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 162, 164, 165,
1186 166, 167, 168, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182,
1187 183, 184, 185, 186, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
1188 199, 200, 201, 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 212,
1189 213, 214, 215, 215, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 224,
1190 225, 226, 227, 227, 228, 229, 229, 230, 231, 231, 232, 233, 233, 234, 235,
1191 235, 236, 237, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 243,
1192 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 248, 249, 249, 249,
1193 250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 254,
1194 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1195 255, 255, 255, 255, 255, 255
1196 };
b6884a17
PB
1197
1198 u32 xtal = state->cfg.bw->xtal_hz / 1000;
75b697f7 1199 int f_rel = DIV_ROUND_CLOSEST(rf_khz, xtal) * xtal - rf_khz;
b6884a17 1200 int k;
713d54a8 1201 int coef_re[8], coef_im[8];
b6884a17
PB
1202 int bw_khz = bw;
1203 u32 pha;
1204
713d54a8 1205 dprintk("relative position of the Spur: %dk (RF: %dk, XTAL: %dk)", f_rel, rf_khz, xtal);
b6884a17 1206
713d54a8 1207 if (f_rel < -bw_khz / 2 || f_rel > bw_khz / 2)
b6884a17
PB
1208 return;
1209
1210 bw_khz /= 100;
1211
713d54a8 1212 dib7000p_write_word(state, 142, 0x0610);
b6884a17
PB
1213
1214 for (k = 0; k < 8; k++) {
713d54a8 1215 pha = ((f_rel * (k + 1) * 112 * 80 / bw_khz) / 1000) & 0x3ff;
b6884a17 1216
713d54a8 1217 if (pha == 0) {
b6884a17
PB
1218 coef_re[k] = 256;
1219 coef_im[k] = 0;
713d54a8
OG
1220 } else if (pha < 256) {
1221 coef_re[k] = sine[256 - (pha & 0xff)];
1222 coef_im[k] = sine[pha & 0xff];
b6884a17
PB
1223 } else if (pha == 256) {
1224 coef_re[k] = 0;
1225 coef_im[k] = 256;
1226 } else if (pha < 512) {
713d54a8
OG
1227 coef_re[k] = -sine[pha & 0xff];
1228 coef_im[k] = sine[256 - (pha & 0xff)];
b6884a17
PB
1229 } else if (pha == 512) {
1230 coef_re[k] = -256;
1231 coef_im[k] = 0;
1232 } else if (pha < 768) {
713d54a8
OG
1233 coef_re[k] = -sine[256 - (pha & 0xff)];
1234 coef_im[k] = -sine[pha & 0xff];
b6884a17
PB
1235 } else if (pha == 768) {
1236 coef_re[k] = 0;
1237 coef_im[k] = -256;
1238 } else {
713d54a8
OG
1239 coef_re[k] = sine[pha & 0xff];
1240 coef_im[k] = -sine[256 - (pha & 0xff)];
b6884a17
PB
1241 }
1242
1243 coef_re[k] *= notch[k];
713d54a8
OG
1244 coef_re[k] += (1 << 14);
1245 if (coef_re[k] >= (1 << 24))
1246 coef_re[k] = (1 << 24) - 1;
1247 coef_re[k] /= (1 << 15);
b6884a17
PB
1248
1249 coef_im[k] *= notch[k];
713d54a8
OG
1250 coef_im[k] += (1 << 14);
1251 if (coef_im[k] >= (1 << 24))
1252 coef_im[k] = (1 << 24) - 1;
1253 coef_im[k] /= (1 << 15);
b6884a17 1254
713d54a8 1255 dprintk("PALF COEF: %d re: %d im: %d", k, coef_re[k], coef_im[k]);
b6884a17
PB
1256
1257 dib7000p_write_word(state, 143, (0 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
1258 dib7000p_write_word(state, 144, coef_im[k] & 0x3ff);
1259 dib7000p_write_word(state, 143, (1 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
1260 }
713d54a8 1261 dib7000p_write_word(state, 143, 0);
b6884a17
PB
1262}
1263
c1f814f4 1264static int dib7000p_tune(struct dvb_frontend *demod)
a75763ff 1265{
c1f814f4 1266 struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
a75763ff
PB
1267 struct dib7000p_state *state = demod->demodulator_priv;
1268 u16 tmp = 0;
1269
1270 if (ch != NULL)
1271 dib7000p_set_channel(state, ch, 0);
1272 else
1273 return -EINVAL;
1274
1275 // restart demod
1276 dib7000p_write_word(state, 770, 0x4000);
1277 dib7000p_write_word(state, 770, 0x0000);
1278 msleep(45);
1279
1280 /* 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 */
8f6956c7
MD
1281 tmp = (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3);
1282 if (state->sfn_workaround_active) {
713d54a8 1283 dprintk("SFN workaround is active");
8f6956c7 1284 tmp |= (1 << 9);
b4d6046e 1285 dib7000p_write_word(state, 166, 0x4000);
8f6956c7 1286 } else {
b4d6046e 1287 dib7000p_write_word(state, 166, 0x0000);
8f6956c7
MD
1288 }
1289 dib7000p_write_word(state, 29, tmp);
a75763ff
PB
1290
1291 // never achieved a lock with that bandwidth so far - wait for osc-freq to update
1292 if (state->timf == 0)
1293 msleep(200);
1294
1295 /* offset loop parameters */
1296
1297 /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
1298 tmp = (6 << 8) | 0x80;
c1f814f4 1299 switch (ch->transmission_mode) {
713d54a8
OG
1300 case TRANSMISSION_MODE_2K:
1301 tmp |= (2 << 12);
1302 break;
46f7296a 1303 case TRANSMISSION_MODE_4K:
713d54a8
OG
1304 tmp |= (3 << 12);
1305 break;
1306 default:
1307 case TRANSMISSION_MODE_8K:
1308 tmp |= (4 << 12);
1309 break;
a75763ff 1310 }
713d54a8 1311 dib7000p_write_word(state, 26, tmp); /* timf_a(6xxx) */
a75763ff
PB
1312
1313 /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
1314 tmp = (0 << 4);
c1f814f4 1315 switch (ch->transmission_mode) {
713d54a8
OG
1316 case TRANSMISSION_MODE_2K:
1317 tmp |= 0x6;
1318 break;
46f7296a 1319 case TRANSMISSION_MODE_4K:
713d54a8
OG
1320 tmp |= 0x7;
1321 break;
1322 default:
1323 case TRANSMISSION_MODE_8K:
1324 tmp |= 0x8;
1325 break;
a75763ff 1326 }
713d54a8 1327 dib7000p_write_word(state, 32, tmp);
a75763ff
PB
1328
1329 /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
1330 tmp = (0 << 4);
c1f814f4 1331 switch (ch->transmission_mode) {
713d54a8
OG
1332 case TRANSMISSION_MODE_2K:
1333 tmp |= 0x6;
1334 break;
1335 case TRANSMISSION_MODE_4K:
1336 tmp |= 0x7;
1337 break;
1338 default:
1339 case TRANSMISSION_MODE_8K:
1340 tmp |= 0x8;
1341 break;
a75763ff 1342 }
713d54a8 1343 dib7000p_write_word(state, 33, tmp);
a75763ff 1344
713d54a8 1345 tmp = dib7000p_read_word(state, 509);
a75763ff
PB
1346 if (!((tmp >> 6) & 0x1)) {
1347 /* restart the fec */
713d54a8 1348 tmp = dib7000p_read_word(state, 771);
a75763ff
PB
1349 dib7000p_write_word(state, 771, tmp | (1 << 1));
1350 dib7000p_write_word(state, 771, tmp);
713d54a8
OG
1351 msleep(40);
1352 tmp = dib7000p_read_word(state, 509);
a75763ff 1353 }
a75763ff 1354 // we achieved a lock - it's time to update the osc freq
713d54a8 1355 if ((tmp >> 6) & 0x1) {
b6884a17 1356 dib7000p_update_timf(state);
713d54a8
OG
1357 /* P_timf_alpha += 2 */
1358 tmp = dib7000p_read_word(state, 26);
1359 dib7000p_write_word(state, 26, (tmp & ~(0xf << 12)) | ((((tmp >> 12) & 0xf) + 5) << 12));
1360 }
b6884a17
PB
1361
1362 if (state->cfg.spur_protect)
c1f814f4 1363 dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
a75763ff 1364
c1f814f4 1365 dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
041ad449
MCC
1366
1367 dib7000p_reset_stats(demod);
1368
a75763ff
PB
1369 return 0;
1370}
1371
b6884a17 1372static int dib7000p_wakeup(struct dvb_frontend *demod)
a75763ff 1373{
a75763ff 1374 struct dib7000p_state *state = demod->demodulator_priv;
a75763ff
PB
1375 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
1376 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
713d54a8
OG
1377 if (state->version == SOC7090)
1378 dib7000p_sad_calib(state);
b6884a17 1379 return 0;
a75763ff
PB
1380}
1381
1382static int dib7000p_sleep(struct dvb_frontend *demod)
1383{
1384 struct dib7000p_state *state = demod->demodulator_priv;
713d54a8 1385 if (state->version == SOC7090)
2e802861 1386 return dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
a75763ff
PB
1387 return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
1388}
1389
1390static int dib7000p_identify(struct dib7000p_state *st)
1391{
1392 u16 value;
713d54a8 1393 dprintk("checking demod on I2C address: %d (%x)", st->i2c_addr, st->i2c_addr);
a75763ff
PB
1394
1395 if ((value = dib7000p_read_word(st, 768)) != 0x01b3) {
713d54a8 1396 dprintk("wrong Vendor ID (read=0x%x)", value);
a75763ff
PB
1397 return -EREMOTEIO;
1398 }
1399
1400 if ((value = dib7000p_read_word(st, 769)) != 0x4000) {
713d54a8 1401 dprintk("wrong Device ID (%x)", value);
a75763ff
PB
1402 return -EREMOTEIO;
1403 }
1404
1405 return 0;
1406}
1407
7c61d80a 1408static int dib7000p_get_frontend(struct dvb_frontend *fe)
a75763ff 1409{
7c61d80a 1410 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
a75763ff 1411 struct dib7000p_state *state = fe->demodulator_priv;
713d54a8 1412 u16 tps = dib7000p_read_word(state, 463);
a75763ff
PB
1413
1414 fep->inversion = INVERSION_AUTO;
1415
c1f814f4 1416 fep->bandwidth_hz = BANDWIDTH_TO_HZ(state->current_bandwidth);
a75763ff
PB
1417
1418 switch ((tps >> 8) & 0x3) {
713d54a8 1419 case 0:
c1f814f4 1420 fep->transmission_mode = TRANSMISSION_MODE_2K;
713d54a8
OG
1421 break;
1422 case 1:
c1f814f4 1423 fep->transmission_mode = TRANSMISSION_MODE_8K;
713d54a8 1424 break;
c1f814f4 1425 /* case 2: fep->transmission_mode = TRANSMISSION_MODE_4K; break; */
a75763ff
PB
1426 }
1427
1428 switch (tps & 0x3) {
713d54a8 1429 case 0:
c1f814f4 1430 fep->guard_interval = GUARD_INTERVAL_1_32;
713d54a8
OG
1431 break;
1432 case 1:
c1f814f4 1433 fep->guard_interval = GUARD_INTERVAL_1_16;
713d54a8
OG
1434 break;
1435 case 2:
c1f814f4 1436 fep->guard_interval = GUARD_INTERVAL_1_8;
713d54a8
OG
1437 break;
1438 case 3:
c1f814f4 1439 fep->guard_interval = GUARD_INTERVAL_1_4;
713d54a8 1440 break;
a75763ff
PB
1441 }
1442
1443 switch ((tps >> 14) & 0x3) {
713d54a8 1444 case 0:
c1f814f4 1445 fep->modulation = QPSK;
713d54a8
OG
1446 break;
1447 case 1:
c1f814f4 1448 fep->modulation = QAM_16;
713d54a8
OG
1449 break;
1450 case 2:
1451 default:
c1f814f4 1452 fep->modulation = QAM_64;
713d54a8 1453 break;
a75763ff
PB
1454 }
1455
1456 /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
1457 /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
1458
c1f814f4 1459 fep->hierarchy = HIERARCHY_NONE;
a75763ff 1460 switch ((tps >> 5) & 0x7) {
713d54a8 1461 case 1:
c1f814f4 1462 fep->code_rate_HP = FEC_1_2;
713d54a8
OG
1463 break;
1464 case 2:
c1f814f4 1465 fep->code_rate_HP = FEC_2_3;
713d54a8
OG
1466 break;
1467 case 3:
c1f814f4 1468 fep->code_rate_HP = FEC_3_4;
713d54a8
OG
1469 break;
1470 case 5:
c1f814f4 1471 fep->code_rate_HP = FEC_5_6;
713d54a8
OG
1472 break;
1473 case 7:
1474 default:
c1f814f4 1475 fep->code_rate_HP = FEC_7_8;
713d54a8 1476 break;
a75763ff
PB
1477
1478 }
1479
1480 switch ((tps >> 2) & 0x7) {
713d54a8 1481 case 1:
c1f814f4 1482 fep->code_rate_LP = FEC_1_2;
713d54a8
OG
1483 break;
1484 case 2:
c1f814f4 1485 fep->code_rate_LP = FEC_2_3;
713d54a8
OG
1486 break;
1487 case 3:
c1f814f4 1488 fep->code_rate_LP = FEC_3_4;
713d54a8
OG
1489 break;
1490 case 5:
c1f814f4 1491 fep->code_rate_LP = FEC_5_6;
713d54a8
OG
1492 break;
1493 case 7:
1494 default:
c1f814f4 1495 fep->code_rate_LP = FEC_7_8;
713d54a8 1496 break;
a75763ff
PB
1497 }
1498
1499 /* native interleaver: (dib7000p_read_word(state, 464) >> 5) & 0x1 */
1500
1501 return 0;
1502}
1503
c1f814f4 1504static int dib7000p_set_frontend(struct dvb_frontend *fe)
a75763ff 1505{
7c61d80a 1506 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
a75763ff 1507 struct dib7000p_state *state = fe->demodulator_priv;
853ea132 1508 int time, ret;
a75763ff 1509
2e802861 1510 if (state->version == SOC7090)
713d54a8 1511 dib7090_set_diversity_in(fe, 0);
2e802861 1512 else
713d54a8 1513 dib7000p_set_output_mode(state, OUTMODE_HIGH_Z);
a75763ff 1514
713d54a8 1515 /* maybe the parameter has been changed */
8f6956c7
MD
1516 state->sfn_workaround_active = buggy_sfn_workaround;
1517
a75763ff 1518 if (fe->ops.tuner_ops.set_params)
14d24d14 1519 fe->ops.tuner_ops.set_params(fe);
a75763ff 1520
b6884a17
PB
1521 /* start up the AGC */
1522 state->agc_state = 0;
1523 do {
c1f814f4 1524 time = dib7000p_agc_startup(fe);
b6884a17
PB
1525 if (time != -1)
1526 msleep(time);
1527 } while (time != -1);
1528
c1f814f4
MCC
1529 if (fep->transmission_mode == TRANSMISSION_MODE_AUTO ||
1530 fep->guard_interval == GUARD_INTERVAL_AUTO || fep->modulation == QAM_AUTO || fep->code_rate_HP == FEC_AUTO) {
a75763ff
PB
1531 int i = 800, found;
1532
c1f814f4 1533 dib7000p_autosearch_start(fe);
a75763ff
PB
1534 do {
1535 msleep(1);
1536 found = dib7000p_autosearch_is_irq(fe);
1537 } while (found == 0 && i--);
1538
713d54a8 1539 dprintk("autosearch returns: %d", found);
a75763ff 1540 if (found == 0 || found == 1)
b4d6046e 1541 return 0;
a75763ff 1542
7c61d80a 1543 dib7000p_get_frontend(fe);
a75763ff
PB
1544 }
1545
c1f814f4 1546 ret = dib7000p_tune(fe);
853ea132 1547
a75763ff 1548 /* make this a config parameter */
2e802861 1549 if (state->version == SOC7090) {
713d54a8 1550 dib7090_set_output_mode(fe, state->cfg.output_mode);
2e802861
OG
1551 if (state->cfg.enMpegOutput == 0) {
1552 dib7090_setDibTxMux(state, MPEG_ON_DIBTX);
1553 dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
1554 }
1555 } else
713d54a8
OG
1556 dib7000p_set_output_mode(state, state->cfg.output_mode);
1557
1558 return ret;
a75763ff
PB
1559}
1560
0df289a2 1561static int dib7000p_get_stats(struct dvb_frontend *fe, enum fe_status stat);
041ad449 1562
0df289a2 1563static int dib7000p_read_status(struct dvb_frontend *fe, enum fe_status *stat)
a75763ff
PB
1564{
1565 struct dib7000p_state *state = fe->demodulator_priv;
1566 u16 lock = dib7000p_read_word(state, 509);
1567
1568 *stat = 0;
1569
1570 if (lock & 0x8000)
1571 *stat |= FE_HAS_SIGNAL;
1572 if (lock & 0x3000)
1573 *stat |= FE_HAS_CARRIER;
1574 if (lock & 0x0100)
1575 *stat |= FE_HAS_VITERBI;
1576 if (lock & 0x0010)
1577 *stat |= FE_HAS_SYNC;
713d54a8 1578 if ((lock & 0x0038) == 0x38)
a75763ff
PB
1579 *stat |= FE_HAS_LOCK;
1580
041ad449
MCC
1581 dib7000p_get_stats(fe, *stat);
1582
a75763ff
PB
1583 return 0;
1584}
1585
713d54a8 1586static int dib7000p_read_ber(struct dvb_frontend *fe, u32 * ber)
a75763ff
PB
1587{
1588 struct dib7000p_state *state = fe->demodulator_priv;
1589 *ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501);
1590 return 0;
1591}
1592
713d54a8 1593static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
a75763ff
PB
1594{
1595 struct dib7000p_state *state = fe->demodulator_priv;
1596 *unc = dib7000p_read_word(state, 506);
1597 return 0;
1598}
1599
713d54a8 1600static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
a75763ff
PB
1601{
1602 struct dib7000p_state *state = fe->demodulator_priv;
1603 u16 val = dib7000p_read_word(state, 394);
1604 *strength = 65535 - val;
1605 return 0;
1606}
1607
041ad449 1608static u32 dib7000p_get_snr(struct dvb_frontend *fe)
a75763ff 1609{
ef801964
OG
1610 struct dib7000p_state *state = fe->demodulator_priv;
1611 u16 val;
1612 s32 signal_mant, signal_exp, noise_mant, noise_exp;
1613 u32 result = 0;
1614
1615 val = dib7000p_read_word(state, 479);
1616 noise_mant = (val >> 4) & 0xff;
1617 noise_exp = ((val & 0xf) << 2);
1618 val = dib7000p_read_word(state, 480);
1619 noise_exp += ((val >> 14) & 0x3);
1620 if ((noise_exp & 0x20) != 0)
1621 noise_exp -= 0x40;
1622
1623 signal_mant = (val >> 6) & 0xFF;
713d54a8 1624 signal_exp = (val & 0x3F);
ef801964
OG
1625 if ((signal_exp & 0x20) != 0)
1626 signal_exp -= 0x40;
1627
1628 if (signal_mant != 0)
713d54a8 1629 result = intlog10(2) * 10 * signal_exp + 10 * intlog10(signal_mant);
ef801964
OG
1630 else
1631 result = intlog10(2) * 10 * signal_exp - 100;
1632
1633 if (noise_mant != 0)
713d54a8 1634 result -= intlog10(2) * 10 * noise_exp + 10 * intlog10(noise_mant);
ef801964
OG
1635 else
1636 result -= intlog10(2) * 10 * noise_exp - 100;
1637
041ad449
MCC
1638 return result;
1639}
1640
1641static int dib7000p_read_snr(struct dvb_frontend *fe, u16 *snr)
1642{
1643 u32 result;
1644
1645 result = dib7000p_get_snr(fe);
1646
ef801964 1647 *snr = result / ((1 << 24) / 10);
a75763ff
PB
1648 return 0;
1649}
1650
041ad449
MCC
1651static void dib7000p_reset_stats(struct dvb_frontend *demod)
1652{
1653 struct dib7000p_state *state = demod->demodulator_priv;
1654 struct dtv_frontend_properties *c = &demod->dtv_property_cache;
1655 u32 ucb;
1656
1657 memset(&c->strength, 0, sizeof(c->strength));
1658 memset(&c->cnr, 0, sizeof(c->cnr));
1659 memset(&c->post_bit_error, 0, sizeof(c->post_bit_error));
1660 memset(&c->post_bit_count, 0, sizeof(c->post_bit_count));
1661 memset(&c->block_error, 0, sizeof(c->block_error));
1662
1663 c->strength.len = 1;
1664 c->cnr.len = 1;
1665 c->block_error.len = 1;
1666 c->block_count.len = 1;
1667 c->post_bit_error.len = 1;
1668 c->post_bit_count.len = 1;
1669
1670 c->strength.stat[0].scale = FE_SCALE_DECIBEL;
1671 c->strength.stat[0].uvalue = 0;
1672
1673 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1674 c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1675 c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1676 c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1677 c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1678
1679 dib7000p_read_unc_blocks(demod, &ucb);
1680
1681 state->old_ucb = ucb;
1682 state->ber_jiffies_stats = 0;
1683 state->per_jiffies_stats = 0;
1684}
1685
1686struct linear_segments {
1687 unsigned x;
1688 signed y;
1689};
1690
1691/*
1692 * Table to estimate signal strength in dBm.
1693 * This table should be empirically determinated by measuring the signal
1694 * strength generated by a RF generator directly connected into
1695 * a device.
3926d91a
MCC
1696 * This table was determinated by measuring the signal strength generated
1697 * by a DTA-2111 RF generator directly connected into a dib7000p device
1698 * (a Hauppauge Nova-TD stick), using a good quality 3 meters length
1699 * RC6 cable and good RC6 connectors, connected directly to antenna 1.
1700 * As the minimum output power of DTA-2111 is -31dBm, a 16 dBm attenuator
1701 * were used, for the lower power values.
1702 * The real value can actually be on other devices, or even at the
1703 * second antena input, depending on several factors, like if LNA
1704 * is enabled or not, if diversity is enabled, type of connectors, etc.
1705 * Yet, it is better to use this measure in dB than a random non-linear
1706 * percentage value, especially for antenna adjustments.
1707 * On my tests, the precision of the measure using this table is about
1708 * 0.5 dB, with sounds reasonable enough to adjust antennas.
041ad449 1709 */
3926d91a 1710#define DB_OFFSET 131000
041ad449
MCC
1711
1712static struct linear_segments strength_to_db_table[] = {
3926d91a
MCC
1713 { 63630, DB_OFFSET - 20500},
1714 { 62273, DB_OFFSET - 21000},
1715 { 60162, DB_OFFSET - 22000},
1716 { 58730, DB_OFFSET - 23000},
1717 { 58294, DB_OFFSET - 24000},
1718 { 57778, DB_OFFSET - 25000},
1719 { 57320, DB_OFFSET - 26000},
1720 { 56779, DB_OFFSET - 27000},
1721 { 56293, DB_OFFSET - 28000},
1722 { 55724, DB_OFFSET - 29000},
1723 { 55145, DB_OFFSET - 30000},
1724 { 54680, DB_OFFSET - 31000},
1725 { 54293, DB_OFFSET - 32000},
1726 { 53813, DB_OFFSET - 33000},
1727 { 53427, DB_OFFSET - 34000},
1728 { 52981, DB_OFFSET - 35000},
1729
1730 { 52636, DB_OFFSET - 36000},
1731 { 52014, DB_OFFSET - 37000},
1732 { 51674, DB_OFFSET - 38000},
1733 { 50692, DB_OFFSET - 39000},
1734 { 49824, DB_OFFSET - 40000},
1735 { 49052, DB_OFFSET - 41000},
1736 { 48436, DB_OFFSET - 42000},
1737 { 47836, DB_OFFSET - 43000},
1738 { 47368, DB_OFFSET - 44000},
1739 { 46468, DB_OFFSET - 45000},
1740 { 45597, DB_OFFSET - 46000},
1741 { 44586, DB_OFFSET - 47000},
1742 { 43667, DB_OFFSET - 48000},
1743 { 42673, DB_OFFSET - 49000},
1744 { 41816, DB_OFFSET - 50000},
1745 { 40876, DB_OFFSET - 51000},
041ad449
MCC
1746 { 0, 0},
1747};
1748
1749static u32 interpolate_value(u32 value, struct linear_segments *segments,
1750 unsigned len)
1751{
1752 u64 tmp64;
1753 u32 dx;
1754 s32 dy;
1755 int i, ret;
1756
1757 if (value >= segments[0].x)
1758 return segments[0].y;
1759 if (value < segments[len-1].x)
1760 return segments[len-1].y;
1761
1762 for (i = 1; i < len - 1; i++) {
1763 /* If value is identical, no need to interpolate */
1764 if (value == segments[i].x)
1765 return segments[i].y;
1766 if (value > segments[i].x)
1767 break;
1768 }
1769
1770 /* Linear interpolation between the two (x,y) points */
1771 dy = segments[i - 1].y - segments[i].y;
1772 dx = segments[i - 1].x - segments[i].x;
1773
1774 tmp64 = value - segments[i].x;
1775 tmp64 *= dy;
1776 do_div(tmp64, dx);
1777 ret = segments[i].y + tmp64;
1778
1779 return ret;
1780}
1781
1782/* FIXME: may require changes - this one was borrowed from dib8000 */
986f1686 1783static u32 dib7000p_get_time_us(struct dvb_frontend *demod)
041ad449
MCC
1784{
1785 struct dtv_frontend_properties *c = &demod->dtv_property_cache;
1786 u64 time_us, tmp64;
1787 u32 tmp, denom;
1788 int guard, rate_num, rate_denum = 1, bits_per_symbol;
1789 int interleaving = 0, fft_div;
1790
1791 switch (c->guard_interval) {
1792 case GUARD_INTERVAL_1_4:
1793 guard = 4;
1794 break;
1795 case GUARD_INTERVAL_1_8:
1796 guard = 8;
1797 break;
1798 case GUARD_INTERVAL_1_16:
1799 guard = 16;
1800 break;
1801 default:
1802 case GUARD_INTERVAL_1_32:
1803 guard = 32;
1804 break;
1805 }
1806
1807 switch (c->transmission_mode) {
1808 case TRANSMISSION_MODE_2K:
1809 fft_div = 4;
1810 break;
1811 case TRANSMISSION_MODE_4K:
1812 fft_div = 2;
1813 break;
1814 default:
1815 case TRANSMISSION_MODE_8K:
1816 fft_div = 1;
1817 break;
1818 }
1819
1820 switch (c->modulation) {
1821 case DQPSK:
1822 case QPSK:
1823 bits_per_symbol = 2;
1824 break;
1825 case QAM_16:
1826 bits_per_symbol = 4;
1827 break;
1828 default:
1829 case QAM_64:
1830 bits_per_symbol = 6;
1831 break;
1832 }
1833
1834 switch ((c->hierarchy == 0 || 1 == 1) ? c->code_rate_HP : c->code_rate_LP) {
1835 case FEC_1_2:
1836 rate_num = 1;
1837 rate_denum = 2;
1838 break;
1839 case FEC_2_3:
1840 rate_num = 2;
1841 rate_denum = 3;
1842 break;
1843 case FEC_3_4:
1844 rate_num = 3;
1845 rate_denum = 4;
1846 break;
1847 case FEC_5_6:
1848 rate_num = 5;
1849 rate_denum = 6;
1850 break;
1851 default:
1852 case FEC_7_8:
1853 rate_num = 7;
1854 rate_denum = 8;
1855 break;
1856 }
1857
1858 interleaving = interleaving;
1859
1860 denom = bits_per_symbol * rate_num * fft_div * 384;
1861
1862 /* If calculus gets wrong, wait for 1s for the next stats */
1863 if (!denom)
1864 return 0;
1865
1866 /* Estimate the period for the total bit rate */
1867 time_us = rate_denum * (1008 * 1562500L);
1868 tmp64 = time_us;
1869 do_div(tmp64, guard);
1870 time_us = time_us + tmp64;
1871 time_us += denom / 2;
1872 do_div(time_us, denom);
1873
1874 tmp = 1008 * 96 * interleaving;
1875 time_us += tmp + tmp / guard;
1876
1877 return time_us;
1878}
1879
0df289a2 1880static int dib7000p_get_stats(struct dvb_frontend *demod, enum fe_status stat)
041ad449
MCC
1881{
1882 struct dib7000p_state *state = demod->demodulator_priv;
1883 struct dtv_frontend_properties *c = &demod->dtv_property_cache;
041ad449
MCC
1884 int show_per_stats = 0;
1885 u32 time_us = 0, val, snr;
1886 u64 blocks, ucb;
1887 s32 db;
1888 u16 strength;
1889
1890 /* Get Signal strength */
1891 dib7000p_read_signal_strength(demod, &strength);
1892 val = strength;
1893 db = interpolate_value(val,
1894 strength_to_db_table,
1895 ARRAY_SIZE(strength_to_db_table)) - DB_OFFSET;
1896 c->strength.stat[0].svalue = db;
1897
041ad449
MCC
1898 /* UCB/BER/CNR measures require lock */
1899 if (!(stat & FE_HAS_LOCK)) {
1900 c->cnr.len = 1;
1901 c->block_count.len = 1;
1902 c->block_error.len = 1;
1903 c->post_bit_error.len = 1;
1904 c->post_bit_count.len = 1;
1905 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1906 c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1907 c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1908 c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1909 c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1910 return 0;
1911 }
1912
1913 /* Check if time for stats was elapsed */
1914 if (time_after(jiffies, state->per_jiffies_stats)) {
1915 state->per_jiffies_stats = jiffies + msecs_to_jiffies(1000);
1916
1917 /* Get SNR */
1918 snr = dib7000p_get_snr(demod);
1919 if (snr)
1920 snr = (1000L * snr) >> 24;
1921 else
1922 snr = 0;
1923 c->cnr.stat[0].svalue = snr;
1924 c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
1925
1926 /* Get UCB measures */
1927 dib7000p_read_unc_blocks(demod, &val);
1928 ucb = val - state->old_ucb;
1929 if (val < state->old_ucb)
1930 ucb += 0x100000000LL;
1931
1932 c->block_error.stat[0].scale = FE_SCALE_COUNTER;
1933 c->block_error.stat[0].uvalue = ucb;
1934
1935 /* Estimate the number of packets based on bitrate */
1936 if (!time_us)
986f1686 1937 time_us = dib7000p_get_time_us(demod);
041ad449
MCC
1938
1939 if (time_us) {
1940 blocks = 1250000ULL * 1000000ULL;
1941 do_div(blocks, time_us * 8 * 204);
1942 c->block_count.stat[0].scale = FE_SCALE_COUNTER;
1943 c->block_count.stat[0].uvalue += blocks;
1944 }
1945
1946 show_per_stats = 1;
1947 }
1948
1949 /* Get post-BER measures */
1950 if (time_after(jiffies, state->ber_jiffies_stats)) {
986f1686 1951 time_us = dib7000p_get_time_us(demod);
041ad449
MCC
1952 state->ber_jiffies_stats = jiffies + msecs_to_jiffies((time_us + 500) / 1000);
1953
1954 dprintk("Next all layers stats available in %u us.", time_us);
1955
1956 dib7000p_read_ber(demod, &val);
1957 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
1958 c->post_bit_error.stat[0].uvalue += val;
1959
1960 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
1961 c->post_bit_count.stat[0].uvalue += 100000000;
1962 }
1963
1964 /* Get PER measures */
1965 if (show_per_stats) {
1966 dib7000p_read_unc_blocks(demod, &val);
1967
1968 c->block_error.stat[0].scale = FE_SCALE_COUNTER;
1969 c->block_error.stat[0].uvalue += val;
1970
986f1686 1971 time_us = dib7000p_get_time_us(demod);
041ad449
MCC
1972 if (time_us) {
1973 blocks = 1250000ULL * 1000000ULL;
1974 do_div(blocks, time_us * 8 * 204);
1975 c->block_count.stat[0].scale = FE_SCALE_COUNTER;
1976 c->block_count.stat[0].uvalue += blocks;
1977 }
1978 }
1979 return 0;
1980}
1981
713d54a8 1982static int dib7000p_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
a75763ff
PB
1983{
1984 tune->min_delay_ms = 1000;
1985 return 0;
1986}
1987
1988static void dib7000p_release(struct dvb_frontend *demod)
1989{
1990 struct dib7000p_state *st = demod->demodulator_priv;
1991 dibx000_exit_i2c_master(&st->i2c_master);
713d54a8 1992 i2c_del_adapter(&st->dib7090_tuner_adap);
a75763ff
PB
1993 kfree(st);
1994}
1995
8abe4a0a 1996static int dib7000pc_detection(struct i2c_adapter *i2c_adap)
a75763ff 1997{
5a0deeed 1998 u8 *tx, *rx;
a75763ff 1999 struct i2c_msg msg[2] = {
5a0deeed
OG
2000 {.addr = 18 >> 1, .flags = 0, .len = 2},
2001 {.addr = 18 >> 1, .flags = I2C_M_RD, .len = 2},
a75763ff 2002 };
5a0deeed
OG
2003 int ret = 0;
2004
2005 tx = kzalloc(2*sizeof(u8), GFP_KERNEL);
2006 if (!tx)
2007 return -ENOMEM;
2008 rx = kzalloc(2*sizeof(u8), GFP_KERNEL);
2009 if (!rx) {
5a0deeed 2010 ret = -ENOMEM;
0c61cc3b 2011 goto rx_memory_error;
5a0deeed
OG
2012 }
2013
2014 msg[0].buf = tx;
2015 msg[1].buf = rx;
a75763ff
PB
2016
2017 tx[0] = 0x03;
2018 tx[1] = 0x00;
2019
2020 if (i2c_transfer(i2c_adap, msg, 2) == 2)
2021 if (rx[0] == 0x01 && rx[1] == 0xb3) {
b6884a17 2022 dprintk("-D- DiB7000PC detected");
a75763ff
PB
2023 return 1;
2024 }
2025
2026 msg[0].addr = msg[1].addr = 0x40;
2027
2028 if (i2c_transfer(i2c_adap, msg, 2) == 2)
2029 if (rx[0] == 0x01 && rx[1] == 0xb3) {
b6884a17 2030 dprintk("-D- DiB7000PC detected");
a75763ff
PB
2031 return 1;
2032 }
2033
b6884a17 2034 dprintk("-D- DiB7000PC not detected");
5a0deeed
OG
2035
2036 kfree(rx);
2037rx_memory_error:
2038 kfree(tx);
2039 return ret;
a75763ff 2040}
a75763ff 2041
8abe4a0a 2042static struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
a75763ff
PB
2043{
2044 struct dib7000p_state *st = demod->demodulator_priv;
2045 return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
2046}
a75763ff 2047
8abe4a0a 2048static int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
f8731f4d 2049{
713d54a8
OG
2050 struct dib7000p_state *state = fe->demodulator_priv;
2051 u16 val = dib7000p_read_word(state, 235) & 0xffef;
2052 val |= (onoff & 0x1) << 4;
2053 dprintk("PID filter enabled %d", onoff);
2054 return dib7000p_write_word(state, 235, val);
f8731f4d 2055}
f8731f4d 2056
8abe4a0a 2057static int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
f8731f4d 2058{
713d54a8
OG
2059 struct dib7000p_state *state = fe->demodulator_priv;
2060 dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
2061 return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0);
f8731f4d 2062}
f8731f4d 2063
8abe4a0a 2064static int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
a75763ff 2065{
30d81bb0 2066 struct dib7000p_state *dpst;
a75763ff
PB
2067 int k = 0;
2068 u8 new_addr = 0;
2069
30d81bb0
RD
2070 dpst = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
2071 if (!dpst)
0b42760a 2072 return -ENOMEM;
30d81bb0
RD
2073
2074 dpst->i2c_adap = i2c;
79fcce32 2075 mutex_init(&dpst->i2c_buffer_lock);
30d81bb0 2076
713d54a8 2077 for (k = no_of_demods - 1; k >= 0; k--) {
30d81bb0 2078 dpst->cfg = cfg[k];
a75763ff
PB
2079
2080 /* designated i2c address */
713d54a8
OG
2081 if (cfg[k].default_i2c_addr != 0)
2082 new_addr = cfg[k].default_i2c_addr + (k << 1);
2083 else
2084 new_addr = (0x40 + k) << 1;
30d81bb0 2085 dpst->i2c_addr = new_addr;
713d54a8 2086 dib7000p_write_word(dpst, 1287, 0x0003); /* sram lead in, rdy */
30d81bb0
RD
2087 if (dib7000p_identify(dpst) != 0) {
2088 dpst->i2c_addr = default_addr;
713d54a8 2089 dib7000p_write_word(dpst, 1287, 0x0003); /* sram lead in, rdy */
30d81bb0 2090 if (dib7000p_identify(dpst) != 0) {
a75763ff 2091 dprintk("DiB7000P #%d: not identified\n", k);
30d81bb0 2092 kfree(dpst);
a75763ff
PB
2093 return -EIO;
2094 }
2095 }
2096
2097 /* start diversity to pull_down div_str - just for i2c-enumeration */
30d81bb0 2098 dib7000p_set_output_mode(dpst, OUTMODE_DIVERSITY);
a75763ff
PB
2099
2100 /* set new i2c address and force divstart */
30d81bb0 2101 dib7000p_write_word(dpst, 1285, (new_addr << 2) | 0x2);
a75763ff 2102
b6884a17 2103 dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
a75763ff
PB
2104 }
2105
2106 for (k = 0; k < no_of_demods; k++) {
30d81bb0 2107 dpst->cfg = cfg[k];
713d54a8
OG
2108 if (cfg[k].default_i2c_addr != 0)
2109 dpst->i2c_addr = (cfg[k].default_i2c_addr + k) << 1;
2110 else
2111 dpst->i2c_addr = (0x40 + k) << 1;
a75763ff
PB
2112
2113 // unforce divstr
30d81bb0 2114 dib7000p_write_word(dpst, 1285, dpst->i2c_addr << 2);
a75763ff
PB
2115
2116 /* deactivate div - it was just for i2c-enumeration */
30d81bb0 2117 dib7000p_set_output_mode(dpst, OUTMODE_HIGH_Z);
a75763ff
PB
2118 }
2119
30d81bb0 2120 kfree(dpst);
a75763ff
PB
2121 return 0;
2122}
a75763ff 2123
713d54a8
OG
2124static const s32 lut_1000ln_mant[] = {
2125 6908, 6956, 7003, 7047, 7090, 7131, 7170, 7208, 7244, 7279, 7313, 7346, 7377, 7408, 7438, 7467, 7495, 7523, 7549, 7575, 7600
2126};
2127
2128static s32 dib7000p_get_adc_power(struct dvb_frontend *fe)
2129{
2130 struct dib7000p_state *state = fe->demodulator_priv;
2131 u32 tmp_val = 0, exp = 0, mant = 0;
2132 s32 pow_i;
2133 u16 buf[2];
2134 u8 ix = 0;
2135
2136 buf[0] = dib7000p_read_word(state, 0x184);
2137 buf[1] = dib7000p_read_word(state, 0x185);
2138 pow_i = (buf[0] << 16) | buf[1];
2139 dprintk("raw pow_i = %d", pow_i);
2140
2141 tmp_val = pow_i;
2142 while (tmp_val >>= 1)
2143 exp++;
2144
2145 mant = (pow_i * 1000 / (1 << exp));
2146 dprintk(" mant = %d exp = %d", mant / 1000, exp);
2147
2148 ix = (u8) ((mant - 1000) / 100); /* index of the LUT */
2149 dprintk(" ix = %d", ix);
2150
2151 pow_i = (lut_1000ln_mant[ix] + 693 * (exp - 20) - 6908);
2152 pow_i = (pow_i << 8) / 1000;
2153 dprintk(" pow_i = %d", pow_i);
2154
2155 return pow_i;
2156}
2157
2158static int map_addr_to_serpar_number(struct i2c_msg *msg)
2159{
2160 if ((msg->buf[0] <= 15))
2161 msg->buf[0] -= 1;
2162 else if (msg->buf[0] == 17)
2163 msg->buf[0] = 15;
2164 else if (msg->buf[0] == 16)
2165 msg->buf[0] = 17;
2166 else if (msg->buf[0] == 19)
2167 msg->buf[0] = 16;
2168 else if (msg->buf[0] >= 21 && msg->buf[0] <= 25)
2169 msg->buf[0] -= 3;
2170 else if (msg->buf[0] == 28)
2171 msg->buf[0] = 23;
b4d6046e 2172 else
713d54a8 2173 return -EINVAL;
713d54a8
OG
2174 return 0;
2175}
2176
2177static int w7090p_tuner_write_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
2178{
2179 struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
2180 u8 n_overflow = 1;
2181 u16 i = 1000;
2182 u16 serpar_num = msg[0].buf[0];
2183
2184 while (n_overflow == 1 && i) {
2185 n_overflow = (dib7000p_read_word(state, 1984) >> 1) & 0x1;
2186 i--;
2187 if (i == 0)
2188 dprintk("Tuner ITF: write busy (overflow)");
2189 }
2190 dib7000p_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f));
2191 dib7000p_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]);
2192
2193 return num;
2194}
2195
2196static int w7090p_tuner_read_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
2197{
2198 struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
2199 u8 n_overflow = 1, n_empty = 1;
2200 u16 i = 1000;
2201 u16 serpar_num = msg[0].buf[0];
2202 u16 read_word;
2203
2204 while (n_overflow == 1 && i) {
2205 n_overflow = (dib7000p_read_word(state, 1984) >> 1) & 0x1;
2206 i--;
2207 if (i == 0)
2208 dprintk("TunerITF: read busy (overflow)");
2209 }
2210 dib7000p_write_word(state, 1985, (0 << 6) | (serpar_num & 0x3f));
2211
2212 i = 1000;
2213 while (n_empty == 1 && i) {
2214 n_empty = dib7000p_read_word(state, 1984) & 0x1;
2215 i--;
2216 if (i == 0)
2217 dprintk("TunerITF: read busy (empty)");
2218 }
2219 read_word = dib7000p_read_word(state, 1987);
2220 msg[1].buf[0] = (read_word >> 8) & 0xff;
2221 msg[1].buf[1] = (read_word) & 0xff;
2222
2223 return num;
2224}
2225
2226static int w7090p_tuner_rw_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
2227{
2228 if (map_addr_to_serpar_number(&msg[0]) == 0) { /* else = Tuner regs to ignore : DIG_CFG, CTRL_RF_LT, PLL_CFG, PWM1_REG, ADCCLK, DIG_CFG_3; SLEEP_EN... */
2229 if (num == 1) { /* write */
2230 return w7090p_tuner_write_serpar(i2c_adap, msg, 1);
2231 } else { /* read */
2232 return w7090p_tuner_read_serpar(i2c_adap, msg, 2);
2233 }
2234 }
2235 return num;
2236}
2237
a685dbbc
OG
2238static int dib7090p_rw_on_apb(struct i2c_adapter *i2c_adap,
2239 struct i2c_msg msg[], int num, u16 apb_address)
713d54a8
OG
2240{
2241 struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
2242 u16 word;
2243
2244 if (num == 1) { /* write */
2245 dib7000p_write_word(state, apb_address, ((msg[0].buf[1] << 8) | (msg[0].buf[2])));
2246 } else {
2247 word = dib7000p_read_word(state, apb_address);
2248 msg[1].buf[0] = (word >> 8) & 0xff;
2249 msg[1].buf[1] = (word) & 0xff;
2250 }
2251
2252 return num;
2253}
2254
2255static int dib7090_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
2256{
2257 struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
2258
2259 u16 apb_address = 0, word;
2260 int i = 0;
2261 switch (msg[0].buf[0]) {
2262 case 0x12:
2263 apb_address = 1920;
2264 break;
2265 case 0x14:
2266 apb_address = 1921;
2267 break;
2268 case 0x24:
2269 apb_address = 1922;
2270 break;
2271 case 0x1a:
2272 apb_address = 1923;
2273 break;
2274 case 0x22:
2275 apb_address = 1924;
2276 break;
2277 case 0x33:
2278 apb_address = 1926;
2279 break;
2280 case 0x34:
2281 apb_address = 1927;
2282 break;
2283 case 0x35:
2284 apb_address = 1928;
2285 break;
2286 case 0x36:
2287 apb_address = 1929;
2288 break;
2289 case 0x37:
2290 apb_address = 1930;
2291 break;
2292 case 0x38:
2293 apb_address = 1931;
2294 break;
2295 case 0x39:
2296 apb_address = 1932;
2297 break;
2298 case 0x2a:
2299 apb_address = 1935;
2300 break;
2301 case 0x2b:
2302 apb_address = 1936;
2303 break;
2304 case 0x2c:
2305 apb_address = 1937;
2306 break;
2307 case 0x2d:
2308 apb_address = 1938;
2309 break;
2310 case 0x2e:
2311 apb_address = 1939;
2312 break;
2313 case 0x2f:
2314 apb_address = 1940;
2315 break;
2316 case 0x30:
2317 apb_address = 1941;
2318 break;
2319 case 0x31:
2320 apb_address = 1942;
2321 break;
2322 case 0x32:
2323 apb_address = 1943;
2324 break;
2325 case 0x3e:
2326 apb_address = 1944;
2327 break;
2328 case 0x3f:
2329 apb_address = 1945;
2330 break;
2331 case 0x40:
2332 apb_address = 1948;
2333 break;
2334 case 0x25:
2335 apb_address = 914;
2336 break;
2337 case 0x26:
2338 apb_address = 915;
2339 break;
2340 case 0x27:
2e802861 2341 apb_address = 917;
713d54a8
OG
2342 break;
2343 case 0x28:
2e802861 2344 apb_address = 916;
713d54a8
OG
2345 break;
2346 case 0x1d:
2347 i = ((dib7000p_read_word(state, 72) >> 12) & 0x3);
2348 word = dib7000p_read_word(state, 384 + i);
2349 msg[1].buf[0] = (word >> 8) & 0xff;
2350 msg[1].buf[1] = (word) & 0xff;
2351 return num;
2352 case 0x1f:
2353 if (num == 1) { /* write */
2354 word = (u16) ((msg[0].buf[1] << 8) | msg[0].buf[2]);
2355 word &= 0x3;
b4d6046e 2356 word = (dib7000p_read_word(state, 72) & ~(3 << 12)) | (word << 12);
713d54a8
OG
2357 dib7000p_write_word(state, 72, word); /* Set the proper input */
2358 return num;
2359 }
2360 }
2361
2362 if (apb_address != 0) /* R/W acces via APB */
2363 return dib7090p_rw_on_apb(i2c_adap, msg, num, apb_address);
2364 else /* R/W access via SERPAR */
2365 return w7090p_tuner_rw_serpar(i2c_adap, msg, num);
2366
2367 return 0;
2368}
2369
2370static u32 dib7000p_i2c_func(struct i2c_adapter *adapter)
2371{
2372 return I2C_FUNC_I2C;
2373}
2374
2375static struct i2c_algorithm dib7090_tuner_xfer_algo = {
2376 .master_xfer = dib7090_tuner_xfer,
2377 .functionality = dib7000p_i2c_func,
2378};
2379
8abe4a0a 2380static struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
713d54a8
OG
2381{
2382 struct dib7000p_state *st = fe->demodulator_priv;
2383 return &st->dib7090_tuner_adap;
2384}
713d54a8
OG
2385
2386static int dib7090_host_bus_drive(struct dib7000p_state *state, u8 drive)
2387{
2388 u16 reg;
2389
2390 /* drive host bus 2, 3, 4 */
2391 reg = dib7000p_read_word(state, 1798) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
2392 reg |= (drive << 12) | (drive << 6) | drive;
2393 dib7000p_write_word(state, 1798, reg);
2394
2395 /* drive host bus 5,6 */
2396 reg = dib7000p_read_word(state, 1799) & ~((0x7 << 2) | (0x7 << 8));
2397 reg |= (drive << 8) | (drive << 2);
2398 dib7000p_write_word(state, 1799, reg);
2399
2400 /* drive host bus 7, 8, 9 */
2401 reg = dib7000p_read_word(state, 1800) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
2402 reg |= (drive << 12) | (drive << 6) | drive;
2403 dib7000p_write_word(state, 1800, reg);
2404
2405 /* drive host bus 10, 11 */
2406 reg = dib7000p_read_word(state, 1801) & ~((0x7 << 2) | (0x7 << 8));
2407 reg |= (drive << 8) | (drive << 2);
2408 dib7000p_write_word(state, 1801, reg);
2409
2410 /* drive host bus 12, 13, 14 */
2411 reg = dib7000p_read_word(state, 1802) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
2412 reg |= (drive << 12) | (drive << 6) | drive;
2413 dib7000p_write_word(state, 1802, reg);
2414
2415 return 0;
2416}
2417
2418static u32 dib7090_calcSyncFreq(u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 syncSize)
2419{
2420 u32 quantif = 3;
2421 u32 nom = (insertExtSynchro * P_Kin + syncSize);
2422 u32 denom = P_Kout;
2423 u32 syncFreq = ((nom << quantif) / denom);
2424
2425 if ((syncFreq & ((1 << quantif) - 1)) != 0)
2426 syncFreq = (syncFreq >> quantif) + 1;
2427 else
2428 syncFreq = (syncFreq >> quantif);
2429
2430 if (syncFreq != 0)
2431 syncFreq = syncFreq - 1;
2432
2433 return syncFreq;
2434}
2435
2436static int dib7090_cfg_DibTx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 synchroMode, u32 syncWord, u32 syncSize)
2437{
713d54a8 2438 dprintk("Configure DibStream Tx");
713d54a8
OG
2439
2440 dib7000p_write_word(state, 1615, 1);
2441 dib7000p_write_word(state, 1603, P_Kin);
2442 dib7000p_write_word(state, 1605, P_Kout);
2443 dib7000p_write_word(state, 1606, insertExtSynchro);
2444 dib7000p_write_word(state, 1608, synchroMode);
2445 dib7000p_write_word(state, 1609, (syncWord >> 16) & 0xffff);
2446 dib7000p_write_word(state, 1610, syncWord & 0xffff);
2447 dib7000p_write_word(state, 1612, syncSize);
2448 dib7000p_write_word(state, 1615, 0);
2449
713d54a8
OG
2450 return 0;
2451}
2452
2453static int dib7090_cfg_DibRx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 synchroMode, u32 insertExtSynchro, u32 syncWord, u32 syncSize,
2454 u32 dataOutRate)
2455{
2456 u32 syncFreq;
2457
2458 dprintk("Configure DibStream Rx");
b4d6046e 2459 if ((P_Kin != 0) && (P_Kout != 0)) {
713d54a8
OG
2460 syncFreq = dib7090_calcSyncFreq(P_Kin, P_Kout, insertExtSynchro, syncSize);
2461 dib7000p_write_word(state, 1542, syncFreq);
2462 }
2463 dib7000p_write_word(state, 1554, 1);
2464 dib7000p_write_word(state, 1536, P_Kin);
2465 dib7000p_write_word(state, 1537, P_Kout);
2466 dib7000p_write_word(state, 1539, synchroMode);
2467 dib7000p_write_word(state, 1540, (syncWord >> 16) & 0xffff);
2468 dib7000p_write_word(state, 1541, syncWord & 0xffff);
2469 dib7000p_write_word(state, 1543, syncSize);
2470 dib7000p_write_word(state, 1544, dataOutRate);
2471 dib7000p_write_word(state, 1554, 0);
2472
2473 return 0;
2474}
2475
2e802861 2476static void dib7090_enMpegMux(struct dib7000p_state *state, int onoff)
713d54a8 2477{
2e802861 2478 u16 reg_1287 = dib7000p_read_word(state, 1287);
713d54a8 2479
2e802861
OG
2480 switch (onoff) {
2481 case 1:
2482 reg_1287 &= ~(1<<7);
2483 break;
2484 case 0:
2485 reg_1287 |= (1<<7);
2486 break;
2487 }
713d54a8 2488
2e802861 2489 dib7000p_write_word(state, 1287, reg_1287);
713d54a8
OG
2490}
2491
2e802861
OG
2492static void dib7090_configMpegMux(struct dib7000p_state *state,
2493 u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
713d54a8 2494{
713d54a8 2495 dprintk("Enable Mpeg mux");
713d54a8 2496
2e802861 2497 dib7090_enMpegMux(state, 0);
713d54a8 2498
2e802861
OG
2499 /* If the input mode is MPEG do not divide the serial clock */
2500 if ((enSerialMode == 1) && (state->input_mode_mpeg == 1))
2501 enSerialClkDiv2 = 0;
713d54a8 2502
2e802861
OG
2503 dib7000p_write_word(state, 1287, ((pulseWidth & 0x1f) << 2)
2504 | ((enSerialMode & 0x1) << 1)
2505 | (enSerialClkDiv2 & 0x1));
2506
2507 dib7090_enMpegMux(state, 1);
713d54a8
OG
2508}
2509
2e802861 2510static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode)
713d54a8 2511{
2e802861 2512 u16 reg_1288 = dib7000p_read_word(state, 1288) & ~(0x7 << 7);
713d54a8 2513
2e802861
OG
2514 switch (mode) {
2515 case MPEG_ON_DIBTX:
2516 dprintk("SET MPEG ON DIBSTREAM TX");
2517 dib7090_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
2518 reg_1288 |= (1<<9);
2519 break;
2520 case DIV_ON_DIBTX:
2521 dprintk("SET DIV_OUT ON DIBSTREAM TX");
2522 dib7090_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
2523 reg_1288 |= (1<<8);
2524 break;
2525 case ADC_ON_DIBTX:
2526 dprintk("SET ADC_OUT ON DIBSTREAM TX");
2527 dib7090_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
2528 reg_1288 |= (1<<7);
2529 break;
2530 default:
2531 break;
2532 }
2533 dib7000p_write_word(state, 1288, reg_1288);
713d54a8
OG
2534}
2535
2e802861 2536static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode)
713d54a8 2537{
2e802861 2538 u16 reg_1288 = dib7000p_read_word(state, 1288) & ~(0x7 << 4);
713d54a8 2539
b4d6046e 2540 switch (mode) {
2e802861
OG
2541 case DEMOUT_ON_HOSTBUS:
2542 dprintk("SET DEM OUT OLD INTERF ON HOST BUS");
2543 dib7090_enMpegMux(state, 0);
2544 reg_1288 |= (1<<6);
2545 break;
2546 case DIBTX_ON_HOSTBUS:
2547 dprintk("SET DIBSTREAM TX ON HOST BUS");
2548 dib7090_enMpegMux(state, 0);
2549 reg_1288 |= (1<<5);
713d54a8 2550 break;
2e802861
OG
2551 case MPEG_ON_HOSTBUS:
2552 dprintk("SET MPEG MUX ON HOST BUS");
2553 reg_1288 |= (1<<4);
713d54a8 2554 break;
b4d6046e 2555 default:
713d54a8
OG
2556 break;
2557 }
2e802861 2558 dib7000p_write_word(state, 1288, reg_1288);
713d54a8
OG
2559}
2560
18ef20da 2561static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff)
713d54a8 2562{
2e802861
OG
2563 struct dib7000p_state *state = fe->demodulator_priv;
2564 u16 reg_1287;
2565
713d54a8 2566 switch (onoff) {
2e802861
OG
2567 case 0: /* only use the internal way - not the diversity input */
2568 dprintk("%s mode OFF : by default Enable Mpeg INPUT", __func__);
2569 dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);
2570
2571 /* Do not divide the serial clock of MPEG MUX */
2572 /* in SERIAL MODE in case input mode MPEG is used */
2573 reg_1287 = dib7000p_read_word(state, 1287);
2574 /* enSerialClkDiv2 == 1 ? */
2575 if ((reg_1287 & 0x1) == 1) {
2576 /* force enSerialClkDiv2 = 0 */
2577 reg_1287 &= ~0x1;
2578 dib7000p_write_word(state, 1287, reg_1287);
2579 }
2580 state->input_mode_mpeg = 1;
2581 break;
2582 case 1: /* both ways */
2583 case 2: /* only the diversity input */
2584 dprintk("%s ON : Enable diversity INPUT", __func__);
2585 dib7090_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
2586 state->input_mode_mpeg = 0;
2587 break;
713d54a8
OG
2588 }
2589
2e802861 2590 dib7000p_set_diversity_in(&state->demod, onoff);
713d54a8
OG
2591 return 0;
2592}
2593
2594static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode)
2595{
2596 struct dib7000p_state *state = fe->demodulator_priv;
2597
2598 u16 outreg, smo_mode, fifo_threshold;
2599 u8 prefer_mpeg_mux_use = 1;
2600 int ret = 0;
2601
2602 dib7090_host_bus_drive(state, 1);
2603
2604 fifo_threshold = 1792;
2605 smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1);
2606 outreg = dib7000p_read_word(state, 1286) & ~((1 << 10) | (0x7 << 6) | (1 << 1));
2607
2608 switch (mode) {
2609 case OUTMODE_HIGH_Z:
2610 outreg = 0;
2611 break;
2612
2613 case OUTMODE_MPEG2_SERIAL:
2614 if (prefer_mpeg_mux_use) {
2e802861
OG
2615 dprintk("setting output mode TS_SERIAL using Mpeg Mux");
2616 dib7090_configMpegMux(state, 3, 1, 1);
2617 dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS);
2618 } else {/* Use Smooth block */
2619 dprintk("setting output mode TS_SERIAL using Smooth bloc");
2620 dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
2621 outreg |= (2<<6) | (0 << 1);
713d54a8
OG
2622 }
2623 break;
2624
2625 case OUTMODE_MPEG2_PAR_GATED_CLK:
2626 if (prefer_mpeg_mux_use) {
2e802861
OG
2627 dprintk("setting output mode TS_PARALLEL_GATED using Mpeg Mux");
2628 dib7090_configMpegMux(state, 2, 0, 0);
2629 dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS);
2630 } else { /* Use Smooth block */
2631 dprintk("setting output mode TS_PARALLEL_GATED using Smooth block");
2632 dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
2633 outreg |= (0<<6);
713d54a8
OG
2634 }
2635 break;
2636
2637 case OUTMODE_MPEG2_PAR_CONT_CLK: /* Using Smooth block only */
2e802861
OG
2638 dprintk("setting output mode TS_PARALLEL_CONT using Smooth block");
2639 dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
2640 outreg |= (1<<6);
713d54a8
OG
2641 break;
2642
2643 case OUTMODE_MPEG2_FIFO: /* Using Smooth block because not supported by new Mpeg Mux bloc */
2e802861
OG
2644 dprintk("setting output mode TS_FIFO using Smooth block");
2645 dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
2646 outreg |= (5<<6);
713d54a8
OG
2647 smo_mode |= (3 << 1);
2648 fifo_threshold = 512;
2649 break;
2650
2651 case OUTMODE_DIVERSITY:
2e802861
OG
2652 dprintk("setting output mode MODE_DIVERSITY");
2653 dib7090_setDibTxMux(state, DIV_ON_DIBTX);
2654 dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
713d54a8
OG
2655 break;
2656
2657 case OUTMODE_ANALOG_ADC:
2e802861
OG
2658 dprintk("setting output mode MODE_ANALOG_ADC");
2659 dib7090_setDibTxMux(state, ADC_ON_DIBTX);
2660 dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
713d54a8
OG
2661 break;
2662 }
2e802861
OG
2663 if (mode != OUTMODE_HIGH_Z)
2664 outreg |= (1 << 10);
713d54a8
OG
2665
2666 if (state->cfg.output_mpeg2_in_188_bytes)
2667 smo_mode |= (1 << 5);
2668
2669 ret |= dib7000p_write_word(state, 235, smo_mode);
2670 ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */
2e802861 2671 ret |= dib7000p_write_word(state, 1286, outreg);
713d54a8
OG
2672
2673 return ret;
2674}
2675
8abe4a0a 2676static int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
713d54a8
OG
2677{
2678 struct dib7000p_state *state = fe->demodulator_priv;
2679 u16 en_cur_state;
2680
2681 dprintk("sleep dib7090: %d", onoff);
2682
2683 en_cur_state = dib7000p_read_word(state, 1922);
2684
b4d6046e 2685 if (en_cur_state > 0xff)
713d54a8 2686 state->tuner_enable = en_cur_state;
713d54a8
OG
2687
2688 if (onoff)
b4d6046e 2689 en_cur_state &= 0x00ff;
713d54a8
OG
2690 else {
2691 if (state->tuner_enable != 0)
2692 en_cur_state = state->tuner_enable;
2693 }
2694
2695 dib7000p_write_word(state, 1922, en_cur_state);
2696
2697 return 0;
2698}
713d54a8 2699
8abe4a0a 2700static int dib7090_get_adc_power(struct dvb_frontend *fe)
713d54a8
OG
2701{
2702 return dib7000p_get_adc_power(fe);
2703}
713d54a8 2704
8abe4a0a 2705static int dib7090_slave_reset(struct dvb_frontend *fe)
713d54a8
OG
2706{
2707 struct dib7000p_state *state = fe->demodulator_priv;
b4d6046e 2708 u16 reg;
713d54a8 2709
b4d6046e
OG
2710 reg = dib7000p_read_word(state, 1794);
2711 dib7000p_write_word(state, 1794, reg | (4 << 12));
713d54a8 2712
b4d6046e
OG
2713 dib7000p_write_word(state, 1032, 0xffff);
2714 return 0;
713d54a8 2715}
713d54a8 2716
a75763ff 2717static struct dvb_frontend_ops dib7000p_ops;
8abe4a0a 2718static struct dvb_frontend *dib7000p_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
a75763ff
PB
2719{
2720 struct dvb_frontend *demod;
2721 struct dib7000p_state *st;
2722 st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
2723 if (st == NULL)
2724 return NULL;
2725
2726 memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config));
2727 st->i2c_adap = i2c_adap;
2728 st->i2c_addr = i2c_addr;
2729 st->gpio_val = cfg->gpio_val;
2730 st->gpio_dir = cfg->gpio_dir;
2731
a38d6e37
ST
2732 /* Ensure the output mode remains at the previous default if it's
2733 * not specifically set by the caller.
2734 */
713d54a8 2735 if ((st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (st->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
a38d6e37
ST
2736 st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
2737
713d54a8 2738 demod = &st->demod;
a75763ff
PB
2739 demod->demodulator_priv = st;
2740 memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
79fcce32 2741 mutex_init(&st->i2c_buffer_lock);
a75763ff 2742
713d54a8 2743 dib7000p_write_word(st, 1287, 0x0003); /* sram lead in, rdy */
eac1fe10 2744
a75763ff
PB
2745 if (dib7000p_identify(st) != 0)
2746 goto error;
2747
713d54a8
OG
2748 st->version = dib7000p_read_word(st, 897);
2749
7646b9de 2750 /* FIXME: make sure the dev.parent field is initialized, or else
85ec9d71
DH
2751 request_firmware() will hit an OOPS (this should be moved somewhere
2752 more common) */
2753 st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
2754
a75763ff
PB
2755 dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
2756
713d54a8
OG
2757 /* init 7090 tuner adapter */
2758 strncpy(st->dib7090_tuner_adap.name, "DiB7090 tuner interface", sizeof(st->dib7090_tuner_adap.name));
2759 st->dib7090_tuner_adap.algo = &dib7090_tuner_xfer_algo;
2760 st->dib7090_tuner_adap.algo_data = NULL;
2761 st->dib7090_tuner_adap.dev.parent = st->i2c_adap->dev.parent;
2762 i2c_set_adapdata(&st->dib7090_tuner_adap, st);
2763 i2c_add_adapter(&st->dib7090_tuner_adap);
2764
a75763ff
PB
2765 dib7000p_demod_reset(st);
2766
041ad449
MCC
2767 dib7000p_reset_stats(demod);
2768
713d54a8
OG
2769 if (st->version == SOC7090) {
2770 dib7090_set_output_mode(demod, st->cfg.output_mode);
2771 dib7090_set_diversity_in(demod, 0);
2772 }
2773
a75763ff
PB
2774 return demod;
2775
b4d6046e 2776error:
a75763ff
PB
2777 kfree(st);
2778 return NULL;
2779}
8abe4a0a
MCC
2780
2781void *dib7000p_attach(struct dib7000p_ops *ops)
2782{
2783 if (!ops)
2784 return NULL;
2785
2786 ops->slave_reset = dib7090_slave_reset;
2787 ops->get_adc_power = dib7090_get_adc_power;
2788 ops->dib7000pc_detection = dib7000pc_detection;
2789 ops->get_i2c_tuner = dib7090_get_i2c_tuner;
2790 ops->tuner_sleep = dib7090_tuner_sleep;
2791 ops->init = dib7000p_init;
2792 ops->set_agc1_min = dib7000p_set_agc1_min;
2793 ops->set_gpio = dib7000p_set_gpio;
2794 ops->i2c_enumeration = dib7000p_i2c_enumeration;
2795 ops->pid_filter = dib7000p_pid_filter;
2796 ops->pid_filter_ctrl = dib7000p_pid_filter_ctrl;
2797 ops->get_i2c_master = dib7000p_get_i2c_master;
2798 ops->update_pll = dib7000p_update_pll;
2799 ops->ctrl_timf = dib7000p_ctrl_timf;
2800 ops->get_agc_values = dib7000p_get_agc_values;
2801 ops->set_wbd_ref = dib7000p_set_wbd_ref;
2802
2803 return ops;
2804}
2805EXPORT_SYMBOL(dib7000p_attach);
a75763ff
PB
2806
2807static struct dvb_frontend_ops dib7000p_ops = {
c1f814f4 2808 .delsys = { SYS_DVBT },
a75763ff 2809 .info = {
713d54a8 2810 .name = "DiBcom 7000PC",
713d54a8
OG
2811 .frequency_min = 44250000,
2812 .frequency_max = 867250000,
2813 .frequency_stepsize = 62500,
2814 .caps = FE_CAN_INVERSION_AUTO |
2815 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
2816 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
2817 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
2818 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
2819 },
2820
2821 .release = dib7000p_release,
2822
2823 .init = dib7000p_wakeup,
2824 .sleep = dib7000p_sleep,
2825
c1f814f4 2826 .set_frontend = dib7000p_set_frontend,
713d54a8 2827 .get_tune_settings = dib7000p_fe_get_tune_settings,
c1f814f4 2828 .get_frontend = dib7000p_get_frontend,
713d54a8
OG
2829
2830 .read_status = dib7000p_read_status,
2831 .read_ber = dib7000p_read_ber,
a75763ff 2832 .read_signal_strength = dib7000p_read_signal_strength,
713d54a8
OG
2833 .read_snr = dib7000p_read_snr,
2834 .read_ucblocks = dib7000p_read_unc_blocks,
a75763ff
PB
2835};
2836
713d54a8 2837MODULE_AUTHOR("Olivier Grenie <ogrenie@dibcom.fr>");
a75763ff
PB
2838MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
2839MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator");
2840MODULE_LICENSE("GPL");