Merge branch 'gadget' into for-next
[zen-stable.git] / drivers / media / dvb / frontends / dib0090.c
blobc9c935ae41e47bf9eaccb4f6e9df0ef0701b6e18
1 /*
2 * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
4 * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
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.
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
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * This code is more or less generated from another driver, please
23 * excuse some codingstyle oddities.
27 #include <linux/kernel.h>
28 #include <linux/slab.h>
29 #include <linux/i2c.h>
31 #include "dvb_frontend.h"
33 #include "dib0090.h"
34 #include "dibx000_common.h"
36 static int debug;
37 module_param(debug, int, 0644);
38 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
40 #define dprintk(args...) do { \
41 if (debug) { \
42 printk(KERN_DEBUG "DiB0090: "); \
43 printk(args); \
44 printk("\n"); \
45 } \
46 } while (0)
48 #define CONFIG_SYS_DVBT
49 #define CONFIG_SYS_ISDBT
50 #define CONFIG_BAND_CBAND
51 #define CONFIG_BAND_VHF
52 #define CONFIG_BAND_UHF
53 #define CONFIG_DIB0090_USE_PWM_AGC
55 #define EN_LNA0 0x8000
56 #define EN_LNA1 0x4000
57 #define EN_LNA2 0x2000
58 #define EN_LNA3 0x1000
59 #define EN_MIX0 0x0800
60 #define EN_MIX1 0x0400
61 #define EN_MIX2 0x0200
62 #define EN_MIX3 0x0100
63 #define EN_IQADC 0x0040
64 #define EN_PLL 0x0020
65 #define EN_TX 0x0010
66 #define EN_BB 0x0008
67 #define EN_LO 0x0004
68 #define EN_BIAS 0x0001
70 #define EN_IQANA 0x0002
71 #define EN_DIGCLK 0x0080 /* not in the 0x24 reg, only in 0x1b */
72 #define EN_CRYSTAL 0x0002
74 #define EN_UHF 0x22E9
75 #define EN_VHF 0x44E9
76 #define EN_LBD 0x11E9
77 #define EN_SBD 0x44E9
78 #define EN_CAB 0x88E9
80 /* Calibration defines */
81 #define DC_CAL 0x1
82 #define WBD_CAL 0x2
83 #define TEMP_CAL 0x4
84 #define CAPTRIM_CAL 0x8
86 #define KROSUS_PLL_LOCKED 0x800
87 #define KROSUS 0x2
89 /* Use those defines to identify SOC version */
90 #define SOC 0x02
91 #define SOC_7090_P1G_11R1 0x82
92 #define SOC_7090_P1G_21R1 0x8a
93 #define SOC_8090_P1G_11R1 0x86
94 #define SOC_8090_P1G_21R1 0x8e
96 /* else use thos ones to check */
97 #define P1A_B 0x0
98 #define P1C 0x1
99 #define P1D_E_F 0x3
100 #define P1G 0x7
101 #define P1G_21R2 0xf
103 #define MP001 0x1 /* Single 9090/8096 */
104 #define MP005 0x4 /* Single Sband */
105 #define MP008 0x6 /* Dual diversity VHF-UHF-LBAND */
106 #define MP009 0x7 /* Dual diversity 29098 CBAND-UHF-LBAND-SBAND */
108 #define pgm_read_word(w) (*w)
110 struct dc_calibration;
112 struct dib0090_tuning {
113 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
114 u8 switch_trim;
115 u8 lna_tune;
116 u16 lna_bias;
117 u16 v2i;
118 u16 mix;
119 u16 load;
120 u16 tuner_enable;
123 struct dib0090_pll {
124 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
125 u8 vco_band;
126 u8 hfdiv_code;
127 u8 hfdiv;
128 u8 topresc;
131 struct dib0090_identity {
132 u8 version;
133 u8 product;
134 u8 p1g;
135 u8 in_soc;
138 struct dib0090_state {
139 struct i2c_adapter *i2c;
140 struct dvb_frontend *fe;
141 const struct dib0090_config *config;
143 u8 current_band;
144 enum frontend_tune_state tune_state;
145 u32 current_rf;
147 u16 wbd_offset;
148 s16 wbd_target; /* in dB */
150 s16 rf_gain_limit; /* take-over-point: where to split between bb and rf gain */
151 s16 current_gain; /* keeps the currently programmed gain */
152 u8 agc_step; /* new binary search */
154 u16 gain[2]; /* for channel monitoring */
156 const u16 *rf_ramp;
157 const u16 *bb_ramp;
159 /* for the software AGC ramps */
160 u16 bb_1_def;
161 u16 rf_lt_def;
162 u16 gain_reg[4];
164 /* for the captrim/dc-offset search */
165 s8 step;
166 s16 adc_diff;
167 s16 min_adc_diff;
169 s8 captrim;
170 s8 fcaptrim;
172 const struct dc_calibration *dc;
173 u16 bb6, bb7;
175 const struct dib0090_tuning *current_tune_table_index;
176 const struct dib0090_pll *current_pll_table_index;
178 u8 tuner_is_tuned;
179 u8 agc_freeze;
181 struct dib0090_identity identity;
183 u32 rf_request;
184 u8 current_standard;
186 u8 calibrate;
187 u32 rest;
188 u16 bias;
189 s16 temperature;
191 u8 wbd_calibration_gain;
192 const struct dib0090_wbd_slope *current_wbd_table;
193 u16 wbdmux;
195 /* for the I2C transfer */
196 struct i2c_msg msg[2];
197 u8 i2c_write_buffer[3];
198 u8 i2c_read_buffer[2];
201 struct dib0090_fw_state {
202 struct i2c_adapter *i2c;
203 struct dvb_frontend *fe;
204 struct dib0090_identity identity;
205 const struct dib0090_config *config;
207 /* for the I2C transfer */
208 struct i2c_msg msg;
209 u8 i2c_write_buffer[2];
210 u8 i2c_read_buffer[2];
213 static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
215 state->i2c_write_buffer[0] = reg;
217 memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
218 state->msg[0].addr = state->config->i2c_address;
219 state->msg[0].flags = 0;
220 state->msg[0].buf = state->i2c_write_buffer;
221 state->msg[0].len = 1;
222 state->msg[1].addr = state->config->i2c_address;
223 state->msg[1].flags = I2C_M_RD;
224 state->msg[1].buf = state->i2c_read_buffer;
225 state->msg[1].len = 2;
227 if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
228 printk(KERN_WARNING "DiB0090 I2C read failed\n");
229 return 0;
232 return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
235 static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
237 state->i2c_write_buffer[0] = reg & 0xff;
238 state->i2c_write_buffer[1] = val >> 8;
239 state->i2c_write_buffer[2] = val & 0xff;
241 memset(state->msg, 0, sizeof(struct i2c_msg));
242 state->msg[0].addr = state->config->i2c_address;
243 state->msg[0].flags = 0;
244 state->msg[0].buf = state->i2c_write_buffer;
245 state->msg[0].len = 3;
247 if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
248 printk(KERN_WARNING "DiB0090 I2C write failed\n");
249 return -EREMOTEIO;
251 return 0;
254 static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
256 state->i2c_write_buffer[0] = reg;
258 memset(&state->msg, 0, sizeof(struct i2c_msg));
259 state->msg.addr = reg;
260 state->msg.flags = I2C_M_RD;
261 state->msg.buf = state->i2c_read_buffer;
262 state->msg.len = 2;
263 if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
264 printk(KERN_WARNING "DiB0090 I2C read failed\n");
265 return 0;
267 return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
270 static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
272 state->i2c_write_buffer[0] = val >> 8;
273 state->i2c_write_buffer[1] = val & 0xff;
275 memset(&state->msg, 0, sizeof(struct i2c_msg));
276 state->msg.addr = reg;
277 state->msg.flags = 0;
278 state->msg.buf = state->i2c_write_buffer;
279 state->msg.len = 2;
280 if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
281 printk(KERN_WARNING "DiB0090 I2C write failed\n");
282 return -EREMOTEIO;
284 return 0;
287 #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)
288 #define ADC_TARGET -220
289 #define GAIN_ALPHA 5
290 #define WBD_ALPHA 6
291 #define LPF 100
292 static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c)
294 do {
295 dib0090_write_reg(state, r++, *b++);
296 } while (--c);
299 static int dib0090_identify(struct dvb_frontend *fe)
301 struct dib0090_state *state = fe->tuner_priv;
302 u16 v;
303 struct dib0090_identity *identity = &state->identity;
305 v = dib0090_read_reg(state, 0x1a);
307 identity->p1g = 0;
308 identity->in_soc = 0;
310 dprintk("Tuner identification (Version = 0x%04x)", v);
312 /* without PLL lock info */
313 v &= ~KROSUS_PLL_LOCKED;
315 identity->version = v & 0xff;
316 identity->product = (v >> 8) & 0xf;
318 if (identity->product != KROSUS)
319 goto identification_error;
321 if ((identity->version & 0x3) == SOC) {
322 identity->in_soc = 1;
323 switch (identity->version) {
324 case SOC_8090_P1G_11R1:
325 dprintk("SOC 8090 P1-G11R1 Has been detected");
326 identity->p1g = 1;
327 break;
328 case SOC_8090_P1G_21R1:
329 dprintk("SOC 8090 P1-G21R1 Has been detected");
330 identity->p1g = 1;
331 break;
332 case SOC_7090_P1G_11R1:
333 dprintk("SOC 7090 P1-G11R1 Has been detected");
334 identity->p1g = 1;
335 break;
336 case SOC_7090_P1G_21R1:
337 dprintk("SOC 7090 P1-G21R1 Has been detected");
338 identity->p1g = 1;
339 break;
340 default:
341 goto identification_error;
343 } else {
344 switch ((identity->version >> 5) & 0x7) {
345 case MP001:
346 dprintk("MP001 : 9090/8096");
347 break;
348 case MP005:
349 dprintk("MP005 : Single Sband");
350 break;
351 case MP008:
352 dprintk("MP008 : diversity VHF-UHF-LBAND");
353 break;
354 case MP009:
355 dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND");
356 break;
357 default:
358 goto identification_error;
361 switch (identity->version & 0x1f) {
362 case P1G_21R2:
363 dprintk("P1G_21R2 detected");
364 identity->p1g = 1;
365 break;
366 case P1G:
367 dprintk("P1G detected");
368 identity->p1g = 1;
369 break;
370 case P1D_E_F:
371 dprintk("P1D/E/F detected");
372 break;
373 case P1C:
374 dprintk("P1C detected");
375 break;
376 case P1A_B:
377 dprintk("P1-A/B detected: driver is deactivated - not available");
378 goto identification_error;
379 break;
380 default:
381 goto identification_error;
385 return 0;
387 identification_error:
388 return -EIO;
391 static int dib0090_fw_identify(struct dvb_frontend *fe)
393 struct dib0090_fw_state *state = fe->tuner_priv;
394 struct dib0090_identity *identity = &state->identity;
396 u16 v = dib0090_fw_read_reg(state, 0x1a);
397 identity->p1g = 0;
398 identity->in_soc = 0;
400 dprintk("FE: Tuner identification (Version = 0x%04x)", v);
402 /* without PLL lock info */
403 v &= ~KROSUS_PLL_LOCKED;
405 identity->version = v & 0xff;
406 identity->product = (v >> 8) & 0xf;
408 if (identity->product != KROSUS)
409 goto identification_error;
411 if ((identity->version & 0x3) == SOC) {
412 identity->in_soc = 1;
413 switch (identity->version) {
414 case SOC_8090_P1G_11R1:
415 dprintk("SOC 8090 P1-G11R1 Has been detected");
416 identity->p1g = 1;
417 break;
418 case SOC_8090_P1G_21R1:
419 dprintk("SOC 8090 P1-G21R1 Has been detected");
420 identity->p1g = 1;
421 break;
422 case SOC_7090_P1G_11R1:
423 dprintk("SOC 7090 P1-G11R1 Has been detected");
424 identity->p1g = 1;
425 break;
426 case SOC_7090_P1G_21R1:
427 dprintk("SOC 7090 P1-G21R1 Has been detected");
428 identity->p1g = 1;
429 break;
430 default:
431 goto identification_error;
433 } else {
434 switch ((identity->version >> 5) & 0x7) {
435 case MP001:
436 dprintk("MP001 : 9090/8096");
437 break;
438 case MP005:
439 dprintk("MP005 : Single Sband");
440 break;
441 case MP008:
442 dprintk("MP008 : diversity VHF-UHF-LBAND");
443 break;
444 case MP009:
445 dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND");
446 break;
447 default:
448 goto identification_error;
451 switch (identity->version & 0x1f) {
452 case P1G_21R2:
453 dprintk("P1G_21R2 detected");
454 identity->p1g = 1;
455 break;
456 case P1G:
457 dprintk("P1G detected");
458 identity->p1g = 1;
459 break;
460 case P1D_E_F:
461 dprintk("P1D/E/F detected");
462 break;
463 case P1C:
464 dprintk("P1C detected");
465 break;
466 case P1A_B:
467 dprintk("P1-A/B detected: driver is deactivated - not available");
468 goto identification_error;
469 break;
470 default:
471 goto identification_error;
475 return 0;
477 identification_error:
478 return -EIO;;
481 static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
483 struct dib0090_state *state = fe->tuner_priv;
484 u16 PllCfg, i, v;
486 HARD_RESET(state);
488 dib0090_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
489 dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */
491 if (!cfg->in_soc) {
492 /* adcClkOutRatio=8->7, release reset */
493 dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
494 if (cfg->clkoutdrive != 0)
495 dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
496 | (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
497 else
498 dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
499 | (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
502 /* Read Pll current config * */
503 PllCfg = dib0090_read_reg(state, 0x21);
505 /** Reconfigure PLL if current setting is different from default setting **/
506 if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && (!cfg->in_soc)
507 && !cfg->io.pll_bypass) {
509 /* Set Bypass mode */
510 PllCfg |= (1 << 15);
511 dib0090_write_reg(state, 0x21, PllCfg);
513 /* Set Reset Pll */
514 PllCfg &= ~(1 << 13);
515 dib0090_write_reg(state, 0x21, PllCfg);
517 /*** Set new Pll configuration in bypass and reset state ***/
518 PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
519 dib0090_write_reg(state, 0x21, PllCfg);
521 /* Remove Reset Pll */
522 PllCfg |= (1 << 13);
523 dib0090_write_reg(state, 0x21, PllCfg);
525 /*** Wait for PLL lock ***/
526 i = 100;
527 do {
528 v = !!(dib0090_read_reg(state, 0x1a) & 0x800);
529 if (v)
530 break;
531 } while (--i);
533 if (i == 0) {
534 dprintk("Pll: Unable to lock Pll");
535 return;
538 /* Finally Remove Bypass mode */
539 PllCfg &= ~(1 << 15);
540 dib0090_write_reg(state, 0x21, PllCfg);
543 if (cfg->io.pll_bypass) {
544 PllCfg |= (cfg->io.pll_bypass << 15);
545 dib0090_write_reg(state, 0x21, PllCfg);
549 static int dib0090_fw_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
551 struct dib0090_fw_state *state = fe->tuner_priv;
552 u16 PllCfg;
553 u16 v;
554 int i;
556 dprintk("fw reset digital");
557 HARD_RESET(state);
559 dib0090_fw_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
560 dib0090_fw_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */
562 dib0090_fw_write_reg(state, 0x20,
563 ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (cfg->data_tx_drv << 4) | cfg->ls_cfg_pad_drv);
565 v = (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 9) | (0 << 8) | (cfg->clkouttobamse << 4) | (0 << 2) | (0);
566 if (cfg->clkoutdrive != 0)
567 v |= cfg->clkoutdrive << 5;
568 else
569 v |= 7 << 5;
571 v |= 2 << 10;
572 dib0090_fw_write_reg(state, 0x23, v);
574 /* Read Pll current config * */
575 PllCfg = dib0090_fw_read_reg(state, 0x21);
577 /** Reconfigure PLL if current setting is different from default setting **/
578 if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && !cfg->io.pll_bypass) {
580 /* Set Bypass mode */
581 PllCfg |= (1 << 15);
582 dib0090_fw_write_reg(state, 0x21, PllCfg);
584 /* Set Reset Pll */
585 PllCfg &= ~(1 << 13);
586 dib0090_fw_write_reg(state, 0x21, PllCfg);
588 /*** Set new Pll configuration in bypass and reset state ***/
589 PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
590 dib0090_fw_write_reg(state, 0x21, PllCfg);
592 /* Remove Reset Pll */
593 PllCfg |= (1 << 13);
594 dib0090_fw_write_reg(state, 0x21, PllCfg);
596 /*** Wait for PLL lock ***/
597 i = 100;
598 do {
599 v = !!(dib0090_fw_read_reg(state, 0x1a) & 0x800);
600 if (v)
601 break;
602 } while (--i);
604 if (i == 0) {
605 dprintk("Pll: Unable to lock Pll");
606 return -EIO;
609 /* Finally Remove Bypass mode */
610 PllCfg &= ~(1 << 15);
611 dib0090_fw_write_reg(state, 0x21, PllCfg);
614 if (cfg->io.pll_bypass) {
615 PllCfg |= (cfg->io.pll_bypass << 15);
616 dib0090_fw_write_reg(state, 0x21, PllCfg);
619 return dib0090_fw_identify(fe);
622 static int dib0090_wakeup(struct dvb_frontend *fe)
624 struct dib0090_state *state = fe->tuner_priv;
625 if (state->config->sleep)
626 state->config->sleep(fe, 0);
628 /* enable dataTX in case we have been restarted in the wrong moment */
629 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
630 return 0;
633 static int dib0090_sleep(struct dvb_frontend *fe)
635 struct dib0090_state *state = fe->tuner_priv;
636 if (state->config->sleep)
637 state->config->sleep(fe, 1);
638 return 0;
641 void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
643 struct dib0090_state *state = fe->tuner_priv;
644 if (fast)
645 dib0090_write_reg(state, 0x04, 0);
646 else
647 dib0090_write_reg(state, 0x04, 1);
650 EXPORT_SYMBOL(dib0090_dcc_freq);
652 static const u16 bb_ramp_pwm_normal_socs[] = {
653 550, /* max BB gain in 10th of dB */
654 (1 << 9) | 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
655 440,
656 (4 << 9) | 0, /* BB_RAMP3 = 26dB */
657 (0 << 9) | 208, /* BB_RAMP4 */
658 (4 << 9) | 208, /* BB_RAMP5 = 29dB */
659 (0 << 9) | 440, /* BB_RAMP6 */
662 static const u16 rf_ramp_pwm_cband_7090[] = {
663 280, /* max RF gain in 10th of dB */
664 18, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
665 504, /* ramp_max = maximum X used on the ramp */
666 (29 << 10) | 364, /* RF_RAMP5, LNA 1 = 8dB */
667 (0 << 10) | 504, /* RF_RAMP6, LNA 1 */
668 (60 << 10) | 228, /* RF_RAMP7, LNA 2 = 7.7dB */
669 (0 << 10) | 364, /* RF_RAMP8, LNA 2 */
670 (34 << 10) | 109, /* GAIN_4_1, LNA 3 = 6.8dB */
671 (0 << 10) | 228, /* GAIN_4_2, LNA 3 */
672 (37 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */
673 (0 << 10) | 109, /* RF_RAMP4, LNA 4 */
676 static const u16 rf_ramp_pwm_cband_8090[] = {
677 345, /* max RF gain in 10th of dB */
678 29, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
679 1000, /* ramp_max = maximum X used on the ramp */
680 (35 << 10) | 772, /* RF_RAMP3, LNA 1 = 8dB */
681 (0 << 10) | 1000, /* RF_RAMP4, LNA 1 */
682 (58 << 10) | 496, /* RF_RAMP5, LNA 2 = 9.5dB */
683 (0 << 10) | 772, /* RF_RAMP6, LNA 2 */
684 (27 << 10) | 200, /* RF_RAMP7, LNA 3 = 10.5dB */
685 (0 << 10) | 496, /* RF_RAMP8, LNA 3 */
686 (40 << 10) | 0, /* GAIN_4_1, LNA 4 = 7dB */
687 (0 << 10) | 200, /* GAIN_4_2, LNA 4 */
690 static const u16 rf_ramp_pwm_uhf_7090[] = {
691 407, /* max RF gain in 10th of dB */
692 13, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
693 529, /* ramp_max = maximum X used on the ramp */
694 (23 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
695 (0 << 10) | 176, /* RF_RAMP4, LNA 1 */
696 (63 << 10) | 400, /* RF_RAMP5, LNA 2 = 8dB */
697 (0 << 10) | 529, /* RF_RAMP6, LNA 2 */
698 (48 << 10) | 316, /* RF_RAMP7, LNA 3 = 6.8dB */
699 (0 << 10) | 400, /* RF_RAMP8, LNA 3 */
700 (29 << 10) | 176, /* GAIN_4_1, LNA 4 = 11.5dB */
701 (0 << 10) | 316, /* GAIN_4_2, LNA 4 */
704 static const u16 rf_ramp_pwm_uhf_8090[] = {
705 388, /* max RF gain in 10th of dB */
706 26, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
707 1008, /* ramp_max = maximum X used on the ramp */
708 (11 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
709 (0 << 10) | 369, /* RF_RAMP4, LNA 1 */
710 (41 << 10) | 809, /* RF_RAMP5, LNA 2 = 8dB */
711 (0 << 10) | 1008, /* RF_RAMP6, LNA 2 */
712 (27 << 10) | 659, /* RF_RAMP7, LNA 3 = 6dB */
713 (0 << 10) | 809, /* RF_RAMP8, LNA 3 */
714 (14 << 10) | 369, /* GAIN_4_1, LNA 4 = 11.5dB */
715 (0 << 10) | 659, /* GAIN_4_2, LNA 4 */
718 static const u16 rf_ramp_pwm_cband[] = {
719 0, /* max RF gain in 10th of dB */
720 0, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
721 0, /* ramp_max = maximum X used on the ramp */
722 (0 << 10) | 0, /* 0x2c, LNA 1 = 0dB */
723 (0 << 10) | 0, /* 0x2d, LNA 1 */
724 (0 << 10) | 0, /* 0x2e, LNA 2 = 0dB */
725 (0 << 10) | 0, /* 0x2f, LNA 2 */
726 (0 << 10) | 0, /* 0x30, LNA 3 = 0dB */
727 (0 << 10) | 0, /* 0x31, LNA 3 */
728 (0 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
729 (0 << 10) | 0, /* GAIN_4_2, LNA 4 */
732 static const u16 rf_ramp_vhf[] = {
733 412, /* max RF gain in 10th of dB */
734 132, 307, 127, /* LNA1, 13.2dB */
735 105, 412, 255, /* LNA2, 10.5dB */
736 50, 50, 127, /* LNA3, 5dB */
737 125, 175, 127, /* LNA4, 12.5dB */
738 0, 0, 127, /* CBAND, 0dB */
741 static const u16 rf_ramp_uhf[] = {
742 412, /* max RF gain in 10th of dB */
743 132, 307, 127, /* LNA1 : total gain = 13.2dB, point on the ramp where this amp is full gain, value to write to get full gain */
744 105, 412, 255, /* LNA2 : 10.5 dB */
745 50, 50, 127, /* LNA3 : 5.0 dB */
746 125, 175, 127, /* LNA4 : 12.5 dB */
747 0, 0, 127, /* CBAND : 0.0 dB */
750 static const u16 rf_ramp_cband_broadmatching[] = /* for p1G only */
752 314, /* Calibrated at 200MHz order has been changed g4-g3-g2-g1 */
753 84, 314, 127, /* LNA1 */
754 80, 230, 255, /* LNA2 */
755 80, 150, 127, /* LNA3 It was measured 12dB, do not lock if 120 */
756 70, 70, 127, /* LNA4 */
757 0, 0, 127, /* CBAND */
760 static const u16 rf_ramp_cband[] = {
761 332, /* max RF gain in 10th of dB */
762 132, 252, 127, /* LNA1, dB */
763 80, 332, 255, /* LNA2, dB */
764 0, 0, 127, /* LNA3, dB */
765 0, 0, 127, /* LNA4, dB */
766 120, 120, 127, /* LT1 CBAND */
769 static const u16 rf_ramp_pwm_vhf[] = {
770 404, /* max RF gain in 10th of dB */
771 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
772 1011, /* ramp_max = maximum X used on the ramp */
773 (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */
774 (0 << 10) | 756, /* 0x2d, LNA 1 */
775 (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */
776 (0 << 10) | 1011, /* 0x2f, LNA 2 */
777 (16 << 10) | 290, /* 0x30, LNA 3 = 5dB */
778 (0 << 10) | 417, /* 0x31, LNA 3 */
779 (7 << 10) | 0, /* GAIN_4_1, LNA 4 = 12.5dB */
780 (0 << 10) | 290, /* GAIN_4_2, LNA 4 */
783 static const u16 rf_ramp_pwm_uhf[] = {
784 404, /* max RF gain in 10th of dB */
785 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
786 1011, /* ramp_max = maximum X used on the ramp */
787 (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */
788 (0 << 10) | 756, /* 0x2d, LNA 1 */
789 (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */
790 (0 << 10) | 1011, /* 0x2f, LNA 2 */
791 (16 << 10) | 0, /* 0x30, LNA 3 = 5dB */
792 (0 << 10) | 127, /* 0x31, LNA 3 */
793 (7 << 10) | 127, /* GAIN_4_1, LNA 4 = 12.5dB */
794 (0 << 10) | 417, /* GAIN_4_2, LNA 4 */
797 static const u16 bb_ramp_boost[] = {
798 550, /* max BB gain in 10th of dB */
799 260, 260, 26, /* BB1, 26dB */
800 290, 550, 29, /* BB2, 29dB */
803 static const u16 bb_ramp_pwm_normal[] = {
804 500, /* max RF gain in 10th of dB */
805 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x34 */
806 400,
807 (2 << 9) | 0, /* 0x35 = 21dB */
808 (0 << 9) | 168, /* 0x36 */
809 (2 << 9) | 168, /* 0x37 = 29dB */
810 (0 << 9) | 400, /* 0x38 */
813 struct slope {
814 s16 range;
815 s16 slope;
817 static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
819 u8 i;
820 u16 rest;
821 u16 ret = 0;
822 for (i = 0; i < num; i++) {
823 if (val > slopes[i].range)
824 rest = slopes[i].range;
825 else
826 rest = val;
827 ret += (rest * slopes[i].slope) / slopes[i].range;
828 val -= rest;
830 return ret;
833 static const struct slope dib0090_wbd_slopes[3] = {
834 {66, 120}, /* -64,-52: offset - 65 */
835 {600, 170}, /* -52,-35: 65 - 665 */
836 {170, 250}, /* -45,-10: 665 - 835 */
839 static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
841 wbd &= 0x3ff;
842 if (wbd < state->wbd_offset)
843 wbd = 0;
844 else
845 wbd -= state->wbd_offset;
846 /* -64dB is the floor */
847 return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd);
850 static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
852 u16 offset = 250;
854 /* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */
856 if (state->current_band == BAND_VHF)
857 offset = 650;
858 #ifndef FIRMWARE_FIREFLY
859 if (state->current_band == BAND_VHF)
860 offset = state->config->wbd_vhf_offset;
861 if (state->current_band == BAND_CBAND)
862 offset = state->config->wbd_cband_offset;
863 #endif
865 state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
866 dprintk("wbd-target: %d dB", (u32) state->wbd_target);
869 static const int gain_reg_addr[4] = {
870 0x08, 0x0a, 0x0f, 0x01
873 static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
875 u16 rf, bb, ref;
876 u16 i, v, gain_reg[4] = { 0 }, gain;
877 const u16 *g;
879 if (top_delta < -511)
880 top_delta = -511;
881 if (top_delta > 511)
882 top_delta = 511;
884 if (force) {
885 top_delta *= (1 << WBD_ALPHA);
886 gain_delta *= (1 << GAIN_ALPHA);
889 if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit)) /* overflow */
890 state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
891 else
892 state->rf_gain_limit += top_delta;
894 if (state->rf_gain_limit < 0) /*underflow */
895 state->rf_gain_limit = 0;
897 /* use gain as a temporary variable and correct current_gain */
898 gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA;
899 if (gain_delta >= ((s16) gain - state->current_gain)) /* overflow */
900 state->current_gain = gain;
901 else
902 state->current_gain += gain_delta;
903 /* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */
904 if (state->current_gain < 0)
905 state->current_gain = 0;
907 /* now split total gain to rf and bb gain */
908 gain = state->current_gain >> GAIN_ALPHA;
910 /* requested gain is bigger than rf gain limit - ACI/WBD adjustment */
911 if (gain > (state->rf_gain_limit >> WBD_ALPHA)) {
912 rf = state->rf_gain_limit >> WBD_ALPHA;
913 bb = gain - rf;
914 if (bb > state->bb_ramp[0])
915 bb = state->bb_ramp[0];
916 } else { /* high signal level -> all gains put on RF */
917 rf = gain;
918 bb = 0;
921 state->gain[0] = rf;
922 state->gain[1] = bb;
924 /* software ramp */
925 /* Start with RF gains */
926 g = state->rf_ramp + 1; /* point on RF LNA1 max gain */
927 ref = rf;
928 for (i = 0; i < 7; i++) { /* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */
929 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 */
930 v = 0; /* force the gain to write for the current amp to be null */
931 else if (ref >= g[1]) /* Gain to set is higher than the high working point of this amp */
932 v = g[2]; /* force this amp to be full gain */
933 else /* compute the value to set to this amp because we are somewhere in his range */
934 v = ((ref - (g[1] - g[0])) * g[2]) / g[0];
936 if (i == 0) /* LNA 1 reg mapping */
937 gain_reg[0] = v;
938 else if (i == 1) /* LNA 2 reg mapping */
939 gain_reg[0] |= v << 7;
940 else if (i == 2) /* LNA 3 reg mapping */
941 gain_reg[1] = v;
942 else if (i == 3) /* LNA 4 reg mapping */
943 gain_reg[1] |= v << 7;
944 else if (i == 4) /* CBAND LNA reg mapping */
945 gain_reg[2] = v | state->rf_lt_def;
946 else if (i == 5) /* BB gain 1 reg mapping */
947 gain_reg[3] = v << 3;
948 else if (i == 6) /* BB gain 2 reg mapping */
949 gain_reg[3] |= v << 8;
951 g += 3; /* go to next gain bloc */
953 /* When RF is finished, start with BB */
954 if (i == 4) {
955 g = state->bb_ramp + 1; /* point on BB gain 1 max gain */
956 ref = bb;
959 gain_reg[3] |= state->bb_1_def;
960 gain_reg[3] |= ((bb % 10) * 100) / 125;
962 #ifdef DEBUG_AGC
963 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", rf, bb, rf + bb,
964 gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]);
965 #endif
967 /* Write the amplifier regs */
968 for (i = 0; i < 4; i++) {
969 v = gain_reg[i];
970 if (force || state->gain_reg[i] != v) {
971 state->gain_reg[i] = v;
972 dib0090_write_reg(state, gain_reg_addr[i], v);
977 static void dib0090_set_boost(struct dib0090_state *state, int onoff)
979 state->bb_1_def &= 0xdfff;
980 state->bb_1_def |= onoff << 13;
983 static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
985 state->rf_ramp = cfg;
988 static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
990 state->rf_ramp = cfg;
992 dib0090_write_reg(state, 0x2a, 0xffff);
994 dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
996 dib0090_write_regs(state, 0x2c, cfg + 3, 6);
997 dib0090_write_regs(state, 0x3e, cfg + 9, 2);
1000 static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
1002 state->bb_ramp = cfg;
1003 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
1006 static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
1008 state->bb_ramp = cfg;
1010 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
1012 dib0090_write_reg(state, 0x33, 0xffff);
1013 dprintk("total BB gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x33));
1014 dib0090_write_regs(state, 0x35, cfg + 3, 4);
1017 void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
1019 struct dib0090_state *state = fe->tuner_priv;
1020 /* reset the AGC */
1022 if (state->config->use_pwm_agc) {
1023 #ifdef CONFIG_BAND_SBAND
1024 if (state->current_band == BAND_SBAND) {
1025 dib0090_set_rframp_pwm(state, rf_ramp_pwm_sband);
1026 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_boost);
1027 } else
1028 #endif
1029 #ifdef CONFIG_BAND_CBAND
1030 if (state->current_band == BAND_CBAND) {
1031 if (state->identity.in_soc) {
1032 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
1033 if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1034 dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_8090);
1035 else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1036 dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090);
1037 } else {
1038 dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband);
1039 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
1041 } else
1042 #endif
1043 #ifdef CONFIG_BAND_VHF
1044 if (state->current_band == BAND_VHF) {
1045 if (state->identity.in_soc) {
1046 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
1047 } else {
1048 dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf);
1049 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
1051 } else
1052 #endif
1054 if (state->identity.in_soc) {
1055 if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1056 dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_8090);
1057 else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1058 dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_7090);
1059 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
1060 } else {
1061 dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf);
1062 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
1066 if (state->rf_ramp[0] != 0)
1067 dib0090_write_reg(state, 0x32, (3 << 11));
1068 else
1069 dib0090_write_reg(state, 0x32, (0 << 11));
1071 dib0090_write_reg(state, 0x04, 0x01);
1072 dib0090_write_reg(state, 0x39, (1 << 10));
1076 EXPORT_SYMBOL(dib0090_pwm_gain_reset);
1078 static u32 dib0090_get_slow_adc_val(struct dib0090_state *state)
1080 u16 adc_val = dib0090_read_reg(state, 0x1d);
1081 if (state->identity.in_soc)
1082 adc_val >>= 2;
1083 return adc_val;
1086 int dib0090_gain_control(struct dvb_frontend *fe)
1088 struct dib0090_state *state = fe->tuner_priv;
1089 enum frontend_tune_state *tune_state = &state->tune_state;
1090 int ret = 10;
1092 u16 wbd_val = 0;
1093 u8 apply_gain_immediatly = 1;
1094 s16 wbd_error = 0, adc_error = 0;
1096 if (*tune_state == CT_AGC_START) {
1097 state->agc_freeze = 0;
1098 dib0090_write_reg(state, 0x04, 0x0);
1100 #ifdef CONFIG_BAND_SBAND
1101 if (state->current_band == BAND_SBAND) {
1102 dib0090_set_rframp(state, rf_ramp_sband);
1103 dib0090_set_bbramp(state, bb_ramp_boost);
1104 } else
1105 #endif
1106 #ifdef CONFIG_BAND_VHF
1107 if (state->current_band == BAND_VHF && !state->identity.p1g) {
1108 dib0090_set_rframp(state, rf_ramp_vhf);
1109 dib0090_set_bbramp(state, bb_ramp_boost);
1110 } else
1111 #endif
1112 #ifdef CONFIG_BAND_CBAND
1113 if (state->current_band == BAND_CBAND && !state->identity.p1g) {
1114 dib0090_set_rframp(state, rf_ramp_cband);
1115 dib0090_set_bbramp(state, bb_ramp_boost);
1116 } else
1117 #endif
1118 if ((state->current_band == BAND_CBAND || state->current_band == BAND_VHF) && state->identity.p1g) {
1119 dib0090_set_rframp(state, rf_ramp_cband_broadmatching);
1120 dib0090_set_bbramp(state, bb_ramp_boost);
1121 } else {
1122 dib0090_set_rframp(state, rf_ramp_uhf);
1123 dib0090_set_bbramp(state, bb_ramp_boost);
1126 dib0090_write_reg(state, 0x32, 0);
1127 dib0090_write_reg(state, 0x39, 0);
1129 dib0090_wbd_target(state, state->current_rf);
1131 state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
1132 state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA;
1134 *tune_state = CT_AGC_STEP_0;
1135 } else if (!state->agc_freeze) {
1136 s16 wbd = 0, i, cnt;
1138 int adc;
1139 wbd_val = dib0090_get_slow_adc_val(state);
1141 if (*tune_state == CT_AGC_STEP_0)
1142 cnt = 5;
1143 else
1144 cnt = 1;
1146 for (i = 0; i < cnt; i++) {
1147 wbd_val = dib0090_get_slow_adc_val(state);
1148 wbd += dib0090_wbd_to_db(state, wbd_val);
1150 wbd /= cnt;
1151 wbd_error = state->wbd_target - wbd;
1153 if (*tune_state == CT_AGC_STEP_0) {
1154 if (wbd_error < 0 && state->rf_gain_limit > 0 && !state->identity.p1g) {
1155 #ifdef CONFIG_BAND_CBAND
1156 /* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */
1157 u8 ltg2 = (state->rf_lt_def >> 10) & 0x7;
1158 if (state->current_band == BAND_CBAND && ltg2) {
1159 ltg2 >>= 1;
1160 state->rf_lt_def &= ltg2 << 10; /* reduce in 3 steps from 7 to 0 */
1162 #endif
1163 } else {
1164 state->agc_step = 0;
1165 *tune_state = CT_AGC_STEP_1;
1167 } else {
1168 /* calc the adc power */
1169 adc = state->config->get_adc_power(fe);
1170 adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21; /* included in [0:-700] */
1172 adc_error = (s16) (((s32) ADC_TARGET) - adc);
1173 #ifdef CONFIG_STANDARD_DAB
1174 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)
1175 adc_error -= 10;
1176 #endif
1177 #ifdef CONFIG_STANDARD_DVBT
1178 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT &&
1179 (state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
1180 adc_error += 60;
1181 #endif
1182 #ifdef CONFIG_SYS_ISDBT
1183 if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count >
1186 ((state->fe->dtv_property_cache.layer[0].modulation ==
1187 QAM_64)
1188 || (state->fe->dtv_property_cache.
1189 layer[0].modulation == QAM_16)))
1191 ((state->fe->dtv_property_cache.layer[1].segment_count >
1194 ((state->fe->dtv_property_cache.layer[1].modulation ==
1195 QAM_64)
1196 || (state->fe->dtv_property_cache.
1197 layer[1].modulation == QAM_16)))
1199 ((state->fe->dtv_property_cache.layer[2].segment_count >
1202 ((state->fe->dtv_property_cache.layer[2].modulation ==
1203 QAM_64)
1204 || (state->fe->dtv_property_cache.
1205 layer[2].modulation == QAM_16)))
1208 adc_error += 60;
1209 #endif
1211 if (*tune_state == CT_AGC_STEP_1) { /* quickly go to the correct range of the ADC power */
1212 if (ABS(adc_error) < 50 || state->agc_step++ > 5) {
1214 #ifdef CONFIG_STANDARD_DAB
1215 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) {
1216 dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63)); /* cap value = 63 : narrow BB filter : Fc = 1.8MHz */
1217 dib0090_write_reg(state, 0x04, 0x0);
1218 } else
1219 #endif
1221 dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32));
1222 dib0090_write_reg(state, 0x04, 0x01); /*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */
1225 *tune_state = CT_AGC_STOP;
1227 } else {
1228 /* everything higher than or equal to CT_AGC_STOP means tracking */
1229 ret = 100; /* 10ms interval */
1230 apply_gain_immediatly = 0;
1233 #ifdef DEBUG_AGC
1234 dprintk
1235 ("tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
1236 (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
1237 (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
1238 #endif
1241 /* apply gain */
1242 if (!state->agc_freeze)
1243 dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
1244 return ret;
1247 EXPORT_SYMBOL(dib0090_gain_control);
1249 void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
1251 struct dib0090_state *state = fe->tuner_priv;
1252 if (rf)
1253 *rf = state->gain[0];
1254 if (bb)
1255 *bb = state->gain[1];
1256 if (rf_gain_limit)
1257 *rf_gain_limit = state->rf_gain_limit;
1258 if (rflt)
1259 *rflt = (state->rf_lt_def >> 10) & 0x7;
1262 EXPORT_SYMBOL(dib0090_get_current_gain);
1264 u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
1266 struct dib0090_state *state = fe->tuner_priv;
1267 u32 f_MHz = state->fe->dtv_property_cache.frequency / 1000000;
1268 s32 current_temp = state->temperature;
1269 s32 wbd_thot, wbd_tcold;
1270 const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1272 while (f_MHz > wbd->max_freq)
1273 wbd++;
1275 dprintk("using wbd-table-entry with max freq %d", wbd->max_freq);
1277 if (current_temp < 0)
1278 current_temp = 0;
1279 if (current_temp > 128)
1280 current_temp = 128;
1282 state->wbdmux &= ~(7 << 13);
1283 if (wbd->wbd_gain != 0)
1284 state->wbdmux |= (wbd->wbd_gain << 13);
1285 else
1286 state->wbdmux |= (4 << 13);
1288 dib0090_write_reg(state, 0x10, state->wbdmux);
1290 wbd_thot = wbd->offset_hot - (((u32) wbd->slope_hot * f_MHz) >> 6);
1291 wbd_tcold = wbd->offset_cold - (((u32) wbd->slope_cold * f_MHz) >> 6);
1293 wbd_tcold += ((wbd_thot - wbd_tcold) * current_temp) >> 7;
1295 state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + wbd_tcold);
1296 dprintk("wbd-target: %d dB", (u32) state->wbd_target);
1297 dprintk("wbd offset applied is %d", wbd_tcold);
1299 return state->wbd_offset + wbd_tcold;
1302 EXPORT_SYMBOL(dib0090_get_wbd_offset);
1304 static const u16 dib0090_defaults[] = {
1306 25, 0x01,
1307 0x0000,
1308 0x99a0,
1309 0x6008,
1310 0x0000,
1311 0x8bcb,
1312 0x0000,
1313 0x0405,
1314 0x0000,
1315 0x0000,
1316 0x0000,
1317 0xb802,
1318 0x0300,
1319 0x2d12,
1320 0xbac0,
1321 0x7c00,
1322 0xdbb9,
1323 0x0954,
1324 0x0743,
1325 0x8000,
1326 0x0001,
1327 0x0040,
1328 0x0100,
1329 0x0000,
1330 0xe910,
1331 0x149e,
1333 1, 0x1c,
1334 0xff2d,
1336 1, 0x39,
1337 0x0000,
1339 2, 0x1e,
1340 0x07FF,
1341 0x0007,
1343 1, 0x24,
1344 EN_UHF | EN_CRYSTAL,
1346 2, 0x3c,
1347 0x3ff,
1348 0x111,
1352 static const u16 dib0090_p1g_additionnal_defaults[] = {
1353 1, 0x05,
1354 0xabcd,
1356 1, 0x11,
1357 0x00b4,
1359 1, 0x1c,
1360 0xfffd,
1362 1, 0x40,
1363 0x108,
1367 static void dib0090_set_default_config(struct dib0090_state *state, const u16 * n)
1369 u16 l, r;
1371 l = pgm_read_word(n++);
1372 while (l) {
1373 r = pgm_read_word(n++);
1374 do {
1375 dib0090_write_reg(state, r, pgm_read_word(n++));
1376 r++;
1377 } while (--l);
1378 l = pgm_read_word(n++);
1382 #define CAP_VALUE_MIN (u8) 9
1383 #define CAP_VALUE_MAX (u8) 40
1384 #define HR_MIN (u8) 25
1385 #define HR_MAX (u8) 40
1386 #define POLY_MIN (u8) 0
1387 #define POLY_MAX (u8) 8
1389 void dib0090_set_EFUSE(struct dib0090_state *state)
1391 u8 c, h, n;
1392 u16 e2, e4;
1393 u16 cal;
1395 e2 = dib0090_read_reg(state, 0x26);
1396 e4 = dib0090_read_reg(state, 0x28);
1398 if ((state->identity.version == P1D_E_F) ||
1399 (state->identity.version == P1G) || (e2 == 0xffff)) {
1401 dib0090_write_reg(state, 0x22, 0x10);
1402 cal = (dib0090_read_reg(state, 0x22) >> 6) & 0x3ff;
1404 if ((cal < 670) || (cal == 1023))
1405 cal = 850;
1406 n = 165 - ((cal * 10)>>6) ;
1407 e2 = e4 = (3<<12) | (34<<6) | (n);
1410 if (e2 != e4)
1411 e2 &= e4; /* Remove the redundancy */
1413 if (e2 != 0xffff) {
1414 c = e2 & 0x3f;
1415 n = (e2 >> 12) & 0xf;
1416 h = (e2 >> 6) & 0x3f;
1418 if ((c >= CAP_VALUE_MAX) || (c <= CAP_VALUE_MIN))
1419 c = 32;
1420 if ((h >= HR_MAX) || (h <= HR_MIN))
1421 h = 34;
1422 if ((n >= POLY_MAX) || (n <= POLY_MIN))
1423 n = 3;
1425 dib0090_write_reg(state, 0x13, (h << 10)) ;
1426 e2 = (n<<11) | ((h>>2)<<6) | (c);
1427 dib0090_write_reg(state, 0x2, e2) ; /* Load the BB_2 */
1431 static int dib0090_reset(struct dvb_frontend *fe)
1433 struct dib0090_state *state = fe->tuner_priv;
1435 dib0090_reset_digital(fe, state->config);
1436 if (dib0090_identify(fe) < 0)
1437 return -EIO;
1439 #ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
1440 if (!(state->identity.version & 0x1)) /* it is P1B - reset is already done */
1441 return 0;
1442 #endif
1444 if (!state->identity.in_soc) {
1445 if ((dib0090_read_reg(state, 0x1a) >> 5) & 0x2)
1446 dib0090_write_reg(state, 0x1b, (EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1447 else
1448 dib0090_write_reg(state, 0x1b, (EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1451 dib0090_set_default_config(state, dib0090_defaults);
1453 if (state->identity.in_soc)
1454 dib0090_write_reg(state, 0x18, 0x2910); /* charge pump current = 0 */
1456 if (state->identity.p1g)
1457 dib0090_set_default_config(state, dib0090_p1g_additionnal_defaults);
1459 /* Update the efuse : Only available for KROSUS > P1C and SOC as well*/
1460 if (((state->identity.version & 0x1f) >= P1D_E_F) || (state->identity.in_soc))
1461 dib0090_set_EFUSE(state);
1463 /* Congigure in function of the crystal */
1464 if (state->config->io.clock_khz >= 24000)
1465 dib0090_write_reg(state, 0x14, 1);
1466 else
1467 dib0090_write_reg(state, 0x14, 2);
1468 dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
1470 state->calibrate = DC_CAL | WBD_CAL | TEMP_CAL; /* enable iq-offset-calibration and wbd-calibration when tuning next time */
1472 return 0;
1475 #define steps(u) (((u) > 15) ? ((u)-16) : (u))
1476 #define INTERN_WAIT 10
1477 static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1479 int ret = INTERN_WAIT * 10;
1481 switch (*tune_state) {
1482 case CT_TUNER_STEP_2:
1483 /* Turns to positive */
1484 dib0090_write_reg(state, 0x1f, 0x7);
1485 *tune_state = CT_TUNER_STEP_3;
1486 break;
1488 case CT_TUNER_STEP_3:
1489 state->adc_diff = dib0090_read_reg(state, 0x1d);
1491 /* Turns to negative */
1492 dib0090_write_reg(state, 0x1f, 0x4);
1493 *tune_state = CT_TUNER_STEP_4;
1494 break;
1496 case CT_TUNER_STEP_4:
1497 state->adc_diff -= dib0090_read_reg(state, 0x1d);
1498 *tune_state = CT_TUNER_STEP_5;
1499 ret = 0;
1500 break;
1502 default:
1503 break;
1506 return ret;
1509 struct dc_calibration {
1510 u8 addr;
1511 u8 offset;
1512 u8 pga:1;
1513 u16 bb1;
1514 u8 i:1;
1517 static const struct dc_calibration dc_table[] = {
1518 /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
1519 {0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1},
1520 {0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0},
1521 /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
1522 {0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1},
1523 {0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0},
1524 {0},
1527 static const struct dc_calibration dc_p1g_table[] = {
1528 /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
1529 /* addr ; trim reg offset ; pga ; CTRL_BB1 value ; i or q */
1530 {0x06, 5, 1, (1 << 13) | (0 << 8) | (15 << 3), 1},
1531 {0x07, 11, 1, (1 << 13) | (0 << 8) | (15 << 3), 0},
1532 /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
1533 {0x06, 0, 0, (1 << 13) | (29 << 8) | (15 << 3), 1},
1534 {0x06, 10, 0, (1 << 13) | (29 << 8) | (15 << 3), 0},
1535 {0},
1538 static void dib0090_set_trim(struct dib0090_state *state)
1540 u16 *val;
1542 if (state->dc->addr == 0x07)
1543 val = &state->bb7;
1544 else
1545 val = &state->bb6;
1547 *val &= ~(0x1f << state->dc->offset);
1548 *val |= state->step << state->dc->offset;
1550 dib0090_write_reg(state, state->dc->addr, *val);
1553 static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1555 int ret = 0;
1556 u16 reg;
1558 switch (*tune_state) {
1559 case CT_TUNER_START:
1560 dprintk("Start DC offset calibration");
1562 /* force vcm2 = 0.8V */
1563 state->bb6 = 0;
1564 state->bb7 = 0x040d;
1566 /* the LNA AND LO are off */
1567 reg = dib0090_read_reg(state, 0x24) & 0x0ffb; /* shutdown lna and lo */
1568 dib0090_write_reg(state, 0x24, reg);
1570 state->wbdmux = dib0090_read_reg(state, 0x10);
1571 dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x7 << 3) | 0x3);
1572 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
1574 state->dc = dc_table;
1576 if (state->identity.p1g)
1577 state->dc = dc_p1g_table;
1578 *tune_state = CT_TUNER_STEP_0;
1580 /* fall through */
1582 case CT_TUNER_STEP_0:
1583 dprintk("Sart/continue DC calibration for %s path", (state->dc->i == 1) ? "I" : "Q");
1584 dib0090_write_reg(state, 0x01, state->dc->bb1);
1585 dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
1587 state->step = 0;
1588 state->min_adc_diff = 1023;
1589 *tune_state = CT_TUNER_STEP_1;
1590 ret = 50;
1591 break;
1593 case CT_TUNER_STEP_1:
1594 dib0090_set_trim(state);
1595 *tune_state = CT_TUNER_STEP_2;
1596 break;
1598 case CT_TUNER_STEP_2:
1599 case CT_TUNER_STEP_3:
1600 case CT_TUNER_STEP_4:
1601 ret = dib0090_get_offset(state, tune_state);
1602 break;
1604 case CT_TUNER_STEP_5: /* found an offset */
1605 dprintk("adc_diff = %d, current step= %d", (u32) state->adc_diff, state->step);
1606 if (state->step == 0 && state->adc_diff < 0) {
1607 state->min_adc_diff = -1023;
1608 dprintk("Change of sign of the minimum adc diff");
1611 dprintk("adc_diff = %d, min_adc_diff = %d current_step = %d", state->adc_diff, state->min_adc_diff, state->step);
1613 /* first turn for this frequency */
1614 if (state->step == 0) {
1615 if (state->dc->pga && state->adc_diff < 0)
1616 state->step = 0x10;
1617 if (state->dc->pga == 0 && state->adc_diff > 0)
1618 state->step = 0x10;
1621 /* Look for a change of Sign in the Adc_diff.min_adc_diff is used to STORE the setp N-1 */
1622 if ((state->adc_diff & 0x8000) == (state->min_adc_diff & 0x8000) && steps(state->step) < 15) {
1623 /* stop search when the delta the sign is changing and Steps =15 and Step=0 is force for continuance */
1624 state->step++;
1625 state->min_adc_diff = state->adc_diff;
1626 *tune_state = CT_TUNER_STEP_1;
1627 } else {
1628 /* the minimum was what we have seen in the step before */
1629 if (ABS(state->adc_diff) > ABS(state->min_adc_diff)) {
1630 dprintk("Since adc_diff N = %d > adc_diff step N-1 = %d, Come back one step", state->adc_diff, state->min_adc_diff);
1631 state->step--;
1634 dib0090_set_trim(state);
1635 dprintk("BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->dc->addr, state->adc_diff, state->step);
1637 state->dc++;
1638 if (state->dc->addr == 0) /* done */
1639 *tune_state = CT_TUNER_STEP_6;
1640 else
1641 *tune_state = CT_TUNER_STEP_0;
1644 break;
1646 case CT_TUNER_STEP_6:
1647 dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008);
1648 dib0090_write_reg(state, 0x1f, 0x7);
1649 *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1650 state->calibrate &= ~DC_CAL;
1651 default:
1652 break;
1654 return ret;
1657 static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1659 u8 wbd_gain;
1660 const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1662 switch (*tune_state) {
1663 case CT_TUNER_START:
1664 while (state->current_rf / 1000 > wbd->max_freq)
1665 wbd++;
1666 if (wbd->wbd_gain != 0)
1667 wbd_gain = wbd->wbd_gain;
1668 else {
1669 wbd_gain = 4;
1670 #if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
1671 if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND))
1672 wbd_gain = 2;
1673 #endif
1676 if (wbd_gain == state->wbd_calibration_gain) { /* the WBD calibration has already been done */
1677 *tune_state = CT_TUNER_START;
1678 state->calibrate &= ~WBD_CAL;
1679 return 0;
1682 dib0090_write_reg(state, 0x10, 0x1b81 | (1 << 10) | (wbd_gain << 13) | (1 << 3));
1684 dib0090_write_reg(state, 0x24, ((EN_UHF & 0x0fff) | (1 << 1)));
1685 *tune_state = CT_TUNER_STEP_0;
1686 state->wbd_calibration_gain = wbd_gain;
1687 return 90; /* wait for the WBDMUX to switch and for the ADC to sample */
1689 case CT_TUNER_STEP_0:
1690 state->wbd_offset = dib0090_get_slow_adc_val(state);
1691 dprintk("WBD calibration offset = %d", state->wbd_offset);
1692 *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1693 state->calibrate &= ~WBD_CAL;
1694 break;
1696 default:
1697 break;
1699 return 0;
1702 static void dib0090_set_bandwidth(struct dib0090_state *state)
1704 u16 tmp;
1706 if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000)
1707 tmp = (3 << 14);
1708 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000)
1709 tmp = (2 << 14);
1710 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000)
1711 tmp = (1 << 14);
1712 else
1713 tmp = (0 << 14);
1715 state->bb_1_def &= 0x3fff;
1716 state->bb_1_def |= tmp;
1718 dib0090_write_reg(state, 0x01, state->bb_1_def); /* be sure that we have the right bb-filter */
1720 dib0090_write_reg(state, 0x03, 0x6008); /* = 0x6008 : vcm3_trim = 1 ; filter2_gm1_trim = 8 ; filter2_cutoff_freq = 0 */
1721 dib0090_write_reg(state, 0x04, 0x1); /* 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast */
1722 if (state->identity.in_soc) {
1723 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 */
1724 } else {
1725 dib0090_write_reg(state, 0x02, (5 << 11) | (8 << 6) | (22 & 0x3f)); /* 22 = cap_value */
1726 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 */
1730 static const struct dib0090_pll dib0090_pll_table[] = {
1731 #ifdef CONFIG_BAND_CBAND
1732 {56000, 0, 9, 48, 6},
1733 {70000, 1, 9, 48, 6},
1734 {87000, 0, 8, 32, 4},
1735 {105000, 1, 8, 32, 4},
1736 {115000, 0, 7, 24, 6},
1737 {140000, 1, 7, 24, 6},
1738 {170000, 0, 6, 16, 4},
1739 #endif
1740 #ifdef CONFIG_BAND_VHF
1741 {200000, 1, 6, 16, 4},
1742 {230000, 0, 5, 12, 6},
1743 {280000, 1, 5, 12, 6},
1744 {340000, 0, 4, 8, 4},
1745 {380000, 1, 4, 8, 4},
1746 {450000, 0, 3, 6, 6},
1747 #endif
1748 #ifdef CONFIG_BAND_UHF
1749 {580000, 1, 3, 6, 6},
1750 {700000, 0, 2, 4, 4},
1751 {860000, 1, 2, 4, 4},
1752 #endif
1753 #ifdef CONFIG_BAND_LBAND
1754 {1800000, 1, 0, 2, 4},
1755 #endif
1756 #ifdef CONFIG_BAND_SBAND
1757 {2900000, 0, 14, 1, 4},
1758 #endif
1761 static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
1763 #ifdef CONFIG_BAND_CBAND
1764 {184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1765 {227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1766 {380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1767 #endif
1768 #ifdef CONFIG_BAND_UHF
1769 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1770 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1771 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1772 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1773 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1774 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1775 #endif
1776 #ifdef CONFIG_BAND_LBAND
1777 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1778 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1779 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1780 #endif
1781 #ifdef CONFIG_BAND_SBAND
1782 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1783 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1784 #endif
1787 static const struct dib0090_tuning dib0090_tuning_table[] = {
1789 #ifdef CONFIG_BAND_CBAND
1790 {170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1791 #endif
1792 #ifdef CONFIG_BAND_VHF
1793 {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1794 {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1795 {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1796 #endif
1797 #ifdef CONFIG_BAND_UHF
1798 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1799 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1800 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1801 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1802 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1803 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1804 #endif
1805 #ifdef CONFIG_BAND_LBAND
1806 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1807 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1808 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1809 #endif
1810 #ifdef CONFIG_BAND_SBAND
1811 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1812 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1813 #endif
1816 static const struct dib0090_tuning dib0090_p1g_tuning_table[] = {
1817 #ifdef CONFIG_BAND_CBAND
1818 {170000, 4, 1, 0x820f, 0x300, 0x2d22, 0x82cb, EN_CAB},
1819 #endif
1820 #ifdef CONFIG_BAND_VHF
1821 {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1822 {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1823 {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1824 #endif
1825 #ifdef CONFIG_BAND_UHF
1826 {510000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1827 {540000, 2, 1, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1828 {600000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1829 {630000, 2, 4, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1830 {680000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1831 {720000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1832 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1833 #endif
1834 #ifdef CONFIG_BAND_LBAND
1835 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1836 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1837 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1838 #endif
1839 #ifdef CONFIG_BAND_SBAND
1840 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1841 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1842 #endif
1845 static const struct dib0090_pll dib0090_p1g_pll_table[] = {
1846 #ifdef CONFIG_BAND_CBAND
1847 {57000, 0, 11, 48, 6},
1848 {70000, 1, 11, 48, 6},
1849 {86000, 0, 10, 32, 4},
1850 {105000, 1, 10, 32, 4},
1851 {115000, 0, 9, 24, 6},
1852 {140000, 1, 9, 24, 6},
1853 {170000, 0, 8, 16, 4},
1854 #endif
1855 #ifdef CONFIG_BAND_VHF
1856 {200000, 1, 8, 16, 4},
1857 {230000, 0, 7, 12, 6},
1858 {280000, 1, 7, 12, 6},
1859 {340000, 0, 6, 8, 4},
1860 {380000, 1, 6, 8, 4},
1861 {455000, 0, 5, 6, 6},
1862 #endif
1863 #ifdef CONFIG_BAND_UHF
1864 {580000, 1, 5, 6, 6},
1865 {680000, 0, 4, 4, 4},
1866 {860000, 1, 4, 4, 4},
1867 #endif
1868 #ifdef CONFIG_BAND_LBAND
1869 {1800000, 1, 2, 2, 4},
1870 #endif
1871 #ifdef CONFIG_BAND_SBAND
1872 {2900000, 0, 1, 1, 6},
1873 #endif
1876 static const struct dib0090_tuning dib0090_p1g_tuning_table_fm_vhf_on_cband[] = {
1877 #ifdef CONFIG_BAND_CBAND
1878 {184000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
1879 {227000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
1880 {380000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
1881 #endif
1882 #ifdef CONFIG_BAND_UHF
1883 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1884 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1885 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1886 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1887 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1888 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1889 #endif
1890 #ifdef CONFIG_BAND_LBAND
1891 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1892 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1893 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1894 #endif
1895 #ifdef CONFIG_BAND_SBAND
1896 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1897 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1898 #endif
1901 static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = {
1902 #ifdef CONFIG_BAND_CBAND
1903 {300000, 4, 3, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
1904 {380000, 4, 10, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
1905 {570000, 4, 10, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
1906 {858000, 4, 5, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
1907 #endif
1910 static int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1912 int ret = 0;
1913 u16 lo4 = 0xe900;
1915 s16 adc_target;
1916 u16 adc;
1917 s8 step_sign;
1918 u8 force_soft_search = 0;
1920 if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1921 force_soft_search = 1;
1923 if (*tune_state == CT_TUNER_START) {
1924 dprintk("Start Captrim search : %s", (force_soft_search == 1) ? "FORCE SOFT SEARCH" : "AUTO");
1925 dib0090_write_reg(state, 0x10, 0x2B1);
1926 dib0090_write_reg(state, 0x1e, 0x0032);
1928 if (!state->tuner_is_tuned) {
1929 /* prepare a complete captrim */
1930 if (!state->identity.p1g || force_soft_search)
1931 state->step = state->captrim = state->fcaptrim = 64;
1933 state->current_rf = state->rf_request;
1934 } else { /* we are already tuned to this frequency - the configuration is correct */
1935 if (!state->identity.p1g || force_soft_search) {
1936 /* do a minimal captrim even if the frequency has not changed */
1937 state->step = 4;
1938 state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
1941 state->adc_diff = 3000;
1942 *tune_state = CT_TUNER_STEP_0;
1944 } else if (*tune_state == CT_TUNER_STEP_0) {
1945 if (state->identity.p1g && !force_soft_search) {
1946 u8 ratio = 31;
1948 dib0090_write_reg(state, 0x40, (3 << 7) | (ratio << 2) | (1 << 1) | 1);
1949 dib0090_read_reg(state, 0x40);
1950 ret = 50;
1951 } else {
1952 state->step /= 2;
1953 dib0090_write_reg(state, 0x18, lo4 | state->captrim);
1955 if (state->identity.in_soc)
1956 ret = 25;
1958 *tune_state = CT_TUNER_STEP_1;
1960 } else if (*tune_state == CT_TUNER_STEP_1) {
1961 if (state->identity.p1g && !force_soft_search) {
1962 dib0090_write_reg(state, 0x40, 0x18c | (0 << 1) | 0);
1963 dib0090_read_reg(state, 0x40);
1965 state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7F;
1966 dprintk("***Final Captrim= 0x%x", state->fcaptrim);
1967 *tune_state = CT_TUNER_STEP_3;
1969 } else {
1970 /* MERGE for all krosus before P1G */
1971 adc = dib0090_get_slow_adc_val(state);
1972 dprintk("CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) state->captrim, (u32) adc, (u32) (adc) * (u32) 1800 / (u32) 1024);
1974 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 !!! */
1975 adc_target = 200;
1976 } else
1977 adc_target = 400;
1979 if (adc >= adc_target) {
1980 adc -= adc_target;
1981 step_sign = -1;
1982 } else {
1983 adc = adc_target - adc;
1984 step_sign = 1;
1987 if (adc < state->adc_diff) {
1988 dprintk("CAPTRIM=%d is closer to target (%d/%d)", (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
1989 state->adc_diff = adc;
1990 state->fcaptrim = state->captrim;
1993 state->captrim += step_sign * state->step;
1994 if (state->step >= 1)
1995 *tune_state = CT_TUNER_STEP_0;
1996 else
1997 *tune_state = CT_TUNER_STEP_2;
1999 ret = 25;
2001 } else if (*tune_state == CT_TUNER_STEP_2) { /* this step is only used by krosus < P1G */
2002 /*write the final cptrim config */
2003 dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
2005 *tune_state = CT_TUNER_STEP_3;
2007 } else if (*tune_state == CT_TUNER_STEP_3) {
2008 state->calibrate &= ~CAPTRIM_CAL;
2009 *tune_state = CT_TUNER_STEP_0;
2012 return ret;
2015 static int dib0090_get_temperature(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2017 int ret = 15;
2018 s16 val;
2020 switch (*tune_state) {
2021 case CT_TUNER_START:
2022 state->wbdmux = dib0090_read_reg(state, 0x10);
2023 dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x8 << 3));
2025 state->bias = dib0090_read_reg(state, 0x13);
2026 dib0090_write_reg(state, 0x13, state->bias | (0x3 << 8));
2028 *tune_state = CT_TUNER_STEP_0;
2029 /* wait for the WBDMUX to switch and for the ADC to sample */
2030 break;
2032 case CT_TUNER_STEP_0:
2033 state->adc_diff = dib0090_get_slow_adc_val(state);
2034 dib0090_write_reg(state, 0x13, (state->bias & ~(0x3 << 8)) | (0x2 << 8));
2035 *tune_state = CT_TUNER_STEP_1;
2036 break;
2038 case CT_TUNER_STEP_1:
2039 val = dib0090_get_slow_adc_val(state);
2040 state->temperature = ((s16) ((val - state->adc_diff) * 180) >> 8) + 55;
2042 dprintk("temperature: %d C", state->temperature - 30);
2044 *tune_state = CT_TUNER_STEP_2;
2045 break;
2047 case CT_TUNER_STEP_2:
2048 dib0090_write_reg(state, 0x13, state->bias);
2049 dib0090_write_reg(state, 0x10, state->wbdmux); /* write back original WBDMUX */
2051 *tune_state = CT_TUNER_START;
2052 state->calibrate &= ~TEMP_CAL;
2053 if (state->config->analog_output == 0)
2054 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2056 break;
2058 default:
2059 ret = 0;
2060 break;
2062 return ret;
2065 #define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */
2066 static int dib0090_tune(struct dvb_frontend *fe)
2068 struct dib0090_state *state = fe->tuner_priv;
2069 const struct dib0090_tuning *tune = state->current_tune_table_index;
2070 const struct dib0090_pll *pll = state->current_pll_table_index;
2071 enum frontend_tune_state *tune_state = &state->tune_state;
2073 u16 lo5, lo6, Den, tmp;
2074 u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
2075 int ret = 10; /* 1ms is the default delay most of the time */
2076 u8 c, i;
2078 /************************* VCO ***************************/
2079 /* Default values for FG */
2080 /* from these are needed : */
2081 /* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv */
2083 /* in any case we first need to do a calibration if needed */
2084 if (*tune_state == CT_TUNER_START) {
2085 /* deactivate DataTX before some calibrations */
2086 if (state->calibrate & (DC_CAL | TEMP_CAL | WBD_CAL))
2087 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
2088 else
2089 /* Activate DataTX in case a calibration has been done before */
2090 if (state->config->analog_output == 0)
2091 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2094 if (state->calibrate & DC_CAL)
2095 return dib0090_dc_offset_calibration(state, tune_state);
2096 else if (state->calibrate & WBD_CAL) {
2097 if (state->current_rf == 0)
2098 state->current_rf = state->fe->dtv_property_cache.frequency / 1000;
2099 return dib0090_wbd_calibration(state, tune_state);
2100 } else if (state->calibrate & TEMP_CAL)
2101 return dib0090_get_temperature(state, tune_state);
2102 else if (state->calibrate & CAPTRIM_CAL)
2103 return dib0090_captrim_search(state, tune_state);
2105 if (*tune_state == CT_TUNER_START) {
2106 /* 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 */
2107 if (state->config->use_pwm_agc && state->identity.in_soc) {
2108 tmp = dib0090_read_reg(state, 0x39);
2109 if ((tmp >> 10) & 0x1)
2110 dib0090_write_reg(state, 0x39, tmp & ~(1 << 10));
2113 state->current_band = (u8) BAND_OF_FREQUENCY(state->fe->dtv_property_cache.frequency / 1000);
2114 state->rf_request =
2115 state->fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
2116 BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->
2117 freq_offset_khz_vhf);
2119 /* in ISDB-T 1seg we shift tuning frequency */
2120 if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1
2121 && state->fe->dtv_property_cache.isdbt_partial_reception == 0)) {
2122 const struct dib0090_low_if_offset_table *LUT_offset = state->config->low_if;
2123 u8 found_offset = 0;
2124 u32 margin_khz = 100;
2126 if (LUT_offset != NULL) {
2127 while (LUT_offset->RF_freq != 0xffff) {
2128 if (((state->rf_request > (LUT_offset->RF_freq - margin_khz))
2129 && (state->rf_request < (LUT_offset->RF_freq + margin_khz)))
2130 && LUT_offset->std == state->fe->dtv_property_cache.delivery_system) {
2131 state->rf_request += LUT_offset->offset_khz;
2132 found_offset = 1;
2133 break;
2135 LUT_offset++;
2139 if (found_offset == 0)
2140 state->rf_request += 400;
2142 if (state->current_rf != state->rf_request || (state->current_standard != state->fe->dtv_property_cache.delivery_system)) {
2143 state->tuner_is_tuned = 0;
2144 state->current_rf = 0;
2145 state->current_standard = 0;
2147 tune = dib0090_tuning_table;
2148 if (state->identity.p1g)
2149 tune = dib0090_p1g_tuning_table;
2151 tmp = (state->identity.version >> 5) & 0x7;
2153 if (state->identity.in_soc) {
2154 if (state->config->force_cband_input) { /* Use the CBAND input for all band */
2155 if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF
2156 || state->current_band & BAND_UHF) {
2157 state->current_band = BAND_CBAND;
2158 tune = dib0090_tuning_table_cband_7090;
2160 } else { /* Use the CBAND input for all band under UHF */
2161 if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) {
2162 state->current_band = BAND_CBAND;
2163 tune = dib0090_tuning_table_cband_7090;
2166 } else
2167 if (tmp == 0x4 || tmp == 0x7) {
2168 /* CBAND tuner version for VHF */
2169 if (state->current_band == BAND_FM || state->current_band == BAND_CBAND || state->current_band == BAND_VHF) {
2170 state->current_band = BAND_CBAND; /* Force CBAND */
2172 tune = dib0090_tuning_table_fm_vhf_on_cband;
2173 if (state->identity.p1g)
2174 tune = dib0090_p1g_tuning_table_fm_vhf_on_cband;
2178 pll = dib0090_pll_table;
2179 if (state->identity.p1g)
2180 pll = dib0090_p1g_pll_table;
2182 /* Look for the interval */
2183 while (state->rf_request > tune->max_freq)
2184 tune++;
2185 while (state->rf_request > pll->max_freq)
2186 pll++;
2188 state->current_tune_table_index = tune;
2189 state->current_pll_table_index = pll;
2191 dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
2193 VCOF_kHz = (pll->hfdiv * state->rf_request) * 2;
2195 FREF = state->config->io.clock_khz;
2196 if (state->config->fref_clock_ratio != 0)
2197 FREF /= state->config->fref_clock_ratio;
2199 FBDiv = (VCOF_kHz / pll->topresc / FREF);
2200 Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
2202 if (Rest < LPF)
2203 Rest = 0;
2204 else if (Rest < 2 * LPF)
2205 Rest = 2 * LPF;
2206 else if (Rest > (FREF - LPF)) {
2207 Rest = 0;
2208 FBDiv += 1;
2209 } else if (Rest > (FREF - 2 * LPF))
2210 Rest = FREF - 2 * LPF;
2211 Rest = (Rest * 6528) / (FREF / 10);
2212 state->rest = Rest;
2214 /* external loop filter, otherwise:
2215 * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
2216 * lo6 = 0x0e34 */
2218 if (Rest == 0) {
2219 if (pll->vco_band)
2220 lo5 = 0x049f;
2221 else
2222 lo5 = 0x041f;
2223 } else {
2224 if (pll->vco_band)
2225 lo5 = 0x049e;
2226 else if (state->config->analog_output)
2227 lo5 = 0x041d;
2228 else
2229 lo5 = 0x041c;
2232 if (state->identity.p1g) { /* Bias is done automatically in P1G */
2233 if (state->identity.in_soc) {
2234 if (state->identity.version == SOC_8090_P1G_11R1)
2235 lo5 = 0x46f;
2236 else
2237 lo5 = 0x42f;
2238 } else
2239 lo5 = 0x42c;
2242 lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7); /* bit 15 is the split to the slave, we do not do it here */
2244 if (!state->config->io.pll_int_loop_filt) {
2245 if (state->identity.in_soc)
2246 lo6 = 0xff98;
2247 else if (state->identity.p1g || (Rest == 0))
2248 lo6 = 0xfff8;
2249 else
2250 lo6 = 0xff28;
2251 } else
2252 lo6 = (state->config->io.pll_int_loop_filt << 3);
2254 Den = 1;
2256 if (Rest > 0) {
2257 if (state->config->analog_output)
2258 lo6 |= (1 << 2) | 2;
2259 else {
2260 if (state->identity.in_soc)
2261 lo6 |= (1 << 2) | 2;
2262 else
2263 lo6 |= (1 << 2) | 2;
2265 Den = 255;
2267 dib0090_write_reg(state, 0x15, (u16) FBDiv);
2268 if (state->config->fref_clock_ratio != 0)
2269 dib0090_write_reg(state, 0x16, (Den << 8) | state->config->fref_clock_ratio);
2270 else
2271 dib0090_write_reg(state, 0x16, (Den << 8) | 1);
2272 dib0090_write_reg(state, 0x17, (u16) Rest);
2273 dib0090_write_reg(state, 0x19, lo5);
2274 dib0090_write_reg(state, 0x1c, lo6);
2276 lo6 = tune->tuner_enable;
2277 if (state->config->analog_output)
2278 lo6 = (lo6 & 0xff9f) | 0x2;
2280 dib0090_write_reg(state, 0x24, lo6 | EN_LO | state->config->use_pwm_agc * EN_CRYSTAL);
2284 state->current_rf = state->rf_request;
2285 state->current_standard = state->fe->dtv_property_cache.delivery_system;
2287 ret = 20;
2288 state->calibrate = CAPTRIM_CAL; /* captrim serach now */
2291 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 */
2292 const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
2294 while (state->current_rf / 1000 > wbd->max_freq)
2295 wbd++;
2297 dib0090_write_reg(state, 0x1e, 0x07ff);
2298 dprintk("Final Captrim: %d", (u32) state->fcaptrim);
2299 dprintk("HFDIV code: %d", (u32) pll->hfdiv_code);
2300 dprintk("VCO = %d", (u32) pll->vco_band);
2301 dprintk("VCOF in kHz: %d ((%d*%d) << 1))", (u32) ((pll->hfdiv * state->rf_request) * 2), (u32) pll->hfdiv, (u32) state->rf_request);
2302 dprintk("REFDIV: %d, FREF: %d", (u32) 1, (u32) state->config->io.clock_khz);
2303 dprintk("FBDIV: %d, Rest: %d", (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
2304 dprintk("Num: %d, Den: %d, SD: %d", (u32) dib0090_read_reg(state, 0x17), (u32) (dib0090_read_reg(state, 0x16) >> 8),
2305 (u32) dib0090_read_reg(state, 0x1c) & 0x3);
2307 #define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */
2308 c = 4;
2309 i = 3;
2311 if (wbd->wbd_gain != 0)
2312 c = wbd->wbd_gain;
2314 state->wbdmux = (c << 13) | (i << 11) | (WBD | (state->config->use_pwm_agc << 1));
2315 dib0090_write_reg(state, 0x10, state->wbdmux);
2317 if ((tune->tuner_enable == EN_CAB) && state->identity.p1g) {
2318 dprintk("P1G : The cable band is selected and lna_tune = %d", tune->lna_tune);
2319 dib0090_write_reg(state, 0x09, tune->lna_bias);
2320 dib0090_write_reg(state, 0x0b, 0xb800 | (tune->lna_tune << 6) | (tune->switch_trim));
2321 } else
2322 dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | tune->lna_bias);
2324 dib0090_write_reg(state, 0x0c, tune->v2i);
2325 dib0090_write_reg(state, 0x0d, tune->mix);
2326 dib0090_write_reg(state, 0x0e, tune->load);
2327 *tune_state = CT_TUNER_STEP_1;
2329 } else if (*tune_state == CT_TUNER_STEP_1) {
2330 /* initialize the lt gain register */
2331 state->rf_lt_def = 0x7c00;
2333 dib0090_set_bandwidth(state);
2334 state->tuner_is_tuned = 1;
2336 state->calibrate |= WBD_CAL;
2337 state->calibrate |= TEMP_CAL;
2338 *tune_state = CT_TUNER_STOP;
2339 } else
2340 ret = FE_CALLBACK_TIME_NEVER;
2341 return ret;
2344 static int dib0090_release(struct dvb_frontend *fe)
2346 kfree(fe->tuner_priv);
2347 fe->tuner_priv = NULL;
2348 return 0;
2351 enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
2353 struct dib0090_state *state = fe->tuner_priv;
2355 return state->tune_state;
2358 EXPORT_SYMBOL(dib0090_get_tune_state);
2360 int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
2362 struct dib0090_state *state = fe->tuner_priv;
2364 state->tune_state = tune_state;
2365 return 0;
2368 EXPORT_SYMBOL(dib0090_set_tune_state);
2370 static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
2372 struct dib0090_state *state = fe->tuner_priv;
2374 *frequency = 1000 * state->current_rf;
2375 return 0;
2378 static int dib0090_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
2380 struct dib0090_state *state = fe->tuner_priv;
2381 u32 ret;
2383 state->tune_state = CT_TUNER_START;
2385 do {
2386 ret = dib0090_tune(fe);
2387 if (ret != FE_CALLBACK_TIME_NEVER)
2388 msleep(ret / 10);
2389 else
2390 break;
2391 } while (state->tune_state != CT_TUNER_STOP);
2393 return 0;
2396 static const struct dvb_tuner_ops dib0090_ops = {
2397 .info = {
2398 .name = "DiBcom DiB0090",
2399 .frequency_min = 45000000,
2400 .frequency_max = 860000000,
2401 .frequency_step = 1000,
2403 .release = dib0090_release,
2405 .init = dib0090_wakeup,
2406 .sleep = dib0090_sleep,
2407 .set_params = dib0090_set_params,
2408 .get_frequency = dib0090_get_frequency,
2411 static const struct dvb_tuner_ops dib0090_fw_ops = {
2412 .info = {
2413 .name = "DiBcom DiB0090",
2414 .frequency_min = 45000000,
2415 .frequency_max = 860000000,
2416 .frequency_step = 1000,
2418 .release = dib0090_release,
2420 .init = NULL,
2421 .sleep = NULL,
2422 .set_params = NULL,
2423 .get_frequency = NULL,
2426 static const struct dib0090_wbd_slope dib0090_wbd_table_default[] = {
2427 {470, 0, 250, 0, 100, 4},
2428 {860, 51, 866, 21, 375, 4},
2429 {1700, 0, 800, 0, 850, 4},
2430 {2900, 0, 250, 0, 100, 6},
2431 {0xFFFF, 0, 0, 0, 0, 0},
2434 struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2436 struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
2437 if (st == NULL)
2438 return NULL;
2440 st->config = config;
2441 st->i2c = i2c;
2442 st->fe = fe;
2443 fe->tuner_priv = st;
2445 if (config->wbd == NULL)
2446 st->current_wbd_table = dib0090_wbd_table_default;
2447 else
2448 st->current_wbd_table = config->wbd;
2450 if (dib0090_reset(fe) != 0)
2451 goto free_mem;
2453 printk(KERN_INFO "DiB0090: successfully identified\n");
2454 memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
2456 return fe;
2457 free_mem:
2458 kfree(st);
2459 fe->tuner_priv = NULL;
2460 return NULL;
2463 EXPORT_SYMBOL(dib0090_register);
2465 struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2467 struct dib0090_fw_state *st = kzalloc(sizeof(struct dib0090_fw_state), GFP_KERNEL);
2468 if (st == NULL)
2469 return NULL;
2471 st->config = config;
2472 st->i2c = i2c;
2473 st->fe = fe;
2474 fe->tuner_priv = st;
2476 if (dib0090_fw_reset_digital(fe, st->config) != 0)
2477 goto free_mem;
2479 dprintk("DiB0090 FW: successfully identified");
2480 memcpy(&fe->ops.tuner_ops, &dib0090_fw_ops, sizeof(struct dvb_tuner_ops));
2482 return fe;
2483 free_mem:
2484 kfree(st);
2485 fe->tuner_priv = NULL;
2486 return NULL;
2488 EXPORT_SYMBOL(dib0090_fw_register);
2490 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
2491 MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>");
2492 MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
2493 MODULE_LICENSE("GPL");