ARC: thp: unbork !CONFIG_TRANSPARENT_HUGEPAGE build
[linux/fpc-iii.git] / drivers / media / dvb-frontends / dib0090.c
blob47cb72243b9da6bfc9c62271592633f2ecadc3db
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);
531 dib0090_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
532 if (cfg->in_soc)
533 return;
535 dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */
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));
545 /* Read Pll current config * */
546 PllCfg = dib0090_read_reg(state, 0x21);
548 /** Reconfigure PLL if current setting is different from default setting **/
549 if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && (!cfg->in_soc)
550 && !cfg->io.pll_bypass) {
552 /* Set Bypass mode */
553 PllCfg |= (1 << 15);
554 dib0090_write_reg(state, 0x21, PllCfg);
556 /* Set Reset Pll */
557 PllCfg &= ~(1 << 13);
558 dib0090_write_reg(state, 0x21, PllCfg);
560 /*** Set new Pll configuration in bypass and reset state ***/
561 PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
562 dib0090_write_reg(state, 0x21, PllCfg);
564 /* Remove Reset Pll */
565 PllCfg |= (1 << 13);
566 dib0090_write_reg(state, 0x21, PllCfg);
568 /*** Wait for PLL lock ***/
569 i = 100;
570 do {
571 v = !!(dib0090_read_reg(state, 0x1a) & 0x800);
572 if (v)
573 break;
574 } while (--i);
576 if (i == 0) {
577 dprintk("Pll: Unable to lock Pll");
578 return;
581 /* Finally Remove Bypass mode */
582 PllCfg &= ~(1 << 15);
583 dib0090_write_reg(state, 0x21, PllCfg);
586 if (cfg->io.pll_bypass) {
587 PllCfg |= (cfg->io.pll_bypass << 15);
588 dib0090_write_reg(state, 0x21, PllCfg);
592 static int dib0090_fw_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
594 struct dib0090_fw_state *state = fe->tuner_priv;
595 u16 PllCfg;
596 u16 v;
597 int i;
599 dprintk("fw reset digital");
600 HARD_RESET(state);
602 dib0090_fw_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
603 dib0090_fw_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */
605 dib0090_fw_write_reg(state, 0x20,
606 ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (cfg->data_tx_drv << 4) | cfg->ls_cfg_pad_drv);
608 v = (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 9) | (0 << 8) | (cfg->clkouttobamse << 4) | (0 << 2) | (0);
609 if (cfg->clkoutdrive != 0)
610 v |= cfg->clkoutdrive << 5;
611 else
612 v |= 7 << 5;
614 v |= 2 << 10;
615 dib0090_fw_write_reg(state, 0x23, v);
617 /* Read Pll current config * */
618 PllCfg = dib0090_fw_read_reg(state, 0x21);
620 /** Reconfigure PLL if current setting is different from default setting **/
621 if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && !cfg->io.pll_bypass) {
623 /* Set Bypass mode */
624 PllCfg |= (1 << 15);
625 dib0090_fw_write_reg(state, 0x21, PllCfg);
627 /* Set Reset Pll */
628 PllCfg &= ~(1 << 13);
629 dib0090_fw_write_reg(state, 0x21, PllCfg);
631 /*** Set new Pll configuration in bypass and reset state ***/
632 PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
633 dib0090_fw_write_reg(state, 0x21, PllCfg);
635 /* Remove Reset Pll */
636 PllCfg |= (1 << 13);
637 dib0090_fw_write_reg(state, 0x21, PllCfg);
639 /*** Wait for PLL lock ***/
640 i = 100;
641 do {
642 v = !!(dib0090_fw_read_reg(state, 0x1a) & 0x800);
643 if (v)
644 break;
645 } while (--i);
647 if (i == 0) {
648 dprintk("Pll: Unable to lock Pll");
649 return -EIO;
652 /* Finally Remove Bypass mode */
653 PllCfg &= ~(1 << 15);
654 dib0090_fw_write_reg(state, 0x21, PllCfg);
657 if (cfg->io.pll_bypass) {
658 PllCfg |= (cfg->io.pll_bypass << 15);
659 dib0090_fw_write_reg(state, 0x21, PllCfg);
662 return dib0090_fw_identify(fe);
665 static int dib0090_wakeup(struct dvb_frontend *fe)
667 struct dib0090_state *state = fe->tuner_priv;
668 if (state->config->sleep)
669 state->config->sleep(fe, 0);
671 /* enable dataTX in case we have been restarted in the wrong moment */
672 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
673 return 0;
676 static int dib0090_sleep(struct dvb_frontend *fe)
678 struct dib0090_state *state = fe->tuner_priv;
679 if (state->config->sleep)
680 state->config->sleep(fe, 1);
681 return 0;
684 void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
686 struct dib0090_state *state = fe->tuner_priv;
687 if (fast)
688 dib0090_write_reg(state, 0x04, 0);
689 else
690 dib0090_write_reg(state, 0x04, 1);
693 EXPORT_SYMBOL(dib0090_dcc_freq);
695 static const u16 bb_ramp_pwm_normal_socs[] = {
696 550, /* max BB gain in 10th of dB */
697 (1<<9) | 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
698 440,
699 (4 << 9) | 0, /* BB_RAMP3 = 26dB */
700 (0 << 9) | 208, /* BB_RAMP4 */
701 (4 << 9) | 208, /* BB_RAMP5 = 29dB */
702 (0 << 9) | 440, /* BB_RAMP6 */
705 static const u16 rf_ramp_pwm_cband_7090p[] = {
706 280, /* max RF gain in 10th of dB */
707 18, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
708 504, /* ramp_max = maximum X used on the ramp */
709 (29 << 10) | 364, /* RF_RAMP5, LNA 1 = 8dB */
710 (0 << 10) | 504, /* RF_RAMP6, LNA 1 */
711 (60 << 10) | 228, /* RF_RAMP7, LNA 2 = 7.7dB */
712 (0 << 10) | 364, /* RF_RAMP8, LNA 2 */
713 (34 << 10) | 109, /* GAIN_4_1, LNA 3 = 6.8dB */
714 (0 << 10) | 228, /* GAIN_4_2, LNA 3 */
715 (37 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */
716 (0 << 10) | 109, /* RF_RAMP4, LNA 4 */
719 static const u16 rf_ramp_pwm_cband_7090e_sensitivity[] = {
720 186, /* max RF gain in 10th of dB */
721 40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
722 746, /* ramp_max = maximum X used on the ramp */
723 (10 << 10) | 345, /* RF_RAMP5, LNA 1 = 10dB */
724 (0 << 10) | 746, /* RF_RAMP6, LNA 1 */
725 (0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */
726 (0 << 10) | 0, /* RF_RAMP8, LNA 2 */
727 (28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */
728 (0 << 10) | 345, /* GAIN_4_2, LNA 3 */
729 (20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */
730 (0 << 10) | 200, /* RF_RAMP4, LNA 4 */
733 static const u16 rf_ramp_pwm_cband_7090e_aci[] = {
734 86, /* max RF gain in 10th of dB */
735 40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
736 345, /* ramp_max = maximum X used on the ramp */
737 (0 << 10) | 0, /* RF_RAMP5, LNA 1 = 8dB */ /* 7.47 dB */
738 (0 << 10) | 0, /* RF_RAMP6, LNA 1 */
739 (0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */
740 (0 << 10) | 0, /* RF_RAMP8, LNA 2 */
741 (28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */
742 (0 << 10) | 345, /* GAIN_4_2, LNA 3 */
743 (20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */
744 (0 << 10) | 200, /* RF_RAMP4, LNA 4 */
747 static const u16 rf_ramp_pwm_cband_8090[] = {
748 345, /* max RF gain in 10th of dB */
749 29, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
750 1000, /* ramp_max = maximum X used on the ramp */
751 (35 << 10) | 772, /* RF_RAMP3, LNA 1 = 8dB */
752 (0 << 10) | 1000, /* RF_RAMP4, LNA 1 */
753 (58 << 10) | 496, /* RF_RAMP5, LNA 2 = 9.5dB */
754 (0 << 10) | 772, /* RF_RAMP6, LNA 2 */
755 (27 << 10) | 200, /* RF_RAMP7, LNA 3 = 10.5dB */
756 (0 << 10) | 496, /* RF_RAMP8, LNA 3 */
757 (40 << 10) | 0, /* GAIN_4_1, LNA 4 = 7dB */
758 (0 << 10) | 200, /* GAIN_4_2, LNA 4 */
761 static const u16 rf_ramp_pwm_uhf_7090[] = {
762 407, /* max RF gain in 10th of dB */
763 13, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
764 529, /* ramp_max = maximum X used on the ramp */
765 (23 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
766 (0 << 10) | 176, /* RF_RAMP4, LNA 1 */
767 (63 << 10) | 400, /* RF_RAMP5, LNA 2 = 8dB */
768 (0 << 10) | 529, /* RF_RAMP6, LNA 2 */
769 (48 << 10) | 316, /* RF_RAMP7, LNA 3 = 6.8dB */
770 (0 << 10) | 400, /* RF_RAMP8, LNA 3 */
771 (29 << 10) | 176, /* GAIN_4_1, LNA 4 = 11.5dB */
772 (0 << 10) | 316, /* GAIN_4_2, LNA 4 */
775 static const u16 rf_ramp_pwm_uhf_8090[] = {
776 388, /* max RF gain in 10th of dB */
777 26, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
778 1008, /* ramp_max = maximum X used on the ramp */
779 (11 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
780 (0 << 10) | 369, /* RF_RAMP4, LNA 1 */
781 (41 << 10) | 809, /* RF_RAMP5, LNA 2 = 8dB */
782 (0 << 10) | 1008, /* RF_RAMP6, LNA 2 */
783 (27 << 10) | 659, /* RF_RAMP7, LNA 3 = 6dB */
784 (0 << 10) | 809, /* RF_RAMP8, LNA 3 */
785 (14 << 10) | 369, /* GAIN_4_1, LNA 4 = 11.5dB */
786 (0 << 10) | 659, /* GAIN_4_2, LNA 4 */
789 /* GENERAL PWM ramp definition for all other Krosus */
790 static const u16 bb_ramp_pwm_normal[] = {
791 500, /* max BB gain in 10th of dB */
792 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
793 400,
794 (2 << 9) | 0, /* BB_RAMP3 = 21dB */
795 (0 << 9) | 168, /* BB_RAMP4 */
796 (2 << 9) | 168, /* BB_RAMP5 = 29dB */
797 (0 << 9) | 400, /* BB_RAMP6 */
800 static const u16 bb_ramp_pwm_boost[] = {
801 550, /* max BB gain in 10th of dB */
802 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
803 440,
804 (2 << 9) | 0, /* BB_RAMP3 = 26dB */
805 (0 << 9) | 208, /* BB_RAMP4 */
806 (2 << 9) | 208, /* BB_RAMP5 = 29dB */
807 (0 << 9) | 440, /* BB_RAMP6 */
810 static const u16 rf_ramp_pwm_cband[] = {
811 314, /* max RF gain in 10th of dB */
812 33, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
813 1023, /* ramp_max = maximum X used on the ramp */
814 (8 << 10) | 743, /* RF_RAMP3, LNA 1 = 0dB */
815 (0 << 10) | 1023, /* RF_RAMP4, LNA 1 */
816 (15 << 10) | 469, /* RF_RAMP5, LNA 2 = 0dB */
817 (0 << 10) | 742, /* RF_RAMP6, LNA 2 */
818 (9 << 10) | 234, /* RF_RAMP7, LNA 3 = 0dB */
819 (0 << 10) | 468, /* RF_RAMP8, LNA 3 */
820 (9 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
821 (0 << 10) | 233, /* GAIN_4_2, LNA 4 */
824 static const u16 rf_ramp_pwm_vhf[] = {
825 398, /* max RF gain in 10th of dB */
826 24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
827 954, /* ramp_max = maximum X used on the ramp */
828 (7 << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */
829 (0 << 10) | 290, /* RF_RAMP4, LNA 1 */
830 (16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */
831 (0 << 10) | 954, /* RF_RAMP6, LNA 2 */
832 (17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */
833 (0 << 10) | 699, /* RF_RAMP8, LNA 3 */
834 (7 << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */
835 (0 << 10) | 580, /* GAIN_4_2, LNA 4 */
838 static const u16 rf_ramp_pwm_uhf[] = {
839 398, /* max RF gain in 10th of dB */
840 24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
841 954, /* ramp_max = maximum X used on the ramp */
842 (7 << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */
843 (0 << 10) | 290, /* RF_RAMP4, LNA 1 */
844 (16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */
845 (0 << 10) | 954, /* RF_RAMP6, LNA 2 */
846 (17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */
847 (0 << 10) | 699, /* RF_RAMP8, LNA 3 */
848 (7 << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */
849 (0 << 10) | 580, /* GAIN_4_2, LNA 4 */
852 static const u16 rf_ramp_pwm_sband[] = {
853 253, /* max RF gain in 10th of dB */
854 38, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
855 961,
856 (4 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.1dB */
857 (0 << 10) | 508, /* RF_RAMP4, LNA 1 */
858 (9 << 10) | 508, /* RF_RAMP5, LNA 2 = 11.2dB */
859 (0 << 10) | 961, /* RF_RAMP6, LNA 2 */
860 (0 << 10) | 0, /* RF_RAMP7, LNA 3 = 0dB */
861 (0 << 10) | 0, /* RF_RAMP8, LNA 3 */
862 (0 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
863 (0 << 10) | 0, /* GAIN_4_2, LNA 4 */
866 struct slope {
867 s16 range;
868 s16 slope;
870 static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
872 u8 i;
873 u16 rest;
874 u16 ret = 0;
875 for (i = 0; i < num; i++) {
876 if (val > slopes[i].range)
877 rest = slopes[i].range;
878 else
879 rest = val;
880 ret += (rest * slopes[i].slope) / slopes[i].range;
881 val -= rest;
883 return ret;
886 static const struct slope dib0090_wbd_slopes[3] = {
887 {66, 120}, /* -64,-52: offset - 65 */
888 {600, 170}, /* -52,-35: 65 - 665 */
889 {170, 250}, /* -45,-10: 665 - 835 */
892 static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
894 wbd &= 0x3ff;
895 if (wbd < state->wbd_offset)
896 wbd = 0;
897 else
898 wbd -= state->wbd_offset;
899 /* -64dB is the floor */
900 return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd);
903 static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
905 u16 offset = 250;
907 /* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */
909 if (state->current_band == BAND_VHF)
910 offset = 650;
911 #ifndef FIRMWARE_FIREFLY
912 if (state->current_band == BAND_VHF)
913 offset = state->config->wbd_vhf_offset;
914 if (state->current_band == BAND_CBAND)
915 offset = state->config->wbd_cband_offset;
916 #endif
918 state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
919 dprintk("wbd-target: %d dB", (u32) state->wbd_target);
922 static const int gain_reg_addr[4] = {
923 0x08, 0x0a, 0x0f, 0x01
926 static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
928 u16 rf, bb, ref;
929 u16 i, v, gain_reg[4] = { 0 }, gain;
930 const u16 *g;
932 if (top_delta < -511)
933 top_delta = -511;
934 if (top_delta > 511)
935 top_delta = 511;
937 if (force) {
938 top_delta *= (1 << WBD_ALPHA);
939 gain_delta *= (1 << GAIN_ALPHA);
942 if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit)) /* overflow */
943 state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
944 else
945 state->rf_gain_limit += top_delta;
947 if (state->rf_gain_limit < 0) /*underflow */
948 state->rf_gain_limit = 0;
950 /* use gain as a temporary variable and correct current_gain */
951 gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA;
952 if (gain_delta >= ((s16) gain - state->current_gain)) /* overflow */
953 state->current_gain = gain;
954 else
955 state->current_gain += gain_delta;
956 /* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */
957 if (state->current_gain < 0)
958 state->current_gain = 0;
960 /* now split total gain to rf and bb gain */
961 gain = state->current_gain >> GAIN_ALPHA;
963 /* requested gain is bigger than rf gain limit - ACI/WBD adjustment */
964 if (gain > (state->rf_gain_limit >> WBD_ALPHA)) {
965 rf = state->rf_gain_limit >> WBD_ALPHA;
966 bb = gain - rf;
967 if (bb > state->bb_ramp[0])
968 bb = state->bb_ramp[0];
969 } else { /* high signal level -> all gains put on RF */
970 rf = gain;
971 bb = 0;
974 state->gain[0] = rf;
975 state->gain[1] = bb;
977 /* software ramp */
978 /* Start with RF gains */
979 g = state->rf_ramp + 1; /* point on RF LNA1 max gain */
980 ref = rf;
981 for (i = 0; i < 7; i++) { /* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */
982 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 */
983 v = 0; /* force the gain to write for the current amp to be null */
984 else if (ref >= g[1]) /* Gain to set is higher than the high working point of this amp */
985 v = g[2]; /* force this amp to be full gain */
986 else /* compute the value to set to this amp because we are somewhere in his range */
987 v = ((ref - (g[1] - g[0])) * g[2]) / g[0];
989 if (i == 0) /* LNA 1 reg mapping */
990 gain_reg[0] = v;
991 else if (i == 1) /* LNA 2 reg mapping */
992 gain_reg[0] |= v << 7;
993 else if (i == 2) /* LNA 3 reg mapping */
994 gain_reg[1] = v;
995 else if (i == 3) /* LNA 4 reg mapping */
996 gain_reg[1] |= v << 7;
997 else if (i == 4) /* CBAND LNA reg mapping */
998 gain_reg[2] = v | state->rf_lt_def;
999 else if (i == 5) /* BB gain 1 reg mapping */
1000 gain_reg[3] = v << 3;
1001 else if (i == 6) /* BB gain 2 reg mapping */
1002 gain_reg[3] |= v << 8;
1004 g += 3; /* go to next gain bloc */
1006 /* When RF is finished, start with BB */
1007 if (i == 4) {
1008 g = state->bb_ramp + 1; /* point on BB gain 1 max gain */
1009 ref = bb;
1012 gain_reg[3] |= state->bb_1_def;
1013 gain_reg[3] |= ((bb % 10) * 100) / 125;
1015 #ifdef DEBUG_AGC
1016 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,
1017 gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]);
1018 #endif
1020 /* Write the amplifier regs */
1021 for (i = 0; i < 4; i++) {
1022 v = gain_reg[i];
1023 if (force || state->gain_reg[i] != v) {
1024 state->gain_reg[i] = v;
1025 dib0090_write_reg(state, gain_reg_addr[i], v);
1030 static void dib0090_set_boost(struct dib0090_state *state, int onoff)
1032 state->bb_1_def &= 0xdfff;
1033 state->bb_1_def |= onoff << 13;
1036 static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
1038 state->rf_ramp = cfg;
1041 static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
1043 state->rf_ramp = cfg;
1045 dib0090_write_reg(state, 0x2a, 0xffff);
1047 dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
1049 dib0090_write_regs(state, 0x2c, cfg + 3, 6);
1050 dib0090_write_regs(state, 0x3e, cfg + 9, 2);
1053 static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
1055 state->bb_ramp = cfg;
1056 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
1059 static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
1061 state->bb_ramp = cfg;
1063 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
1065 dib0090_write_reg(state, 0x33, 0xffff);
1066 dprintk("total BB gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x33));
1067 dib0090_write_regs(state, 0x35, cfg + 3, 4);
1070 void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
1072 struct dib0090_state *state = fe->tuner_priv;
1073 u16 *bb_ramp = (u16 *)&bb_ramp_pwm_normal; /* default baseband config */
1074 u16 *rf_ramp = NULL;
1075 u8 en_pwm_rf_mux = 1;
1077 /* reset the AGC */
1078 if (state->config->use_pwm_agc) {
1079 if (state->current_band == BAND_CBAND) {
1080 if (state->identity.in_soc) {
1081 bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
1082 if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1083 rf_ramp = (u16 *)&rf_ramp_pwm_cband_8090;
1084 else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1) {
1085 if (state->config->is_dib7090e) {
1086 if (state->rf_ramp == NULL)
1087 rf_ramp = (u16 *)&rf_ramp_pwm_cband_7090e_sensitivity;
1088 else
1089 rf_ramp = (u16 *)state->rf_ramp;
1090 } else
1091 rf_ramp = (u16 *)&rf_ramp_pwm_cband_7090p;
1093 } else
1094 rf_ramp = (u16 *)&rf_ramp_pwm_cband;
1095 } else
1097 if (state->current_band == BAND_VHF) {
1098 if (state->identity.in_soc) {
1099 bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
1100 /* rf_ramp = &rf_ramp_pwm_vhf_socs; */ /* TODO */
1101 } else
1102 rf_ramp = (u16 *)&rf_ramp_pwm_vhf;
1103 } else if (state->current_band == BAND_UHF) {
1104 if (state->identity.in_soc) {
1105 bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
1106 if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1107 rf_ramp = (u16 *)&rf_ramp_pwm_uhf_8090;
1108 else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1109 rf_ramp = (u16 *)&rf_ramp_pwm_uhf_7090;
1110 } else
1111 rf_ramp = (u16 *)&rf_ramp_pwm_uhf;
1113 if (rf_ramp)
1114 dib0090_set_rframp_pwm(state, rf_ramp);
1115 dib0090_set_bbramp_pwm(state, bb_ramp);
1117 /* activate the ramp generator using PWM control */
1118 dprintk("ramp RF gain = %d BAND = %s version = %d", state->rf_ramp[0], (state->current_band == BAND_CBAND) ? "CBAND" : "NOT CBAND", state->identity.version & 0x1f);
1120 if ((state->rf_ramp[0] == 0) || (state->current_band == BAND_CBAND && (state->identity.version & 0x1f) <= P1D_E_F)) {
1121 dprintk("DE-Engage mux for direct gain reg control");
1122 en_pwm_rf_mux = 0;
1123 } else
1124 dprintk("Engage mux for PWM control");
1126 dib0090_write_reg(state, 0x32, (en_pwm_rf_mux << 12) | (en_pwm_rf_mux << 11));
1128 /* Set fast servo cutoff to start AGC; 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast*/
1129 if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1130 dib0090_write_reg(state, 0x04, 3);
1131 else
1132 dib0090_write_reg(state, 0x04, 1);
1133 dib0090_write_reg(state, 0x39, (1 << 10)); /* 0 gain by default */
1136 EXPORT_SYMBOL(dib0090_pwm_gain_reset);
1138 void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff)
1140 struct dib0090_state *state = fe->tuner_priv;
1141 if (DC_servo_cutoff < 4)
1142 dib0090_write_reg(state, 0x04, DC_servo_cutoff);
1144 EXPORT_SYMBOL(dib0090_set_dc_servo);
1146 static u32 dib0090_get_slow_adc_val(struct dib0090_state *state)
1148 u16 adc_val = dib0090_read_reg(state, 0x1d);
1149 if (state->identity.in_soc)
1150 adc_val >>= 2;
1151 return adc_val;
1154 int dib0090_gain_control(struct dvb_frontend *fe)
1156 struct dib0090_state *state = fe->tuner_priv;
1157 enum frontend_tune_state *tune_state = &state->tune_state;
1158 int ret = 10;
1160 u16 wbd_val = 0;
1161 u8 apply_gain_immediatly = 1;
1162 s16 wbd_error = 0, adc_error = 0;
1164 if (*tune_state == CT_AGC_START) {
1165 state->agc_freeze = 0;
1166 dib0090_write_reg(state, 0x04, 0x0);
1168 #ifdef CONFIG_BAND_SBAND
1169 if (state->current_band == BAND_SBAND) {
1170 dib0090_set_rframp(state, rf_ramp_sband);
1171 dib0090_set_bbramp(state, bb_ramp_boost);
1172 } else
1173 #endif
1174 #ifdef CONFIG_BAND_VHF
1175 if (state->current_band == BAND_VHF && !state->identity.p1g) {
1176 dib0090_set_rframp(state, rf_ramp_pwm_vhf);
1177 dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1178 } else
1179 #endif
1180 #ifdef CONFIG_BAND_CBAND
1181 if (state->current_band == BAND_CBAND && !state->identity.p1g) {
1182 dib0090_set_rframp(state, rf_ramp_pwm_cband);
1183 dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1184 } else
1185 #endif
1186 if ((state->current_band == BAND_CBAND || state->current_band == BAND_VHF) && state->identity.p1g) {
1187 dib0090_set_rframp(state, rf_ramp_pwm_cband_7090p);
1188 dib0090_set_bbramp(state, bb_ramp_pwm_normal_socs);
1189 } else {
1190 dib0090_set_rframp(state, rf_ramp_pwm_uhf);
1191 dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1194 dib0090_write_reg(state, 0x32, 0);
1195 dib0090_write_reg(state, 0x39, 0);
1197 dib0090_wbd_target(state, state->current_rf);
1199 state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
1200 state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA;
1202 *tune_state = CT_AGC_STEP_0;
1203 } else if (!state->agc_freeze) {
1204 s16 wbd = 0, i, cnt;
1206 int adc;
1207 wbd_val = dib0090_get_slow_adc_val(state);
1209 if (*tune_state == CT_AGC_STEP_0)
1210 cnt = 5;
1211 else
1212 cnt = 1;
1214 for (i = 0; i < cnt; i++) {
1215 wbd_val = dib0090_get_slow_adc_val(state);
1216 wbd += dib0090_wbd_to_db(state, wbd_val);
1218 wbd /= cnt;
1219 wbd_error = state->wbd_target - wbd;
1221 if (*tune_state == CT_AGC_STEP_0) {
1222 if (wbd_error < 0 && state->rf_gain_limit > 0 && !state->identity.p1g) {
1223 #ifdef CONFIG_BAND_CBAND
1224 /* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */
1225 u8 ltg2 = (state->rf_lt_def >> 10) & 0x7;
1226 if (state->current_band == BAND_CBAND && ltg2) {
1227 ltg2 >>= 1;
1228 state->rf_lt_def &= ltg2 << 10; /* reduce in 3 steps from 7 to 0 */
1230 #endif
1231 } else {
1232 state->agc_step = 0;
1233 *tune_state = CT_AGC_STEP_1;
1235 } else {
1236 /* calc the adc power */
1237 adc = state->config->get_adc_power(fe);
1238 adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21; /* included in [0:-700] */
1240 adc_error = (s16) (((s32) ADC_TARGET) - adc);
1241 #ifdef CONFIG_STANDARD_DAB
1242 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)
1243 adc_error -= 10;
1244 #endif
1245 #ifdef CONFIG_STANDARD_DVBT
1246 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT &&
1247 (state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
1248 adc_error += 60;
1249 #endif
1250 #ifdef CONFIG_SYS_ISDBT
1251 if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count >
1254 ((state->fe->dtv_property_cache.layer[0].modulation ==
1255 QAM_64)
1256 || (state->fe->dtv_property_cache.
1257 layer[0].modulation == QAM_16)))
1259 ((state->fe->dtv_property_cache.layer[1].segment_count >
1262 ((state->fe->dtv_property_cache.layer[1].modulation ==
1263 QAM_64)
1264 || (state->fe->dtv_property_cache.
1265 layer[1].modulation == QAM_16)))
1267 ((state->fe->dtv_property_cache.layer[2].segment_count >
1270 ((state->fe->dtv_property_cache.layer[2].modulation ==
1271 QAM_64)
1272 || (state->fe->dtv_property_cache.
1273 layer[2].modulation == QAM_16)))
1276 adc_error += 60;
1277 #endif
1279 if (*tune_state == CT_AGC_STEP_1) { /* quickly go to the correct range of the ADC power */
1280 if (ABS(adc_error) < 50 || state->agc_step++ > 5) {
1282 #ifdef CONFIG_STANDARD_DAB
1283 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) {
1284 dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63)); /* cap value = 63 : narrow BB filter : Fc = 1.8MHz */
1285 dib0090_write_reg(state, 0x04, 0x0);
1286 } else
1287 #endif
1289 dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32));
1290 dib0090_write_reg(state, 0x04, 0x01); /*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */
1293 *tune_state = CT_AGC_STOP;
1295 } else {
1296 /* everything higher than or equal to CT_AGC_STOP means tracking */
1297 ret = 100; /* 10ms interval */
1298 apply_gain_immediatly = 0;
1301 #ifdef DEBUG_AGC
1302 dprintk
1303 ("tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
1304 (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
1305 (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
1306 #endif
1309 /* apply gain */
1310 if (!state->agc_freeze)
1311 dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
1312 return ret;
1315 EXPORT_SYMBOL(dib0090_gain_control);
1317 void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
1319 struct dib0090_state *state = fe->tuner_priv;
1320 if (rf)
1321 *rf = state->gain[0];
1322 if (bb)
1323 *bb = state->gain[1];
1324 if (rf_gain_limit)
1325 *rf_gain_limit = state->rf_gain_limit;
1326 if (rflt)
1327 *rflt = (state->rf_lt_def >> 10) & 0x7;
1330 EXPORT_SYMBOL(dib0090_get_current_gain);
1332 u16 dib0090_get_wbd_target(struct dvb_frontend *fe)
1334 struct dib0090_state *state = fe->tuner_priv;
1335 u32 f_MHz = state->fe->dtv_property_cache.frequency / 1000000;
1336 s32 current_temp = state->temperature;
1337 s32 wbd_thot, wbd_tcold;
1338 const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1340 while (f_MHz > wbd->max_freq)
1341 wbd++;
1343 dprintk("using wbd-table-entry with max freq %d", wbd->max_freq);
1345 if (current_temp < 0)
1346 current_temp = 0;
1347 if (current_temp > 128)
1348 current_temp = 128;
1350 state->wbdmux &= ~(7 << 13);
1351 if (wbd->wbd_gain != 0)
1352 state->wbdmux |= (wbd->wbd_gain << 13);
1353 else
1354 state->wbdmux |= (4 << 13);
1356 dib0090_write_reg(state, 0x10, state->wbdmux);
1358 wbd_thot = wbd->offset_hot - (((u32) wbd->slope_hot * f_MHz) >> 6);
1359 wbd_tcold = wbd->offset_cold - (((u32) wbd->slope_cold * f_MHz) >> 6);
1361 wbd_tcold += ((wbd_thot - wbd_tcold) * current_temp) >> 7;
1363 state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + wbd_tcold);
1364 dprintk("wbd-target: %d dB", (u32) state->wbd_target);
1365 dprintk("wbd offset applied is %d", wbd_tcold);
1367 return state->wbd_offset + wbd_tcold;
1369 EXPORT_SYMBOL(dib0090_get_wbd_target);
1371 u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
1373 struct dib0090_state *state = fe->tuner_priv;
1374 return state->wbd_offset;
1376 EXPORT_SYMBOL(dib0090_get_wbd_offset);
1378 int dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3)
1380 struct dib0090_state *state = fe->tuner_priv;
1382 dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xfff8)
1383 | ((sw3 & 1) << 2) | ((sw2 & 1) << 1) | (sw1 & 1));
1385 return 0;
1387 EXPORT_SYMBOL(dib0090_set_switch);
1389 int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff)
1391 struct dib0090_state *state = fe->tuner_priv;
1393 dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x7fff)
1394 | ((onoff & 1) << 15));
1395 return 0;
1397 EXPORT_SYMBOL(dib0090_set_vga);
1399 int dib0090_update_rframp_7090(struct dvb_frontend *fe, u8 cfg_sensitivity)
1401 struct dib0090_state *state = fe->tuner_priv;
1403 if ((!state->identity.p1g) || (!state->identity.in_soc)
1404 || ((state->identity.version != SOC_7090_P1G_21R1)
1405 && (state->identity.version != SOC_7090_P1G_11R1))) {
1406 dprintk("%s() function can only be used for dib7090P", __func__);
1407 return -ENODEV;
1410 if (cfg_sensitivity)
1411 state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_sensitivity;
1412 else
1413 state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_aci;
1414 dib0090_pwm_gain_reset(fe);
1416 return 0;
1418 EXPORT_SYMBOL(dib0090_update_rframp_7090);
1420 static const u16 dib0090_defaults[] = {
1422 25, 0x01,
1423 0x0000,
1424 0x99a0,
1425 0x6008,
1426 0x0000,
1427 0x8bcb,
1428 0x0000,
1429 0x0405,
1430 0x0000,
1431 0x0000,
1432 0x0000,
1433 0xb802,
1434 0x0300,
1435 0x2d12,
1436 0xbac0,
1437 0x7c00,
1438 0xdbb9,
1439 0x0954,
1440 0x0743,
1441 0x8000,
1442 0x0001,
1443 0x0040,
1444 0x0100,
1445 0x0000,
1446 0xe910,
1447 0x149e,
1449 1, 0x1c,
1450 0xff2d,
1452 1, 0x39,
1453 0x0000,
1455 2, 0x1e,
1456 0x07FF,
1457 0x0007,
1459 1, 0x24,
1460 EN_UHF | EN_CRYSTAL,
1462 2, 0x3c,
1463 0x3ff,
1464 0x111,
1468 static const u16 dib0090_p1g_additionnal_defaults[] = {
1469 1, 0x05,
1470 0xabcd,
1472 1, 0x11,
1473 0x00b4,
1475 1, 0x1c,
1476 0xfffd,
1478 1, 0x40,
1479 0x108,
1483 static void dib0090_set_default_config(struct dib0090_state *state, const u16 * n)
1485 u16 l, r;
1487 l = pgm_read_word(n++);
1488 while (l) {
1489 r = pgm_read_word(n++);
1490 do {
1491 dib0090_write_reg(state, r, pgm_read_word(n++));
1492 r++;
1493 } while (--l);
1494 l = pgm_read_word(n++);
1498 #define CAP_VALUE_MIN (u8) 9
1499 #define CAP_VALUE_MAX (u8) 40
1500 #define HR_MIN (u8) 25
1501 #define HR_MAX (u8) 40
1502 #define POLY_MIN (u8) 0
1503 #define POLY_MAX (u8) 8
1505 static void dib0090_set_EFUSE(struct dib0090_state *state)
1507 u8 c, h, n;
1508 u16 e2, e4;
1509 u16 cal;
1511 e2 = dib0090_read_reg(state, 0x26);
1512 e4 = dib0090_read_reg(state, 0x28);
1514 if ((state->identity.version == P1D_E_F) ||
1515 (state->identity.version == P1G) || (e2 == 0xffff)) {
1517 dib0090_write_reg(state, 0x22, 0x10);
1518 cal = (dib0090_read_reg(state, 0x22) >> 6) & 0x3ff;
1520 if ((cal < 670) || (cal == 1023))
1521 cal = 850;
1522 n = 165 - ((cal * 10)>>6) ;
1523 e2 = e4 = (3<<12) | (34<<6) | (n);
1526 if (e2 != e4)
1527 e2 &= e4; /* Remove the redundancy */
1529 if (e2 != 0xffff) {
1530 c = e2 & 0x3f;
1531 n = (e2 >> 12) & 0xf;
1532 h = (e2 >> 6) & 0x3f;
1534 if ((c >= CAP_VALUE_MAX) || (c <= CAP_VALUE_MIN))
1535 c = 32;
1536 else
1537 c += 14;
1538 if ((h >= HR_MAX) || (h <= HR_MIN))
1539 h = 34;
1540 if ((n >= POLY_MAX) || (n <= POLY_MIN))
1541 n = 3;
1543 dib0090_write_reg(state, 0x13, (h << 10));
1544 e2 = (n << 11) | ((h >> 2)<<6) | c;
1545 dib0090_write_reg(state, 0x2, e2); /* Load the BB_2 */
1549 static int dib0090_reset(struct dvb_frontend *fe)
1551 struct dib0090_state *state = fe->tuner_priv;
1553 dib0090_reset_digital(fe, state->config);
1554 if (dib0090_identify(fe) < 0)
1555 return -EIO;
1557 #ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
1558 if (!(state->identity.version & 0x1)) /* it is P1B - reset is already done */
1559 return 0;
1560 #endif
1562 if (!state->identity.in_soc) {
1563 if ((dib0090_read_reg(state, 0x1a) >> 5) & 0x2)
1564 dib0090_write_reg(state, 0x1b, (EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1565 else
1566 dib0090_write_reg(state, 0x1b, (EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1569 dib0090_set_default_config(state, dib0090_defaults);
1571 if (state->identity.in_soc)
1572 dib0090_write_reg(state, 0x18, 0x2910); /* charge pump current = 0 */
1574 if (state->identity.p1g)
1575 dib0090_set_default_config(state, dib0090_p1g_additionnal_defaults);
1577 /* Update the efuse : Only available for KROSUS > P1C and SOC as well*/
1578 if (((state->identity.version & 0x1f) >= P1D_E_F) || (state->identity.in_soc))
1579 dib0090_set_EFUSE(state);
1581 /* Congigure in function of the crystal */
1582 if (state->config->force_crystal_mode != 0)
1583 dib0090_write_reg(state, 0x14,
1584 state->config->force_crystal_mode & 3);
1585 else if (state->config->io.clock_khz >= 24000)
1586 dib0090_write_reg(state, 0x14, 1);
1587 else
1588 dib0090_write_reg(state, 0x14, 2);
1589 dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
1591 state->calibrate = DC_CAL | WBD_CAL | TEMP_CAL; /* enable iq-offset-calibration and wbd-calibration when tuning next time */
1593 return 0;
1596 #define steps(u) (((u) > 15) ? ((u)-16) : (u))
1597 #define INTERN_WAIT 10
1598 static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1600 int ret = INTERN_WAIT * 10;
1602 switch (*tune_state) {
1603 case CT_TUNER_STEP_2:
1604 /* Turns to positive */
1605 dib0090_write_reg(state, 0x1f, 0x7);
1606 *tune_state = CT_TUNER_STEP_3;
1607 break;
1609 case CT_TUNER_STEP_3:
1610 state->adc_diff = dib0090_read_reg(state, 0x1d);
1612 /* Turns to negative */
1613 dib0090_write_reg(state, 0x1f, 0x4);
1614 *tune_state = CT_TUNER_STEP_4;
1615 break;
1617 case CT_TUNER_STEP_4:
1618 state->adc_diff -= dib0090_read_reg(state, 0x1d);
1619 *tune_state = CT_TUNER_STEP_5;
1620 ret = 0;
1621 break;
1623 default:
1624 break;
1627 return ret;
1630 struct dc_calibration {
1631 u8 addr;
1632 u8 offset;
1633 u8 pga:1;
1634 u16 bb1;
1635 u8 i:1;
1638 static const struct dc_calibration dc_table[] = {
1639 /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
1640 {0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1},
1641 {0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0},
1642 /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
1643 {0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1},
1644 {0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0},
1645 {0},
1648 static const struct dc_calibration dc_p1g_table[] = {
1649 /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
1650 /* addr ; trim reg offset ; pga ; CTRL_BB1 value ; i or q */
1651 {0x06, 5, 1, (1 << 13) | (0 << 8) | (15 << 3), 1},
1652 {0x07, 11, 1, (1 << 13) | (0 << 8) | (15 << 3), 0},
1653 /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
1654 {0x06, 0, 0, (1 << 13) | (29 << 8) | (15 << 3), 1},
1655 {0x06, 10, 0, (1 << 13) | (29 << 8) | (15 << 3), 0},
1656 {0},
1659 static void dib0090_set_trim(struct dib0090_state *state)
1661 u16 *val;
1663 if (state->dc->addr == 0x07)
1664 val = &state->bb7;
1665 else
1666 val = &state->bb6;
1668 *val &= ~(0x1f << state->dc->offset);
1669 *val |= state->step << state->dc->offset;
1671 dib0090_write_reg(state, state->dc->addr, *val);
1674 static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1676 int ret = 0;
1677 u16 reg;
1679 switch (*tune_state) {
1680 case CT_TUNER_START:
1681 dprintk("Start DC offset calibration");
1683 /* force vcm2 = 0.8V */
1684 state->bb6 = 0;
1685 state->bb7 = 0x040d;
1687 /* the LNA AND LO are off */
1688 reg = dib0090_read_reg(state, 0x24) & 0x0ffb; /* shutdown lna and lo */
1689 dib0090_write_reg(state, 0x24, reg);
1691 state->wbdmux = dib0090_read_reg(state, 0x10);
1692 dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x7 << 3) | 0x3);
1693 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
1695 state->dc = dc_table;
1697 if (state->identity.p1g)
1698 state->dc = dc_p1g_table;
1700 /* fall through */
1701 case CT_TUNER_STEP_0:
1702 dprintk("Start/continue DC calibration for %s path", (state->dc->i == 1) ? "I" : "Q");
1703 dib0090_write_reg(state, 0x01, state->dc->bb1);
1704 dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
1706 state->step = 0;
1707 state->min_adc_diff = 1023;
1708 *tune_state = CT_TUNER_STEP_1;
1709 ret = 50;
1710 break;
1712 case CT_TUNER_STEP_1:
1713 dib0090_set_trim(state);
1714 *tune_state = CT_TUNER_STEP_2;
1715 break;
1717 case CT_TUNER_STEP_2:
1718 case CT_TUNER_STEP_3:
1719 case CT_TUNER_STEP_4:
1720 ret = dib0090_get_offset(state, tune_state);
1721 break;
1723 case CT_TUNER_STEP_5: /* found an offset */
1724 dprintk("adc_diff = %d, current step= %d", (u32) state->adc_diff, state->step);
1725 if (state->step == 0 && state->adc_diff < 0) {
1726 state->min_adc_diff = -1023;
1727 dprintk("Change of sign of the minimum adc diff");
1730 dprintk("adc_diff = %d, min_adc_diff = %d current_step = %d", state->adc_diff, state->min_adc_diff, state->step);
1732 /* first turn for this frequency */
1733 if (state->step == 0) {
1734 if (state->dc->pga && state->adc_diff < 0)
1735 state->step = 0x10;
1736 if (state->dc->pga == 0 && state->adc_diff > 0)
1737 state->step = 0x10;
1740 /* Look for a change of Sign in the Adc_diff.min_adc_diff is used to STORE the setp N-1 */
1741 if ((state->adc_diff & 0x8000) == (state->min_adc_diff & 0x8000) && steps(state->step) < 15) {
1742 /* stop search when the delta the sign is changing and Steps =15 and Step=0 is force for continuance */
1743 state->step++;
1744 state->min_adc_diff = state->adc_diff;
1745 *tune_state = CT_TUNER_STEP_1;
1746 } else {
1747 /* the minimum was what we have seen in the step before */
1748 if (ABS(state->adc_diff) > ABS(state->min_adc_diff)) {
1749 dprintk("Since adc_diff N = %d > adc_diff step N-1 = %d, Come back one step", state->adc_diff, state->min_adc_diff);
1750 state->step--;
1753 dib0090_set_trim(state);
1754 dprintk("BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->dc->addr, state->adc_diff, state->step);
1756 state->dc++;
1757 if (state->dc->addr == 0) /* done */
1758 *tune_state = CT_TUNER_STEP_6;
1759 else
1760 *tune_state = CT_TUNER_STEP_0;
1763 break;
1765 case CT_TUNER_STEP_6:
1766 dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008);
1767 dib0090_write_reg(state, 0x1f, 0x7);
1768 *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1769 state->calibrate &= ~DC_CAL;
1770 default:
1771 break;
1773 return ret;
1776 static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1778 u8 wbd_gain;
1779 const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1781 switch (*tune_state) {
1782 case CT_TUNER_START:
1783 while (state->current_rf / 1000 > wbd->max_freq)
1784 wbd++;
1785 if (wbd->wbd_gain != 0)
1786 wbd_gain = wbd->wbd_gain;
1787 else {
1788 wbd_gain = 4;
1789 #if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
1790 if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND))
1791 wbd_gain = 2;
1792 #endif
1795 if (wbd_gain == state->wbd_calibration_gain) { /* the WBD calibration has already been done */
1796 *tune_state = CT_TUNER_START;
1797 state->calibrate &= ~WBD_CAL;
1798 return 0;
1801 dib0090_write_reg(state, 0x10, 0x1b81 | (1 << 10) | (wbd_gain << 13) | (1 << 3));
1803 dib0090_write_reg(state, 0x24, ((EN_UHF & 0x0fff) | (1 << 1)));
1804 *tune_state = CT_TUNER_STEP_0;
1805 state->wbd_calibration_gain = wbd_gain;
1806 return 90; /* wait for the WBDMUX to switch and for the ADC to sample */
1808 case CT_TUNER_STEP_0:
1809 state->wbd_offset = dib0090_get_slow_adc_val(state);
1810 dprintk("WBD calibration offset = %d", state->wbd_offset);
1811 *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1812 state->calibrate &= ~WBD_CAL;
1813 break;
1815 default:
1816 break;
1818 return 0;
1821 static void dib0090_set_bandwidth(struct dib0090_state *state)
1823 u16 tmp;
1825 if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000)
1826 tmp = (3 << 14);
1827 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000)
1828 tmp = (2 << 14);
1829 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000)
1830 tmp = (1 << 14);
1831 else
1832 tmp = (0 << 14);
1834 state->bb_1_def &= 0x3fff;
1835 state->bb_1_def |= tmp;
1837 dib0090_write_reg(state, 0x01, state->bb_1_def); /* be sure that we have the right bb-filter */
1839 dib0090_write_reg(state, 0x03, 0x6008); /* = 0x6008 : vcm3_trim = 1 ; filter2_gm1_trim = 8 ; filter2_cutoff_freq = 0 */
1840 dib0090_write_reg(state, 0x04, 0x1); /* 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast */
1841 if (state->identity.in_soc) {
1842 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 */
1843 } else {
1844 dib0090_write_reg(state, 0x02, (5 << 11) | (8 << 6) | (22 & 0x3f)); /* 22 = cap_value */
1845 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 */
1849 static const struct dib0090_pll dib0090_pll_table[] = {
1850 #ifdef CONFIG_BAND_CBAND
1851 {56000, 0, 9, 48, 6},
1852 {70000, 1, 9, 48, 6},
1853 {87000, 0, 8, 32, 4},
1854 {105000, 1, 8, 32, 4},
1855 {115000, 0, 7, 24, 6},
1856 {140000, 1, 7, 24, 6},
1857 {170000, 0, 6, 16, 4},
1858 #endif
1859 #ifdef CONFIG_BAND_VHF
1860 {200000, 1, 6, 16, 4},
1861 {230000, 0, 5, 12, 6},
1862 {280000, 1, 5, 12, 6},
1863 {340000, 0, 4, 8, 4},
1864 {380000, 1, 4, 8, 4},
1865 {450000, 0, 3, 6, 6},
1866 #endif
1867 #ifdef CONFIG_BAND_UHF
1868 {580000, 1, 3, 6, 6},
1869 {700000, 0, 2, 4, 4},
1870 {860000, 1, 2, 4, 4},
1871 #endif
1872 #ifdef CONFIG_BAND_LBAND
1873 {1800000, 1, 0, 2, 4},
1874 #endif
1875 #ifdef CONFIG_BAND_SBAND
1876 {2900000, 0, 14, 1, 4},
1877 #endif
1880 static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
1882 #ifdef CONFIG_BAND_CBAND
1883 {184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1884 {227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1885 {380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1886 #endif
1887 #ifdef CONFIG_BAND_UHF
1888 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1889 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1890 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1891 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1892 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1893 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1894 #endif
1895 #ifdef CONFIG_BAND_LBAND
1896 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1897 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1898 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1899 #endif
1900 #ifdef CONFIG_BAND_SBAND
1901 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1902 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1903 #endif
1906 static const struct dib0090_tuning dib0090_tuning_table[] = {
1908 #ifdef CONFIG_BAND_CBAND
1909 {170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1910 #endif
1911 #ifdef CONFIG_BAND_VHF
1912 {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1913 {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1914 {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1915 #endif
1916 #ifdef CONFIG_BAND_UHF
1917 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1918 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1919 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1920 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1921 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1922 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1923 #endif
1924 #ifdef CONFIG_BAND_LBAND
1925 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1926 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1927 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1928 #endif
1929 #ifdef CONFIG_BAND_SBAND
1930 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1931 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1932 #endif
1935 static const struct dib0090_tuning dib0090_p1g_tuning_table[] = {
1936 #ifdef CONFIG_BAND_CBAND
1937 {170000, 4, 1, 0x820f, 0x300, 0x2d22, 0x82cb, EN_CAB},
1938 #endif
1939 #ifdef CONFIG_BAND_VHF
1940 {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1941 {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1942 {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1943 #endif
1944 #ifdef CONFIG_BAND_UHF
1945 {510000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1946 {540000, 2, 1, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1947 {600000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1948 {630000, 2, 4, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1949 {680000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1950 {720000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1951 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1952 #endif
1953 #ifdef CONFIG_BAND_LBAND
1954 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1955 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1956 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1957 #endif
1958 #ifdef CONFIG_BAND_SBAND
1959 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1960 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1961 #endif
1964 static const struct dib0090_pll dib0090_p1g_pll_table[] = {
1965 #ifdef CONFIG_BAND_CBAND
1966 {57000, 0, 11, 48, 6},
1967 {70000, 1, 11, 48, 6},
1968 {86000, 0, 10, 32, 4},
1969 {105000, 1, 10, 32, 4},
1970 {115000, 0, 9, 24, 6},
1971 {140000, 1, 9, 24, 6},
1972 {170000, 0, 8, 16, 4},
1973 #endif
1974 #ifdef CONFIG_BAND_VHF
1975 {200000, 1, 8, 16, 4},
1976 {230000, 0, 7, 12, 6},
1977 {280000, 1, 7, 12, 6},
1978 {340000, 0, 6, 8, 4},
1979 {380000, 1, 6, 8, 4},
1980 {455000, 0, 5, 6, 6},
1981 #endif
1982 #ifdef CONFIG_BAND_UHF
1983 {580000, 1, 5, 6, 6},
1984 {680000, 0, 4, 4, 4},
1985 {860000, 1, 4, 4, 4},
1986 #endif
1987 #ifdef CONFIG_BAND_LBAND
1988 {1800000, 1, 2, 2, 4},
1989 #endif
1990 #ifdef CONFIG_BAND_SBAND
1991 {2900000, 0, 1, 1, 6},
1992 #endif
1995 static const struct dib0090_tuning dib0090_p1g_tuning_table_fm_vhf_on_cband[] = {
1996 #ifdef CONFIG_BAND_CBAND
1997 {184000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
1998 {227000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
1999 {380000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
2000 #endif
2001 #ifdef CONFIG_BAND_UHF
2002 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2003 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2004 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2005 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2006 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2007 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2008 #endif
2009 #ifdef CONFIG_BAND_LBAND
2010 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2011 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2012 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2013 #endif
2014 #ifdef CONFIG_BAND_SBAND
2015 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
2016 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
2017 #endif
2020 static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = {
2021 #ifdef CONFIG_BAND_CBAND
2022 {300000, 4, 3, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2023 {380000, 4, 10, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2024 {570000, 4, 10, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2025 {858000, 4, 5, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2026 #endif
2029 static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_sensitivity[] = {
2030 #ifdef CONFIG_BAND_CBAND
2031 { 300000, 0 , 3, 0x8105, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2032 { 380000, 0 , 10, 0x810F, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2033 { 600000, 0 , 10, 0x815E, 0x280, 0x2d12, 0xb84e, EN_CAB },
2034 { 660000, 0 , 5, 0x85E3, 0x280, 0x2d12, 0xb84e, EN_CAB },
2035 { 720000, 0 , 5, 0x852E, 0x280, 0x2d12, 0xb84e, EN_CAB },
2036 { 860000, 0 , 4, 0x85E5, 0x280, 0x2d12, 0xb84e, EN_CAB },
2037 #endif
2040 int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
2041 u8 cfg_sensitivity)
2043 struct dib0090_state *state = fe->tuner_priv;
2044 const struct dib0090_tuning *tune =
2045 dib0090_tuning_table_cband_7090e_sensitivity;
2046 const struct dib0090_tuning dib0090_tuning_table_cband_7090e_aci[] = {
2047 { 300000, 0 , 3, 0x8165, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2048 { 650000, 0 , 4, 0x815B, 0x280, 0x2d12, 0xb84e, EN_CAB },
2049 { 860000, 0 , 5, 0x84EF, 0x280, 0x2d12, 0xb84e, EN_CAB },
2052 if ((!state->identity.p1g) || (!state->identity.in_soc)
2053 || ((state->identity.version != SOC_7090_P1G_21R1)
2054 && (state->identity.version != SOC_7090_P1G_11R1))) {
2055 dprintk("%s() function can only be used for dib7090", __func__);
2056 return -ENODEV;
2059 if (cfg_sensitivity)
2060 tune = dib0090_tuning_table_cband_7090e_sensitivity;
2061 else
2062 tune = dib0090_tuning_table_cband_7090e_aci;
2064 while (state->rf_request > tune->max_freq)
2065 tune++;
2067 dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x8000)
2068 | (tune->lna_bias & 0x7fff));
2069 dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xf83f)
2070 | ((tune->lna_tune << 6) & 0x07c0));
2071 return 0;
2073 EXPORT_SYMBOL(dib0090_update_tuning_table_7090);
2075 static int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2077 int ret = 0;
2078 u16 lo4 = 0xe900;
2080 s16 adc_target;
2081 u16 adc;
2082 s8 step_sign;
2083 u8 force_soft_search = 0;
2085 if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
2086 force_soft_search = 1;
2088 if (*tune_state == CT_TUNER_START) {
2089 dprintk("Start Captrim search : %s", (force_soft_search == 1) ? "FORCE SOFT SEARCH" : "AUTO");
2090 dib0090_write_reg(state, 0x10, 0x2B1);
2091 dib0090_write_reg(state, 0x1e, 0x0032);
2093 if (!state->tuner_is_tuned) {
2094 /* prepare a complete captrim */
2095 if (!state->identity.p1g || force_soft_search)
2096 state->step = state->captrim = state->fcaptrim = 64;
2098 state->current_rf = state->rf_request;
2099 } else { /* we are already tuned to this frequency - the configuration is correct */
2100 if (!state->identity.p1g || force_soft_search) {
2101 /* do a minimal captrim even if the frequency has not changed */
2102 state->step = 4;
2103 state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
2106 state->adc_diff = 3000;
2107 *tune_state = CT_TUNER_STEP_0;
2109 } else if (*tune_state == CT_TUNER_STEP_0) {
2110 if (state->identity.p1g && !force_soft_search) {
2111 u8 ratio = 31;
2113 dib0090_write_reg(state, 0x40, (3 << 7) | (ratio << 2) | (1 << 1) | 1);
2114 dib0090_read_reg(state, 0x40);
2115 ret = 50;
2116 } else {
2117 state->step /= 2;
2118 dib0090_write_reg(state, 0x18, lo4 | state->captrim);
2120 if (state->identity.in_soc)
2121 ret = 25;
2123 *tune_state = CT_TUNER_STEP_1;
2125 } else if (*tune_state == CT_TUNER_STEP_1) {
2126 if (state->identity.p1g && !force_soft_search) {
2127 dib0090_write_reg(state, 0x40, 0x18c | (0 << 1) | 0);
2128 dib0090_read_reg(state, 0x40);
2130 state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7F;
2131 dprintk("***Final Captrim= 0x%x", state->fcaptrim);
2132 *tune_state = CT_TUNER_STEP_3;
2134 } else {
2135 /* MERGE for all krosus before P1G */
2136 adc = dib0090_get_slow_adc_val(state);
2137 dprintk("CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) state->captrim, (u32) adc, (u32) (adc) * (u32) 1800 / (u32) 1024);
2139 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 !!! */
2140 adc_target = 200;
2141 } else
2142 adc_target = 400;
2144 if (adc >= adc_target) {
2145 adc -= adc_target;
2146 step_sign = -1;
2147 } else {
2148 adc = adc_target - adc;
2149 step_sign = 1;
2152 if (adc < state->adc_diff) {
2153 dprintk("CAPTRIM=%d is closer to target (%d/%d)", (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
2154 state->adc_diff = adc;
2155 state->fcaptrim = state->captrim;
2158 state->captrim += step_sign * state->step;
2159 if (state->step >= 1)
2160 *tune_state = CT_TUNER_STEP_0;
2161 else
2162 *tune_state = CT_TUNER_STEP_2;
2164 ret = 25;
2166 } else if (*tune_state == CT_TUNER_STEP_2) { /* this step is only used by krosus < P1G */
2167 /*write the final cptrim config */
2168 dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
2170 *tune_state = CT_TUNER_STEP_3;
2172 } else if (*tune_state == CT_TUNER_STEP_3) {
2173 state->calibrate &= ~CAPTRIM_CAL;
2174 *tune_state = CT_TUNER_STEP_0;
2177 return ret;
2180 static int dib0090_get_temperature(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2182 int ret = 15;
2183 s16 val;
2185 switch (*tune_state) {
2186 case CT_TUNER_START:
2187 state->wbdmux = dib0090_read_reg(state, 0x10);
2188 dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x8 << 3));
2190 state->bias = dib0090_read_reg(state, 0x13);
2191 dib0090_write_reg(state, 0x13, state->bias | (0x3 << 8));
2193 *tune_state = CT_TUNER_STEP_0;
2194 /* wait for the WBDMUX to switch and for the ADC to sample */
2195 break;
2197 case CT_TUNER_STEP_0:
2198 state->adc_diff = dib0090_get_slow_adc_val(state);
2199 dib0090_write_reg(state, 0x13, (state->bias & ~(0x3 << 8)) | (0x2 << 8));
2200 *tune_state = CT_TUNER_STEP_1;
2201 break;
2203 case CT_TUNER_STEP_1:
2204 val = dib0090_get_slow_adc_val(state);
2205 state->temperature = ((s16) ((val - state->adc_diff) * 180) >> 8) + 55;
2207 dprintk("temperature: %d C", state->temperature - 30);
2209 *tune_state = CT_TUNER_STEP_2;
2210 break;
2212 case CT_TUNER_STEP_2:
2213 dib0090_write_reg(state, 0x13, state->bias);
2214 dib0090_write_reg(state, 0x10, state->wbdmux); /* write back original WBDMUX */
2216 *tune_state = CT_TUNER_START;
2217 state->calibrate &= ~TEMP_CAL;
2218 if (state->config->analog_output == 0)
2219 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2221 break;
2223 default:
2224 ret = 0;
2225 break;
2227 return ret;
2230 #define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */
2231 static int dib0090_tune(struct dvb_frontend *fe)
2233 struct dib0090_state *state = fe->tuner_priv;
2234 const struct dib0090_tuning *tune = state->current_tune_table_index;
2235 const struct dib0090_pll *pll = state->current_pll_table_index;
2236 enum frontend_tune_state *tune_state = &state->tune_state;
2238 u16 lo5, lo6, Den, tmp;
2239 u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
2240 int ret = 10; /* 1ms is the default delay most of the time */
2241 u8 c, i;
2243 /************************* VCO ***************************/
2244 /* Default values for FG */
2245 /* from these are needed : */
2246 /* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv */
2248 /* in any case we first need to do a calibration if needed */
2249 if (*tune_state == CT_TUNER_START) {
2250 /* deactivate DataTX before some calibrations */
2251 if (state->calibrate & (DC_CAL | TEMP_CAL | WBD_CAL))
2252 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
2253 else
2254 /* Activate DataTX in case a calibration has been done before */
2255 if (state->config->analog_output == 0)
2256 dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2259 if (state->calibrate & DC_CAL)
2260 return dib0090_dc_offset_calibration(state, tune_state);
2261 else if (state->calibrate & WBD_CAL) {
2262 if (state->current_rf == 0)
2263 state->current_rf = state->fe->dtv_property_cache.frequency / 1000;
2264 return dib0090_wbd_calibration(state, tune_state);
2265 } else if (state->calibrate & TEMP_CAL)
2266 return dib0090_get_temperature(state, tune_state);
2267 else if (state->calibrate & CAPTRIM_CAL)
2268 return dib0090_captrim_search(state, tune_state);
2270 if (*tune_state == CT_TUNER_START) {
2271 /* 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 */
2272 if (state->config->use_pwm_agc && state->identity.in_soc) {
2273 tmp = dib0090_read_reg(state, 0x39);
2274 if ((tmp >> 10) & 0x1)
2275 dib0090_write_reg(state, 0x39, tmp & ~(1 << 10));
2278 state->current_band = (u8) BAND_OF_FREQUENCY(state->fe->dtv_property_cache.frequency / 1000);
2279 state->rf_request =
2280 state->fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
2281 BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->
2282 freq_offset_khz_vhf);
2284 /* in ISDB-T 1seg we shift tuning frequency */
2285 if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1
2286 && state->fe->dtv_property_cache.isdbt_partial_reception == 0)) {
2287 const struct dib0090_low_if_offset_table *LUT_offset = state->config->low_if;
2288 u8 found_offset = 0;
2289 u32 margin_khz = 100;
2291 if (LUT_offset != NULL) {
2292 while (LUT_offset->RF_freq != 0xffff) {
2293 if (((state->rf_request > (LUT_offset->RF_freq - margin_khz))
2294 && (state->rf_request < (LUT_offset->RF_freq + margin_khz)))
2295 && LUT_offset->std == state->fe->dtv_property_cache.delivery_system) {
2296 state->rf_request += LUT_offset->offset_khz;
2297 found_offset = 1;
2298 break;
2300 LUT_offset++;
2304 if (found_offset == 0)
2305 state->rf_request += 400;
2307 if (state->current_rf != state->rf_request || (state->current_standard != state->fe->dtv_property_cache.delivery_system)) {
2308 state->tuner_is_tuned = 0;
2309 state->current_rf = 0;
2310 state->current_standard = 0;
2312 tune = dib0090_tuning_table;
2313 if (state->identity.p1g)
2314 tune = dib0090_p1g_tuning_table;
2316 tmp = (state->identity.version >> 5) & 0x7;
2318 if (state->identity.in_soc) {
2319 if (state->config->force_cband_input) { /* Use the CBAND input for all band */
2320 if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF
2321 || state->current_band & BAND_UHF) {
2322 state->current_band = BAND_CBAND;
2323 if (state->config->is_dib7090e)
2324 tune = dib0090_tuning_table_cband_7090e_sensitivity;
2325 else
2326 tune = dib0090_tuning_table_cband_7090;
2328 } else { /* Use the CBAND input for all band under UHF */
2329 if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) {
2330 state->current_band = BAND_CBAND;
2331 if (state->config->is_dib7090e)
2332 tune = dib0090_tuning_table_cband_7090e_sensitivity;
2333 else
2334 tune = dib0090_tuning_table_cband_7090;
2337 } else
2338 if (tmp == 0x4 || tmp == 0x7) {
2339 /* CBAND tuner version for VHF */
2340 if (state->current_band == BAND_FM || state->current_band == BAND_CBAND || state->current_band == BAND_VHF) {
2341 state->current_band = BAND_CBAND; /* Force CBAND */
2343 tune = dib0090_tuning_table_fm_vhf_on_cband;
2344 if (state->identity.p1g)
2345 tune = dib0090_p1g_tuning_table_fm_vhf_on_cband;
2349 pll = dib0090_pll_table;
2350 if (state->identity.p1g)
2351 pll = dib0090_p1g_pll_table;
2353 /* Look for the interval */
2354 while (state->rf_request > tune->max_freq)
2355 tune++;
2356 while (state->rf_request > pll->max_freq)
2357 pll++;
2359 state->current_tune_table_index = tune;
2360 state->current_pll_table_index = pll;
2362 dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
2364 VCOF_kHz = (pll->hfdiv * state->rf_request) * 2;
2366 FREF = state->config->io.clock_khz;
2367 if (state->config->fref_clock_ratio != 0)
2368 FREF /= state->config->fref_clock_ratio;
2370 FBDiv = (VCOF_kHz / pll->topresc / FREF);
2371 Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
2373 if (Rest < LPF)
2374 Rest = 0;
2375 else if (Rest < 2 * LPF)
2376 Rest = 2 * LPF;
2377 else if (Rest > (FREF - LPF)) {
2378 Rest = 0;
2379 FBDiv += 1;
2380 } else if (Rest > (FREF - 2 * LPF))
2381 Rest = FREF - 2 * LPF;
2382 Rest = (Rest * 6528) / (FREF / 10);
2383 state->rest = Rest;
2385 /* external loop filter, otherwise:
2386 * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
2387 * lo6 = 0x0e34 */
2389 if (Rest == 0) {
2390 if (pll->vco_band)
2391 lo5 = 0x049f;
2392 else
2393 lo5 = 0x041f;
2394 } else {
2395 if (pll->vco_band)
2396 lo5 = 0x049e;
2397 else if (state->config->analog_output)
2398 lo5 = 0x041d;
2399 else
2400 lo5 = 0x041c;
2403 if (state->identity.p1g) { /* Bias is done automatically in P1G */
2404 if (state->identity.in_soc) {
2405 if (state->identity.version == SOC_8090_P1G_11R1)
2406 lo5 = 0x46f;
2407 else
2408 lo5 = 0x42f;
2409 } else
2410 lo5 = 0x42c;
2413 lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7); /* bit 15 is the split to the slave, we do not do it here */
2415 if (!state->config->io.pll_int_loop_filt) {
2416 if (state->identity.in_soc)
2417 lo6 = 0xff98;
2418 else if (state->identity.p1g || (Rest == 0))
2419 lo6 = 0xfff8;
2420 else
2421 lo6 = 0xff28;
2422 } else
2423 lo6 = (state->config->io.pll_int_loop_filt << 3);
2425 Den = 1;
2427 if (Rest > 0) {
2428 if (state->config->analog_output)
2429 lo6 |= (1 << 2) | 2;
2430 else {
2431 if (state->identity.in_soc)
2432 lo6 |= (1 << 2) | 2;
2433 else
2434 lo6 |= (1 << 2) | 2;
2436 Den = 255;
2438 dib0090_write_reg(state, 0x15, (u16) FBDiv);
2439 if (state->config->fref_clock_ratio != 0)
2440 dib0090_write_reg(state, 0x16, (Den << 8) | state->config->fref_clock_ratio);
2441 else
2442 dib0090_write_reg(state, 0x16, (Den << 8) | 1);
2443 dib0090_write_reg(state, 0x17, (u16) Rest);
2444 dib0090_write_reg(state, 0x19, lo5);
2445 dib0090_write_reg(state, 0x1c, lo6);
2447 lo6 = tune->tuner_enable;
2448 if (state->config->analog_output)
2449 lo6 = (lo6 & 0xff9f) | 0x2;
2451 dib0090_write_reg(state, 0x24, lo6 | EN_LO | state->config->use_pwm_agc * EN_CRYSTAL);
2455 state->current_rf = state->rf_request;
2456 state->current_standard = state->fe->dtv_property_cache.delivery_system;
2458 ret = 20;
2459 state->calibrate = CAPTRIM_CAL; /* captrim serach now */
2462 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 */
2463 const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
2465 while (state->current_rf / 1000 > wbd->max_freq)
2466 wbd++;
2468 dib0090_write_reg(state, 0x1e, 0x07ff);
2469 dprintk("Final Captrim: %d", (u32) state->fcaptrim);
2470 dprintk("HFDIV code: %d", (u32) pll->hfdiv_code);
2471 dprintk("VCO = %d", (u32) pll->vco_band);
2472 dprintk("VCOF in kHz: %d ((%d*%d) << 1))", (u32) ((pll->hfdiv * state->rf_request) * 2), (u32) pll->hfdiv, (u32) state->rf_request);
2473 dprintk("REFDIV: %d, FREF: %d", (u32) 1, (u32) state->config->io.clock_khz);
2474 dprintk("FBDIV: %d, Rest: %d", (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
2475 dprintk("Num: %d, Den: %d, SD: %d", (u32) dib0090_read_reg(state, 0x17), (u32) (dib0090_read_reg(state, 0x16) >> 8),
2476 (u32) dib0090_read_reg(state, 0x1c) & 0x3);
2478 #define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */
2479 c = 4;
2480 i = 3;
2482 if (wbd->wbd_gain != 0)
2483 c = wbd->wbd_gain;
2485 state->wbdmux = (c << 13) | (i << 11) | (WBD | (state->config->use_pwm_agc << 1));
2486 dib0090_write_reg(state, 0x10, state->wbdmux);
2488 if ((tune->tuner_enable == EN_CAB) && state->identity.p1g) {
2489 dprintk("P1G : The cable band is selected and lna_tune = %d", tune->lna_tune);
2490 dib0090_write_reg(state, 0x09, tune->lna_bias);
2491 dib0090_write_reg(state, 0x0b, 0xb800 | (tune->lna_tune << 6) | (tune->switch_trim));
2492 } else
2493 dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | tune->lna_bias);
2495 dib0090_write_reg(state, 0x0c, tune->v2i);
2496 dib0090_write_reg(state, 0x0d, tune->mix);
2497 dib0090_write_reg(state, 0x0e, tune->load);
2498 *tune_state = CT_TUNER_STEP_1;
2500 } else if (*tune_state == CT_TUNER_STEP_1) {
2501 /* initialize the lt gain register */
2502 state->rf_lt_def = 0x7c00;
2504 dib0090_set_bandwidth(state);
2505 state->tuner_is_tuned = 1;
2507 state->calibrate |= WBD_CAL;
2508 state->calibrate |= TEMP_CAL;
2509 *tune_state = CT_TUNER_STOP;
2510 } else
2511 ret = FE_CALLBACK_TIME_NEVER;
2512 return ret;
2515 static int dib0090_release(struct dvb_frontend *fe)
2517 kfree(fe->tuner_priv);
2518 fe->tuner_priv = NULL;
2519 return 0;
2522 enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
2524 struct dib0090_state *state = fe->tuner_priv;
2526 return state->tune_state;
2529 EXPORT_SYMBOL(dib0090_get_tune_state);
2531 int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
2533 struct dib0090_state *state = fe->tuner_priv;
2535 state->tune_state = tune_state;
2536 return 0;
2539 EXPORT_SYMBOL(dib0090_set_tune_state);
2541 static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
2543 struct dib0090_state *state = fe->tuner_priv;
2545 *frequency = 1000 * state->current_rf;
2546 return 0;
2549 static int dib0090_set_params(struct dvb_frontend *fe)
2551 struct dib0090_state *state = fe->tuner_priv;
2552 u32 ret;
2554 state->tune_state = CT_TUNER_START;
2556 do {
2557 ret = dib0090_tune(fe);
2558 if (ret == FE_CALLBACK_TIME_NEVER)
2559 break;
2562 * Despite dib0090_tune returns time at a 0.1 ms range,
2563 * the actual sleep time depends on CONFIG_HZ. The worse case
2564 * is when CONFIG_HZ=100. In such case, the minimum granularity
2565 * is 10ms. On some real field tests, the tuner sometimes don't
2566 * lock when this timer is lower than 10ms. So, enforce a 10ms
2567 * granularity and use usleep_range() instead of msleep().
2569 ret = 10 * (ret + 99)/100;
2570 usleep_range(ret * 1000, (ret + 1) * 1000);
2571 } while (state->tune_state != CT_TUNER_STOP);
2573 return 0;
2576 static const struct dvb_tuner_ops dib0090_ops = {
2577 .info = {
2578 .name = "DiBcom DiB0090",
2579 .frequency_min = 45000000,
2580 .frequency_max = 860000000,
2581 .frequency_step = 1000,
2583 .release = dib0090_release,
2585 .init = dib0090_wakeup,
2586 .sleep = dib0090_sleep,
2587 .set_params = dib0090_set_params,
2588 .get_frequency = dib0090_get_frequency,
2591 static const struct dvb_tuner_ops dib0090_fw_ops = {
2592 .info = {
2593 .name = "DiBcom DiB0090",
2594 .frequency_min = 45000000,
2595 .frequency_max = 860000000,
2596 .frequency_step = 1000,
2598 .release = dib0090_release,
2600 .init = NULL,
2601 .sleep = NULL,
2602 .set_params = NULL,
2603 .get_frequency = NULL,
2606 static const struct dib0090_wbd_slope dib0090_wbd_table_default[] = {
2607 {470, 0, 250, 0, 100, 4},
2608 {860, 51, 866, 21, 375, 4},
2609 {1700, 0, 800, 0, 850, 4},
2610 {2900, 0, 250, 0, 100, 6},
2611 {0xFFFF, 0, 0, 0, 0, 0},
2614 struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2616 struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
2617 if (st == NULL)
2618 return NULL;
2620 st->config = config;
2621 st->i2c = i2c;
2622 st->fe = fe;
2623 mutex_init(&st->i2c_buffer_lock);
2624 fe->tuner_priv = st;
2626 if (config->wbd == NULL)
2627 st->current_wbd_table = dib0090_wbd_table_default;
2628 else
2629 st->current_wbd_table = config->wbd;
2631 if (dib0090_reset(fe) != 0)
2632 goto free_mem;
2634 printk(KERN_INFO "DiB0090: successfully identified\n");
2635 memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
2637 return fe;
2638 free_mem:
2639 kfree(st);
2640 fe->tuner_priv = NULL;
2641 return NULL;
2644 EXPORT_SYMBOL(dib0090_register);
2646 struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2648 struct dib0090_fw_state *st = kzalloc(sizeof(struct dib0090_fw_state), GFP_KERNEL);
2649 if (st == NULL)
2650 return NULL;
2652 st->config = config;
2653 st->i2c = i2c;
2654 st->fe = fe;
2655 mutex_init(&st->i2c_buffer_lock);
2656 fe->tuner_priv = st;
2658 if (dib0090_fw_reset_digital(fe, st->config) != 0)
2659 goto free_mem;
2661 dprintk("DiB0090 FW: successfully identified");
2662 memcpy(&fe->ops.tuner_ops, &dib0090_fw_ops, sizeof(struct dvb_tuner_ops));
2664 return fe;
2665 free_mem:
2666 kfree(st);
2667 fe->tuner_priv = NULL;
2668 return NULL;
2670 EXPORT_SYMBOL(dib0090_fw_register);
2672 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
2673 MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>");
2674 MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
2675 MODULE_LICENSE("GPL");