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