DiBcom: protect the I2C bufer access
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / media / dvb / frontends / dib0090.c
blobb174d1c78583ee1001b8892626c80b00450f25fa
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>
30 #include <linux/mutex.h>
32 #include "dvb_frontend.h"
34 #include "dib0090.h"
35 #include "dibx000_common.h"
37 static int debug;
38 module_param(debug, int, 0644);
39 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
41 #define dprintk(args...) do { \
42 if (debug) { \
43 printk(KERN_DEBUG "DiB0090: "); \
44 printk(args); \
45 printk("\n"); \
46 } \
47 } while (0)
49 #define CONFIG_SYS_DVBT
50 #define CONFIG_SYS_ISDBT
51 #define CONFIG_BAND_CBAND
52 #define CONFIG_BAND_VHF
53 #define CONFIG_BAND_UHF
54 #define CONFIG_DIB0090_USE_PWM_AGC
56 #define EN_LNA0 0x8000
57 #define EN_LNA1 0x4000
58 #define EN_LNA2 0x2000
59 #define EN_LNA3 0x1000
60 #define EN_MIX0 0x0800
61 #define EN_MIX1 0x0400
62 #define EN_MIX2 0x0200
63 #define EN_MIX3 0x0100
64 #define EN_IQADC 0x0040
65 #define EN_PLL 0x0020
66 #define EN_TX 0x0010
67 #define EN_BB 0x0008
68 #define EN_LO 0x0004
69 #define EN_BIAS 0x0001
71 #define EN_IQANA 0x0002
72 #define EN_DIGCLK 0x0080 /* not in the 0x24 reg, only in 0x1b */
73 #define EN_CRYSTAL 0x0002
75 #define EN_UHF 0x22E9
76 #define EN_VHF 0x44E9
77 #define EN_LBD 0x11E9
78 #define EN_SBD 0x44E9
79 #define EN_CAB 0x88E9
81 /* Calibration defines */
82 #define DC_CAL 0x1
83 #define WBD_CAL 0x2
84 #define TEMP_CAL 0x4
85 #define CAPTRIM_CAL 0x8
87 #define KROSUS_PLL_LOCKED 0x800
88 #define KROSUS 0x2
90 /* Use those defines to identify SOC version */
91 #define SOC 0x02
92 #define SOC_7090_P1G_11R1 0x82
93 #define SOC_7090_P1G_21R1 0x8a
94 #define SOC_8090_P1G_11R1 0x86
95 #define SOC_8090_P1G_21R1 0x8e
97 /* else use thos ones to check */
98 #define P1A_B 0x0
99 #define P1C 0x1
100 #define P1D_E_F 0x3
101 #define P1G 0x7
102 #define P1G_21R2 0xf
104 #define MP001 0x1 /* Single 9090/8096 */
105 #define MP005 0x4 /* Single Sband */
106 #define MP008 0x6 /* Dual diversity VHF-UHF-LBAND */
107 #define MP009 0x7 /* Dual diversity 29098 CBAND-UHF-LBAND-SBAND */
109 #define pgm_read_word(w) (*w)
111 struct dc_calibration;
113 struct dib0090_tuning {
114 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
115 u8 switch_trim;
116 u8 lna_tune;
117 u16 lna_bias;
118 u16 v2i;
119 u16 mix;
120 u16 load;
121 u16 tuner_enable;
124 struct dib0090_pll {
125 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
126 u8 vco_band;
127 u8 hfdiv_code;
128 u8 hfdiv;
129 u8 topresc;
132 struct dib0090_identity {
133 u8 version;
134 u8 product;
135 u8 p1g;
136 u8 in_soc;
139 struct dib0090_state {
140 struct i2c_adapter *i2c;
141 struct dvb_frontend *fe;
142 const struct dib0090_config *config;
144 u8 current_band;
145 enum frontend_tune_state tune_state;
146 u32 current_rf;
148 u16 wbd_offset;
149 s16 wbd_target; /* in dB */
151 s16 rf_gain_limit; /* take-over-point: where to split between bb and rf gain */
152 s16 current_gain; /* keeps the currently programmed gain */
153 u8 agc_step; /* new binary search */
155 u16 gain[2]; /* for channel monitoring */
157 const u16 *rf_ramp;
158 const u16 *bb_ramp;
160 /* for the software AGC ramps */
161 u16 bb_1_def;
162 u16 rf_lt_def;
163 u16 gain_reg[4];
165 /* for the captrim/dc-offset search */
166 s8 step;
167 s16 adc_diff;
168 s16 min_adc_diff;
170 s8 captrim;
171 s8 fcaptrim;
173 const struct dc_calibration *dc;
174 u16 bb6, bb7;
176 const struct dib0090_tuning *current_tune_table_index;
177 const struct dib0090_pll *current_pll_table_index;
179 u8 tuner_is_tuned;
180 u8 agc_freeze;
182 struct dib0090_identity identity;
184 u32 rf_request;
185 u8 current_standard;
187 u8 calibrate;
188 u32 rest;
189 u16 bias;
190 s16 temperature;
192 u8 wbd_calibration_gain;
193 const struct dib0090_wbd_slope *current_wbd_table;
194 u16 wbdmux;
196 /* for the I2C transfer */
197 struct i2c_msg msg[2];
198 u8 i2c_write_buffer[3];
199 u8 i2c_read_buffer[2];
200 struct mutex i2c_buffer_lock;
203 struct dib0090_fw_state {
204 struct i2c_adapter *i2c;
205 struct dvb_frontend *fe;
206 struct dib0090_identity identity;
207 const struct dib0090_config *config;
209 /* for the I2C transfer */
210 struct i2c_msg msg;
211 u8 i2c_write_buffer[2];
212 u8 i2c_read_buffer[2];
213 struct mutex i2c_buffer_lock;
216 static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
218 u16 ret;
220 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
221 dprintk("could not acquire lock");
222 return 0;
225 state->i2c_write_buffer[0] = reg;
227 memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
228 state->msg[0].addr = state->config->i2c_address;
229 state->msg[0].flags = 0;
230 state->msg[0].buf = state->i2c_write_buffer;
231 state->msg[0].len = 1;
232 state->msg[1].addr = state->config->i2c_address;
233 state->msg[1].flags = I2C_M_RD;
234 state->msg[1].buf = state->i2c_read_buffer;
235 state->msg[1].len = 2;
237 if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
238 printk(KERN_WARNING "DiB0090 I2C read failed\n");
239 ret = 0;
240 } else
241 ret = (state->i2c_read_buffer[0] << 8)
242 | state->i2c_read_buffer[1];
244 mutex_unlock(&state->i2c_buffer_lock);
245 return ret;
248 static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
250 int ret;
252 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
253 dprintk("could not acquire lock");
254 return -EINVAL;
257 state->i2c_write_buffer[0] = reg & 0xff;
258 state->i2c_write_buffer[1] = val >> 8;
259 state->i2c_write_buffer[2] = val & 0xff;
261 memset(state->msg, 0, sizeof(struct i2c_msg));
262 state->msg[0].addr = state->config->i2c_address;
263 state->msg[0].flags = 0;
264 state->msg[0].buf = state->i2c_write_buffer;
265 state->msg[0].len = 3;
267 if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
268 printk(KERN_WARNING "DiB0090 I2C write failed\n");
269 ret = -EREMOTEIO;
270 } else
271 ret = 0;
273 mutex_unlock(&state->i2c_buffer_lock);
274 return ret;
277 static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
279 u16 ret;
281 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
282 dprintk("could not acquire lock");
283 return 0;
286 state->i2c_write_buffer[0] = reg;
288 memset(&state->msg, 0, sizeof(struct i2c_msg));
289 state->msg.addr = reg;
290 state->msg.flags = I2C_M_RD;
291 state->msg.buf = state->i2c_read_buffer;
292 state->msg.len = 2;
293 if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
294 printk(KERN_WARNING "DiB0090 I2C read failed\n");
295 ret = 0;
296 } else
297 ret = (state->i2c_read_buffer[0] << 8)
298 | state->i2c_read_buffer[1];
300 mutex_unlock(&state->i2c_buffer_lock);
301 return ret;
304 static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
306 int ret;
308 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
309 dprintk("could not acquire lock");
310 return -EINVAL;
313 state->i2c_write_buffer[0] = val >> 8;
314 state->i2c_write_buffer[1] = val & 0xff;
316 memset(&state->msg, 0, sizeof(struct i2c_msg));
317 state->msg.addr = reg;
318 state->msg.flags = 0;
319 state->msg.buf = state->i2c_write_buffer;
320 state->msg.len = 2;
321 if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
322 printk(KERN_WARNING "DiB0090 I2C write failed\n");
323 ret = -EREMOTEIO;
324 } else
325 ret = 0;
327 mutex_unlock(&state->i2c_buffer_lock);
328 return ret;
331 #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)
332 #define ADC_TARGET -220
333 #define GAIN_ALPHA 5
334 #define WBD_ALPHA 6
335 #define LPF 100
336 static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c)
338 do {
339 dib0090_write_reg(state, r++, *b++);
340 } while (--c);
343 static int dib0090_identify(struct dvb_frontend *fe)
345 struct dib0090_state *state = fe->tuner_priv;
346 u16 v;
347 struct dib0090_identity *identity = &state->identity;
349 v = dib0090_read_reg(state, 0x1a);
351 identity->p1g = 0;
352 identity->in_soc = 0;
354 dprintk("Tuner identification (Version = 0x%04x)", v);
356 /* without PLL lock info */
357 v &= ~KROSUS_PLL_LOCKED;
359 identity->version = v & 0xff;
360 identity->product = (v >> 8) & 0xf;
362 if (identity->product != KROSUS)
363 goto identification_error;
365 if ((identity->version & 0x3) == SOC) {
366 identity->in_soc = 1;
367 switch (identity->version) {
368 case SOC_8090_P1G_11R1:
369 dprintk("SOC 8090 P1-G11R1 Has been detected");
370 identity->p1g = 1;
371 break;
372 case SOC_8090_P1G_21R1:
373 dprintk("SOC 8090 P1-G21R1 Has been detected");
374 identity->p1g = 1;
375 break;
376 case SOC_7090_P1G_11R1:
377 dprintk("SOC 7090 P1-G11R1 Has been detected");
378 identity->p1g = 1;
379 break;
380 case SOC_7090_P1G_21R1:
381 dprintk("SOC 7090 P1-G21R1 Has been detected");
382 identity->p1g = 1;
383 break;
384 default:
385 goto identification_error;
387 } else {
388 switch ((identity->version >> 5) & 0x7) {
389 case MP001:
390 dprintk("MP001 : 9090/8096");
391 break;
392 case MP005:
393 dprintk("MP005 : Single Sband");
394 break;
395 case MP008:
396 dprintk("MP008 : diversity VHF-UHF-LBAND");
397 break;
398 case MP009:
399 dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND");
400 break;
401 default:
402 goto identification_error;
405 switch (identity->version & 0x1f) {
406 case P1G_21R2:
407 dprintk("P1G_21R2 detected");
408 identity->p1g = 1;
409 break;
410 case P1G:
411 dprintk("P1G detected");
412 identity->p1g = 1;
413 break;
414 case P1D_E_F:
415 dprintk("P1D/E/F detected");
416 break;
417 case P1C:
418 dprintk("P1C detected");
419 break;
420 case P1A_B:
421 dprintk("P1-A/B detected: driver is deactivated - not available");
422 goto identification_error;
423 break;
424 default:
425 goto identification_error;
429 return 0;
431 identification_error:
432 return -EIO;
435 static int dib0090_fw_identify(struct dvb_frontend *fe)
437 struct dib0090_fw_state *state = fe->tuner_priv;
438 struct dib0090_identity *identity = &state->identity;
440 u16 v = dib0090_fw_read_reg(state, 0x1a);
441 identity->p1g = 0;
442 identity->in_soc = 0;
444 dprintk("FE: Tuner identification (Version = 0x%04x)", v);
446 /* without PLL lock info */
447 v &= ~KROSUS_PLL_LOCKED;
449 identity->version = v & 0xff;
450 identity->product = (v >> 8) & 0xf;
452 if (identity->product != KROSUS)
453 goto identification_error;
455 if ((identity->version & 0x3) == SOC) {
456 identity->in_soc = 1;
457 switch (identity->version) {
458 case SOC_8090_P1G_11R1:
459 dprintk("SOC 8090 P1-G11R1 Has been detected");
460 identity->p1g = 1;
461 break;
462 case SOC_8090_P1G_21R1:
463 dprintk("SOC 8090 P1-G21R1 Has been detected");
464 identity->p1g = 1;
465 break;
466 case SOC_7090_P1G_11R1:
467 dprintk("SOC 7090 P1-G11R1 Has been detected");
468 identity->p1g = 1;
469 break;
470 case SOC_7090_P1G_21R1:
471 dprintk("SOC 7090 P1-G21R1 Has been detected");
472 identity->p1g = 1;
473 break;
474 default:
475 goto identification_error;
477 } else {
478 switch ((identity->version >> 5) & 0x7) {
479 case MP001:
480 dprintk("MP001 : 9090/8096");
481 break;
482 case MP005:
483 dprintk("MP005 : Single Sband");
484 break;
485 case MP008:
486 dprintk("MP008 : diversity VHF-UHF-LBAND");
487 break;
488 case MP009:
489 dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND");
490 break;
491 default:
492 goto identification_error;
495 switch (identity->version & 0x1f) {
496 case P1G_21R2:
497 dprintk("P1G_21R2 detected");
498 identity->p1g = 1;
499 break;
500 case P1G:
501 dprintk("P1G detected");
502 identity->p1g = 1;
503 break;
504 case P1D_E_F:
505 dprintk("P1D/E/F detected");
506 break;
507 case P1C:
508 dprintk("P1C detected");
509 break;
510 case P1A_B:
511 dprintk("P1-A/B detected: driver is deactivated - not available");
512 goto identification_error;
513 break;
514 default:
515 goto identification_error;
519 return 0;
521 identification_error:
522 return -EIO;;
525 static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
527 struct dib0090_state *state = fe->tuner_priv;
528 u16 PllCfg, i, v;
530 HARD_RESET(state);
532 dib0090_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
533 dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */
535 if (!cfg->in_soc) {
536 /* adcClkOutRatio=8->7, release reset */
537 dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
538 if (cfg->clkoutdrive != 0)
539 dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
540 | (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
541 else
542 dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
543 | (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
546 /* Read Pll current config * */
547 PllCfg = dib0090_read_reg(state, 0x21);
549 /** Reconfigure PLL if current setting is different from default setting **/
550 if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && (!cfg->in_soc)
551 && !cfg->io.pll_bypass) {
553 /* Set Bypass mode */
554 PllCfg |= (1 << 15);
555 dib0090_write_reg(state, 0x21, PllCfg);
557 /* Set Reset Pll */
558 PllCfg &= ~(1 << 13);
559 dib0090_write_reg(state, 0x21, PllCfg);
561 /*** Set new Pll configuration in bypass and reset state ***/
562 PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
563 dib0090_write_reg(state, 0x21, PllCfg);
565 /* Remove Reset Pll */
566 PllCfg |= (1 << 13);
567 dib0090_write_reg(state, 0x21, PllCfg);
569 /*** Wait for PLL lock ***/
570 i = 100;
571 do {
572 v = !!(dib0090_read_reg(state, 0x1a) & 0x800);
573 if (v)
574 break;
575 } while (--i);
577 if (i == 0) {
578 dprintk("Pll: Unable to lock Pll");
579 return;
582 /* Finally Remove Bypass mode */
583 PllCfg &= ~(1 << 15);
584 dib0090_write_reg(state, 0x21, PllCfg);
587 if (cfg->io.pll_bypass) {
588 PllCfg |= (cfg->io.pll_bypass << 15);
589 dib0090_write_reg(state, 0x21, PllCfg);
593 static int dib0090_fw_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
595 struct dib0090_fw_state *state = fe->tuner_priv;
596 u16 PllCfg;
597 u16 v;
598 int i;
600 dprintk("fw reset digital");
601 HARD_RESET(state);
603 dib0090_fw_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
604 dib0090_fw_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */
606 dib0090_fw_write_reg(state, 0x20,
607 ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (cfg->data_tx_drv << 4) | cfg->ls_cfg_pad_drv);
609 v = (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 9) | (0 << 8) | (cfg->clkouttobamse << 4) | (0 << 2) | (0);
610 if (cfg->clkoutdrive != 0)
611 v |= cfg->clkoutdrive << 5;
612 else
613 v |= 7 << 5;
615 v |= 2 << 10;
616 dib0090_fw_write_reg(state, 0x23, v);
618 /* Read Pll current config * */
619 PllCfg = dib0090_fw_read_reg(state, 0x21);
621 /** Reconfigure PLL if current setting is different from default setting **/
622 if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && !cfg->io.pll_bypass) {
624 /* Set Bypass mode */
625 PllCfg |= (1 << 15);
626 dib0090_fw_write_reg(state, 0x21, PllCfg);
628 /* Set Reset Pll */
629 PllCfg &= ~(1 << 13);
630 dib0090_fw_write_reg(state, 0x21, PllCfg);
632 /*** Set new Pll configuration in bypass and reset state ***/
633 PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
634 dib0090_fw_write_reg(state, 0x21, PllCfg);
636 /* Remove Reset Pll */
637 PllCfg |= (1 << 13);
638 dib0090_fw_write_reg(state, 0x21, PllCfg);
640 /*** Wait for PLL lock ***/
641 i = 100;
642 do {
643 v = !!(dib0090_fw_read_reg(state, 0x1a) & 0x800);
644 if (v)
645 break;
646 } while (--i);
648 if (i == 0) {
649 dprintk("Pll: Unable to lock Pll");
650 return -EIO;
653 /* Finally Remove Bypass mode */
654 PllCfg &= ~(1 << 15);
655 dib0090_fw_write_reg(state, 0x21, PllCfg);
658 if (cfg->io.pll_bypass) {
659 PllCfg |= (cfg->io.pll_bypass << 15);
660 dib0090_fw_write_reg(state, 0x21, PllCfg);
663 return dib0090_fw_identify(fe);
666 static int dib0090_wakeup(struct dvb_frontend *fe)
668 struct dib0090_state *state = fe->tuner_priv;
669 if (state->config->sleep)
670 state->config->sleep(fe, 0);
672 /* enable dataTX in case we have been restarted in the wrong moment */
673 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
674 return 0;
677 static int dib0090_sleep(struct dvb_frontend *fe)
679 struct dib0090_state *state = fe->tuner_priv;
680 if (state->config->sleep)
681 state->config->sleep(fe, 1);
682 return 0;
685 void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
687 struct dib0090_state *state = fe->tuner_priv;
688 if (fast)
689 dib0090_write_reg(state, 0x04, 0);
690 else
691 dib0090_write_reg(state, 0x04, 1);
694 EXPORT_SYMBOL(dib0090_dcc_freq);
696 static const u16 bb_ramp_pwm_normal_socs[] = {
697 550, /* max BB gain in 10th of dB */
698 (1 << 9) | 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
699 440,
700 (4 << 9) | 0, /* BB_RAMP3 = 26dB */
701 (0 << 9) | 208, /* BB_RAMP4 */
702 (4 << 9) | 208, /* BB_RAMP5 = 29dB */
703 (0 << 9) | 440, /* BB_RAMP6 */
706 static const u16 rf_ramp_pwm_cband_7090[] = {
707 280, /* max RF gain in 10th of dB */
708 18, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
709 504, /* ramp_max = maximum X used on the ramp */
710 (29 << 10) | 364, /* RF_RAMP5, LNA 1 = 8dB */
711 (0 << 10) | 504, /* RF_RAMP6, LNA 1 */
712 (60 << 10) | 228, /* RF_RAMP7, LNA 2 = 7.7dB */
713 (0 << 10) | 364, /* RF_RAMP8, LNA 2 */
714 (34 << 10) | 109, /* GAIN_4_1, LNA 3 = 6.8dB */
715 (0 << 10) | 228, /* GAIN_4_2, LNA 3 */
716 (37 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */
717 (0 << 10) | 109, /* RF_RAMP4, LNA 4 */
720 static const u16 rf_ramp_pwm_cband_8090[] = {
721 345, /* max RF gain in 10th of dB */
722 29, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
723 1000, /* ramp_max = maximum X used on the ramp */
724 (35 << 10) | 772, /* RF_RAMP3, LNA 1 = 8dB */
725 (0 << 10) | 1000, /* RF_RAMP4, LNA 1 */
726 (58 << 10) | 496, /* RF_RAMP5, LNA 2 = 9.5dB */
727 (0 << 10) | 772, /* RF_RAMP6, LNA 2 */
728 (27 << 10) | 200, /* RF_RAMP7, LNA 3 = 10.5dB */
729 (0 << 10) | 496, /* RF_RAMP8, LNA 3 */
730 (40 << 10) | 0, /* GAIN_4_1, LNA 4 = 7dB */
731 (0 << 10) | 200, /* GAIN_4_2, LNA 4 */
734 static const u16 rf_ramp_pwm_uhf_7090[] = {
735 407, /* max RF gain in 10th of dB */
736 13, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
737 529, /* ramp_max = maximum X used on the ramp */
738 (23 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
739 (0 << 10) | 176, /* RF_RAMP4, LNA 1 */
740 (63 << 10) | 400, /* RF_RAMP5, LNA 2 = 8dB */
741 (0 << 10) | 529, /* RF_RAMP6, LNA 2 */
742 (48 << 10) | 316, /* RF_RAMP7, LNA 3 = 6.8dB */
743 (0 << 10) | 400, /* RF_RAMP8, LNA 3 */
744 (29 << 10) | 176, /* GAIN_4_1, LNA 4 = 11.5dB */
745 (0 << 10) | 316, /* GAIN_4_2, LNA 4 */
748 static const u16 rf_ramp_pwm_uhf_8090[] = {
749 388, /* max RF gain in 10th of dB */
750 26, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
751 1008, /* ramp_max = maximum X used on the ramp */
752 (11 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
753 (0 << 10) | 369, /* RF_RAMP4, LNA 1 */
754 (41 << 10) | 809, /* RF_RAMP5, LNA 2 = 8dB */
755 (0 << 10) | 1008, /* RF_RAMP6, LNA 2 */
756 (27 << 10) | 659, /* RF_RAMP7, LNA 3 = 6dB */
757 (0 << 10) | 809, /* RF_RAMP8, LNA 3 */
758 (14 << 10) | 369, /* GAIN_4_1, LNA 4 = 11.5dB */
759 (0 << 10) | 659, /* GAIN_4_2, LNA 4 */
762 static const u16 rf_ramp_pwm_cband[] = {
763 0, /* max RF gain in 10th of dB */
764 0, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
765 0, /* ramp_max = maximum X used on the ramp */
766 (0 << 10) | 0, /* 0x2c, LNA 1 = 0dB */
767 (0 << 10) | 0, /* 0x2d, LNA 1 */
768 (0 << 10) | 0, /* 0x2e, LNA 2 = 0dB */
769 (0 << 10) | 0, /* 0x2f, LNA 2 */
770 (0 << 10) | 0, /* 0x30, LNA 3 = 0dB */
771 (0 << 10) | 0, /* 0x31, LNA 3 */
772 (0 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
773 (0 << 10) | 0, /* GAIN_4_2, LNA 4 */
776 static const u16 rf_ramp_vhf[] = {
777 412, /* max RF gain in 10th of dB */
778 132, 307, 127, /* LNA1, 13.2dB */
779 105, 412, 255, /* LNA2, 10.5dB */
780 50, 50, 127, /* LNA3, 5dB */
781 125, 175, 127, /* LNA4, 12.5dB */
782 0, 0, 127, /* CBAND, 0dB */
785 static const u16 rf_ramp_uhf[] = {
786 412, /* max RF gain in 10th of dB */
787 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 */
788 105, 412, 255, /* LNA2 : 10.5 dB */
789 50, 50, 127, /* LNA3 : 5.0 dB */
790 125, 175, 127, /* LNA4 : 12.5 dB */
791 0, 0, 127, /* CBAND : 0.0 dB */
794 static const u16 rf_ramp_cband_broadmatching[] = /* for p1G only */
796 314, /* Calibrated at 200MHz order has been changed g4-g3-g2-g1 */
797 84, 314, 127, /* LNA1 */
798 80, 230, 255, /* LNA2 */
799 80, 150, 127, /* LNA3 It was measured 12dB, do not lock if 120 */
800 70, 70, 127, /* LNA4 */
801 0, 0, 127, /* CBAND */
804 static const u16 rf_ramp_cband[] = {
805 332, /* max RF gain in 10th of dB */
806 132, 252, 127, /* LNA1, dB */
807 80, 332, 255, /* LNA2, dB */
808 0, 0, 127, /* LNA3, dB */
809 0, 0, 127, /* LNA4, dB */
810 120, 120, 127, /* LT1 CBAND */
813 static const u16 rf_ramp_pwm_vhf[] = {
814 404, /* max RF gain in 10th of dB */
815 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
816 1011, /* ramp_max = maximum X used on the ramp */
817 (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */
818 (0 << 10) | 756, /* 0x2d, LNA 1 */
819 (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */
820 (0 << 10) | 1011, /* 0x2f, LNA 2 */
821 (16 << 10) | 290, /* 0x30, LNA 3 = 5dB */
822 (0 << 10) | 417, /* 0x31, LNA 3 */
823 (7 << 10) | 0, /* GAIN_4_1, LNA 4 = 12.5dB */
824 (0 << 10) | 290, /* GAIN_4_2, LNA 4 */
827 static const u16 rf_ramp_pwm_uhf[] = {
828 404, /* max RF gain in 10th of dB */
829 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
830 1011, /* ramp_max = maximum X used on the ramp */
831 (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */
832 (0 << 10) | 756, /* 0x2d, LNA 1 */
833 (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */
834 (0 << 10) | 1011, /* 0x2f, LNA 2 */
835 (16 << 10) | 0, /* 0x30, LNA 3 = 5dB */
836 (0 << 10) | 127, /* 0x31, LNA 3 */
837 (7 << 10) | 127, /* GAIN_4_1, LNA 4 = 12.5dB */
838 (0 << 10) | 417, /* GAIN_4_2, LNA 4 */
841 static const u16 bb_ramp_boost[] = {
842 550, /* max BB gain in 10th of dB */
843 260, 260, 26, /* BB1, 26dB */
844 290, 550, 29, /* BB2, 29dB */
847 static const u16 bb_ramp_pwm_normal[] = {
848 500, /* max RF gain in 10th of dB */
849 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x34 */
850 400,
851 (2 << 9) | 0, /* 0x35 = 21dB */
852 (0 << 9) | 168, /* 0x36 */
853 (2 << 9) | 168, /* 0x37 = 29dB */
854 (0 << 9) | 400, /* 0x38 */
857 struct slope {
858 s16 range;
859 s16 slope;
861 static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
863 u8 i;
864 u16 rest;
865 u16 ret = 0;
866 for (i = 0; i < num; i++) {
867 if (val > slopes[i].range)
868 rest = slopes[i].range;
869 else
870 rest = val;
871 ret += (rest * slopes[i].slope) / slopes[i].range;
872 val -= rest;
874 return ret;
877 static const struct slope dib0090_wbd_slopes[3] = {
878 {66, 120}, /* -64,-52: offset - 65 */
879 {600, 170}, /* -52,-35: 65 - 665 */
880 {170, 250}, /* -45,-10: 665 - 835 */
883 static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
885 wbd &= 0x3ff;
886 if (wbd < state->wbd_offset)
887 wbd = 0;
888 else
889 wbd -= state->wbd_offset;
890 /* -64dB is the floor */
891 return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd);
894 static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
896 u16 offset = 250;
898 /* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */
900 if (state->current_band == BAND_VHF)
901 offset = 650;
902 #ifndef FIRMWARE_FIREFLY
903 if (state->current_band == BAND_VHF)
904 offset = state->config->wbd_vhf_offset;
905 if (state->current_band == BAND_CBAND)
906 offset = state->config->wbd_cband_offset;
907 #endif
909 state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
910 dprintk("wbd-target: %d dB", (u32) state->wbd_target);
913 static const int gain_reg_addr[4] = {
914 0x08, 0x0a, 0x0f, 0x01
917 static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
919 u16 rf, bb, ref;
920 u16 i, v, gain_reg[4] = { 0 }, gain;
921 const u16 *g;
923 if (top_delta < -511)
924 top_delta = -511;
925 if (top_delta > 511)
926 top_delta = 511;
928 if (force) {
929 top_delta *= (1 << WBD_ALPHA);
930 gain_delta *= (1 << GAIN_ALPHA);
933 if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit)) /* overflow */
934 state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
935 else
936 state->rf_gain_limit += top_delta;
938 if (state->rf_gain_limit < 0) /*underflow */
939 state->rf_gain_limit = 0;
941 /* use gain as a temporary variable and correct current_gain */
942 gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA;
943 if (gain_delta >= ((s16) gain - state->current_gain)) /* overflow */
944 state->current_gain = gain;
945 else
946 state->current_gain += gain_delta;
947 /* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */
948 if (state->current_gain < 0)
949 state->current_gain = 0;
951 /* now split total gain to rf and bb gain */
952 gain = state->current_gain >> GAIN_ALPHA;
954 /* requested gain is bigger than rf gain limit - ACI/WBD adjustment */
955 if (gain > (state->rf_gain_limit >> WBD_ALPHA)) {
956 rf = state->rf_gain_limit >> WBD_ALPHA;
957 bb = gain - rf;
958 if (bb > state->bb_ramp[0])
959 bb = state->bb_ramp[0];
960 } else { /* high signal level -> all gains put on RF */
961 rf = gain;
962 bb = 0;
965 state->gain[0] = rf;
966 state->gain[1] = bb;
968 /* software ramp */
969 /* Start with RF gains */
970 g = state->rf_ramp + 1; /* point on RF LNA1 max gain */
971 ref = rf;
972 for (i = 0; i < 7; i++) { /* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */
973 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 */
974 v = 0; /* force the gain to write for the current amp to be null */
975 else if (ref >= g[1]) /* Gain to set is higher than the high working point of this amp */
976 v = g[2]; /* force this amp to be full gain */
977 else /* compute the value to set to this amp because we are somewhere in his range */
978 v = ((ref - (g[1] - g[0])) * g[2]) / g[0];
980 if (i == 0) /* LNA 1 reg mapping */
981 gain_reg[0] = v;
982 else if (i == 1) /* LNA 2 reg mapping */
983 gain_reg[0] |= v << 7;
984 else if (i == 2) /* LNA 3 reg mapping */
985 gain_reg[1] = v;
986 else if (i == 3) /* LNA 4 reg mapping */
987 gain_reg[1] |= v << 7;
988 else if (i == 4) /* CBAND LNA reg mapping */
989 gain_reg[2] = v | state->rf_lt_def;
990 else if (i == 5) /* BB gain 1 reg mapping */
991 gain_reg[3] = v << 3;
992 else if (i == 6) /* BB gain 2 reg mapping */
993 gain_reg[3] |= v << 8;
995 g += 3; /* go to next gain bloc */
997 /* When RF is finished, start with BB */
998 if (i == 4) {
999 g = state->bb_ramp + 1; /* point on BB gain 1 max gain */
1000 ref = bb;
1003 gain_reg[3] |= state->bb_1_def;
1004 gain_reg[3] |= ((bb % 10) * 100) / 125;
1006 #ifdef DEBUG_AGC
1007 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,
1008 gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]);
1009 #endif
1011 /* Write the amplifier regs */
1012 for (i = 0; i < 4; i++) {
1013 v = gain_reg[i];
1014 if (force || state->gain_reg[i] != v) {
1015 state->gain_reg[i] = v;
1016 dib0090_write_reg(state, gain_reg_addr[i], v);
1021 static void dib0090_set_boost(struct dib0090_state *state, int onoff)
1023 state->bb_1_def &= 0xdfff;
1024 state->bb_1_def |= onoff << 13;
1027 static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
1029 state->rf_ramp = cfg;
1032 static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
1034 state->rf_ramp = cfg;
1036 dib0090_write_reg(state, 0x2a, 0xffff);
1038 dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
1040 dib0090_write_regs(state, 0x2c, cfg + 3, 6);
1041 dib0090_write_regs(state, 0x3e, cfg + 9, 2);
1044 static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
1046 state->bb_ramp = cfg;
1047 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
1050 static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
1052 state->bb_ramp = cfg;
1054 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
1056 dib0090_write_reg(state, 0x33, 0xffff);
1057 dprintk("total BB gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x33));
1058 dib0090_write_regs(state, 0x35, cfg + 3, 4);
1061 void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
1063 struct dib0090_state *state = fe->tuner_priv;
1064 /* reset the AGC */
1066 if (state->config->use_pwm_agc) {
1067 #ifdef CONFIG_BAND_SBAND
1068 if (state->current_band == BAND_SBAND) {
1069 dib0090_set_rframp_pwm(state, rf_ramp_pwm_sband);
1070 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_boost);
1071 } else
1072 #endif
1073 #ifdef CONFIG_BAND_CBAND
1074 if (state->current_band == BAND_CBAND) {
1075 if (state->identity.in_soc) {
1076 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
1077 if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1078 dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_8090);
1079 else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1080 dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090);
1081 } else {
1082 dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband);
1083 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
1085 } else
1086 #endif
1087 #ifdef CONFIG_BAND_VHF
1088 if (state->current_band == BAND_VHF) {
1089 if (state->identity.in_soc) {
1090 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
1091 } else {
1092 dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf);
1093 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
1095 } else
1096 #endif
1098 if (state->identity.in_soc) {
1099 if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1100 dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_8090);
1101 else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1102 dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_7090);
1103 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
1104 } else {
1105 dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf);
1106 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
1110 if (state->rf_ramp[0] != 0)
1111 dib0090_write_reg(state, 0x32, (3 << 11));
1112 else
1113 dib0090_write_reg(state, 0x32, (0 << 11));
1115 dib0090_write_reg(state, 0x04, 0x01);
1116 dib0090_write_reg(state, 0x39, (1 << 10));
1120 EXPORT_SYMBOL(dib0090_pwm_gain_reset);
1122 static u32 dib0090_get_slow_adc_val(struct dib0090_state *state)
1124 u16 adc_val = dib0090_read_reg(state, 0x1d);
1125 if (state->identity.in_soc)
1126 adc_val >>= 2;
1127 return adc_val;
1130 int dib0090_gain_control(struct dvb_frontend *fe)
1132 struct dib0090_state *state = fe->tuner_priv;
1133 enum frontend_tune_state *tune_state = &state->tune_state;
1134 int ret = 10;
1136 u16 wbd_val = 0;
1137 u8 apply_gain_immediatly = 1;
1138 s16 wbd_error = 0, adc_error = 0;
1140 if (*tune_state == CT_AGC_START) {
1141 state->agc_freeze = 0;
1142 dib0090_write_reg(state, 0x04, 0x0);
1144 #ifdef CONFIG_BAND_SBAND
1145 if (state->current_band == BAND_SBAND) {
1146 dib0090_set_rframp(state, rf_ramp_sband);
1147 dib0090_set_bbramp(state, bb_ramp_boost);
1148 } else
1149 #endif
1150 #ifdef CONFIG_BAND_VHF
1151 if (state->current_band == BAND_VHF && !state->identity.p1g) {
1152 dib0090_set_rframp(state, rf_ramp_vhf);
1153 dib0090_set_bbramp(state, bb_ramp_boost);
1154 } else
1155 #endif
1156 #ifdef CONFIG_BAND_CBAND
1157 if (state->current_band == BAND_CBAND && !state->identity.p1g) {
1158 dib0090_set_rframp(state, rf_ramp_cband);
1159 dib0090_set_bbramp(state, bb_ramp_boost);
1160 } else
1161 #endif
1162 if ((state->current_band == BAND_CBAND || state->current_band == BAND_VHF) && state->identity.p1g) {
1163 dib0090_set_rframp(state, rf_ramp_cband_broadmatching);
1164 dib0090_set_bbramp(state, bb_ramp_boost);
1165 } else {
1166 dib0090_set_rframp(state, rf_ramp_uhf);
1167 dib0090_set_bbramp(state, bb_ramp_boost);
1170 dib0090_write_reg(state, 0x32, 0);
1171 dib0090_write_reg(state, 0x39, 0);
1173 dib0090_wbd_target(state, state->current_rf);
1175 state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
1176 state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA;
1178 *tune_state = CT_AGC_STEP_0;
1179 } else if (!state->agc_freeze) {
1180 s16 wbd = 0, i, cnt;
1182 int adc;
1183 wbd_val = dib0090_get_slow_adc_val(state);
1185 if (*tune_state == CT_AGC_STEP_0)
1186 cnt = 5;
1187 else
1188 cnt = 1;
1190 for (i = 0; i < cnt; i++) {
1191 wbd_val = dib0090_get_slow_adc_val(state);
1192 wbd += dib0090_wbd_to_db(state, wbd_val);
1194 wbd /= cnt;
1195 wbd_error = state->wbd_target - wbd;
1197 if (*tune_state == CT_AGC_STEP_0) {
1198 if (wbd_error < 0 && state->rf_gain_limit > 0 && !state->identity.p1g) {
1199 #ifdef CONFIG_BAND_CBAND
1200 /* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */
1201 u8 ltg2 = (state->rf_lt_def >> 10) & 0x7;
1202 if (state->current_band == BAND_CBAND && ltg2) {
1203 ltg2 >>= 1;
1204 state->rf_lt_def &= ltg2 << 10; /* reduce in 3 steps from 7 to 0 */
1206 #endif
1207 } else {
1208 state->agc_step = 0;
1209 *tune_state = CT_AGC_STEP_1;
1211 } else {
1212 /* calc the adc power */
1213 adc = state->config->get_adc_power(fe);
1214 adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21; /* included in [0:-700] */
1216 adc_error = (s16) (((s32) ADC_TARGET) - adc);
1217 #ifdef CONFIG_STANDARD_DAB
1218 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)
1219 adc_error -= 10;
1220 #endif
1221 #ifdef CONFIG_STANDARD_DVBT
1222 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT &&
1223 (state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
1224 adc_error += 60;
1225 #endif
1226 #ifdef CONFIG_SYS_ISDBT
1227 if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count >
1230 ((state->fe->dtv_property_cache.layer[0].modulation ==
1231 QAM_64)
1232 || (state->fe->dtv_property_cache.
1233 layer[0].modulation == QAM_16)))
1235 ((state->fe->dtv_property_cache.layer[1].segment_count >
1238 ((state->fe->dtv_property_cache.layer[1].modulation ==
1239 QAM_64)
1240 || (state->fe->dtv_property_cache.
1241 layer[1].modulation == QAM_16)))
1243 ((state->fe->dtv_property_cache.layer[2].segment_count >
1246 ((state->fe->dtv_property_cache.layer[2].modulation ==
1247 QAM_64)
1248 || (state->fe->dtv_property_cache.
1249 layer[2].modulation == QAM_16)))
1252 adc_error += 60;
1253 #endif
1255 if (*tune_state == CT_AGC_STEP_1) { /* quickly go to the correct range of the ADC power */
1256 if (ABS(adc_error) < 50 || state->agc_step++ > 5) {
1258 #ifdef CONFIG_STANDARD_DAB
1259 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) {
1260 dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63)); /* cap value = 63 : narrow BB filter : Fc = 1.8MHz */
1261 dib0090_write_reg(state, 0x04, 0x0);
1262 } else
1263 #endif
1265 dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32));
1266 dib0090_write_reg(state, 0x04, 0x01); /*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */
1269 *tune_state = CT_AGC_STOP;
1271 } else {
1272 /* everything higher than or equal to CT_AGC_STOP means tracking */
1273 ret = 100; /* 10ms interval */
1274 apply_gain_immediatly = 0;
1277 #ifdef DEBUG_AGC
1278 dprintk
1279 ("tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
1280 (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
1281 (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
1282 #endif
1285 /* apply gain */
1286 if (!state->agc_freeze)
1287 dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
1288 return ret;
1291 EXPORT_SYMBOL(dib0090_gain_control);
1293 void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
1295 struct dib0090_state *state = fe->tuner_priv;
1296 if (rf)
1297 *rf = state->gain[0];
1298 if (bb)
1299 *bb = state->gain[1];
1300 if (rf_gain_limit)
1301 *rf_gain_limit = state->rf_gain_limit;
1302 if (rflt)
1303 *rflt = (state->rf_lt_def >> 10) & 0x7;
1306 EXPORT_SYMBOL(dib0090_get_current_gain);
1308 u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
1310 struct dib0090_state *state = fe->tuner_priv;
1311 u32 f_MHz = state->fe->dtv_property_cache.frequency / 1000000;
1312 s32 current_temp = state->temperature;
1313 s32 wbd_thot, wbd_tcold;
1314 const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1316 while (f_MHz > wbd->max_freq)
1317 wbd++;
1319 dprintk("using wbd-table-entry with max freq %d", wbd->max_freq);
1321 if (current_temp < 0)
1322 current_temp = 0;
1323 if (current_temp > 128)
1324 current_temp = 128;
1326 state->wbdmux &= ~(7 << 13);
1327 if (wbd->wbd_gain != 0)
1328 state->wbdmux |= (wbd->wbd_gain << 13);
1329 else
1330 state->wbdmux |= (4 << 13);
1332 dib0090_write_reg(state, 0x10, state->wbdmux);
1334 wbd_thot = wbd->offset_hot - (((u32) wbd->slope_hot * f_MHz) >> 6);
1335 wbd_tcold = wbd->offset_cold - (((u32) wbd->slope_cold * f_MHz) >> 6);
1337 wbd_tcold += ((wbd_thot - wbd_tcold) * current_temp) >> 7;
1339 state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + wbd_tcold);
1340 dprintk("wbd-target: %d dB", (u32) state->wbd_target);
1341 dprintk("wbd offset applied is %d", wbd_tcold);
1343 return state->wbd_offset + wbd_tcold;
1346 EXPORT_SYMBOL(dib0090_get_wbd_offset);
1348 static const u16 dib0090_defaults[] = {
1350 25, 0x01,
1351 0x0000,
1352 0x99a0,
1353 0x6008,
1354 0x0000,
1355 0x8bcb,
1356 0x0000,
1357 0x0405,
1358 0x0000,
1359 0x0000,
1360 0x0000,
1361 0xb802,
1362 0x0300,
1363 0x2d12,
1364 0xbac0,
1365 0x7c00,
1366 0xdbb9,
1367 0x0954,
1368 0x0743,
1369 0x8000,
1370 0x0001,
1371 0x0040,
1372 0x0100,
1373 0x0000,
1374 0xe910,
1375 0x149e,
1377 1, 0x1c,
1378 0xff2d,
1380 1, 0x39,
1381 0x0000,
1383 2, 0x1e,
1384 0x07FF,
1385 0x0007,
1387 1, 0x24,
1388 EN_UHF | EN_CRYSTAL,
1390 2, 0x3c,
1391 0x3ff,
1392 0x111,
1396 static const u16 dib0090_p1g_additionnal_defaults[] = {
1397 1, 0x05,
1398 0xabcd,
1400 1, 0x11,
1401 0x00b4,
1403 1, 0x1c,
1404 0xfffd,
1406 1, 0x40,
1407 0x108,
1411 static void dib0090_set_default_config(struct dib0090_state *state, const u16 * n)
1413 u16 l, r;
1415 l = pgm_read_word(n++);
1416 while (l) {
1417 r = pgm_read_word(n++);
1418 do {
1419 dib0090_write_reg(state, r, pgm_read_word(n++));
1420 r++;
1421 } while (--l);
1422 l = pgm_read_word(n++);
1426 #define CAP_VALUE_MIN (u8) 9
1427 #define CAP_VALUE_MAX (u8) 40
1428 #define HR_MIN (u8) 25
1429 #define HR_MAX (u8) 40
1430 #define POLY_MIN (u8) 0
1431 #define POLY_MAX (u8) 8
1433 void dib0090_set_EFUSE(struct dib0090_state *state)
1435 u8 c, h, n;
1436 u16 e2, e4;
1437 u16 cal;
1439 e2 = dib0090_read_reg(state, 0x26);
1440 e4 = dib0090_read_reg(state, 0x28);
1442 if ((state->identity.version == P1D_E_F) ||
1443 (state->identity.version == P1G) || (e2 == 0xffff)) {
1445 dib0090_write_reg(state, 0x22, 0x10);
1446 cal = (dib0090_read_reg(state, 0x22) >> 6) & 0x3ff;
1448 if ((cal < 670) || (cal == 1023))
1449 cal = 850;
1450 n = 165 - ((cal * 10)>>6) ;
1451 e2 = e4 = (3<<12) | (34<<6) | (n);
1454 if (e2 != e4)
1455 e2 &= e4; /* Remove the redundancy */
1457 if (e2 != 0xffff) {
1458 c = e2 & 0x3f;
1459 n = (e2 >> 12) & 0xf;
1460 h = (e2 >> 6) & 0x3f;
1462 if ((c >= CAP_VALUE_MAX) || (c <= CAP_VALUE_MIN))
1463 c = 32;
1464 if ((h >= HR_MAX) || (h <= HR_MIN))
1465 h = 34;
1466 if ((n >= POLY_MAX) || (n <= POLY_MIN))
1467 n = 3;
1469 dib0090_write_reg(state, 0x13, (h << 10)) ;
1470 e2 = (n<<11) | ((h>>2)<<6) | (c);
1471 dib0090_write_reg(state, 0x2, e2) ; /* Load the BB_2 */
1475 static int dib0090_reset(struct dvb_frontend *fe)
1477 struct dib0090_state *state = fe->tuner_priv;
1479 dib0090_reset_digital(fe, state->config);
1480 if (dib0090_identify(fe) < 0)
1481 return -EIO;
1483 #ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
1484 if (!(state->identity.version & 0x1)) /* it is P1B - reset is already done */
1485 return 0;
1486 #endif
1488 if (!state->identity.in_soc) {
1489 if ((dib0090_read_reg(state, 0x1a) >> 5) & 0x2)
1490 dib0090_write_reg(state, 0x1b, (EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1491 else
1492 dib0090_write_reg(state, 0x1b, (EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1495 dib0090_set_default_config(state, dib0090_defaults);
1497 if (state->identity.in_soc)
1498 dib0090_write_reg(state, 0x18, 0x2910); /* charge pump current = 0 */
1500 if (state->identity.p1g)
1501 dib0090_set_default_config(state, dib0090_p1g_additionnal_defaults);
1503 /* Update the efuse : Only available for KROSUS > P1C and SOC as well*/
1504 if (((state->identity.version & 0x1f) >= P1D_E_F) || (state->identity.in_soc))
1505 dib0090_set_EFUSE(state);
1507 /* Congigure in function of the crystal */
1508 if (state->config->io.clock_khz >= 24000)
1509 dib0090_write_reg(state, 0x14, 1);
1510 else
1511 dib0090_write_reg(state, 0x14, 2);
1512 dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
1514 state->calibrate = DC_CAL | WBD_CAL | TEMP_CAL; /* enable iq-offset-calibration and wbd-calibration when tuning next time */
1516 return 0;
1519 #define steps(u) (((u) > 15) ? ((u)-16) : (u))
1520 #define INTERN_WAIT 10
1521 static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1523 int ret = INTERN_WAIT * 10;
1525 switch (*tune_state) {
1526 case CT_TUNER_STEP_2:
1527 /* Turns to positive */
1528 dib0090_write_reg(state, 0x1f, 0x7);
1529 *tune_state = CT_TUNER_STEP_3;
1530 break;
1532 case CT_TUNER_STEP_3:
1533 state->adc_diff = dib0090_read_reg(state, 0x1d);
1535 /* Turns to negative */
1536 dib0090_write_reg(state, 0x1f, 0x4);
1537 *tune_state = CT_TUNER_STEP_4;
1538 break;
1540 case CT_TUNER_STEP_4:
1541 state->adc_diff -= dib0090_read_reg(state, 0x1d);
1542 *tune_state = CT_TUNER_STEP_5;
1543 ret = 0;
1544 break;
1546 default:
1547 break;
1550 return ret;
1553 struct dc_calibration {
1554 u8 addr;
1555 u8 offset;
1556 u8 pga:1;
1557 u16 bb1;
1558 u8 i:1;
1561 static const struct dc_calibration dc_table[] = {
1562 /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
1563 {0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1},
1564 {0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0},
1565 /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
1566 {0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1},
1567 {0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0},
1568 {0},
1571 static const struct dc_calibration dc_p1g_table[] = {
1572 /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
1573 /* addr ; trim reg offset ; pga ; CTRL_BB1 value ; i or q */
1574 {0x06, 5, 1, (1 << 13) | (0 << 8) | (15 << 3), 1},
1575 {0x07, 11, 1, (1 << 13) | (0 << 8) | (15 << 3), 0},
1576 /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
1577 {0x06, 0, 0, (1 << 13) | (29 << 8) | (15 << 3), 1},
1578 {0x06, 10, 0, (1 << 13) | (29 << 8) | (15 << 3), 0},
1579 {0},
1582 static void dib0090_set_trim(struct dib0090_state *state)
1584 u16 *val;
1586 if (state->dc->addr == 0x07)
1587 val = &state->bb7;
1588 else
1589 val = &state->bb6;
1591 *val &= ~(0x1f << state->dc->offset);
1592 *val |= state->step << state->dc->offset;
1594 dib0090_write_reg(state, state->dc->addr, *val);
1597 static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1599 int ret = 0;
1600 u16 reg;
1602 switch (*tune_state) {
1603 case CT_TUNER_START:
1604 dprintk("Start DC offset calibration");
1606 /* force vcm2 = 0.8V */
1607 state->bb6 = 0;
1608 state->bb7 = 0x040d;
1610 /* the LNA AND LO are off */
1611 reg = dib0090_read_reg(state, 0x24) & 0x0ffb; /* shutdown lna and lo */
1612 dib0090_write_reg(state, 0x24, reg);
1614 state->wbdmux = dib0090_read_reg(state, 0x10);
1615 dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x7 << 3) | 0x3);
1616 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
1618 state->dc = dc_table;
1620 if (state->identity.p1g)
1621 state->dc = dc_p1g_table;
1622 *tune_state = CT_TUNER_STEP_0;
1624 /* fall through */
1626 case CT_TUNER_STEP_0:
1627 dprintk("Sart/continue DC calibration for %s path", (state->dc->i == 1) ? "I" : "Q");
1628 dib0090_write_reg(state, 0x01, state->dc->bb1);
1629 dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
1631 state->step = 0;
1632 state->min_adc_diff = 1023;
1633 *tune_state = CT_TUNER_STEP_1;
1634 ret = 50;
1635 break;
1637 case CT_TUNER_STEP_1:
1638 dib0090_set_trim(state);
1639 *tune_state = CT_TUNER_STEP_2;
1640 break;
1642 case CT_TUNER_STEP_2:
1643 case CT_TUNER_STEP_3:
1644 case CT_TUNER_STEP_4:
1645 ret = dib0090_get_offset(state, tune_state);
1646 break;
1648 case CT_TUNER_STEP_5: /* found an offset */
1649 dprintk("adc_diff = %d, current step= %d", (u32) state->adc_diff, state->step);
1650 if (state->step == 0 && state->adc_diff < 0) {
1651 state->min_adc_diff = -1023;
1652 dprintk("Change of sign of the minimum adc diff");
1655 dprintk("adc_diff = %d, min_adc_diff = %d current_step = %d", state->adc_diff, state->min_adc_diff, state->step);
1657 /* first turn for this frequency */
1658 if (state->step == 0) {
1659 if (state->dc->pga && state->adc_diff < 0)
1660 state->step = 0x10;
1661 if (state->dc->pga == 0 && state->adc_diff > 0)
1662 state->step = 0x10;
1665 /* Look for a change of Sign in the Adc_diff.min_adc_diff is used to STORE the setp N-1 */
1666 if ((state->adc_diff & 0x8000) == (state->min_adc_diff & 0x8000) && steps(state->step) < 15) {
1667 /* stop search when the delta the sign is changing and Steps =15 and Step=0 is force for continuance */
1668 state->step++;
1669 state->min_adc_diff = state->adc_diff;
1670 *tune_state = CT_TUNER_STEP_1;
1671 } else {
1672 /* the minimum was what we have seen in the step before */
1673 if (ABS(state->adc_diff) > ABS(state->min_adc_diff)) {
1674 dprintk("Since adc_diff N = %d > adc_diff step N-1 = %d, Come back one step", state->adc_diff, state->min_adc_diff);
1675 state->step--;
1678 dib0090_set_trim(state);
1679 dprintk("BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->dc->addr, state->adc_diff, state->step);
1681 state->dc++;
1682 if (state->dc->addr == 0) /* done */
1683 *tune_state = CT_TUNER_STEP_6;
1684 else
1685 *tune_state = CT_TUNER_STEP_0;
1688 break;
1690 case CT_TUNER_STEP_6:
1691 dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008);
1692 dib0090_write_reg(state, 0x1f, 0x7);
1693 *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1694 state->calibrate &= ~DC_CAL;
1695 default:
1696 break;
1698 return ret;
1701 static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1703 u8 wbd_gain;
1704 const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1706 switch (*tune_state) {
1707 case CT_TUNER_START:
1708 while (state->current_rf / 1000 > wbd->max_freq)
1709 wbd++;
1710 if (wbd->wbd_gain != 0)
1711 wbd_gain = wbd->wbd_gain;
1712 else {
1713 wbd_gain = 4;
1714 #if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
1715 if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND))
1716 wbd_gain = 2;
1717 #endif
1720 if (wbd_gain == state->wbd_calibration_gain) { /* the WBD calibration has already been done */
1721 *tune_state = CT_TUNER_START;
1722 state->calibrate &= ~WBD_CAL;
1723 return 0;
1726 dib0090_write_reg(state, 0x10, 0x1b81 | (1 << 10) | (wbd_gain << 13) | (1 << 3));
1728 dib0090_write_reg(state, 0x24, ((EN_UHF & 0x0fff) | (1 << 1)));
1729 *tune_state = CT_TUNER_STEP_0;
1730 state->wbd_calibration_gain = wbd_gain;
1731 return 90; /* wait for the WBDMUX to switch and for the ADC to sample */
1733 case CT_TUNER_STEP_0:
1734 state->wbd_offset = dib0090_get_slow_adc_val(state);
1735 dprintk("WBD calibration offset = %d", state->wbd_offset);
1736 *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1737 state->calibrate &= ~WBD_CAL;
1738 break;
1740 default:
1741 break;
1743 return 0;
1746 static void dib0090_set_bandwidth(struct dib0090_state *state)
1748 u16 tmp;
1750 if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000)
1751 tmp = (3 << 14);
1752 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000)
1753 tmp = (2 << 14);
1754 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000)
1755 tmp = (1 << 14);
1756 else
1757 tmp = (0 << 14);
1759 state->bb_1_def &= 0x3fff;
1760 state->bb_1_def |= tmp;
1762 dib0090_write_reg(state, 0x01, state->bb_1_def); /* be sure that we have the right bb-filter */
1764 dib0090_write_reg(state, 0x03, 0x6008); /* = 0x6008 : vcm3_trim = 1 ; filter2_gm1_trim = 8 ; filter2_cutoff_freq = 0 */
1765 dib0090_write_reg(state, 0x04, 0x1); /* 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast */
1766 if (state->identity.in_soc) {
1767 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 */
1768 } else {
1769 dib0090_write_reg(state, 0x02, (5 << 11) | (8 << 6) | (22 & 0x3f)); /* 22 = cap_value */
1770 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 */
1774 static const struct dib0090_pll dib0090_pll_table[] = {
1775 #ifdef CONFIG_BAND_CBAND
1776 {56000, 0, 9, 48, 6},
1777 {70000, 1, 9, 48, 6},
1778 {87000, 0, 8, 32, 4},
1779 {105000, 1, 8, 32, 4},
1780 {115000, 0, 7, 24, 6},
1781 {140000, 1, 7, 24, 6},
1782 {170000, 0, 6, 16, 4},
1783 #endif
1784 #ifdef CONFIG_BAND_VHF
1785 {200000, 1, 6, 16, 4},
1786 {230000, 0, 5, 12, 6},
1787 {280000, 1, 5, 12, 6},
1788 {340000, 0, 4, 8, 4},
1789 {380000, 1, 4, 8, 4},
1790 {450000, 0, 3, 6, 6},
1791 #endif
1792 #ifdef CONFIG_BAND_UHF
1793 {580000, 1, 3, 6, 6},
1794 {700000, 0, 2, 4, 4},
1795 {860000, 1, 2, 4, 4},
1796 #endif
1797 #ifdef CONFIG_BAND_LBAND
1798 {1800000, 1, 0, 2, 4},
1799 #endif
1800 #ifdef CONFIG_BAND_SBAND
1801 {2900000, 0, 14, 1, 4},
1802 #endif
1805 static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
1807 #ifdef CONFIG_BAND_CBAND
1808 {184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1809 {227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1810 {380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1811 #endif
1812 #ifdef CONFIG_BAND_UHF
1813 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1814 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1815 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1816 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1817 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1818 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1819 #endif
1820 #ifdef CONFIG_BAND_LBAND
1821 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1822 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1823 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1824 #endif
1825 #ifdef CONFIG_BAND_SBAND
1826 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1827 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1828 #endif
1831 static const struct dib0090_tuning dib0090_tuning_table[] = {
1833 #ifdef CONFIG_BAND_CBAND
1834 {170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1835 #endif
1836 #ifdef CONFIG_BAND_VHF
1837 {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1838 {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1839 {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1840 #endif
1841 #ifdef CONFIG_BAND_UHF
1842 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1843 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1844 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1845 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1846 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1847 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1848 #endif
1849 #ifdef CONFIG_BAND_LBAND
1850 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1851 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1852 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1853 #endif
1854 #ifdef CONFIG_BAND_SBAND
1855 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1856 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1857 #endif
1860 static const struct dib0090_tuning dib0090_p1g_tuning_table[] = {
1861 #ifdef CONFIG_BAND_CBAND
1862 {170000, 4, 1, 0x820f, 0x300, 0x2d22, 0x82cb, EN_CAB},
1863 #endif
1864 #ifdef CONFIG_BAND_VHF
1865 {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1866 {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1867 {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1868 #endif
1869 #ifdef CONFIG_BAND_UHF
1870 {510000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1871 {540000, 2, 1, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1872 {600000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1873 {630000, 2, 4, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1874 {680000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1875 {720000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1876 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1877 #endif
1878 #ifdef CONFIG_BAND_LBAND
1879 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1880 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1881 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1882 #endif
1883 #ifdef CONFIG_BAND_SBAND
1884 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1885 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1886 #endif
1889 static const struct dib0090_pll dib0090_p1g_pll_table[] = {
1890 #ifdef CONFIG_BAND_CBAND
1891 {57000, 0, 11, 48, 6},
1892 {70000, 1, 11, 48, 6},
1893 {86000, 0, 10, 32, 4},
1894 {105000, 1, 10, 32, 4},
1895 {115000, 0, 9, 24, 6},
1896 {140000, 1, 9, 24, 6},
1897 {170000, 0, 8, 16, 4},
1898 #endif
1899 #ifdef CONFIG_BAND_VHF
1900 {200000, 1, 8, 16, 4},
1901 {230000, 0, 7, 12, 6},
1902 {280000, 1, 7, 12, 6},
1903 {340000, 0, 6, 8, 4},
1904 {380000, 1, 6, 8, 4},
1905 {455000, 0, 5, 6, 6},
1906 #endif
1907 #ifdef CONFIG_BAND_UHF
1908 {580000, 1, 5, 6, 6},
1909 {680000, 0, 4, 4, 4},
1910 {860000, 1, 4, 4, 4},
1911 #endif
1912 #ifdef CONFIG_BAND_LBAND
1913 {1800000, 1, 2, 2, 4},
1914 #endif
1915 #ifdef CONFIG_BAND_SBAND
1916 {2900000, 0, 1, 1, 6},
1917 #endif
1920 static const struct dib0090_tuning dib0090_p1g_tuning_table_fm_vhf_on_cband[] = {
1921 #ifdef CONFIG_BAND_CBAND
1922 {184000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
1923 {227000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
1924 {380000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
1925 #endif
1926 #ifdef CONFIG_BAND_UHF
1927 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1928 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1929 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1930 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1931 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1932 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1933 #endif
1934 #ifdef CONFIG_BAND_LBAND
1935 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1936 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1937 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1938 #endif
1939 #ifdef CONFIG_BAND_SBAND
1940 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1941 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1942 #endif
1945 static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = {
1946 #ifdef CONFIG_BAND_CBAND
1947 {300000, 4, 3, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
1948 {380000, 4, 10, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
1949 {570000, 4, 10, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
1950 {858000, 4, 5, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
1951 #endif
1954 static int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1956 int ret = 0;
1957 u16 lo4 = 0xe900;
1959 s16 adc_target;
1960 u16 adc;
1961 s8 step_sign;
1962 u8 force_soft_search = 0;
1964 if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1965 force_soft_search = 1;
1967 if (*tune_state == CT_TUNER_START) {
1968 dprintk("Start Captrim search : %s", (force_soft_search == 1) ? "FORCE SOFT SEARCH" : "AUTO");
1969 dib0090_write_reg(state, 0x10, 0x2B1);
1970 dib0090_write_reg(state, 0x1e, 0x0032);
1972 if (!state->tuner_is_tuned) {
1973 /* prepare a complete captrim */
1974 if (!state->identity.p1g || force_soft_search)
1975 state->step = state->captrim = state->fcaptrim = 64;
1977 state->current_rf = state->rf_request;
1978 } else { /* we are already tuned to this frequency - the configuration is correct */
1979 if (!state->identity.p1g || force_soft_search) {
1980 /* do a minimal captrim even if the frequency has not changed */
1981 state->step = 4;
1982 state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
1985 state->adc_diff = 3000;
1986 *tune_state = CT_TUNER_STEP_0;
1988 } else if (*tune_state == CT_TUNER_STEP_0) {
1989 if (state->identity.p1g && !force_soft_search) {
1990 u8 ratio = 31;
1992 dib0090_write_reg(state, 0x40, (3 << 7) | (ratio << 2) | (1 << 1) | 1);
1993 dib0090_read_reg(state, 0x40);
1994 ret = 50;
1995 } else {
1996 state->step /= 2;
1997 dib0090_write_reg(state, 0x18, lo4 | state->captrim);
1999 if (state->identity.in_soc)
2000 ret = 25;
2002 *tune_state = CT_TUNER_STEP_1;
2004 } else if (*tune_state == CT_TUNER_STEP_1) {
2005 if (state->identity.p1g && !force_soft_search) {
2006 dib0090_write_reg(state, 0x40, 0x18c | (0 << 1) | 0);
2007 dib0090_read_reg(state, 0x40);
2009 state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7F;
2010 dprintk("***Final Captrim= 0x%x", state->fcaptrim);
2011 *tune_state = CT_TUNER_STEP_3;
2013 } else {
2014 /* MERGE for all krosus before P1G */
2015 adc = dib0090_get_slow_adc_val(state);
2016 dprintk("CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) state->captrim, (u32) adc, (u32) (adc) * (u32) 1800 / (u32) 1024);
2018 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 !!! */
2019 adc_target = 200;
2020 } else
2021 adc_target = 400;
2023 if (adc >= adc_target) {
2024 adc -= adc_target;
2025 step_sign = -1;
2026 } else {
2027 adc = adc_target - adc;
2028 step_sign = 1;
2031 if (adc < state->adc_diff) {
2032 dprintk("CAPTRIM=%d is closer to target (%d/%d)", (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
2033 state->adc_diff = adc;
2034 state->fcaptrim = state->captrim;
2037 state->captrim += step_sign * state->step;
2038 if (state->step >= 1)
2039 *tune_state = CT_TUNER_STEP_0;
2040 else
2041 *tune_state = CT_TUNER_STEP_2;
2043 ret = 25;
2045 } else if (*tune_state == CT_TUNER_STEP_2) { /* this step is only used by krosus < P1G */
2046 /*write the final cptrim config */
2047 dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
2049 *tune_state = CT_TUNER_STEP_3;
2051 } else if (*tune_state == CT_TUNER_STEP_3) {
2052 state->calibrate &= ~CAPTRIM_CAL;
2053 *tune_state = CT_TUNER_STEP_0;
2056 return ret;
2059 static int dib0090_get_temperature(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2061 int ret = 15;
2062 s16 val;
2064 switch (*tune_state) {
2065 case CT_TUNER_START:
2066 state->wbdmux = dib0090_read_reg(state, 0x10);
2067 dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x8 << 3));
2069 state->bias = dib0090_read_reg(state, 0x13);
2070 dib0090_write_reg(state, 0x13, state->bias | (0x3 << 8));
2072 *tune_state = CT_TUNER_STEP_0;
2073 /* wait for the WBDMUX to switch and for the ADC to sample */
2074 break;
2076 case CT_TUNER_STEP_0:
2077 state->adc_diff = dib0090_get_slow_adc_val(state);
2078 dib0090_write_reg(state, 0x13, (state->bias & ~(0x3 << 8)) | (0x2 << 8));
2079 *tune_state = CT_TUNER_STEP_1;
2080 break;
2082 case CT_TUNER_STEP_1:
2083 val = dib0090_get_slow_adc_val(state);
2084 state->temperature = ((s16) ((val - state->adc_diff) * 180) >> 8) + 55;
2086 dprintk("temperature: %d C", state->temperature - 30);
2088 *tune_state = CT_TUNER_STEP_2;
2089 break;
2091 case CT_TUNER_STEP_2:
2092 dib0090_write_reg(state, 0x13, state->bias);
2093 dib0090_write_reg(state, 0x10, state->wbdmux); /* write back original WBDMUX */
2095 *tune_state = CT_TUNER_START;
2096 state->calibrate &= ~TEMP_CAL;
2097 if (state->config->analog_output == 0)
2098 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2100 break;
2102 default:
2103 ret = 0;
2104 break;
2106 return ret;
2109 #define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */
2110 static int dib0090_tune(struct dvb_frontend *fe)
2112 struct dib0090_state *state = fe->tuner_priv;
2113 const struct dib0090_tuning *tune = state->current_tune_table_index;
2114 const struct dib0090_pll *pll = state->current_pll_table_index;
2115 enum frontend_tune_state *tune_state = &state->tune_state;
2117 u16 lo5, lo6, Den, tmp;
2118 u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
2119 int ret = 10; /* 1ms is the default delay most of the time */
2120 u8 c, i;
2122 /************************* VCO ***************************/
2123 /* Default values for FG */
2124 /* from these are needed : */
2125 /* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv */
2127 /* in any case we first need to do a calibration if needed */
2128 if (*tune_state == CT_TUNER_START) {
2129 /* deactivate DataTX before some calibrations */
2130 if (state->calibrate & (DC_CAL | TEMP_CAL | WBD_CAL))
2131 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
2132 else
2133 /* Activate DataTX in case a calibration has been done before */
2134 if (state->config->analog_output == 0)
2135 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2138 if (state->calibrate & DC_CAL)
2139 return dib0090_dc_offset_calibration(state, tune_state);
2140 else if (state->calibrate & WBD_CAL) {
2141 if (state->current_rf == 0)
2142 state->current_rf = state->fe->dtv_property_cache.frequency / 1000;
2143 return dib0090_wbd_calibration(state, tune_state);
2144 } else if (state->calibrate & TEMP_CAL)
2145 return dib0090_get_temperature(state, tune_state);
2146 else if (state->calibrate & CAPTRIM_CAL)
2147 return dib0090_captrim_search(state, tune_state);
2149 if (*tune_state == CT_TUNER_START) {
2150 /* 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 */
2151 if (state->config->use_pwm_agc && state->identity.in_soc) {
2152 tmp = dib0090_read_reg(state, 0x39);
2153 if ((tmp >> 10) & 0x1)
2154 dib0090_write_reg(state, 0x39, tmp & ~(1 << 10));
2157 state->current_band = (u8) BAND_OF_FREQUENCY(state->fe->dtv_property_cache.frequency / 1000);
2158 state->rf_request =
2159 state->fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
2160 BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->
2161 freq_offset_khz_vhf);
2163 /* in ISDB-T 1seg we shift tuning frequency */
2164 if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1
2165 && state->fe->dtv_property_cache.isdbt_partial_reception == 0)) {
2166 const struct dib0090_low_if_offset_table *LUT_offset = state->config->low_if;
2167 u8 found_offset = 0;
2168 u32 margin_khz = 100;
2170 if (LUT_offset != NULL) {
2171 while (LUT_offset->RF_freq != 0xffff) {
2172 if (((state->rf_request > (LUT_offset->RF_freq - margin_khz))
2173 && (state->rf_request < (LUT_offset->RF_freq + margin_khz)))
2174 && LUT_offset->std == state->fe->dtv_property_cache.delivery_system) {
2175 state->rf_request += LUT_offset->offset_khz;
2176 found_offset = 1;
2177 break;
2179 LUT_offset++;
2183 if (found_offset == 0)
2184 state->rf_request += 400;
2186 if (state->current_rf != state->rf_request || (state->current_standard != state->fe->dtv_property_cache.delivery_system)) {
2187 state->tuner_is_tuned = 0;
2188 state->current_rf = 0;
2189 state->current_standard = 0;
2191 tune = dib0090_tuning_table;
2192 if (state->identity.p1g)
2193 tune = dib0090_p1g_tuning_table;
2195 tmp = (state->identity.version >> 5) & 0x7;
2197 if (state->identity.in_soc) {
2198 if (state->config->force_cband_input) { /* Use the CBAND input for all band */
2199 if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF
2200 || state->current_band & BAND_UHF) {
2201 state->current_band = BAND_CBAND;
2202 tune = dib0090_tuning_table_cband_7090;
2204 } else { /* Use the CBAND input for all band under UHF */
2205 if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) {
2206 state->current_band = BAND_CBAND;
2207 tune = dib0090_tuning_table_cband_7090;
2210 } else
2211 if (tmp == 0x4 || tmp == 0x7) {
2212 /* CBAND tuner version for VHF */
2213 if (state->current_band == BAND_FM || state->current_band == BAND_CBAND || state->current_band == BAND_VHF) {
2214 state->current_band = BAND_CBAND; /* Force CBAND */
2216 tune = dib0090_tuning_table_fm_vhf_on_cband;
2217 if (state->identity.p1g)
2218 tune = dib0090_p1g_tuning_table_fm_vhf_on_cband;
2222 pll = dib0090_pll_table;
2223 if (state->identity.p1g)
2224 pll = dib0090_p1g_pll_table;
2226 /* Look for the interval */
2227 while (state->rf_request > tune->max_freq)
2228 tune++;
2229 while (state->rf_request > pll->max_freq)
2230 pll++;
2232 state->current_tune_table_index = tune;
2233 state->current_pll_table_index = pll;
2235 dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
2237 VCOF_kHz = (pll->hfdiv * state->rf_request) * 2;
2239 FREF = state->config->io.clock_khz;
2240 if (state->config->fref_clock_ratio != 0)
2241 FREF /= state->config->fref_clock_ratio;
2243 FBDiv = (VCOF_kHz / pll->topresc / FREF);
2244 Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
2246 if (Rest < LPF)
2247 Rest = 0;
2248 else if (Rest < 2 * LPF)
2249 Rest = 2 * LPF;
2250 else if (Rest > (FREF - LPF)) {
2251 Rest = 0;
2252 FBDiv += 1;
2253 } else if (Rest > (FREF - 2 * LPF))
2254 Rest = FREF - 2 * LPF;
2255 Rest = (Rest * 6528) / (FREF / 10);
2256 state->rest = Rest;
2258 /* external loop filter, otherwise:
2259 * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
2260 * lo6 = 0x0e34 */
2262 if (Rest == 0) {
2263 if (pll->vco_band)
2264 lo5 = 0x049f;
2265 else
2266 lo5 = 0x041f;
2267 } else {
2268 if (pll->vco_band)
2269 lo5 = 0x049e;
2270 else if (state->config->analog_output)
2271 lo5 = 0x041d;
2272 else
2273 lo5 = 0x041c;
2276 if (state->identity.p1g) { /* Bias is done automatically in P1G */
2277 if (state->identity.in_soc) {
2278 if (state->identity.version == SOC_8090_P1G_11R1)
2279 lo5 = 0x46f;
2280 else
2281 lo5 = 0x42f;
2282 } else
2283 lo5 = 0x42c;
2286 lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7); /* bit 15 is the split to the slave, we do not do it here */
2288 if (!state->config->io.pll_int_loop_filt) {
2289 if (state->identity.in_soc)
2290 lo6 = 0xff98;
2291 else if (state->identity.p1g || (Rest == 0))
2292 lo6 = 0xfff8;
2293 else
2294 lo6 = 0xff28;
2295 } else
2296 lo6 = (state->config->io.pll_int_loop_filt << 3);
2298 Den = 1;
2300 if (Rest > 0) {
2301 if (state->config->analog_output)
2302 lo6 |= (1 << 2) | 2;
2303 else {
2304 if (state->identity.in_soc)
2305 lo6 |= (1 << 2) | 2;
2306 else
2307 lo6 |= (1 << 2) | 2;
2309 Den = 255;
2311 dib0090_write_reg(state, 0x15, (u16) FBDiv);
2312 if (state->config->fref_clock_ratio != 0)
2313 dib0090_write_reg(state, 0x16, (Den << 8) | state->config->fref_clock_ratio);
2314 else
2315 dib0090_write_reg(state, 0x16, (Den << 8) | 1);
2316 dib0090_write_reg(state, 0x17, (u16) Rest);
2317 dib0090_write_reg(state, 0x19, lo5);
2318 dib0090_write_reg(state, 0x1c, lo6);
2320 lo6 = tune->tuner_enable;
2321 if (state->config->analog_output)
2322 lo6 = (lo6 & 0xff9f) | 0x2;
2324 dib0090_write_reg(state, 0x24, lo6 | EN_LO | state->config->use_pwm_agc * EN_CRYSTAL);
2328 state->current_rf = state->rf_request;
2329 state->current_standard = state->fe->dtv_property_cache.delivery_system;
2331 ret = 20;
2332 state->calibrate = CAPTRIM_CAL; /* captrim serach now */
2335 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 */
2336 const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
2338 while (state->current_rf / 1000 > wbd->max_freq)
2339 wbd++;
2341 dib0090_write_reg(state, 0x1e, 0x07ff);
2342 dprintk("Final Captrim: %d", (u32) state->fcaptrim);
2343 dprintk("HFDIV code: %d", (u32) pll->hfdiv_code);
2344 dprintk("VCO = %d", (u32) pll->vco_band);
2345 dprintk("VCOF in kHz: %d ((%d*%d) << 1))", (u32) ((pll->hfdiv * state->rf_request) * 2), (u32) pll->hfdiv, (u32) state->rf_request);
2346 dprintk("REFDIV: %d, FREF: %d", (u32) 1, (u32) state->config->io.clock_khz);
2347 dprintk("FBDIV: %d, Rest: %d", (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
2348 dprintk("Num: %d, Den: %d, SD: %d", (u32) dib0090_read_reg(state, 0x17), (u32) (dib0090_read_reg(state, 0x16) >> 8),
2349 (u32) dib0090_read_reg(state, 0x1c) & 0x3);
2351 #define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */
2352 c = 4;
2353 i = 3;
2355 if (wbd->wbd_gain != 0)
2356 c = wbd->wbd_gain;
2358 state->wbdmux = (c << 13) | (i << 11) | (WBD | (state->config->use_pwm_agc << 1));
2359 dib0090_write_reg(state, 0x10, state->wbdmux);
2361 if ((tune->tuner_enable == EN_CAB) && state->identity.p1g) {
2362 dprintk("P1G : The cable band is selected and lna_tune = %d", tune->lna_tune);
2363 dib0090_write_reg(state, 0x09, tune->lna_bias);
2364 dib0090_write_reg(state, 0x0b, 0xb800 | (tune->lna_tune << 6) | (tune->switch_trim));
2365 } else
2366 dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | tune->lna_bias);
2368 dib0090_write_reg(state, 0x0c, tune->v2i);
2369 dib0090_write_reg(state, 0x0d, tune->mix);
2370 dib0090_write_reg(state, 0x0e, tune->load);
2371 *tune_state = CT_TUNER_STEP_1;
2373 } else if (*tune_state == CT_TUNER_STEP_1) {
2374 /* initialize the lt gain register */
2375 state->rf_lt_def = 0x7c00;
2377 dib0090_set_bandwidth(state);
2378 state->tuner_is_tuned = 1;
2380 state->calibrate |= WBD_CAL;
2381 state->calibrate |= TEMP_CAL;
2382 *tune_state = CT_TUNER_STOP;
2383 } else
2384 ret = FE_CALLBACK_TIME_NEVER;
2385 return ret;
2388 static int dib0090_release(struct dvb_frontend *fe)
2390 kfree(fe->tuner_priv);
2391 fe->tuner_priv = NULL;
2392 return 0;
2395 enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
2397 struct dib0090_state *state = fe->tuner_priv;
2399 return state->tune_state;
2402 EXPORT_SYMBOL(dib0090_get_tune_state);
2404 int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
2406 struct dib0090_state *state = fe->tuner_priv;
2408 state->tune_state = tune_state;
2409 return 0;
2412 EXPORT_SYMBOL(dib0090_set_tune_state);
2414 static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
2416 struct dib0090_state *state = fe->tuner_priv;
2418 *frequency = 1000 * state->current_rf;
2419 return 0;
2422 static int dib0090_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
2424 struct dib0090_state *state = fe->tuner_priv;
2425 u32 ret;
2427 state->tune_state = CT_TUNER_START;
2429 do {
2430 ret = dib0090_tune(fe);
2431 if (ret != FE_CALLBACK_TIME_NEVER)
2432 msleep(ret / 10);
2433 else
2434 break;
2435 } while (state->tune_state != CT_TUNER_STOP);
2437 return 0;
2440 static const struct dvb_tuner_ops dib0090_ops = {
2441 .info = {
2442 .name = "DiBcom DiB0090",
2443 .frequency_min = 45000000,
2444 .frequency_max = 860000000,
2445 .frequency_step = 1000,
2447 .release = dib0090_release,
2449 .init = dib0090_wakeup,
2450 .sleep = dib0090_sleep,
2451 .set_params = dib0090_set_params,
2452 .get_frequency = dib0090_get_frequency,
2455 static const struct dvb_tuner_ops dib0090_fw_ops = {
2456 .info = {
2457 .name = "DiBcom DiB0090",
2458 .frequency_min = 45000000,
2459 .frequency_max = 860000000,
2460 .frequency_step = 1000,
2462 .release = dib0090_release,
2464 .init = NULL,
2465 .sleep = NULL,
2466 .set_params = NULL,
2467 .get_frequency = NULL,
2470 static const struct dib0090_wbd_slope dib0090_wbd_table_default[] = {
2471 {470, 0, 250, 0, 100, 4},
2472 {860, 51, 866, 21, 375, 4},
2473 {1700, 0, 800, 0, 850, 4},
2474 {2900, 0, 250, 0, 100, 6},
2475 {0xFFFF, 0, 0, 0, 0, 0},
2478 struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2480 struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
2481 if (st == NULL)
2482 return NULL;
2484 st->config = config;
2485 st->i2c = i2c;
2486 st->fe = fe;
2487 mutex_init(&st->i2c_buffer_lock);
2488 fe->tuner_priv = st;
2490 if (config->wbd == NULL)
2491 st->current_wbd_table = dib0090_wbd_table_default;
2492 else
2493 st->current_wbd_table = config->wbd;
2495 if (dib0090_reset(fe) != 0)
2496 goto free_mem;
2498 printk(KERN_INFO "DiB0090: successfully identified\n");
2499 memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
2501 return fe;
2502 free_mem:
2503 kfree(st);
2504 fe->tuner_priv = NULL;
2505 return NULL;
2508 EXPORT_SYMBOL(dib0090_register);
2510 struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2512 struct dib0090_fw_state *st = kzalloc(sizeof(struct dib0090_fw_state), GFP_KERNEL);
2513 if (st == NULL)
2514 return NULL;
2516 st->config = config;
2517 st->i2c = i2c;
2518 st->fe = fe;
2519 mutex_init(&st->i2c_buffer_lock);
2520 fe->tuner_priv = st;
2522 if (dib0090_fw_reset_digital(fe, st->config) != 0)
2523 goto free_mem;
2525 dprintk("DiB0090 FW: successfully identified");
2526 memcpy(&fe->ops.tuner_ops, &dib0090_fw_ops, sizeof(struct dvb_tuner_ops));
2528 return fe;
2529 free_mem:
2530 kfree(st);
2531 fe->tuner_priv = NULL;
2532 return NULL;
2534 EXPORT_SYMBOL(dib0090_fw_register);
2536 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
2537 MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>");
2538 MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
2539 MODULE_LICENSE("GPL");