1 /*
2 * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
3 *
4 * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 *
15 * GNU General Public License for more details.
16 *
17 *
18 * This code is more or less generated from another driver, please
19 * excuse some codingstyle oddities.
20 *
21 */
22
23 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
25 #include <linux/kernel.h>
26 #include <linux/slab.h>
27 #include <linux/i2c.h>
28 #include <linux/mutex.h>
29
30 #include <media/dvb_frontend.h>
31
32 #include "dib0090.h"
33 #include "dibx000_common.h"
34
35 static int debug;
36 module_param(debug, int, 0644);
37 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
38
39 #define dprintk(fmt, arg...) do { \
40 if (debug) \
41 printk(KERN_DEBUG pr_fmt("%s: " fmt), \
42 __func__, ##arg); \
43 } while (0)
44
45 #define CONFIG_SYS_DVBT
46 #define CONFIG_SYS_ISDBT
47 #define CONFIG_BAND_CBAND
48 #define CONFIG_BAND_VHF
49 #define CONFIG_BAND_UHF
50 #define CONFIG_DIB0090_USE_PWM_AGC
51
52 #define EN_LNA0 0x8000
53 #define EN_LNA1 0x4000
54 #define EN_LNA2 0x2000
55 #define EN_LNA3 0x1000
56 #define EN_MIX0 0x0800
57 #define EN_MIX1 0x0400
58 #define EN_MIX2 0x0200
59 #define EN_MIX3 0x0100
60 #define EN_IQADC 0x0040
61 #define EN_PLL 0x0020
62 #define EN_TX 0x0010
63 #define EN_BB 0x0008
64 #define EN_LO 0x0004
65 #define EN_BIAS 0x0001
66
67 #define EN_IQANA 0x0002
68 #define EN_DIGCLK 0x0080 /* not in the 0x24 reg, only in 0x1b */
69 #define EN_CRYSTAL 0x0002
70
71 #define EN_UHF 0x22E9
72 #define EN_VHF 0x44E9
73 #define EN_LBD 0x11E9
74 #define EN_SBD 0x44E9
75 #define EN_CAB 0x88E9
76
77 /* Calibration defines */
78 #define DC_CAL 0x1
79 #define WBD_CAL 0x2
80 #define TEMP_CAL 0x4
81 #define CAPTRIM_CAL 0x8
82
83 #define KROSUS_PLL_LOCKED 0x800
84 #define KROSUS 0x2
85
86 /* Use those defines to identify SOC version */
87 #define SOC 0x02
88 #define SOC_7090_P1G_11R1 0x82
89 #define SOC_7090_P1G_21R1 0x8a
90 #define SOC_8090_P1G_11R1 0x86
91 #define SOC_8090_P1G_21R1 0x8e
92
93 /* else use thos ones to check */
94 #define P1A_B 0x0
95 #define P1C 0x1
96 #define P1D_E_F 0x3
97 #define P1G 0x7
98 #define P1G_21R2 0xf
99
100 #define MP001 0x1 /* Single 9090/8096 */
101 #define MP005 0x4 /* Single Sband */
102 #define MP008 0x6 /* Dual diversity VHF-UHF-LBAND */
103 #define MP009 0x7 /* Dual diversity 29098 CBAND-UHF-LBAND-SBAND */
104
105 #define pgm_read_word(w) (*w)
106
107 struct dc_calibration;
108
109 struct dib0090_tuning {
110 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
111 u8 switch_trim;
112 u8 lna_tune;
113 u16 lna_bias;
114 u16 v2i;
115 u16 mix;
116 u16 load;
117 u16 tuner_enable;
118 };
119
120 struct dib0090_pll {
121 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
122 u8 vco_band;
123 u8 hfdiv_code;
124 u8 hfdiv;
125 u8 topresc;
126 };
127
128 struct dib0090_identity {
129 u8 version;
130 u8 product;
131 u8 p1g;
132 u8 in_soc;
133 };
134
135 struct dib0090_state {
136 struct i2c_adapter *i2c;
137 struct dvb_frontend *fe;
138 const struct dib0090_config *config;
139
140 u8 current_band;
141 enum frontend_tune_state tune_state;
142 u32 current_rf;
143
144 u16 wbd_offset;
145 s16 wbd_target; /* in dB */
146
147 s16 rf_gain_limit; /* take-over-point: where to split between bb and rf gain */
148 s16 current_gain; /* keeps the currently programmed gain */
149 u8 agc_step; /* new binary search */
150
151 u16 gain[2]; /* for channel monitoring */
152
153 const u16 *rf_ramp;
154 const u16 *bb_ramp;
155
156 /* for the software AGC ramps */
157 u16 bb_1_def;
158 u16 rf_lt_def;
159 u16 gain_reg[4];
160
161 /* for the captrim/dc-offset search */
162 s8 step;
163 s16 adc_diff;
164 s16 min_adc_diff;
165
166 s8 captrim;
167 s8 fcaptrim;
168
169 const struct dc_calibration *dc;
170 u16 bb6, bb7;
171
172 const struct dib0090_tuning *current_tune_table_index;
173 const struct dib0090_pll *current_pll_table_index;
174
175 u8 tuner_is_tuned;
176 u8 agc_freeze;
177
178 struct dib0090_identity identity;
179
180 u32 rf_request;
181 u8 current_standard;
182
183 u8 calibrate;
184 u32 rest;
185 u16 bias;
186 s16 temperature;
187
188 u8 wbd_calibration_gain;
189 const struct dib0090_wbd_slope *current_wbd_table;
190 u16 wbdmux;
191
192 /* for the I2C transfer */
193 struct i2c_msg msg[2];
194 u8 i2c_write_buffer[3];
195 u8 i2c_read_buffer[2];
196 struct mutex i2c_buffer_lock;
197 };
198
199 struct dib0090_fw_state {
200 struct i2c_adapter *i2c;
201 struct dvb_frontend *fe;
202 struct dib0090_identity identity;
203 const struct dib0090_config *config;
204
205 /* for the I2C transfer */
206 struct i2c_msg msg;
207 u8 i2c_write_buffer[2];
208 u8 i2c_read_buffer[2];
209 struct mutex i2c_buffer_lock;
210 };
211
dib0090_read_reg(struct dib0090_state * state,u8 reg)212 static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
213 {
214 u16 ret;
215
216 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
217 dprintk("could not acquire lock\n");
218 return 0;
219 }
220
221 state->i2c_write_buffer[0] = reg;
222
223 memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
224 state->msg[0].addr = state->config->i2c_address;
225 state->msg[0].flags = 0;
226 state->msg[0].buf = state->i2c_write_buffer;
227 state->msg[0].len = 1;
228 state->msg[1].addr = state->config->i2c_address;
229 state->msg[1].flags = I2C_M_RD;
230 state->msg[1].buf = state->i2c_read_buffer;
231 state->msg[1].len = 2;
232
233 if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
234 pr_warn("DiB0090 I2C read failed\n");
235 ret = 0;
236 } else
237 ret = (state->i2c_read_buffer[0] << 8)
238 | state->i2c_read_buffer[1];
239
240 mutex_unlock(&state->i2c_buffer_lock);
241 return ret;
242 }
243
dib0090_write_reg(struct dib0090_state * state,u32 reg,u16 val)244 static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
245 {
246 int ret;
247
248 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
249 dprintk("could not acquire lock\n");
250 return -EINVAL;
251 }
252
253 state->i2c_write_buffer[0] = reg & 0xff;
254 state->i2c_write_buffer[1] = val >> 8;
255 state->i2c_write_buffer[2] = val & 0xff;
256
257 memset(state->msg, 0, sizeof(struct i2c_msg));
258 state->msg[0].addr = state->config->i2c_address;
259 state->msg[0].flags = 0;
260 state->msg[0].buf = state->i2c_write_buffer;
261 state->msg[0].len = 3;
262
263 if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
264 pr_warn("DiB0090 I2C write failed\n");
265 ret = -EREMOTEIO;
266 } else
267 ret = 0;
268
269 mutex_unlock(&state->i2c_buffer_lock);
270 return ret;
271 }
272
dib0090_fw_read_reg(struct dib0090_fw_state * state,u8 reg)273 static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
274 {
275 u16 ret;
276
277 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
278 dprintk("could not acquire lock\n");
279 return 0;
280 }
281
282 state->i2c_write_buffer[0] = reg;
283
284 memset(&state->msg, 0, sizeof(struct i2c_msg));
285 state->msg.addr = reg;
286 state->msg.flags = I2C_M_RD;
287 state->msg.buf = state->i2c_read_buffer;
288 state->msg.len = 2;
289 if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
290 pr_warn("DiB0090 I2C read failed\n");
291 ret = 0;
292 } else
293 ret = (state->i2c_read_buffer[0] << 8)
294 | state->i2c_read_buffer[1];
295
296 mutex_unlock(&state->i2c_buffer_lock);
297 return ret;
298 }
299
dib0090_fw_write_reg(struct dib0090_fw_state * state,u8 reg,u16 val)300 static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
301 {
302 int ret;
303
304 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
305 dprintk("could not acquire lock\n");
306 return -EINVAL;
307 }
308
309 state->i2c_write_buffer[0] = val >> 8;
310 state->i2c_write_buffer[1] = val & 0xff;
311
312 memset(&state->msg, 0, sizeof(struct i2c_msg));
313 state->msg.addr = reg;
314 state->msg.flags = 0;
315 state->msg.buf = state->i2c_write_buffer;
316 state->msg.len = 2;
317 if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
318 pr_warn("DiB0090 I2C write failed\n");
319 ret = -EREMOTEIO;
320 } else
321 ret = 0;
322
323 mutex_unlock(&state->i2c_buffer_lock);
324 return ret;
325 }
326
327 #define HARD_RESET(state) do { if (cfg->reset) { if (cfg->sleep) cfg->sleep(fe, 0); msleep(10); cfg->reset(fe, 1); msleep(10); cfg->reset(fe, 0); msleep(10); } } while (0)
328 #define ADC_TARGET -220
329 #define GAIN_ALPHA 5
330 #define WBD_ALPHA 6
331 #define LPF 100
dib0090_write_regs(struct dib0090_state * state,u8 r,const u16 * b,u8 c)332 static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c)
333 {
334 do {
335 dib0090_write_reg(state, r++, *b++);
336 } while (--c);
337 }
338
dib0090_identify(struct dvb_frontend * fe)339 static int dib0090_identify(struct dvb_frontend *fe)
340 {
341 struct dib0090_state *state = fe->tuner_priv;
342 u16 v;
343 struct dib0090_identity *identity = &state->identity;
344
345 v = dib0090_read_reg(state, 0x1a);
346
347 identity->p1g = 0;
348 identity->in_soc = 0;
349
350 dprintk("Tuner identification (Version = 0x%04x)\n", v);
351
352 /* without PLL lock info */
353 v &= ~KROSUS_PLL_LOCKED;
354
355 identity->version = v & 0xff;
356 identity->product = (v >> 8) & 0xf;
357
358 if (identity->product != KROSUS)
359 goto identification_error;
360
361 if ((identity->version & 0x3) == SOC) {
362 identity->in_soc = 1;
363 switch (identity->version) {
364 case SOC_8090_P1G_11R1:
365 dprintk("SOC 8090 P1-G11R1 Has been detected\n");
366 identity->p1g = 1;
367 break;
368 case SOC_8090_P1G_21R1:
369 dprintk("SOC 8090 P1-G21R1 Has been detected\n");
370 identity->p1g = 1;
371 break;
372 case SOC_7090_P1G_11R1:
373 dprintk("SOC 7090 P1-G11R1 Has been detected\n");
374 identity->p1g = 1;
375 break;
376 case SOC_7090_P1G_21R1:
377 dprintk("SOC 7090 P1-G21R1 Has been detected\n");
378 identity->p1g = 1;
379 break;
380 default:
381 goto identification_error;
382 }
383 } else {
384 switch ((identity->version >> 5) & 0x7) {
385 case MP001:
386 dprintk("MP001 : 9090/8096\n");
387 break;
388 case MP005:
389 dprintk("MP005 : Single Sband\n");
390 break;
391 case MP008:
392 dprintk("MP008 : diversity VHF-UHF-LBAND\n");
393 break;
394 case MP009:
395 dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND\n");
396 break;
397 default:
398 goto identification_error;
399 }
400
401 switch (identity->version & 0x1f) {
402 case P1G_21R2:
403 dprintk("P1G_21R2 detected\n");
404 identity->p1g = 1;
405 break;
406 case P1G:
407 dprintk("P1G detected\n");
408 identity->p1g = 1;
409 break;
410 case P1D_E_F:
411 dprintk("P1D/E/F detected\n");
412 break;
413 case P1C:
414 dprintk("P1C detected\n");
415 break;
416 case P1A_B:
417 dprintk("P1-A/B detected: driver is deactivated - not available\n");
418 goto identification_error;
419 break;
420 default:
421 goto identification_error;
422 }
423 }
424
425 return 0;
426
427 identification_error:
428 return -EIO;
429 }
430
dib0090_fw_identify(struct dvb_frontend * fe)431 static int dib0090_fw_identify(struct dvb_frontend *fe)
432 {
433 struct dib0090_fw_state *state = fe->tuner_priv;
434 struct dib0090_identity *identity = &state->identity;
435
436 u16 v = dib0090_fw_read_reg(state, 0x1a);
437 identity->p1g = 0;
438 identity->in_soc = 0;
439
440 dprintk("FE: Tuner identification (Version = 0x%04x)\n", v);
441
442 /* without PLL lock info */
443 v &= ~KROSUS_PLL_LOCKED;
444
445 identity->version = v & 0xff;
446 identity->product = (v >> 8) & 0xf;
447
448 if (identity->product != KROSUS)
449 goto identification_error;
450
451 if ((identity->version & 0x3) == SOC) {
452 identity->in_soc = 1;
453 switch (identity->version) {
454 case SOC_8090_P1G_11R1:
455 dprintk("SOC 8090 P1-G11R1 Has been detected\n");
456 identity->p1g = 1;
457 break;
458 case SOC_8090_P1G_21R1:
459 dprintk("SOC 8090 P1-G21R1 Has been detected\n");
460 identity->p1g = 1;
461 break;
462 case SOC_7090_P1G_11R1:
463 dprintk("SOC 7090 P1-G11R1 Has been detected\n");
464 identity->p1g = 1;
465 break;
466 case SOC_7090_P1G_21R1:
467 dprintk("SOC 7090 P1-G21R1 Has been detected\n");
468 identity->p1g = 1;
469 break;
470 default:
471 goto identification_error;
472 }
473 } else {
474 switch ((identity->version >> 5) & 0x7) {
475 case MP001:
476 dprintk("MP001 : 9090/8096\n");
477 break;
478 case MP005:
479 dprintk("MP005 : Single Sband\n");
480 break;
481 case MP008:
482 dprintk("MP008 : diversity VHF-UHF-LBAND\n");
483 break;
484 case MP009:
485 dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND\n");
486 break;
487 default:
488 goto identification_error;
489 }
490
491 switch (identity->version & 0x1f) {
492 case P1G_21R2:
493 dprintk("P1G_21R2 detected\n");
494 identity->p1g = 1;
495 break;
496 case P1G:
497 dprintk("P1G detected\n");
498 identity->p1g = 1;
499 break;
500 case P1D_E_F:
501 dprintk("P1D/E/F detected\n");
502 break;
503 case P1C:
504 dprintk("P1C detected\n");
505 break;
506 case P1A_B:
507 dprintk("P1-A/B detected: driver is deactivated - not available\n");
508 goto identification_error;
509 break;
510 default:
511 goto identification_error;
512 }
513 }
514
515 return 0;
516
517 identification_error:
518 return -EIO;
519 }
520
dib0090_reset_digital(struct dvb_frontend * fe,const struct dib0090_config * cfg)521 static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
522 {
523 struct dib0090_state *state = fe->tuner_priv;
524 u16 PllCfg, i, v;
525
526 HARD_RESET(state);
527 dib0090_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
528 if (cfg->in_soc)
529 return;
530
531 dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */
532 /* adcClkOutRatio=8->7, release reset */
533 dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
534 if (cfg->clkoutdrive != 0)
535 dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
536 | (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
537 else
538 dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
539 | (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
540
541 /* Read Pll current config * */
542 PllCfg = dib0090_read_reg(state, 0x21);
543
544 /** Reconfigure PLL if current setting is different from default setting **/
545 if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && (!cfg->in_soc)
546 && !cfg->io.pll_bypass) {
547
548 /* Set Bypass mode */
549 PllCfg |= (1 << 15);
550 dib0090_write_reg(state, 0x21, PllCfg);
551
552 /* Set Reset Pll */
553 PllCfg &= ~(1 << 13);
554 dib0090_write_reg(state, 0x21, PllCfg);
555
556 /*** Set new Pll configuration in bypass and reset state ***/
557 PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
558 dib0090_write_reg(state, 0x21, PllCfg);
559
560 /* Remove Reset Pll */
561 PllCfg |= (1 << 13);
562 dib0090_write_reg(state, 0x21, PllCfg);
563
564 /*** Wait for PLL lock ***/
565 i = 100;
566 do {
567 v = !!(dib0090_read_reg(state, 0x1a) & 0x800);
568 if (v)
569 break;
570 } while (--i);
571
572 if (i == 0) {
573 dprintk("Pll: Unable to lock Pll\n");
574 return;
575 }
576
577 /* Finally Remove Bypass mode */
578 PllCfg &= ~(1 << 15);
579 dib0090_write_reg(state, 0x21, PllCfg);
580 }
581
582 if (cfg->io.pll_bypass) {
583 PllCfg |= (cfg->io.pll_bypass << 15);
584 dib0090_write_reg(state, 0x21, PllCfg);
585 }
586 }
587
dib0090_fw_reset_digital(struct dvb_frontend * fe,const struct dib0090_config * cfg)588 static int dib0090_fw_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
589 {
590 struct dib0090_fw_state *state = fe->tuner_priv;
591 u16 PllCfg;
592 u16 v;
593 int i;
594
595 dprintk("fw reset digital\n");
596 HARD_RESET(state);
597
598 dib0090_fw_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
599 dib0090_fw_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */
600
601 dib0090_fw_write_reg(state, 0x20,
602 ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (cfg->data_tx_drv << 4) | cfg->ls_cfg_pad_drv);
603
604 v = (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 9) | (0 << 8) | (cfg->clkouttobamse << 4) | (0 << 2) | (0);
605 if (cfg->clkoutdrive != 0)
606 v |= cfg->clkoutdrive << 5;
607 else
608 v |= 7 << 5;
609
610 v |= 2 << 10;
611 dib0090_fw_write_reg(state, 0x23, v);
612
613 /* Read Pll current config * */
614 PllCfg = dib0090_fw_read_reg(state, 0x21);
615
616 /** Reconfigure PLL if current setting is different from default setting **/
617 if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && !cfg->io.pll_bypass) {
618
619 /* Set Bypass mode */
620 PllCfg |= (1 << 15);
621 dib0090_fw_write_reg(state, 0x21, PllCfg);
622
623 /* Set Reset Pll */
624 PllCfg &= ~(1 << 13);
625 dib0090_fw_write_reg(state, 0x21, PllCfg);
626
627 /*** Set new Pll configuration in bypass and reset state ***/
628 PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
629 dib0090_fw_write_reg(state, 0x21, PllCfg);
630
631 /* Remove Reset Pll */
632 PllCfg |= (1 << 13);
633 dib0090_fw_write_reg(state, 0x21, PllCfg);
634
635 /*** Wait for PLL lock ***/
636 i = 100;
637 do {
638 v = !!(dib0090_fw_read_reg(state, 0x1a) & 0x800);
639 if (v)
640 break;
641 } while (--i);
642
643 if (i == 0) {
644 dprintk("Pll: Unable to lock Pll\n");
645 return -EIO;
646 }
647
648 /* Finally Remove Bypass mode */
649 PllCfg &= ~(1 << 15);
650 dib0090_fw_write_reg(state, 0x21, PllCfg);
651 }
652
653 if (cfg->io.pll_bypass) {
654 PllCfg |= (cfg->io.pll_bypass << 15);
655 dib0090_fw_write_reg(state, 0x21, PllCfg);
656 }
657
658 return dib0090_fw_identify(fe);
659 }
660
dib0090_wakeup(struct dvb_frontend * fe)661 static int dib0090_wakeup(struct dvb_frontend *fe)
662 {
663 struct dib0090_state *state = fe->tuner_priv;
664 if (state->config->sleep)
665 state->config->sleep(fe, 0);
666
667 /* enable dataTX in case we have been restarted in the wrong moment */
668 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
669 return 0;
670 }
671
dib0090_sleep(struct dvb_frontend * fe)672 static int dib0090_sleep(struct dvb_frontend *fe)
673 {
674 struct dib0090_state *state = fe->tuner_priv;
675 if (state->config->sleep)
676 state->config->sleep(fe, 1);
677 return 0;
678 }
679
dib0090_dcc_freq(struct dvb_frontend * fe,u8 fast)680 void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
681 {
682 struct dib0090_state *state = fe->tuner_priv;
683 if (fast)
684 dib0090_write_reg(state, 0x04, 0);
685 else
686 dib0090_write_reg(state, 0x04, 1);
687 }
688
689 EXPORT_SYMBOL(dib0090_dcc_freq);
690
691 static const u16 bb_ramp_pwm_normal_socs[] = {
692 550, /* max BB gain in 10th of dB */
693 (1<<9) | 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
694 440,
695 (4 << 9) | 0, /* BB_RAMP3 = 26dB */
696 (0 << 9) | 208, /* BB_RAMP4 */
697 (4 << 9) | 208, /* BB_RAMP5 = 29dB */
698 (0 << 9) | 440, /* BB_RAMP6 */
699 };
700
701 static const u16 rf_ramp_pwm_cband_7090p[] = {
702 280, /* max RF gain in 10th of dB */
703 18, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
704 504, /* ramp_max = maximum X used on the ramp */
705 (29 << 10) | 364, /* RF_RAMP5, LNA 1 = 8dB */
706 (0 << 10) | 504, /* RF_RAMP6, LNA 1 */
707 (60 << 10) | 228, /* RF_RAMP7, LNA 2 = 7.7dB */
708 (0 << 10) | 364, /* RF_RAMP8, LNA 2 */
709 (34 << 10) | 109, /* GAIN_4_1, LNA 3 = 6.8dB */
710 (0 << 10) | 228, /* GAIN_4_2, LNA 3 */
711 (37 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */
712 (0 << 10) | 109, /* RF_RAMP4, LNA 4 */
713 };
714
715 static const u16 rf_ramp_pwm_cband_7090e_sensitivity[] = {
716 186, /* max RF gain in 10th of dB */
717 40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
718 746, /* ramp_max = maximum X used on the ramp */
719 (10 << 10) | 345, /* RF_RAMP5, LNA 1 = 10dB */
720 (0 << 10) | 746, /* RF_RAMP6, LNA 1 */
721 (0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */
722 (0 << 10) | 0, /* RF_RAMP8, LNA 2 */
723 (28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */
724 (0 << 10) | 345, /* GAIN_4_2, LNA 3 */
725 (20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */
726 (0 << 10) | 200, /* RF_RAMP4, LNA 4 */
727 };
728
729 static const u16 rf_ramp_pwm_cband_7090e_aci[] = {
730 86, /* max RF gain in 10th of dB */
731 40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
732 345, /* ramp_max = maximum X used on the ramp */
733 (0 << 10) | 0, /* RF_RAMP5, LNA 1 = 8dB */ /* 7.47 dB */
734 (0 << 10) | 0, /* RF_RAMP6, LNA 1 */
735 (0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */
736 (0 << 10) | 0, /* RF_RAMP8, LNA 2 */
737 (28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */
738 (0 << 10) | 345, /* GAIN_4_2, LNA 3 */
739 (20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */
740 (0 << 10) | 200, /* RF_RAMP4, LNA 4 */
741 };
742
743 static const u16 rf_ramp_pwm_cband_8090[] = {
744 345, /* max RF gain in 10th of dB */
745 29, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
746 1000, /* ramp_max = maximum X used on the ramp */
747 (35 << 10) | 772, /* RF_RAMP3, LNA 1 = 8dB */
748 (0 << 10) | 1000, /* RF_RAMP4, LNA 1 */
749 (58 << 10) | 496, /* RF_RAMP5, LNA 2 = 9.5dB */
750 (0 << 10) | 772, /* RF_RAMP6, LNA 2 */
751 (27 << 10) | 200, /* RF_RAMP7, LNA 3 = 10.5dB */
752 (0 << 10) | 496, /* RF_RAMP8, LNA 3 */
753 (40 << 10) | 0, /* GAIN_4_1, LNA 4 = 7dB */
754 (0 << 10) | 200, /* GAIN_4_2, LNA 4 */
755 };
756
757 static const u16 rf_ramp_pwm_uhf_7090[] = {
758 407, /* max RF gain in 10th of dB */
759 13, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
760 529, /* ramp_max = maximum X used on the ramp */
761 (23 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
762 (0 << 10) | 176, /* RF_RAMP4, LNA 1 */
763 (63 << 10) | 400, /* RF_RAMP5, LNA 2 = 8dB */
764 (0 << 10) | 529, /* RF_RAMP6, LNA 2 */
765 (48 << 10) | 316, /* RF_RAMP7, LNA 3 = 6.8dB */
766 (0 << 10) | 400, /* RF_RAMP8, LNA 3 */
767 (29 << 10) | 176, /* GAIN_4_1, LNA 4 = 11.5dB */
768 (0 << 10) | 316, /* GAIN_4_2, LNA 4 */
769 };
770
771 static const u16 rf_ramp_pwm_uhf_8090[] = {
772 388, /* max RF gain in 10th of dB */
773 26, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
774 1008, /* ramp_max = maximum X used on the ramp */
775 (11 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
776 (0 << 10) | 369, /* RF_RAMP4, LNA 1 */
777 (41 << 10) | 809, /* RF_RAMP5, LNA 2 = 8dB */
778 (0 << 10) | 1008, /* RF_RAMP6, LNA 2 */
779 (27 << 10) | 659, /* RF_RAMP7, LNA 3 = 6dB */
780 (0 << 10) | 809, /* RF_RAMP8, LNA 3 */
781 (14 << 10) | 369, /* GAIN_4_1, LNA 4 = 11.5dB */
782 (0 << 10) | 659, /* GAIN_4_2, LNA 4 */
783 };
784
785 /* GENERAL PWM ramp definition for all other Krosus */
786 static const u16 bb_ramp_pwm_normal[] = {
787 500, /* max BB gain in 10th of dB */
788 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
789 400,
790 (2 << 9) | 0, /* BB_RAMP3 = 21dB */
791 (0 << 9) | 168, /* BB_RAMP4 */
792 (2 << 9) | 168, /* BB_RAMP5 = 29dB */
793 (0 << 9) | 400, /* BB_RAMP6 */
794 };
795
796 #if 0
797 /* Currently unused */
798 static const u16 bb_ramp_pwm_boost[] = {
799 550, /* max BB gain in 10th of dB */
800 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
801 440,
802 (2 << 9) | 0, /* BB_RAMP3 = 26dB */
803 (0 << 9) | 208, /* BB_RAMP4 */
804 (2 << 9) | 208, /* BB_RAMP5 = 29dB */
805 (0 << 9) | 440, /* BB_RAMP6 */
806 };
807 #endif
808
809 static const u16 rf_ramp_pwm_cband[] = {
810 314, /* max RF gain in 10th of dB */
811 33, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
812 1023, /* ramp_max = maximum X used on the ramp */
813 (8 << 10) | 743, /* RF_RAMP3, LNA 1 = 0dB */
814 (0 << 10) | 1023, /* RF_RAMP4, LNA 1 */
815 (15 << 10) | 469, /* RF_RAMP5, LNA 2 = 0dB */
816 (0 << 10) | 742, /* RF_RAMP6, LNA 2 */
817 (9 << 10) | 234, /* RF_RAMP7, LNA 3 = 0dB */
818 (0 << 10) | 468, /* RF_RAMP8, LNA 3 */
819 (9 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
820 (0 << 10) | 233, /* GAIN_4_2, LNA 4 */
821 };
822
823 static const u16 rf_ramp_pwm_vhf[] = {
824 398, /* max RF gain in 10th of dB */
825 24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
826 954, /* ramp_max = maximum X used on the ramp */
827 (7 << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */
828 (0 << 10) | 290, /* RF_RAMP4, LNA 1 */
829 (16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */
830 (0 << 10) | 954, /* RF_RAMP6, LNA 2 */
831 (17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */
832 (0 << 10) | 699, /* RF_RAMP8, LNA 3 */
833 (7 << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */
834 (0 << 10) | 580, /* GAIN_4_2, LNA 4 */
835 };
836
837 static const u16 rf_ramp_pwm_uhf[] = {
838 398, /* max RF gain in 10th of dB */
839 24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
840 954, /* ramp_max = maximum X used on the ramp */
841 (7 << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */
842 (0 << 10) | 290, /* RF_RAMP4, LNA 1 */
843 (16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */
844 (0 << 10) | 954, /* RF_RAMP6, LNA 2 */
845 (17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */
846 (0 << 10) | 699, /* RF_RAMP8, LNA 3 */
847 (7 << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */
848 (0 << 10) | 580, /* GAIN_4_2, LNA 4 */
849 };
850
851 #if 0
852 /* Currently unused */
853 static const u16 rf_ramp_pwm_sband[] = {
854 253, /* max RF gain in 10th of dB */
855 38, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
856 961,
857 (4 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.1dB */
858 (0 << 10) | 508, /* RF_RAMP4, LNA 1 */
859 (9 << 10) | 508, /* RF_RAMP5, LNA 2 = 11.2dB */
860 (0 << 10) | 961, /* RF_RAMP6, LNA 2 */
861 (0 << 10) | 0, /* RF_RAMP7, LNA 3 = 0dB */
862 (0 << 10) | 0, /* RF_RAMP8, LNA 3 */
863 (0 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
864 (0 << 10) | 0, /* GAIN_4_2, LNA 4 */
865 };
866 #endif
867
868 struct slope {
869 s16 range;
870 s16 slope;
871 };
slopes_to_scale(const struct slope * slopes,u8 num,s16 val)872 static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
873 {
874 u8 i;
875 u16 rest;
876 u16 ret = 0;
877 for (i = 0; i < num; i++) {
878 if (val > slopes[i].range)
879 rest = slopes[i].range;
880 else
881 rest = val;
882 ret += (rest * slopes[i].slope) / slopes[i].range;
883 val -= rest;
884 }
885 return ret;
886 }
887
888 static const struct slope dib0090_wbd_slopes[3] = {
889 {66, 120}, /* -64,-52: offset - 65 */
890 {600, 170}, /* -52,-35: 65 - 665 */
891 {170, 250}, /* -45,-10: 665 - 835 */
892 };
893
dib0090_wbd_to_db(struct dib0090_state * state,u16 wbd)894 static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
895 {
896 wbd &= 0x3ff;
897 if (wbd < state->wbd_offset)
898 wbd = 0;
899 else
900 wbd -= state->wbd_offset;
901 /* -64dB is the floor */
902 return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd);
903 }
904
dib0090_wbd_target(struct dib0090_state * state,u32 rf)905 static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
906 {
907 u16 offset = 250;
908
909 /* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */
910
911 if (state->current_band == BAND_VHF)
912 offset = 650;
913 #ifndef FIRMWARE_FIREFLY
914 if (state->current_band == BAND_VHF)
915 offset = state->config->wbd_vhf_offset;
916 if (state->current_band == BAND_CBAND)
917 offset = state->config->wbd_cband_offset;
918 #endif
919
920 state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
921 dprintk("wbd-target: %d dB\n", (u32) state->wbd_target);
922 }
923
924 static const int gain_reg_addr[4] = {
925 0x08, 0x0a, 0x0f, 0x01
926 };
927
dib0090_gain_apply(struct dib0090_state * state,s16 gain_delta,s16 top_delta,u8 force)928 static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
929 {
930 u16 rf, bb, ref;
931 u16 i, v, gain_reg[4] = { 0 }, gain;
932 const u16 *g;
933
934 if (top_delta < -511)
935 top_delta = -511;
936 if (top_delta > 511)
937 top_delta = 511;
938
939 if (force) {
940 top_delta *= (1 << WBD_ALPHA);
941 gain_delta *= (1 << GAIN_ALPHA);
942 }
943
944 if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit)) /* overflow */
945 state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
946 else
947 state->rf_gain_limit += top_delta;
948
949 if (state->rf_gain_limit < 0) /*underflow */
950 state->rf_gain_limit = 0;
951
952 /* use gain as a temporary variable and correct current_gain */
953 gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA;
954 if (gain_delta >= ((s16) gain - state->current_gain)) /* overflow */
955 state->current_gain = gain;
956 else
957 state->current_gain += gain_delta;
958 /* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */
959 if (state->current_gain < 0)
960 state->current_gain = 0;
961
962 /* now split total gain to rf and bb gain */
963 gain = state->current_gain >> GAIN_ALPHA;
964
965 /* requested gain is bigger than rf gain limit - ACI/WBD adjustment */
966 if (gain > (state->rf_gain_limit >> WBD_ALPHA)) {
967 rf = state->rf_gain_limit >> WBD_ALPHA;
968 bb = gain - rf;
969 if (bb > state->bb_ramp[0])
970 bb = state->bb_ramp[0];
971 } else { /* high signal level -> all gains put on RF */
972 rf = gain;
973 bb = 0;
974 }
975
976 state->gain[0] = rf;
977 state->gain[1] = bb;
978
979 /* software ramp */
980 /* Start with RF gains */
981 g = state->rf_ramp + 1; /* point on RF LNA1 max gain */
982 ref = rf;
983 for (i = 0; i < 7; i++) { /* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */
984 if (g[0] == 0 || ref < (g[1] - g[0])) /* if total gain of the current amp is null or this amp is not concerned because it starts to work from an higher gain value */
985 v = 0; /* force the gain to write for the current amp to be null */
986 else if (ref >= g[1]) /* Gain to set is higher than the high working point of this amp */
987 v = g[2]; /* force this amp to be full gain */
988 else /* compute the value to set to this amp because we are somewhere in his range */
989 v = ((ref - (g[1] - g[0])) * g[2]) / g[0];
990
991 if (i == 0) /* LNA 1 reg mapping */
992 gain_reg[0] = v;
993 else if (i == 1) /* LNA 2 reg mapping */
994 gain_reg[0] |= v << 7;
995 else if (i == 2) /* LNA 3 reg mapping */
996 gain_reg[1] = v;
997 else if (i == 3) /* LNA 4 reg mapping */
998 gain_reg[1] |= v << 7;
999 else if (i == 4) /* CBAND LNA reg mapping */
1000 gain_reg[2] = v | state->rf_lt_def;
1001 else if (i == 5) /* BB gain 1 reg mapping */
1002 gain_reg[3] = v << 3;
1003 else if (i == 6) /* BB gain 2 reg mapping */
1004 gain_reg[3] |= v << 8;
1005
1006 g += 3; /* go to next gain bloc */
1007
1008 /* When RF is finished, start with BB */
1009 if (i == 4) {
1010 g = state->bb_ramp + 1; /* point on BB gain 1 max gain */
1011 ref = bb;
1012 }
1013 }
1014 gain_reg[3] |= state->bb_1_def;
1015 gain_reg[3] |= ((bb % 10) * 100) / 125;
1016
1017 #ifdef DEBUG_AGC
1018 dprintk("GA CALC: DB: %3d(rf) + %3d(bb) = %3d gain_reg[0]=%04x gain_reg[1]=%04x gain_reg[2]=%04x gain_reg[0]=%04x\n", rf, bb, rf + bb,
1019 gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]);
1020 #endif
1021
1022 /* Write the amplifier regs */
1023 for (i = 0; i < 4; i++) {
1024 v = gain_reg[i];
1025 if (force || state->gain_reg[i] != v) {
1026 state->gain_reg[i] = v;
1027 dib0090_write_reg(state, gain_reg_addr[i], v);
1028 }
1029 }
1030 }
1031
dib0090_set_boost(struct dib0090_state * state,int onoff)1032 static void dib0090_set_boost(struct dib0090_state *state, int onoff)
1033 {
1034 state->bb_1_def &= 0xdfff;
1035 state->bb_1_def |= onoff << 13;
1036 }
1037
dib0090_set_rframp(struct dib0090_state * state,const u16 * cfg)1038 static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
1039 {
1040 state->rf_ramp = cfg;
1041 }
1042
dib0090_set_rframp_pwm(struct dib0090_state * state,const u16 * cfg)1043 static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
1044 {
1045 state->rf_ramp = cfg;
1046
1047 dib0090_write_reg(state, 0x2a, 0xffff);
1048
1049 dprintk("total RF gain: %ddB, step: %d\n", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
1050
1051 dib0090_write_regs(state, 0x2c, cfg + 3, 6);
1052 dib0090_write_regs(state, 0x3e, cfg + 9, 2);
1053 }
1054
dib0090_set_bbramp(struct dib0090_state * state,const u16 * cfg)1055 static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
1056 {
1057 state->bb_ramp = cfg;
1058 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
1059 }
1060
dib0090_set_bbramp_pwm(struct dib0090_state * state,const u16 * cfg)1061 static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
1062 {
1063 state->bb_ramp = cfg;
1064
1065 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
1066
1067 dib0090_write_reg(state, 0x33, 0xffff);
1068 dprintk("total BB gain: %ddB, step: %d\n", (u32) cfg[0], dib0090_read_reg(state, 0x33));
1069 dib0090_write_regs(state, 0x35, cfg + 3, 4);
1070 }
1071
dib0090_pwm_gain_reset(struct dvb_frontend * fe)1072 void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
1073 {
1074 struct dib0090_state *state = fe->tuner_priv;
1075 u16 *bb_ramp = (u16 *)&bb_ramp_pwm_normal; /* default baseband config */
1076 u16 *rf_ramp = NULL;
1077 u8 en_pwm_rf_mux = 1;
1078
1079 /* reset the AGC */
1080 if (state->config->use_pwm_agc) {
1081 if (state->current_band == BAND_CBAND) {
1082 if (state->identity.in_soc) {
1083 bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
1084 if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1085 rf_ramp = (u16 *)&rf_ramp_pwm_cband_8090;
1086 else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1) {
1087 if (state->config->is_dib7090e) {
1088 if (state->rf_ramp == NULL)
1089 rf_ramp = (u16 *)&rf_ramp_pwm_cband_7090e_sensitivity;
1090 else
1091 rf_ramp = (u16 *)state->rf_ramp;
1092 } else
1093 rf_ramp = (u16 *)&rf_ramp_pwm_cband_7090p;
1094 }
1095 } else
1096 rf_ramp = (u16 *)&rf_ramp_pwm_cband;
1097 } else
1098
1099 if (state->current_band == BAND_VHF) {
1100 if (state->identity.in_soc) {
1101 bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
1102 /* rf_ramp = &rf_ramp_pwm_vhf_socs; */ /* TODO */
1103 } else
1104 rf_ramp = (u16 *)&rf_ramp_pwm_vhf;
1105 } else if (state->current_band == BAND_UHF) {
1106 if (state->identity.in_soc) {
1107 bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
1108 if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1109 rf_ramp = (u16 *)&rf_ramp_pwm_uhf_8090;
1110 else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1111 rf_ramp = (u16 *)&rf_ramp_pwm_uhf_7090;
1112 } else
1113 rf_ramp = (u16 *)&rf_ramp_pwm_uhf;
1114 }
1115 if (rf_ramp)
1116 dib0090_set_rframp_pwm(state, rf_ramp);
1117 dib0090_set_bbramp_pwm(state, bb_ramp);
1118
1119 /* activate the ramp generator using PWM control */
1120 if (state->rf_ramp)
1121 dprintk("ramp RF gain = %d BAND = %s version = %d\n",
1122 state->rf_ramp[0],
1123 (state->current_band == BAND_CBAND) ? "CBAND" : "NOT CBAND",
1124 state->identity.version & 0x1f);
1125
1126 if (rf_ramp && ((state->rf_ramp && state->rf_ramp[0] == 0) ||
1127 (state->current_band == BAND_CBAND &&
1128 (state->identity.version & 0x1f) <= P1D_E_F))) {
1129 dprintk("DE-Engage mux for direct gain reg control\n");
1130 en_pwm_rf_mux = 0;
1131 } else
1132 dprintk("Engage mux for PWM control\n");
1133
1134 dib0090_write_reg(state, 0x32, (en_pwm_rf_mux << 12) | (en_pwm_rf_mux << 11));
1135
1136 /* Set fast servo cutoff to start AGC; 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast*/
1137 if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1138 dib0090_write_reg(state, 0x04, 3);
1139 else
1140 dib0090_write_reg(state, 0x04, 1);
1141 dib0090_write_reg(state, 0x39, (1 << 10)); /* 0 gain by default */
1142 }
1143 }
1144 EXPORT_SYMBOL(dib0090_pwm_gain_reset);
1145
dib0090_set_dc_servo(struct dvb_frontend * fe,u8 DC_servo_cutoff)1146 void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff)
1147 {
1148 struct dib0090_state *state = fe->tuner_priv;
1149 if (DC_servo_cutoff < 4)
1150 dib0090_write_reg(state, 0x04, DC_servo_cutoff);
1151 }
1152 EXPORT_SYMBOL(dib0090_set_dc_servo);
1153
dib0090_get_slow_adc_val(struct dib0090_state * state)1154 static u32 dib0090_get_slow_adc_val(struct dib0090_state *state)
1155 {
1156 u16 adc_val = dib0090_read_reg(state, 0x1d);
1157 if (state->identity.in_soc)
1158 adc_val >>= 2;
1159 return adc_val;
1160 }
1161
dib0090_gain_control(struct dvb_frontend * fe)1162 int dib0090_gain_control(struct dvb_frontend *fe)
1163 {
1164 struct dib0090_state *state = fe->tuner_priv;
1165 enum frontend_tune_state *tune_state = &state->tune_state;
1166 int ret = 10;
1167
1168 u16 wbd_val = 0;
1169 u8 apply_gain_immediatly = 1;
1170 s16 wbd_error = 0, adc_error = 0;
1171
1172 if (*tune_state == CT_AGC_START) {
1173 state->agc_freeze = 0;
1174 dib0090_write_reg(state, 0x04, 0x0);
1175
1176 #ifdef CONFIG_BAND_SBAND
1177 if (state->current_band == BAND_SBAND) {
1178 dib0090_set_rframp(state, rf_ramp_sband);
1179 dib0090_set_bbramp(state, bb_ramp_boost);
1180 } else
1181 #endif
1182 #ifdef CONFIG_BAND_VHF
1183 if (state->current_band == BAND_VHF && !state->identity.p1g) {
1184 dib0090_set_rframp(state, rf_ramp_pwm_vhf);
1185 dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1186 } else
1187 #endif
1188 #ifdef CONFIG_BAND_CBAND
1189 if (state->current_band == BAND_CBAND && !state->identity.p1g) {
1190 dib0090_set_rframp(state, rf_ramp_pwm_cband);
1191 dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1192 } else
1193 #endif
1194 if ((state->current_band == BAND_CBAND || state->current_band == BAND_VHF) && state->identity.p1g) {
1195 dib0090_set_rframp(state, rf_ramp_pwm_cband_7090p);
1196 dib0090_set_bbramp(state, bb_ramp_pwm_normal_socs);
1197 } else {
1198 dib0090_set_rframp(state, rf_ramp_pwm_uhf);
1199 dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1200 }
1201
1202 dib0090_write_reg(state, 0x32, 0);
1203 dib0090_write_reg(state, 0x39, 0);
1204
1205 dib0090_wbd_target(state, state->current_rf);
1206
1207 state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
1208 state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA;
1209
1210 *tune_state = CT_AGC_STEP_0;
1211 } else if (!state->agc_freeze) {
1212 s16 wbd = 0, i, cnt;
1213
1214 int adc;
1215 wbd_val = dib0090_get_slow_adc_val(state);
1216
1217 if (*tune_state == CT_AGC_STEP_0)
1218 cnt = 5;
1219 else
1220 cnt = 1;
1221
1222 for (i = 0; i < cnt; i++) {
1223 wbd_val = dib0090_get_slow_adc_val(state);
1224 wbd += dib0090_wbd_to_db(state, wbd_val);
1225 }
1226 wbd /= cnt;
1227 wbd_error = state->wbd_target - wbd;
1228
1229 if (*tune_state == CT_AGC_STEP_0) {
1230 if (wbd_error < 0 && state->rf_gain_limit > 0 && !state->identity.p1g) {
1231 #ifdef CONFIG_BAND_CBAND
1232 /* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */
1233 u8 ltg2 = (state->rf_lt_def >> 10) & 0x7;
1234 if (state->current_band == BAND_CBAND && ltg2) {
1235 ltg2 >>= 1;
1236 state->rf_lt_def &= ltg2 << 10; /* reduce in 3 steps from 7 to 0 */
1237 }
1238 #endif
1239 } else {
1240 state->agc_step = 0;
1241 *tune_state = CT_AGC_STEP_1;
1242 }
1243 } else {
1244 /* calc the adc power */
1245 adc = state->config->get_adc_power(fe);
1246 adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21; /* included in [0:-700] */
1247
1248 adc_error = (s16) (((s32) ADC_TARGET) - adc);
1249 #ifdef CONFIG_STANDARD_DAB
1250 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)
1251 adc_error -= 10;
1252 #endif
1253 #ifdef CONFIG_STANDARD_DVBT
1254 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT &&
1255 (state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
1256 adc_error += 60;
1257 #endif
1258 #ifdef CONFIG_SYS_ISDBT
1259 if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count >
1260 0)
1261 &&
1262 ((state->fe->dtv_property_cache.layer[0].modulation ==
1263 QAM_64)
1264 || (state->fe->dtv_property_cache.
1265 layer[0].modulation == QAM_16)))
1266 ||
1267 ((state->fe->dtv_property_cache.layer[1].segment_count >
1268 0)
1269 &&
1270 ((state->fe->dtv_property_cache.layer[1].modulation ==
1271 QAM_64)
1272 || (state->fe->dtv_property_cache.
1273 layer[1].modulation == QAM_16)))
1274 ||
1275 ((state->fe->dtv_property_cache.layer[2].segment_count >
1276 0)
1277 &&
1278 ((state->fe->dtv_property_cache.layer[2].modulation ==
1279 QAM_64)
1280 || (state->fe->dtv_property_cache.
1281 layer[2].modulation == QAM_16)))
1282 )
1283 )
1284 adc_error += 60;
1285 #endif
1286
1287 if (*tune_state == CT_AGC_STEP_1) { /* quickly go to the correct range of the ADC power */
1288 if (abs(adc_error) < 50 || state->agc_step++ > 5) {
1289
1290 #ifdef CONFIG_STANDARD_DAB
1291 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) {
1292 dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63)); /* cap value = 63 : narrow BB filter : Fc = 1.8MHz */
1293 dib0090_write_reg(state, 0x04, 0x0);
1294 } else
1295 #endif
1296 {
1297 dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32));
1298 dib0090_write_reg(state, 0x04, 0x01); /*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */
1299 }
1300
1301 *tune_state = CT_AGC_STOP;
1302 }
1303 } else {
1304 /* everything higher than or equal to CT_AGC_STOP means tracking */
1305 ret = 100; /* 10ms interval */
1306 apply_gain_immediatly = 0;
1307 }
1308 }
1309 #ifdef DEBUG_AGC
1310 dprintk
1311 ("tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
1312 (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
1313 (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
1314 #endif
1315 }
1316
1317 /* apply gain */
1318 if (!state->agc_freeze)
1319 dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
1320 return ret;
1321 }
1322
1323 EXPORT_SYMBOL(dib0090_gain_control);
1324
dib0090_get_current_gain(struct dvb_frontend * fe,u16 * rf,u16 * bb,u16 * rf_gain_limit,u16 * rflt)1325 void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
1326 {
1327 struct dib0090_state *state = fe->tuner_priv;
1328 if (rf)
1329 *rf = state->gain[0];
1330 if (bb)
1331 *bb = state->gain[1];
1332 if (rf_gain_limit)
1333 *rf_gain_limit = state->rf_gain_limit;
1334 if (rflt)
1335 *rflt = (state->rf_lt_def >> 10) & 0x7;
1336 }
1337
1338 EXPORT_SYMBOL(dib0090_get_current_gain);
1339
dib0090_get_wbd_target(struct dvb_frontend * fe)1340 u16 dib0090_get_wbd_target(struct dvb_frontend *fe)
1341 {
1342 struct dib0090_state *state = fe->tuner_priv;
1343 u32 f_MHz = state->fe->dtv_property_cache.frequency / 1000000;
1344 s32 current_temp = state->temperature;
1345 s32 wbd_thot, wbd_tcold;
1346 const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1347
1348 while (f_MHz > wbd->max_freq)
1349 wbd++;
1350
1351 dprintk("using wbd-table-entry with max freq %d\n", wbd->max_freq);
1352
1353 if (current_temp < 0)
1354 current_temp = 0;
1355 if (current_temp > 128)
1356 current_temp = 128;
1357
1358 state->wbdmux &= ~(7 << 13);
1359 if (wbd->wbd_gain != 0)
1360 state->wbdmux |= (wbd->wbd_gain << 13);
1361 else
1362 state->wbdmux |= (4 << 13);
1363
1364 dib0090_write_reg(state, 0x10, state->wbdmux);
1365
1366 wbd_thot = wbd->offset_hot - (((u32) wbd->slope_hot * f_MHz) >> 6);
1367 wbd_tcold = wbd->offset_cold - (((u32) wbd->slope_cold * f_MHz) >> 6);
1368
1369 wbd_tcold += ((wbd_thot - wbd_tcold) * current_temp) >> 7;
1370
1371 state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + wbd_tcold);
1372 dprintk("wbd-target: %d dB\n", (u32) state->wbd_target);
1373 dprintk("wbd offset applied is %d\n", wbd_tcold);
1374
1375 return state->wbd_offset + wbd_tcold;
1376 }
1377 EXPORT_SYMBOL(dib0090_get_wbd_target);
1378
dib0090_get_wbd_offset(struct dvb_frontend * fe)1379 u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
1380 {
1381 struct dib0090_state *state = fe->tuner_priv;
1382 return state->wbd_offset;
1383 }
1384 EXPORT_SYMBOL(dib0090_get_wbd_offset);
1385
dib0090_set_switch(struct dvb_frontend * fe,u8 sw1,u8 sw2,u8 sw3)1386 int dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3)
1387 {
1388 struct dib0090_state *state = fe->tuner_priv;
1389
1390 dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xfff8)
1391 | ((sw3 & 1) << 2) | ((sw2 & 1) << 1) | (sw1 & 1));
1392
1393 return 0;
1394 }
1395 EXPORT_SYMBOL(dib0090_set_switch);
1396
dib0090_set_vga(struct dvb_frontend * fe,u8 onoff)1397 int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff)
1398 {
1399 struct dib0090_state *state = fe->tuner_priv;
1400
1401 dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x7fff)
1402 | ((onoff & 1) << 15));
1403 return 0;
1404 }
1405 EXPORT_SYMBOL(dib0090_set_vga);
1406
dib0090_update_rframp_7090(struct dvb_frontend * fe,u8 cfg_sensitivity)1407 int dib0090_update_rframp_7090(struct dvb_frontend *fe, u8 cfg_sensitivity)
1408 {
1409 struct dib0090_state *state = fe->tuner_priv;
1410
1411 if ((!state->identity.p1g) || (!state->identity.in_soc)
1412 || ((state->identity.version != SOC_7090_P1G_21R1)
1413 && (state->identity.version != SOC_7090_P1G_11R1))) {
1414 dprintk("%s() function can only be used for dib7090P\n", __func__);
1415 return -ENODEV;
1416 }
1417
1418 if (cfg_sensitivity)
1419 state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_sensitivity;
1420 else
1421 state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_aci;
1422 dib0090_pwm_gain_reset(fe);
1423
1424 return 0;
1425 }
1426 EXPORT_SYMBOL(dib0090_update_rframp_7090);
1427
1428 static const u16 dib0090_defaults[] = {
1429
1430 25, 0x01,
1431 0x0000,
1432 0x99a0,
1433 0x6008,
1434 0x0000,
1435 0x8bcb,
1436 0x0000,
1437 0x0405,
1438 0x0000,
1439 0x0000,
1440 0x0000,
1441 0xb802,
1442 0x0300,
1443 0x2d12,
1444 0xbac0,
1445 0x7c00,
1446 0xdbb9,
1447 0x0954,
1448 0x0743,
1449 0x8000,
1450 0x0001,
1451 0x0040,
1452 0x0100,
1453 0x0000,
1454 0xe910,
1455 0x149e,
1456
1457 1, 0x1c,
1458 0xff2d,
1459
1460 1, 0x39,
1461 0x0000,
1462
1463 2, 0x1e,
1464 0x07FF,
1465 0x0007,
1466
1467 1, 0x24,
1468 EN_UHF | EN_CRYSTAL,
1469
1470 2, 0x3c,
1471 0x3ff,
1472 0x111,
1473 0
1474 };
1475
1476 static const u16 dib0090_p1g_additionnal_defaults[] = {
1477 1, 0x05,
1478 0xabcd,
1479
1480 1, 0x11,
1481 0x00b4,
1482
1483 1, 0x1c,
1484 0xfffd,
1485
1486 1, 0x40,
1487 0x108,
1488 0
1489 };
1490
dib0090_set_default_config(struct dib0090_state * state,const u16 * n)1491 static void dib0090_set_default_config(struct dib0090_state *state, const u16 * n)
1492 {
1493 u16 l, r;
1494
1495 l = pgm_read_word(n++);
1496 while (l) {
1497 r = pgm_read_word(n++);
1498 do {
1499 dib0090_write_reg(state, r, pgm_read_word(n++));
1500 r++;
1501 } while (--l);
1502 l = pgm_read_word(n++);
1503 }
1504 }
1505
1506 #define CAP_VALUE_MIN (u8) 9
1507 #define CAP_VALUE_MAX (u8) 40
1508 #define HR_MIN (u8) 25
1509 #define HR_MAX (u8) 40
1510 #define POLY_MIN (u8) 0
1511 #define POLY_MAX (u8) 8
1512
dib0090_set_EFUSE(struct dib0090_state * state)1513 static void dib0090_set_EFUSE(struct dib0090_state *state)
1514 {
1515 u8 c, h, n;
1516 u16 e2, e4;
1517 u16 cal;
1518
1519 e2 = dib0090_read_reg(state, 0x26);
1520 e4 = dib0090_read_reg(state, 0x28);
1521
1522 if ((state->identity.version == P1D_E_F) ||
1523 (state->identity.version == P1G) || (e2 == 0xffff)) {
1524
1525 dib0090_write_reg(state, 0x22, 0x10);
1526 cal = (dib0090_read_reg(state, 0x22) >> 6) & 0x3ff;
1527
1528 if ((cal < 670) || (cal == 1023))
1529 cal = 850;
1530 n = 165 - ((cal * 10)>>6) ;
1531 e2 = e4 = (3<<12) | (34<<6) | (n);
1532 }
1533
1534 if (e2 != e4)
1535 e2 &= e4; /* Remove the redundancy */
1536
1537 if (e2 != 0xffff) {
1538 c = e2 & 0x3f;
1539 n = (e2 >> 12) & 0xf;
1540 h = (e2 >> 6) & 0x3f;
1541
1542 if ((c >= CAP_VALUE_MAX) || (c <= CAP_VALUE_MIN))
1543 c = 32;
1544 else
1545 c += 14;
1546 if ((h >= HR_MAX) || (h <= HR_MIN))
1547 h = 34;
1548 if ((n >= POLY_MAX) || (n <= POLY_MIN))
1549 n = 3;
1550
1551 dib0090_write_reg(state, 0x13, (h << 10));
1552 e2 = (n << 11) | ((h >> 2)<<6) | c;
1553 dib0090_write_reg(state, 0x2, e2); /* Load the BB_2 */
1554 }
1555 }
1556
dib0090_reset(struct dvb_frontend * fe)1557 static int dib0090_reset(struct dvb_frontend *fe)
1558 {
1559 struct dib0090_state *state = fe->tuner_priv;
1560
1561 dib0090_reset_digital(fe, state->config);
1562 if (dib0090_identify(fe) < 0)
1563 return -EIO;
1564
1565 #ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
1566 if (!(state->identity.version & 0x1)) /* it is P1B - reset is already done */
1567 return 0;
1568 #endif
1569
1570 if (!state->identity.in_soc) {
1571 if ((dib0090_read_reg(state, 0x1a) >> 5) & 0x2)
1572 dib0090_write_reg(state, 0x1b, (EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1573 else
1574 dib0090_write_reg(state, 0x1b, (EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1575 }
1576
1577 dib0090_set_default_config(state, dib0090_defaults);
1578
1579 if (state->identity.in_soc)
1580 dib0090_write_reg(state, 0x18, 0x2910); /* charge pump current = 0 */
1581
1582 if (state->identity.p1g)
1583 dib0090_set_default_config(state, dib0090_p1g_additionnal_defaults);
1584
1585 /* Update the efuse : Only available for KROSUS > P1C and SOC as well*/
1586 if (((state->identity.version & 0x1f) >= P1D_E_F) || (state->identity.in_soc))
1587 dib0090_set_EFUSE(state);
1588
1589 /* Congigure in function of the crystal */
1590 if (state->config->force_crystal_mode != 0)
1591 dib0090_write_reg(state, 0x14,
1592 state->config->force_crystal_mode & 3);
1593 else if (state->config->io.clock_khz >= 24000)
1594 dib0090_write_reg(state, 0x14, 1);
1595 else
1596 dib0090_write_reg(state, 0x14, 2);
1597 dprintk("Pll lock : %d\n", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
1598
1599 state->calibrate = DC_CAL | WBD_CAL | TEMP_CAL; /* enable iq-offset-calibration and wbd-calibration when tuning next time */
1600
1601 return 0;
1602 }
1603
1604 #define steps(u) (((u) > 15) ? ((u)-16) : (u))
1605 #define INTERN_WAIT 10
dib0090_get_offset(struct dib0090_state * state,enum frontend_tune_state * tune_state)1606 static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1607 {
1608 int ret = INTERN_WAIT * 10;
1609
1610 switch (*tune_state) {
1611 case CT_TUNER_STEP_2:
1612 /* Turns to positive */
1613 dib0090_write_reg(state, 0x1f, 0x7);
1614 *tune_state = CT_TUNER_STEP_3;
1615 break;
1616
1617 case CT_TUNER_STEP_3:
1618 state->adc_diff = dib0090_read_reg(state, 0x1d);
1619
1620 /* Turns to negative */
1621 dib0090_write_reg(state, 0x1f, 0x4);
1622 *tune_state = CT_TUNER_STEP_4;
1623 break;
1624
1625 case CT_TUNER_STEP_4:
1626 state->adc_diff -= dib0090_read_reg(state, 0x1d);
1627 *tune_state = CT_TUNER_STEP_5;
1628 ret = 0;
1629 break;
1630
1631 default:
1632 break;
1633 }
1634
1635 return ret;
1636 }
1637
1638 struct dc_calibration {
1639 u8 addr;
1640 u8 offset;
1641 u8 pga:1;
1642 u16 bb1;
1643 u8 i:1;
1644 };
1645
1646 static const struct dc_calibration dc_table[] = {
1647 /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
1648 {0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1},
1649 {0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0},
1650 /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
1651 {0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1},
1652 {0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0},
1653 {0},
1654 };
1655
1656 static const struct dc_calibration dc_p1g_table[] = {
1657 /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
1658 /* addr ; trim reg offset ; pga ; CTRL_BB1 value ; i or q */
1659 {0x06, 5, 1, (1 << 13) | (0 << 8) | (15 << 3), 1},
1660 {0x07, 11, 1, (1 << 13) | (0 << 8) | (15 << 3), 0},
1661 /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
1662 {0x06, 0, 0, (1 << 13) | (29 << 8) | (15 << 3), 1},
1663 {0x06, 10, 0, (1 << 13) | (29 << 8) | (15 << 3), 0},
1664 {0},
1665 };
1666
dib0090_set_trim(struct dib0090_state * state)1667 static void dib0090_set_trim(struct dib0090_state *state)
1668 {
1669 u16 *val;
1670
1671 if (state->dc->addr == 0x07)
1672 val = &state->bb7;
1673 else
1674 val = &state->bb6;
1675
1676 *val &= ~(0x1f << state->dc->offset);
1677 *val |= state->step << state->dc->offset;
1678
1679 dib0090_write_reg(state, state->dc->addr, *val);
1680 }
1681
dib0090_dc_offset_calibration(struct dib0090_state * state,enum frontend_tune_state * tune_state)1682 static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1683 {
1684 int ret = 0;
1685 u16 reg;
1686
1687 switch (*tune_state) {
1688 case CT_TUNER_START:
1689 dprintk("Start DC offset calibration");
1690
1691 /* force vcm2 = 0.8V */
1692 state->bb6 = 0;
1693 state->bb7 = 0x040d;
1694
1695 /* the LNA AND LO are off */
1696 reg = dib0090_read_reg(state, 0x24) & 0x0ffb; /* shutdown lna and lo */
1697 dib0090_write_reg(state, 0x24, reg);
1698
1699 state->wbdmux = dib0090_read_reg(state, 0x10);
1700 dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x7 << 3) | 0x3);
1701 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
1702
1703 state->dc = dc_table;
1704
1705 if (state->identity.p1g)
1706 state->dc = dc_p1g_table;
1707
1708 /* fall through */
1709 case CT_TUNER_STEP_0:
1710 dprintk("Start/continue DC calibration for %s path\n",
1711 (state->dc->i == 1) ? "I" : "Q");
1712 dib0090_write_reg(state, 0x01, state->dc->bb1);
1713 dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
1714
1715 state->step = 0;
1716 state->min_adc_diff = 1023;
1717 *tune_state = CT_TUNER_STEP_1;
1718 ret = 50;
1719 break;
1720
1721 case CT_TUNER_STEP_1:
1722 dib0090_set_trim(state);
1723 *tune_state = CT_TUNER_STEP_2;
1724 break;
1725
1726 case CT_TUNER_STEP_2:
1727 case CT_TUNER_STEP_3:
1728 case CT_TUNER_STEP_4:
1729 ret = dib0090_get_offset(state, tune_state);
1730 break;
1731
1732 case CT_TUNER_STEP_5: /* found an offset */
1733 dprintk("adc_diff = %d, current step= %d\n", (u32) state->adc_diff, state->step);
1734 if (state->step == 0 && state->adc_diff < 0) {
1735 state->min_adc_diff = -1023;
1736 dprintk("Change of sign of the minimum adc diff\n");
1737 }
1738
1739 dprintk("adc_diff = %d, min_adc_diff = %d current_step = %d\n", state->adc_diff, state->min_adc_diff, state->step);
1740
1741 /* first turn for this frequency */
1742 if (state->step == 0) {
1743 if (state->dc->pga && state->adc_diff < 0)
1744 state->step = 0x10;
1745 if (state->dc->pga == 0 && state->adc_diff > 0)
1746 state->step = 0x10;
1747 }
1748
1749 /* Look for a change of Sign in the Adc_diff.min_adc_diff is used to STORE the setp N-1 */
1750 if ((state->adc_diff & 0x8000) == (state->min_adc_diff & 0x8000) && steps(state->step) < 15) {
1751 /* stop search when the delta the sign is changing and Steps =15 and Step=0 is force for continuance */
1752 state->step++;
1753 state->min_adc_diff = state->adc_diff;
1754 *tune_state = CT_TUNER_STEP_1;
1755 } else {
1756 /* the minimum was what we have seen in the step before */
1757 if (abs(state->adc_diff) > abs(state->min_adc_diff)) {
1758 dprintk("Since adc_diff N = %d > adc_diff step N-1 = %d, Come back one step\n", state->adc_diff, state->min_adc_diff);
1759 state->step--;
1760 }
1761
1762 dib0090_set_trim(state);
1763 dprintk("BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd\n", state->dc->addr, state->adc_diff, state->step);
1764
1765 state->dc++;
1766 if (state->dc->addr == 0) /* done */
1767 *tune_state = CT_TUNER_STEP_6;
1768 else
1769 *tune_state = CT_TUNER_STEP_0;
1770
1771 }
1772 break;
1773
1774 case CT_TUNER_STEP_6:
1775 dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008);
1776 dib0090_write_reg(state, 0x1f, 0x7);
1777 *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1778 state->calibrate &= ~DC_CAL;
1779 default:
1780 break;
1781 }
1782 return ret;
1783 }
1784
dib0090_wbd_calibration(struct dib0090_state * state,enum frontend_tune_state * tune_state)1785 static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1786 {
1787 u8 wbd_gain;
1788 const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1789
1790 switch (*tune_state) {
1791 case CT_TUNER_START:
1792 while (state->current_rf / 1000 > wbd->max_freq)
1793 wbd++;
1794 if (wbd->wbd_gain != 0)
1795 wbd_gain = wbd->wbd_gain;
1796 else {
1797 wbd_gain = 4;
1798 #if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
1799 if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND))
1800 wbd_gain = 2;
1801 #endif
1802 }
1803
1804 if (wbd_gain == state->wbd_calibration_gain) { /* the WBD calibration has already been done */
1805 *tune_state = CT_TUNER_START;
1806 state->calibrate &= ~WBD_CAL;
1807 return 0;
1808 }
1809
1810 dib0090_write_reg(state, 0x10, 0x1b81 | (1 << 10) | (wbd_gain << 13) | (1 << 3));
1811
1812 dib0090_write_reg(state, 0x24, ((EN_UHF & 0x0fff) | (1 << 1)));
1813 *tune_state = CT_TUNER_STEP_0;
1814 state->wbd_calibration_gain = wbd_gain;
1815 return 90; /* wait for the WBDMUX to switch and for the ADC to sample */
1816
1817 case CT_TUNER_STEP_0:
1818 state->wbd_offset = dib0090_get_slow_adc_val(state);
1819 dprintk("WBD calibration offset = %d\n", state->wbd_offset);
1820 *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1821 state->calibrate &= ~WBD_CAL;
1822 break;
1823
1824 default:
1825 break;
1826 }
1827 return 0;
1828 }
1829
dib0090_set_bandwidth(struct dib0090_state * state)1830 static void dib0090_set_bandwidth(struct dib0090_state *state)
1831 {
1832 u16 tmp;
1833
1834 if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000)
1835 tmp = (3 << 14);
1836 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000)
1837 tmp = (2 << 14);
1838 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000)
1839 tmp = (1 << 14);
1840 else
1841 tmp = (0 << 14);
1842
1843 state->bb_1_def &= 0x3fff;
1844 state->bb_1_def |= tmp;
1845
1846 dib0090_write_reg(state, 0x01, state->bb_1_def); /* be sure that we have the right bb-filter */
1847
1848 dib0090_write_reg(state, 0x03, 0x6008); /* = 0x6008 : vcm3_trim = 1 ; filter2_gm1_trim = 8 ; filter2_cutoff_freq = 0 */
1849 dib0090_write_reg(state, 0x04, 0x1); /* 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast */
1850 if (state->identity.in_soc) {
1851 dib0090_write_reg(state, 0x05, 0x9bcf); /* attenuator_ibias_tri = 2 ; input_stage_ibias_tr = 1 ; nc = 11 ; ext_gm_trim = 1 ; obuf_ibias_trim = 4 ; filter13_gm2_ibias_t = 15 */
1852 } else {
1853 dib0090_write_reg(state, 0x02, (5 << 11) | (8 << 6) | (22 & 0x3f)); /* 22 = cap_value */
1854 dib0090_write_reg(state, 0x05, 0xabcd); /* = 0xabcd : attenuator_ibias_tri = 2 ; input_stage_ibias_tr = 2 ; nc = 11 ; ext_gm_trim = 1 ; obuf_ibias_trim = 4 ; filter13_gm2_ibias_t = 13 */
1855 }
1856 }
1857
1858 static const struct dib0090_pll dib0090_pll_table[] = {
1859 #ifdef CONFIG_BAND_CBAND
1860 {56000, 0, 9, 48, 6},
1861 {70000, 1, 9, 48, 6},
1862 {87000, 0, 8, 32, 4},
1863 {105000, 1, 8, 32, 4},
1864 {115000, 0, 7, 24, 6},
1865 {140000, 1, 7, 24, 6},
1866 {170000, 0, 6, 16, 4},
1867 #endif
1868 #ifdef CONFIG_BAND_VHF
1869 {200000, 1, 6, 16, 4},
1870 {230000, 0, 5, 12, 6},
1871 {280000, 1, 5, 12, 6},
1872 {340000, 0, 4, 8, 4},
1873 {380000, 1, 4, 8, 4},
1874 {450000, 0, 3, 6, 6},
1875 #endif
1876 #ifdef CONFIG_BAND_UHF
1877 {580000, 1, 3, 6, 6},
1878 {700000, 0, 2, 4, 4},
1879 {860000, 1, 2, 4, 4},
1880 #endif
1881 #ifdef CONFIG_BAND_LBAND
1882 {1800000, 1, 0, 2, 4},
1883 #endif
1884 #ifdef CONFIG_BAND_SBAND
1885 {2900000, 0, 14, 1, 4},
1886 #endif
1887 };
1888
1889 static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
1890
1891 #ifdef CONFIG_BAND_CBAND
1892 {184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1893 {227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1894 {380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1895 #endif
1896 #ifdef CONFIG_BAND_UHF
1897 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1898 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1899 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1900 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1901 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1902 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1903 #endif
1904 #ifdef CONFIG_BAND_LBAND
1905 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1906 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1907 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1908 #endif
1909 #ifdef CONFIG_BAND_SBAND
1910 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1911 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1912 #endif
1913 };
1914
1915 static const struct dib0090_tuning dib0090_tuning_table[] = {
1916
1917 #ifdef CONFIG_BAND_CBAND
1918 {170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1919 #endif
1920 #ifdef CONFIG_BAND_VHF
1921 {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1922 {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1923 {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1924 #endif
1925 #ifdef CONFIG_BAND_UHF
1926 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1927 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1928 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1929 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1930 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1931 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1932 #endif
1933 #ifdef CONFIG_BAND_LBAND
1934 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1935 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1936 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1937 #endif
1938 #ifdef CONFIG_BAND_SBAND
1939 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1940 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1941 #endif
1942 };
1943
1944 static const struct dib0090_tuning dib0090_p1g_tuning_table[] = {
1945 #ifdef CONFIG_BAND_CBAND
1946 {170000, 4, 1, 0x820f, 0x300, 0x2d22, 0x82cb, EN_CAB},
1947 #endif
1948 #ifdef CONFIG_BAND_VHF
1949 {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1950 {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1951 {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1952 #endif
1953 #ifdef CONFIG_BAND_UHF
1954 {510000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1955 {540000, 2, 1, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1956 {600000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1957 {630000, 2, 4, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1958 {680000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1959 {720000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1960 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1961 #endif
1962 #ifdef CONFIG_BAND_LBAND
1963 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1964 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1965 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1966 #endif
1967 #ifdef CONFIG_BAND_SBAND
1968 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1969 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1970 #endif
1971 };
1972
1973 static const struct dib0090_pll dib0090_p1g_pll_table[] = {
1974 #ifdef CONFIG_BAND_CBAND
1975 {57000, 0, 11, 48, 6},
1976 {70000, 1, 11, 48, 6},
1977 {86000, 0, 10, 32, 4},
1978 {105000, 1, 10, 32, 4},
1979 {115000, 0, 9, 24, 6},
1980 {140000, 1, 9, 24, 6},
1981 {170000, 0, 8, 16, 4},
1982 #endif
1983 #ifdef CONFIG_BAND_VHF
1984 {200000, 1, 8, 16, 4},
1985 {230000, 0, 7, 12, 6},
1986 {280000, 1, 7, 12, 6},
1987 {340000, 0, 6, 8, 4},
1988 {380000, 1, 6, 8, 4},
1989 {455000, 0, 5, 6, 6},
1990 #endif
1991 #ifdef CONFIG_BAND_UHF
1992 {580000, 1, 5, 6, 6},
1993 {680000, 0, 4, 4, 4},
1994 {860000, 1, 4, 4, 4},
1995 #endif
1996 #ifdef CONFIG_BAND_LBAND
1997 {1800000, 1, 2, 2, 4},
1998 #endif
1999 #ifdef CONFIG_BAND_SBAND
2000 {2900000, 0, 1, 1, 6},
2001 #endif
2002 };
2003
2004 static const struct dib0090_tuning dib0090_p1g_tuning_table_fm_vhf_on_cband[] = {
2005 #ifdef CONFIG_BAND_CBAND
2006 {184000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
2007 {227000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
2008 {380000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
2009 #endif
2010 #ifdef CONFIG_BAND_UHF
2011 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2012 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2013 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2014 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2015 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2016 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2017 #endif
2018 #ifdef CONFIG_BAND_LBAND
2019 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2020 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2021 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2022 #endif
2023 #ifdef CONFIG_BAND_SBAND
2024 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
2025 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
2026 #endif
2027 };
2028
2029 static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = {
2030 #ifdef CONFIG_BAND_CBAND
2031 {300000, 4, 3, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2032 {380000, 4, 10, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2033 {570000, 4, 10, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2034 {858000, 4, 5, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2035 #endif
2036 };
2037
2038 static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_sensitivity[] = {
2039 #ifdef CONFIG_BAND_CBAND
2040 { 300000, 0 , 3, 0x8105, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2041 { 380000, 0 , 10, 0x810F, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2042 { 600000, 0 , 10, 0x815E, 0x280, 0x2d12, 0xb84e, EN_CAB },
2043 { 660000, 0 , 5, 0x85E3, 0x280, 0x2d12, 0xb84e, EN_CAB },
2044 { 720000, 0 , 5, 0x852E, 0x280, 0x2d12, 0xb84e, EN_CAB },
2045 { 860000, 0 , 4, 0x85E5, 0x280, 0x2d12, 0xb84e, EN_CAB },
2046 #endif
2047 };
2048
dib0090_update_tuning_table_7090(struct dvb_frontend * fe,u8 cfg_sensitivity)2049 int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
2050 u8 cfg_sensitivity)
2051 {
2052 struct dib0090_state *state = fe->tuner_priv;
2053 const struct dib0090_tuning *tune =
2054 dib0090_tuning_table_cband_7090e_sensitivity;
2055 static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_aci[] = {
2056 { 300000, 0 , 3, 0x8165, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2057 { 650000, 0 , 4, 0x815B, 0x280, 0x2d12, 0xb84e, EN_CAB },
2058 { 860000, 0 , 5, 0x84EF, 0x280, 0x2d12, 0xb84e, EN_CAB },
2059 };
2060
2061 if ((!state->identity.p1g) || (!state->identity.in_soc)
2062 || ((state->identity.version != SOC_7090_P1G_21R1)
2063 && (state->identity.version != SOC_7090_P1G_11R1))) {
2064 dprintk("%s() function can only be used for dib7090\n", __func__);
2065 return -ENODEV;
2066 }
2067
2068 if (cfg_sensitivity)
2069 tune = dib0090_tuning_table_cband_7090e_sensitivity;
2070 else
2071 tune = dib0090_tuning_table_cband_7090e_aci;
2072
2073 while (state->rf_request > tune->max_freq)
2074 tune++;
2075
2076 dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x8000)
2077 | (tune->lna_bias & 0x7fff));
2078 dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xf83f)
2079 | ((tune->lna_tune << 6) & 0x07c0));
2080 return 0;
2081 }
2082 EXPORT_SYMBOL(dib0090_update_tuning_table_7090);
2083
dib0090_captrim_search(struct dib0090_state * state,enum frontend_tune_state * tune_state)2084 static int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2085 {
2086 int ret = 0;
2087 u16 lo4 = 0xe900;
2088
2089 s16 adc_target;
2090 u16 adc;
2091 s8 step_sign;
2092 u8 force_soft_search = 0;
2093
2094 if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
2095 force_soft_search = 1;
2096
2097 if (*tune_state == CT_TUNER_START) {
2098 dprintk("Start Captrim search : %s\n",
2099 (force_soft_search == 1) ? "FORCE SOFT SEARCH" : "AUTO");
2100 dib0090_write_reg(state, 0x10, 0x2B1);
2101 dib0090_write_reg(state, 0x1e, 0x0032);
2102
2103 if (!state->tuner_is_tuned) {
2104 /* prepare a complete captrim */
2105 if (!state->identity.p1g || force_soft_search)
2106 state->step = state->captrim = state->fcaptrim = 64;
2107
2108 state->current_rf = state->rf_request;
2109 } else { /* we are already tuned to this frequency - the configuration is correct */
2110 if (!state->identity.p1g || force_soft_search) {
2111 /* do a minimal captrim even if the frequency has not changed */
2112 state->step = 4;
2113 state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
2114 }
2115 }
2116 state->adc_diff = 3000;
2117 *tune_state = CT_TUNER_STEP_0;
2118
2119 } else if (*tune_state == CT_TUNER_STEP_0) {
2120 if (state->identity.p1g && !force_soft_search) {
2121 u8 ratio = 31;
2122
2123 dib0090_write_reg(state, 0x40, (3 << 7) | (ratio << 2) | (1 << 1) | 1);
2124 dib0090_read_reg(state, 0x40);
2125 ret = 50;
2126 } else {
2127 state->step /= 2;
2128 dib0090_write_reg(state, 0x18, lo4 | state->captrim);
2129
2130 if (state->identity.in_soc)
2131 ret = 25;
2132 }
2133 *tune_state = CT_TUNER_STEP_1;
2134
2135 } else if (*tune_state == CT_TUNER_STEP_1) {
2136 if (state->identity.p1g && !force_soft_search) {
2137 dib0090_write_reg(state, 0x40, 0x18c | (0 << 1) | 0);
2138 dib0090_read_reg(state, 0x40);
2139
2140 state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7F;
2141 dprintk("***Final Captrim= 0x%x\n", state->fcaptrim);
2142 *tune_state = CT_TUNER_STEP_3;
2143
2144 } else {
2145 /* MERGE for all krosus before P1G */
2146 adc = dib0090_get_slow_adc_val(state);
2147 dprintk("CAPTRIM=%d; ADC = %d (ADC) & %dmV\n", (u32) state->captrim, (u32) adc, (u32) (adc) * (u32) 1800 / (u32) 1024);
2148
2149 if (state->rest == 0 || state->identity.in_soc) { /* Just for 8090P SOCS where auto captrim HW bug : TO CHECK IN ACI for SOCS !!! if 400 for 8090p SOC => tune issue !!! */
2150 adc_target = 200;
2151 } else
2152 adc_target = 400;
2153
2154 if (adc >= adc_target) {
2155 adc -= adc_target;
2156 step_sign = -1;
2157 } else {
2158 adc = adc_target - adc;
2159 step_sign = 1;
2160 }
2161
2162 if (adc < state->adc_diff) {
2163 dprintk("CAPTRIM=%d is closer to target (%d/%d)\n", (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
2164 state->adc_diff = adc;
2165 state->fcaptrim = state->captrim;
2166 }
2167
2168 state->captrim += step_sign * state->step;
2169 if (state->step >= 1)
2170 *tune_state = CT_TUNER_STEP_0;
2171 else
2172 *tune_state = CT_TUNER_STEP_2;
2173
2174 ret = 25;
2175 }
2176 } else if (*tune_state == CT_TUNER_STEP_2) { /* this step is only used by krosus < P1G */
2177 /*write the final cptrim config */
2178 dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
2179
2180 *tune_state = CT_TUNER_STEP_3;
2181
2182 } else if (*tune_state == CT_TUNER_STEP_3) {
2183 state->calibrate &= ~CAPTRIM_CAL;
2184 *tune_state = CT_TUNER_STEP_0;
2185 }
2186
2187 return ret;
2188 }
2189
dib0090_get_temperature(struct dib0090_state * state,enum frontend_tune_state * tune_state)2190 static int dib0090_get_temperature(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2191 {
2192 int ret = 15;
2193 s16 val;
2194
2195 switch (*tune_state) {
2196 case CT_TUNER_START:
2197 state->wbdmux = dib0090_read_reg(state, 0x10);
2198 dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x8 << 3));
2199
2200 state->bias = dib0090_read_reg(state, 0x13);
2201 dib0090_write_reg(state, 0x13, state->bias | (0x3 << 8));
2202
2203 *tune_state = CT_TUNER_STEP_0;
2204 /* wait for the WBDMUX to switch and for the ADC to sample */
2205 break;
2206
2207 case CT_TUNER_STEP_0:
2208 state->adc_diff = dib0090_get_slow_adc_val(state);
2209 dib0090_write_reg(state, 0x13, (state->bias & ~(0x3 << 8)) | (0x2 << 8));
2210 *tune_state = CT_TUNER_STEP_1;
2211 break;
2212
2213 case CT_TUNER_STEP_1:
2214 val = dib0090_get_slow_adc_val(state);
2215 state->temperature = ((s16) ((val - state->adc_diff) * 180) >> 8) + 55;
2216
2217 dprintk("temperature: %d C\n", state->temperature - 30);
2218
2219 *tune_state = CT_TUNER_STEP_2;
2220 break;
2221
2222 case CT_TUNER_STEP_2:
2223 dib0090_write_reg(state, 0x13, state->bias);
2224 dib0090_write_reg(state, 0x10, state->wbdmux); /* write back original WBDMUX */
2225
2226 *tune_state = CT_TUNER_START;
2227 state->calibrate &= ~TEMP_CAL;
2228 if (state->config->analog_output == 0)
2229 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2230
2231 break;
2232
2233 default:
2234 ret = 0;
2235 break;
2236 }
2237 return ret;
2238 }
2239
2240 #define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */
dib0090_tune(struct dvb_frontend * fe)2241 static int dib0090_tune(struct dvb_frontend *fe)
2242 {
2243 struct dib0090_state *state = fe->tuner_priv;
2244 const struct dib0090_tuning *tune = state->current_tune_table_index;
2245 const struct dib0090_pll *pll = state->current_pll_table_index;
2246 enum frontend_tune_state *tune_state = &state->tune_state;
2247
2248 u16 lo5, lo6, Den, tmp;
2249 u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
2250 int ret = 10; /* 1ms is the default delay most of the time */
2251 u8 c, i;
2252
2253 /************************* VCO ***************************/
2254 /* Default values for FG */
2255 /* from these are needed : */
2256 /* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv */
2257
2258 /* in any case we first need to do a calibration if needed */
2259 if (*tune_state == CT_TUNER_START) {
2260 /* deactivate DataTX before some calibrations */
2261 if (state->calibrate & (DC_CAL | TEMP_CAL | WBD_CAL))
2262 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
2263 else
2264 /* Activate DataTX in case a calibration has been done before */
2265 if (state->config->analog_output == 0)
2266 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2267 }
2268
2269 if (state->calibrate & DC_CAL)
2270 return dib0090_dc_offset_calibration(state, tune_state);
2271 else if (state->calibrate & WBD_CAL) {
2272 if (state->current_rf == 0)
2273 state->current_rf = state->fe->dtv_property_cache.frequency / 1000;
2274 return dib0090_wbd_calibration(state, tune_state);
2275 } else if (state->calibrate & TEMP_CAL)
2276 return dib0090_get_temperature(state, tune_state);
2277 else if (state->calibrate & CAPTRIM_CAL)
2278 return dib0090_captrim_search(state, tune_state);
2279
2280 if (*tune_state == CT_TUNER_START) {
2281 /* if soc and AGC pwm control, disengage mux to be able to R/W access to 0x01 register to set the right filter (cutoff_freq_select) during the tune sequence, otherwise, SOC SERPAR error when accessing to 0x01 */
2282 if (state->config->use_pwm_agc && state->identity.in_soc) {
2283 tmp = dib0090_read_reg(state, 0x39);
2284 if ((tmp >> 10) & 0x1)
2285 dib0090_write_reg(state, 0x39, tmp & ~(1 << 10));
2286 }
2287
2288 state->current_band = (u8) BAND_OF_FREQUENCY(state->fe->dtv_property_cache.frequency / 1000);
2289 state->rf_request =
2290 state->fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
2291 BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->
2292 freq_offset_khz_vhf);
2293
2294 /* in ISDB-T 1seg we shift tuning frequency */
2295 if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1
2296 && state->fe->dtv_property_cache.isdbt_partial_reception == 0)) {
2297 const struct dib0090_low_if_offset_table *LUT_offset = state->config->low_if;
2298 u8 found_offset = 0;
2299 u32 margin_khz = 100;
2300
2301 if (LUT_offset != NULL) {
2302 while (LUT_offset->RF_freq != 0xffff) {
2303 if (((state->rf_request > (LUT_offset->RF_freq - margin_khz))
2304 && (state->rf_request < (LUT_offset->RF_freq + margin_khz)))
2305 && LUT_offset->std == state->fe->dtv_property_cache.delivery_system) {
2306 state->rf_request += LUT_offset->offset_khz;
2307 found_offset = 1;
2308 break;
2309 }
2310 LUT_offset++;
2311 }
2312 }
2313
2314 if (found_offset == 0)
2315 state->rf_request += 400;
2316 }
2317 if (state->current_rf != state->rf_request || (state->current_standard != state->fe->dtv_property_cache.delivery_system)) {
2318 state->tuner_is_tuned = 0;
2319 state->current_rf = 0;
2320 state->current_standard = 0;
2321
2322 tune = dib0090_tuning_table;
2323 if (state->identity.p1g)
2324 tune = dib0090_p1g_tuning_table;
2325
2326 tmp = (state->identity.version >> 5) & 0x7;
2327
2328 if (state->identity.in_soc) {
2329 if (state->config->force_cband_input) { /* Use the CBAND input for all band */
2330 if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF
2331 || state->current_band & BAND_UHF) {
2332 state->current_band = BAND_CBAND;
2333 if (state->config->is_dib7090e)
2334 tune = dib0090_tuning_table_cband_7090e_sensitivity;
2335 else
2336 tune = dib0090_tuning_table_cband_7090;
2337 }
2338 } else { /* Use the CBAND input for all band under UHF */
2339 if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) {
2340 state->current_band = BAND_CBAND;
2341 if (state->config->is_dib7090e)
2342 tune = dib0090_tuning_table_cband_7090e_sensitivity;
2343 else
2344 tune = dib0090_tuning_table_cband_7090;
2345 }
2346 }
2347 } else
2348 if (tmp == 0x4 || tmp == 0x7) {
2349 /* CBAND tuner version for VHF */
2350 if (state->current_band == BAND_FM || state->current_band == BAND_CBAND || state->current_band == BAND_VHF) {
2351 state->current_band = BAND_CBAND; /* Force CBAND */
2352
2353 tune = dib0090_tuning_table_fm_vhf_on_cband;
2354 if (state->identity.p1g)
2355 tune = dib0090_p1g_tuning_table_fm_vhf_on_cband;
2356 }
2357 }
2358
2359 pll = dib0090_pll_table;
2360 if (state->identity.p1g)
2361 pll = dib0090_p1g_pll_table;
2362
2363 /* Look for the interval */
2364 while (state->rf_request > tune->max_freq)
2365 tune++;
2366 while (state->rf_request > pll->max_freq)
2367 pll++;
2368
2369 state->current_tune_table_index = tune;
2370 state->current_pll_table_index = pll;
2371
2372 dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
2373
2374 VCOF_kHz = (pll->hfdiv * state->rf_request) * 2;
2375
2376 FREF = state->config->io.clock_khz;
2377 if (state->config->fref_clock_ratio != 0)
2378 FREF /= state->config->fref_clock_ratio;
2379
2380 FBDiv = (VCOF_kHz / pll->topresc / FREF);
2381 Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
2382
2383 if (Rest < LPF)
2384 Rest = 0;
2385 else if (Rest < 2 * LPF)
2386 Rest = 2 * LPF;
2387 else if (Rest > (FREF - LPF)) {
2388 Rest = 0;
2389 FBDiv += 1;
2390 } else if (Rest > (FREF - 2 * LPF))
2391 Rest = FREF - 2 * LPF;
2392 Rest = (Rest * 6528) / (FREF / 10);
2393 state->rest = Rest;
2394
2395 /* external loop filter, otherwise:
2396 * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
2397 * lo6 = 0x0e34 */
2398
2399 if (Rest == 0) {
2400 if (pll->vco_band)
2401 lo5 = 0x049f;
2402 else
2403 lo5 = 0x041f;
2404 } else {
2405 if (pll->vco_band)
2406 lo5 = 0x049e;
2407 else if (state->config->analog_output)
2408 lo5 = 0x041d;
2409 else
2410 lo5 = 0x041c;
2411 }
2412
2413 if (state->identity.p1g) { /* Bias is done automatically in P1G */
2414 if (state->identity.in_soc) {
2415 if (state->identity.version == SOC_8090_P1G_11R1)
2416 lo5 = 0x46f;
2417 else
2418 lo5 = 0x42f;
2419 } else
2420 lo5 = 0x42c;
2421 }
2422
2423 lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7); /* bit 15 is the split to the slave, we do not do it here */
2424
2425 if (!state->config->io.pll_int_loop_filt) {
2426 if (state->identity.in_soc)
2427 lo6 = 0xff98;
2428 else if (state->identity.p1g || (Rest == 0))
2429 lo6 = 0xfff8;
2430 else
2431 lo6 = 0xff28;
2432 } else
2433 lo6 = (state->config->io.pll_int_loop_filt << 3);
2434
2435 Den = 1;
2436
2437 if (Rest > 0) {
2438 lo6 |= (1 << 2) | 2;
2439 Den = 255;
2440 }
2441 dib0090_write_reg(state, 0x15, (u16) FBDiv);
2442 if (state->config->fref_clock_ratio != 0)
2443 dib0090_write_reg(state, 0x16, (Den << 8) | state->config->fref_clock_ratio);
2444 else
2445 dib0090_write_reg(state, 0x16, (Den << 8) | 1);
2446 dib0090_write_reg(state, 0x17, (u16) Rest);
2447 dib0090_write_reg(state, 0x19, lo5);
2448 dib0090_write_reg(state, 0x1c, lo6);
2449
2450 lo6 = tune->tuner_enable;
2451 if (state->config->analog_output)
2452 lo6 = (lo6 & 0xff9f) | 0x2;
2453
2454 dib0090_write_reg(state, 0x24, lo6 | EN_LO | state->config->use_pwm_agc * EN_CRYSTAL);
2455
2456 }
2457
2458 state->current_rf = state->rf_request;
2459 state->current_standard = state->fe->dtv_property_cache.delivery_system;
2460
2461 ret = 20;
2462 state->calibrate = CAPTRIM_CAL; /* captrim serach now */
2463 }
2464
2465 else if (*tune_state == CT_TUNER_STEP_0) { /* Warning : because of captrim cal, if you change this step, change it also in _cal.c file because it is the step following captrim cal state machine */
2466 const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
2467
2468 while (state->current_rf / 1000 > wbd->max_freq)
2469 wbd++;
2470
2471 dib0090_write_reg(state, 0x1e, 0x07ff);
2472 dprintk("Final Captrim: %d\n", (u32) state->fcaptrim);
2473 dprintk("HFDIV code: %d\n", (u32) pll->hfdiv_code);
2474 dprintk("VCO = %d\n", (u32) pll->vco_band);
2475 dprintk("VCOF in kHz: %d ((%d*%d) << 1))\n", (u32) ((pll->hfdiv * state->rf_request) * 2), (u32) pll->hfdiv, (u32) state->rf_request);
2476 dprintk("REFDIV: %d, FREF: %d\n", (u32) 1, (u32) state->config->io.clock_khz);
2477 dprintk("FBDIV: %d, Rest: %d\n", (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
2478 dprintk("Num: %d, Den: %d, SD: %d\n", (u32) dib0090_read_reg(state, 0x17), (u32) (dib0090_read_reg(state, 0x16) >> 8),
2479 (u32) dib0090_read_reg(state, 0x1c) & 0x3);
2480
2481 #define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */
2482 c = 4;
2483 i = 3;
2484
2485 if (wbd->wbd_gain != 0)
2486 c = wbd->wbd_gain;
2487
2488 state->wbdmux = (c << 13) | (i << 11) | (WBD | (state->config->use_pwm_agc << 1));
2489 dib0090_write_reg(state, 0x10, state->wbdmux);
2490
2491 if ((tune->tuner_enable == EN_CAB) && state->identity.p1g) {
2492 dprintk("P1G : The cable band is selected and lna_tune = %d\n", tune->lna_tune);
2493 dib0090_write_reg(state, 0x09, tune->lna_bias);
2494 dib0090_write_reg(state, 0x0b, 0xb800 | (tune->lna_tune << 6) | (tune->switch_trim));
2495 } else
2496 dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | tune->lna_bias);
2497
2498 dib0090_write_reg(state, 0x0c, tune->v2i);
2499 dib0090_write_reg(state, 0x0d, tune->mix);
2500 dib0090_write_reg(state, 0x0e, tune->load);
2501 *tune_state = CT_TUNER_STEP_1;
2502
2503 } else if (*tune_state == CT_TUNER_STEP_1) {
2504 /* initialize the lt gain register */
2505 state->rf_lt_def = 0x7c00;
2506
2507 dib0090_set_bandwidth(state);
2508 state->tuner_is_tuned = 1;
2509
2510 state->calibrate |= WBD_CAL;
2511 state->calibrate |= TEMP_CAL;
2512 *tune_state = CT_TUNER_STOP;
2513 } else
2514 ret = FE_CALLBACK_TIME_NEVER;
2515 return ret;
2516 }
2517
dib0090_release(struct dvb_frontend * fe)2518 static void dib0090_release(struct dvb_frontend *fe)
2519 {
2520 kfree(fe->tuner_priv);
2521 fe->tuner_priv = NULL;
2522 }
2523
dib0090_get_tune_state(struct dvb_frontend * fe)2524 enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
2525 {
2526 struct dib0090_state *state = fe->tuner_priv;
2527
2528 return state->tune_state;
2529 }
2530
2531 EXPORT_SYMBOL(dib0090_get_tune_state);
2532
dib0090_set_tune_state(struct dvb_frontend * fe,enum frontend_tune_state tune_state)2533 int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
2534 {
2535 struct dib0090_state *state = fe->tuner_priv;
2536
2537 state->tune_state = tune_state;
2538 return 0;
2539 }
2540
2541 EXPORT_SYMBOL(dib0090_set_tune_state);
2542
dib0090_get_frequency(struct dvb_frontend * fe,u32 * frequency)2543 static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
2544 {
2545 struct dib0090_state *state = fe->tuner_priv;
2546
2547 *frequency = 1000 * state->current_rf;
2548 return 0;
2549 }
2550
dib0090_set_params(struct dvb_frontend * fe)2551 static int dib0090_set_params(struct dvb_frontend *fe)
2552 {
2553 struct dib0090_state *state = fe->tuner_priv;
2554 u32 ret;
2555
2556 state->tune_state = CT_TUNER_START;
2557
2558 do {
2559 ret = dib0090_tune(fe);
2560 if (ret == FE_CALLBACK_TIME_NEVER)
2561 break;
2562
2563 /*
2564 * Despite dib0090_tune returns time at a 0.1 ms range,
2565 * the actual sleep time depends on CONFIG_HZ. The worse case
2566 * is when CONFIG_HZ=100. In such case, the minimum granularity
2567 * is 10ms. On some real field tests, the tuner sometimes don't
2568 * lock when this timer is lower than 10ms. So, enforce a 10ms
2569 * granularity and use usleep_range() instead of msleep().
2570 */
2571 ret = 10 * (ret + 99)/100;
2572 usleep_range(ret * 1000, (ret + 1) * 1000);
2573 } while (state->tune_state != CT_TUNER_STOP);
2574
2575 return 0;
2576 }
2577
2578 static const struct dvb_tuner_ops dib0090_ops = {
2579 .info = {
2580 .name = "DiBcom DiB0090",
2581 .frequency_min_hz = 45 * MHz,
2582 .frequency_max_hz = 860 * MHz,
2583 .frequency_step_hz = 1 * kHz,
2584 },
2585 .release = dib0090_release,
2586
2587 .init = dib0090_wakeup,
2588 .sleep = dib0090_sleep,
2589 .set_params = dib0090_set_params,
2590 .get_frequency = dib0090_get_frequency,
2591 };
2592
2593 static const struct dvb_tuner_ops dib0090_fw_ops = {
2594 .info = {
2595 .name = "DiBcom DiB0090",
2596 .frequency_min_hz = 45 * MHz,
2597 .frequency_max_hz = 860 * MHz,
2598 .frequency_step_hz = 1 * kHz,
2599 },
2600 .release = dib0090_release,
2601
2602 .init = NULL,
2603 .sleep = NULL,
2604 .set_params = NULL,
2605 .get_frequency = NULL,
2606 };
2607
2608 static const struct dib0090_wbd_slope dib0090_wbd_table_default[] = {
2609 {470, 0, 250, 0, 100, 4},
2610 {860, 51, 866, 21, 375, 4},
2611 {1700, 0, 800, 0, 850, 4},
2612 {2900, 0, 250, 0, 100, 6},
2613 {0xFFFF, 0, 0, 0, 0, 0},
2614 };
2615
dib0090_register(struct dvb_frontend * fe,struct i2c_adapter * i2c,const struct dib0090_config * config)2616 struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2617 {
2618 struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
2619 if (st == NULL)
2620 return NULL;
2621
2622 st->config = config;
2623 st->i2c = i2c;
2624 st->fe = fe;
2625 mutex_init(&st->i2c_buffer_lock);
2626 fe->tuner_priv = st;
2627
2628 if (config->wbd == NULL)
2629 st->current_wbd_table = dib0090_wbd_table_default;
2630 else
2631 st->current_wbd_table = config->wbd;
2632
2633 if (dib0090_reset(fe) != 0)
2634 goto free_mem;
2635
2636 pr_info("DiB0090: successfully identified\n");
2637 memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
2638
2639 return fe;
2640 free_mem:
2641 kfree(st);
2642 fe->tuner_priv = NULL;
2643 return NULL;
2644 }
2645
2646 EXPORT_SYMBOL(dib0090_register);
2647
dib0090_fw_register(struct dvb_frontend * fe,struct i2c_adapter * i2c,const struct dib0090_config * config)2648 struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2649 {
2650 struct dib0090_fw_state *st = kzalloc(sizeof(struct dib0090_fw_state), GFP_KERNEL);
2651 if (st == NULL)
2652 return NULL;
2653
2654 st->config = config;
2655 st->i2c = i2c;
2656 st->fe = fe;
2657 mutex_init(&st->i2c_buffer_lock);
2658 fe->tuner_priv = st;
2659
2660 if (dib0090_fw_reset_digital(fe, st->config) != 0)
2661 goto free_mem;
2662
2663 dprintk("DiB0090 FW: successfully identified\n");
2664 memcpy(&fe->ops.tuner_ops, &dib0090_fw_ops, sizeof(struct dvb_tuner_ops));
2665
2666 return fe;
2667 free_mem:
2668 kfree(st);
2669 fe->tuner_priv = NULL;
2670 return NULL;
2671 }
2672 EXPORT_SYMBOL(dib0090_fw_register);
2673
2674 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
2675 MODULE_AUTHOR("Olivier Grenie <olivier.grenie@parrot.com>");
2676 MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
2677 MODULE_LICENSE("GPL");
2678