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