Linux 2.6.34-rc3
[pohmelfs.git] / drivers / media / dvb / frontends / dib0090.c
blob7eac178f57b2c10093198c653b4e03e332c9e431
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/i2c.h>
30 #include "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(args...) do { \
40 if (debug) { \
41 printk(KERN_DEBUG "DiB0090: "); \
42 printk(args); \
43 printk("\n"); \
44 } \
45 } while (0)
47 #define CONFIG_SYS_ISDBT
48 #define CONFIG_BAND_CBAND
49 #define CONFIG_BAND_VHF
50 #define CONFIG_BAND_UHF
51 #define CONFIG_DIB0090_USE_PWM_AGC
53 #define EN_LNA0 0x8000
54 #define EN_LNA1 0x4000
55 #define EN_LNA2 0x2000
56 #define EN_LNA3 0x1000
57 #define EN_MIX0 0x0800
58 #define EN_MIX1 0x0400
59 #define EN_MIX2 0x0200
60 #define EN_MIX3 0x0100
61 #define EN_IQADC 0x0040
62 #define EN_PLL 0x0020
63 #define EN_TX 0x0010
64 #define EN_BB 0x0008
65 #define EN_LO 0x0004
66 #define EN_BIAS 0x0001
68 #define EN_IQANA 0x0002
69 #define EN_DIGCLK 0x0080 /* not in the 0x24 reg, only in 0x1b */
70 #define EN_CRYSTAL 0x0002
72 #define EN_UHF 0x22E9
73 #define EN_VHF 0x44E9
74 #define EN_LBD 0x11E9
75 #define EN_SBD 0x44E9
76 #define EN_CAB 0x88E9
78 #define pgm_read_word(w) (*w)
80 struct dc_calibration;
82 struct dib0090_tuning {
83 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
84 u8 switch_trim;
85 u8 lna_tune;
86 u8 lna_bias;
87 u16 v2i;
88 u16 mix;
89 u16 load;
90 u16 tuner_enable;
93 struct dib0090_pll {
94 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
95 u8 vco_band;
96 u8 hfdiv_code;
97 u8 hfdiv;
98 u8 topresc;
101 struct dib0090_state {
102 struct i2c_adapter *i2c;
103 struct dvb_frontend *fe;
104 const struct dib0090_config *config;
106 u8 current_band;
107 u16 revision;
108 enum frontend_tune_state tune_state;
109 u32 current_rf;
111 u16 wbd_offset;
112 s16 wbd_target; /* in dB */
114 s16 rf_gain_limit; /* take-over-point: where to split between bb and rf gain */
115 s16 current_gain; /* keeps the currently programmed gain */
116 u8 agc_step; /* new binary search */
118 u16 gain[2]; /* for channel monitoring */
120 const u16 *rf_ramp;
121 const u16 *bb_ramp;
123 /* for the software AGC ramps */
124 u16 bb_1_def;
125 u16 rf_lt_def;
126 u16 gain_reg[4];
128 /* for the captrim/dc-offset search */
129 s8 step;
130 s16 adc_diff;
131 s16 min_adc_diff;
133 s8 captrim;
134 s8 fcaptrim;
136 const struct dc_calibration *dc;
137 u16 bb6, bb7;
139 const struct dib0090_tuning *current_tune_table_index;
140 const struct dib0090_pll *current_pll_table_index;
142 u8 tuner_is_tuned;
143 u8 agc_freeze;
145 u8 reset;
148 static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
150 u8 b[2];
151 struct i2c_msg msg[2] = {
152 {.addr = state->config->i2c_address, .flags = 0, .buf = &reg, .len = 1},
153 {.addr = state->config->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2},
155 if (i2c_transfer(state->i2c, msg, 2) != 2) {
156 printk(KERN_WARNING "DiB0090 I2C read failed\n");
157 return 0;
159 return (b[0] << 8) | b[1];
162 static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
164 u8 b[3] = { reg & 0xff, val >> 8, val & 0xff };
165 struct i2c_msg msg = {.addr = state->config->i2c_address, .flags = 0, .buf = b, .len = 3 };
166 if (i2c_transfer(state->i2c, &msg, 1) != 1) {
167 printk(KERN_WARNING "DiB0090 I2C write failed\n");
168 return -EREMOTEIO;
170 return 0;
173 #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)
174 #define ADC_TARGET -220
175 #define GAIN_ALPHA 5
176 #define WBD_ALPHA 6
177 #define LPF 100
178 static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c)
180 do {
181 dib0090_write_reg(state, r++, *b++);
182 } while (--c);
185 static u16 dib0090_identify(struct dvb_frontend *fe)
187 struct dib0090_state *state = fe->tuner_priv;
188 u16 v;
190 v = dib0090_read_reg(state, 0x1a);
192 #ifdef FIRMWARE_FIREFLY
193 /* pll is not locked locked */
194 if (!(v & 0x800))
195 dprintk("FE%d : Identification : pll is not yet locked", fe->id);
196 #endif
198 /* without PLL lock info */
199 v &= 0x3ff;
200 dprintk("P/V: %04x:", v);
202 if ((v >> 8) & 0xf)
203 dprintk("FE%d : Product ID = 0x%x : KROSUS", fe->id, (v >> 8) & 0xf);
204 else
205 return 0xff;
207 v &= 0xff;
208 if (((v >> 5) & 0x7) == 0x1)
209 dprintk("FE%d : MP001 : 9090/8096", fe->id);
210 else if (((v >> 5) & 0x7) == 0x4)
211 dprintk("FE%d : MP005 : Single Sband", fe->id);
212 else if (((v >> 5) & 0x7) == 0x6)
213 dprintk("FE%d : MP008 : diversity VHF-UHF-LBAND", fe->id);
214 else if (((v >> 5) & 0x7) == 0x7)
215 dprintk("FE%d : MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND", fe->id);
216 else
217 return 0xff;
219 /* revision only */
220 if ((v & 0x1f) == 0x3)
221 dprintk("FE%d : P1-D/E/F detected", fe->id);
222 else if ((v & 0x1f) == 0x1)
223 dprintk("FE%d : P1C detected", fe->id);
224 else if ((v & 0x1f) == 0x0) {
225 #ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
226 dprintk("FE%d : P1-A/B detected: using previous driver - support will be removed soon", fe->id);
227 dib0090_p1b_register(fe);
228 #else
229 dprintk("FE%d : P1-A/B detected: driver is deactivated - not available", fe->id);
230 return 0xff;
231 #endif
234 return v;
237 static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
239 struct dib0090_state *state = fe->tuner_priv;
241 HARD_RESET(state);
243 dib0090_write_reg(state, 0x24, EN_PLL);
244 dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */
246 /* adcClkOutRatio=8->7, release reset */
247 dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
248 if (cfg->clkoutdrive != 0)
249 dib0090_write_reg(state, 0x23,
250 (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 10) | (1 << 9) | (0 << 8) | (cfg->clkoutdrive << 5) | (cfg->
251 clkouttobamse
252 << 4) | (0
255 | (0));
256 else
257 dib0090_write_reg(state, 0x23,
258 (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 10) | (1 << 9) | (0 << 8) | (7 << 5) | (cfg->
259 clkouttobamse << 4) | (0
262 | (0));
264 /* enable pll, de-activate reset, ratio: 2/1 = 60MHz */
265 dib0090_write_reg(state, 0x21,
266 (cfg->io.pll_bypass << 15) | (1 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv));
270 static int dib0090_wakeup(struct dvb_frontend *fe)
272 struct dib0090_state *state = fe->tuner_priv;
273 if (state->config->sleep)
274 state->config->sleep(fe, 0);
275 return 0;
278 static int dib0090_sleep(struct dvb_frontend *fe)
280 struct dib0090_state *state = fe->tuner_priv;
281 if (state->config->sleep)
282 state->config->sleep(fe, 1);
283 return 0;
286 void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
288 struct dib0090_state *state = fe->tuner_priv;
289 if (fast)
290 dib0090_write_reg(state, 0x04, 0);
291 else
292 dib0090_write_reg(state, 0x04, 1);
294 EXPORT_SYMBOL(dib0090_dcc_freq);
296 static const u16 rf_ramp_pwm_cband[] = {
297 0, /* max RF gain in 10th of dB */
298 0, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
299 0, /* ramp_max = maximum X used on the ramp */
300 (0 << 10) | 0, /* 0x2c, LNA 1 = 0dB */
301 (0 << 10) | 0, /* 0x2d, LNA 1 */
302 (0 << 10) | 0, /* 0x2e, LNA 2 = 0dB */
303 (0 << 10) | 0, /* 0x2f, LNA 2 */
304 (0 << 10) | 0, /* 0x30, LNA 3 = 0dB */
305 (0 << 10) | 0, /* 0x31, LNA 3 */
306 (0 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
307 (0 << 10) | 0, /* GAIN_4_2, LNA 4 */
310 static const u16 rf_ramp_vhf[] = {
311 412, /* max RF gain in 10th of dB */
312 132, 307, 127, /* LNA1, 13.2dB */
313 105, 412, 255, /* LNA2, 10.5dB */
314 50, 50, 127, /* LNA3, 5dB */
315 125, 175, 127, /* LNA4, 12.5dB */
316 0, 0, 127, /* CBAND, 0dB */
319 static const u16 rf_ramp_uhf[] = {
320 412, /* max RF gain in 10th of dB */
321 132, 307, 127, /* LNA1 : total gain = 13.2dB, point on the ramp where this amp is full gain, value to write to get full gain */
322 105, 412, 255, /* LNA2 : 10.5 dB */
323 50, 50, 127, /* LNA3 : 5.0 dB */
324 125, 175, 127, /* LNA4 : 12.5 dB */
325 0, 0, 127, /* CBAND : 0.0 dB */
328 static const u16 rf_ramp_cband[] = {
329 332, /* max RF gain in 10th of dB */
330 132, 252, 127, /* LNA1, dB */
331 80, 332, 255, /* LNA2, dB */
332 0, 0, 127, /* LNA3, dB */
333 0, 0, 127, /* LNA4, dB */
334 120, 120, 127, /* LT1 CBAND */
337 static const u16 rf_ramp_pwm_vhf[] = {
338 404, /* max RF gain in 10th of dB */
339 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
340 1011, /* ramp_max = maximum X used on the ramp */
341 (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */
342 (0 << 10) | 756, /* 0x2d, LNA 1 */
343 (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */
344 (0 << 10) | 1011, /* 0x2f, LNA 2 */
345 (16 << 10) | 290, /* 0x30, LNA 3 = 5dB */
346 (0 << 10) | 417, /* 0x31, LNA 3 */
347 (7 << 10) | 0, /* GAIN_4_1, LNA 4 = 12.5dB */
348 (0 << 10) | 290, /* GAIN_4_2, LNA 4 */
351 static const u16 rf_ramp_pwm_uhf[] = {
352 404, /* max RF gain in 10th of dB */
353 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
354 1011, /* ramp_max = maximum X used on the ramp */
355 (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */
356 (0 << 10) | 756, /* 0x2d, LNA 1 */
357 (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */
358 (0 << 10) | 1011, /* 0x2f, LNA 2 */
359 (16 << 10) | 0, /* 0x30, LNA 3 = 5dB */
360 (0 << 10) | 127, /* 0x31, LNA 3 */
361 (7 << 10) | 127, /* GAIN_4_1, LNA 4 = 12.5dB */
362 (0 << 10) | 417, /* GAIN_4_2, LNA 4 */
365 static const u16 bb_ramp_boost[] = {
366 550, /* max BB gain in 10th of dB */
367 260, 260, 26, /* BB1, 26dB */
368 290, 550, 29, /* BB2, 29dB */
371 static const u16 bb_ramp_pwm_normal[] = {
372 500, /* max RF gain in 10th of dB */
373 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x34 */
374 400,
375 (2 << 9) | 0, /* 0x35 = 21dB */
376 (0 << 9) | 168, /* 0x36 */
377 (2 << 9) | 168, /* 0x37 = 29dB */
378 (0 << 9) | 400, /* 0x38 */
381 struct slope {
382 int16_t range;
383 int16_t slope;
385 static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
387 u8 i;
388 u16 rest;
389 u16 ret = 0;
390 for (i = 0; i < num; i++) {
391 if (val > slopes[i].range)
392 rest = slopes[i].range;
393 else
394 rest = val;
395 ret += (rest * slopes[i].slope) / slopes[i].range;
396 val -= rest;
398 return ret;
401 static const struct slope dib0090_wbd_slopes[3] = {
402 {66, 120}, /* -64,-52: offset - 65 */
403 {600, 170}, /* -52,-35: 65 - 665 */
404 {170, 250}, /* -45,-10: 665 - 835 */
407 static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
409 wbd &= 0x3ff;
410 if (wbd < state->wbd_offset)
411 wbd = 0;
412 else
413 wbd -= state->wbd_offset;
414 /* -64dB is the floor */
415 return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd);
418 static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
420 u16 offset = 250;
422 /* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */
424 if (state->current_band == BAND_VHF)
425 offset = 650;
426 #ifndef FIRMWARE_FIREFLY
427 if (state->current_band == BAND_VHF)
428 offset = state->config->wbd_vhf_offset;
429 if (state->current_band == BAND_CBAND)
430 offset = state->config->wbd_cband_offset;
431 #endif
433 state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
434 dprintk("wbd-target: %d dB", (u32) state->wbd_target);
437 static const int gain_reg_addr[4] = {
438 0x08, 0x0a, 0x0f, 0x01
441 static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
443 u16 rf, bb, ref;
444 u16 i, v, gain_reg[4] = { 0 }, gain;
445 const u16 *g;
447 if (top_delta < -511)
448 top_delta = -511;
449 if (top_delta > 511)
450 top_delta = 511;
452 if (force) {
453 top_delta *= (1 << WBD_ALPHA);
454 gain_delta *= (1 << GAIN_ALPHA);
457 if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit)) /* overflow */
458 state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
459 else
460 state->rf_gain_limit += top_delta;
462 if (state->rf_gain_limit < 0) /*underflow */
463 state->rf_gain_limit = 0;
465 /* use gain as a temporary variable and correct current_gain */
466 gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA;
467 if (gain_delta >= ((s16) gain - state->current_gain)) /* overflow */
468 state->current_gain = gain;
469 else
470 state->current_gain += gain_delta;
471 /* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */
472 if (state->current_gain < 0)
473 state->current_gain = 0;
475 /* now split total gain to rf and bb gain */
476 gain = state->current_gain >> GAIN_ALPHA;
478 /* requested gain is bigger than rf gain limit - ACI/WBD adjustment */
479 if (gain > (state->rf_gain_limit >> WBD_ALPHA)) {
480 rf = state->rf_gain_limit >> WBD_ALPHA;
481 bb = gain - rf;
482 if (bb > state->bb_ramp[0])
483 bb = state->bb_ramp[0];
484 } else { /* high signal level -> all gains put on RF */
485 rf = gain;
486 bb = 0;
489 state->gain[0] = rf;
490 state->gain[1] = bb;
492 /* software ramp */
493 /* Start with RF gains */
494 g = state->rf_ramp + 1; /* point on RF LNA1 max gain */
495 ref = rf;
496 for (i = 0; i < 7; i++) { /* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */
497 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 */
498 v = 0; /* force the gain to write for the current amp to be null */
499 else if (ref >= g[1]) /* Gain to set is higher than the high working point of this amp */
500 v = g[2]; /* force this amp to be full gain */
501 else /* compute the value to set to this amp because we are somewhere in his range */
502 v = ((ref - (g[1] - g[0])) * g[2]) / g[0];
504 if (i == 0) /* LNA 1 reg mapping */
505 gain_reg[0] = v;
506 else if (i == 1) /* LNA 2 reg mapping */
507 gain_reg[0] |= v << 7;
508 else if (i == 2) /* LNA 3 reg mapping */
509 gain_reg[1] = v;
510 else if (i == 3) /* LNA 4 reg mapping */
511 gain_reg[1] |= v << 7;
512 else if (i == 4) /* CBAND LNA reg mapping */
513 gain_reg[2] = v | state->rf_lt_def;
514 else if (i == 5) /* BB gain 1 reg mapping */
515 gain_reg[3] = v << 3;
516 else if (i == 6) /* BB gain 2 reg mapping */
517 gain_reg[3] |= v << 8;
519 g += 3; /* go to next gain bloc */
521 /* When RF is finished, start with BB */
522 if (i == 4) {
523 g = state->bb_ramp + 1; /* point on BB gain 1 max gain */
524 ref = bb;
527 gain_reg[3] |= state->bb_1_def;
528 gain_reg[3] |= ((bb % 10) * 100) / 125;
530 #ifdef DEBUG_AGC
531 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,
532 gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]);
533 #endif
535 /* Write the amplifier regs */
536 for (i = 0; i < 4; i++) {
537 v = gain_reg[i];
538 if (force || state->gain_reg[i] != v) {
539 state->gain_reg[i] = v;
540 dib0090_write_reg(state, gain_reg_addr[i], v);
545 static void dib0090_set_boost(struct dib0090_state *state, int onoff)
547 state->bb_1_def &= 0xdfff;
548 state->bb_1_def |= onoff << 13;
551 static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
553 state->rf_ramp = cfg;
556 static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
558 state->rf_ramp = cfg;
560 dib0090_write_reg(state, 0x2a, 0xffff);
562 dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
564 dib0090_write_regs(state, 0x2c, cfg + 3, 6);
565 dib0090_write_regs(state, 0x3e, cfg + 9, 2);
568 static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
570 state->bb_ramp = cfg;
571 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
574 static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
576 state->bb_ramp = cfg;
578 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
580 dib0090_write_reg(state, 0x33, 0xffff);
581 dprintk("total BB gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x33));
582 dib0090_write_regs(state, 0x35, cfg + 3, 4);
585 void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
587 struct dib0090_state *state = fe->tuner_priv;
588 /* reset the AGC */
590 if (state->config->use_pwm_agc) {
591 #ifdef CONFIG_BAND_SBAND
592 if (state->current_band == BAND_SBAND) {
593 dib0090_set_rframp_pwm(state, rf_ramp_pwm_sband);
594 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_boost);
595 } else
596 #endif
597 #ifdef CONFIG_BAND_CBAND
598 if (state->current_band == BAND_CBAND) {
599 dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband);
600 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
601 } else
602 #endif
603 #ifdef CONFIG_BAND_VHF
604 if (state->current_band == BAND_VHF) {
605 dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf);
606 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
607 } else
608 #endif
610 dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf);
611 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
614 if (state->rf_ramp[0] != 0)
615 dib0090_write_reg(state, 0x32, (3 << 11));
616 else
617 dib0090_write_reg(state, 0x32, (0 << 11));
619 dib0090_write_reg(state, 0x39, (1 << 10));
622 EXPORT_SYMBOL(dib0090_pwm_gain_reset);
624 int dib0090_gain_control(struct dvb_frontend *fe)
626 struct dib0090_state *state = fe->tuner_priv;
627 enum frontend_tune_state *tune_state = &state->tune_state;
628 int ret = 10;
630 u16 wbd_val = 0;
631 u8 apply_gain_immediatly = 1;
632 s16 wbd_error = 0, adc_error = 0;
634 if (*tune_state == CT_AGC_START) {
635 state->agc_freeze = 0;
636 dib0090_write_reg(state, 0x04, 0x0);
638 #ifdef CONFIG_BAND_SBAND
639 if (state->current_band == BAND_SBAND) {
640 dib0090_set_rframp(state, rf_ramp_sband);
641 dib0090_set_bbramp(state, bb_ramp_boost);
642 } else
643 #endif
644 #ifdef CONFIG_BAND_VHF
645 if (state->current_band == BAND_VHF) {
646 dib0090_set_rframp(state, rf_ramp_vhf);
647 dib0090_set_bbramp(state, bb_ramp_boost);
648 } else
649 #endif
650 #ifdef CONFIG_BAND_CBAND
651 if (state->current_band == BAND_CBAND) {
652 dib0090_set_rframp(state, rf_ramp_cband);
653 dib0090_set_bbramp(state, bb_ramp_boost);
654 } else
655 #endif
657 dib0090_set_rframp(state, rf_ramp_uhf);
658 dib0090_set_bbramp(state, bb_ramp_boost);
661 dib0090_write_reg(state, 0x32, 0);
662 dib0090_write_reg(state, 0x39, 0);
664 dib0090_wbd_target(state, state->current_rf);
666 state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
667 state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA;
669 *tune_state = CT_AGC_STEP_0;
670 } else if (!state->agc_freeze) {
671 s16 wbd;
673 int adc;
674 wbd_val = dib0090_read_reg(state, 0x1d);
676 /* read and calc the wbd power */
677 wbd = dib0090_wbd_to_db(state, wbd_val);
678 wbd_error = state->wbd_target - wbd;
680 if (*tune_state == CT_AGC_STEP_0) {
681 if (wbd_error < 0 && state->rf_gain_limit > 0) {
682 #ifdef CONFIG_BAND_CBAND
683 /* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */
684 u8 ltg2 = (state->rf_lt_def >> 10) & 0x7;
685 if (state->current_band == BAND_CBAND && ltg2) {
686 ltg2 >>= 1;
687 state->rf_lt_def &= ltg2 << 10; /* reduce in 3 steps from 7 to 0 */
689 #endif
690 } else {
691 state->agc_step = 0;
692 *tune_state = CT_AGC_STEP_1;
694 } else {
695 /* calc the adc power */
696 adc = state->config->get_adc_power(fe);
697 adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21; /* included in [0:-700] */
699 adc_error = (s16) (((s32) ADC_TARGET) - adc);
700 #ifdef CONFIG_STANDARD_DAB
701 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)
702 adc_error += 130;
703 #endif
704 #ifdef CONFIG_STANDARD_DVBT
705 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT &&
706 (state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
707 adc_error += 60;
708 #endif
709 #ifdef CONFIG_SYS_ISDBT
710 if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count >
713 ((state->fe->dtv_property_cache.layer[0].modulation ==
714 QAM_64)
715 || (state->fe->dtv_property_cache.layer[0].
716 modulation == QAM_16)))
718 ((state->fe->dtv_property_cache.layer[1].segment_count >
721 ((state->fe->dtv_property_cache.layer[1].modulation ==
722 QAM_64)
723 || (state->fe->dtv_property_cache.layer[1].
724 modulation == QAM_16)))
726 ((state->fe->dtv_property_cache.layer[2].segment_count >
729 ((state->fe->dtv_property_cache.layer[2].modulation ==
730 QAM_64)
731 || (state->fe->dtv_property_cache.layer[2].
732 modulation == QAM_16)))
735 adc_error += 60;
736 #endif
738 if (*tune_state == CT_AGC_STEP_1) { /* quickly go to the correct range of the ADC power */
739 if (ABS(adc_error) < 50 || state->agc_step++ > 5) {
741 #ifdef CONFIG_STANDARD_DAB
742 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) {
743 dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63)); /* cap value = 63 : narrow BB filter : Fc = 1.8MHz */
744 dib0090_write_reg(state, 0x04, 0x0);
745 } else
746 #endif
748 dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32));
749 dib0090_write_reg(state, 0x04, 0x01); /*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */
752 *tune_state = CT_AGC_STOP;
754 } else {
755 /* everything higher than or equal to CT_AGC_STOP means tracking */
756 ret = 100; /* 10ms interval */
757 apply_gain_immediatly = 0;
760 #ifdef DEBUG_AGC
761 dprintk
762 ("FE: %d, tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
763 (u32) fe->id, (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
764 (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
765 #endif
768 /* apply gain */
769 if (!state->agc_freeze)
770 dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
771 return ret;
773 EXPORT_SYMBOL(dib0090_gain_control);
775 void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
777 struct dib0090_state *state = fe->tuner_priv;
778 if (rf)
779 *rf = state->gain[0];
780 if (bb)
781 *bb = state->gain[1];
782 if (rf_gain_limit)
783 *rf_gain_limit = state->rf_gain_limit;
784 if (rflt)
785 *rflt = (state->rf_lt_def >> 10) & 0x7;
787 EXPORT_SYMBOL(dib0090_get_current_gain);
789 u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner)
791 struct dib0090_state *st = tuner->tuner_priv;
792 return st->wbd_offset;
794 EXPORT_SYMBOL(dib0090_get_wbd_offset);
796 static const u16 dib0090_defaults[] = {
798 25, 0x01,
799 0x0000,
800 0x99a0,
801 0x6008,
802 0x0000,
803 0x8acb,
804 0x0000,
805 0x0405,
806 0x0000,
807 0x0000,
808 0x0000,
809 0xb802,
810 0x0300,
811 0x2d12,
812 0xbac0,
813 0x7c00,
814 0xdbb9,
815 0x0954,
816 0x0743,
817 0x8000,
818 0x0001,
819 0x0040,
820 0x0100,
821 0x0000,
822 0xe910,
823 0x149e,
825 1, 0x1c,
826 0xff2d,
828 1, 0x39,
829 0x0000,
831 1, 0x1b,
832 EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL,
833 2, 0x1e,
834 0x07FF,
835 0x0007,
837 1, 0x24,
838 EN_UHF | EN_CRYSTAL,
840 2, 0x3c,
841 0x3ff,
842 0x111,
846 static int dib0090_reset(struct dvb_frontend *fe)
848 struct dib0090_state *state = fe->tuner_priv;
849 u16 l, r, *n;
851 dib0090_reset_digital(fe, state->config);
852 state->revision = dib0090_identify(fe);
854 /* Revision definition */
855 if (state->revision == 0xff)
856 return -EINVAL;
857 #ifdef EFUSE
858 else if ((state->revision & 0x1f) >= 3) /* Update the efuse : Only available for KROSUS > P1C */
859 dib0090_set_EFUSE(state);
860 #endif
862 #ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
863 if (!(state->revision & 0x1)) /* it is P1B - reset is already done */
864 return 0;
865 #endif
867 /* Upload the default values */
868 n = (u16 *) dib0090_defaults;
869 l = pgm_read_word(n++);
870 while (l) {
871 r = pgm_read_word(n++);
872 do {
873 /* DEBUG_TUNER */
874 /* dprintk("%d, %d, %d", l, r, pgm_read_word(n)); */
875 dib0090_write_reg(state, r, pgm_read_word(n++));
876 r++;
877 } while (--l);
878 l = pgm_read_word(n++);
881 /* Congigure in function of the crystal */
882 if (state->config->io.clock_khz >= 24000)
883 l = 1;
884 else
885 l = 2;
886 dib0090_write_reg(state, 0x14, l);
887 dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
889 state->reset = 3; /* enable iq-offset-calibration and wbd-calibration when tuning next time */
891 return 0;
894 #define steps(u) (((u) > 15) ? ((u)-16) : (u))
895 #define INTERN_WAIT 10
896 static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
898 int ret = INTERN_WAIT * 10;
900 switch (*tune_state) {
901 case CT_TUNER_STEP_2:
902 /* Turns to positive */
903 dib0090_write_reg(state, 0x1f, 0x7);
904 *tune_state = CT_TUNER_STEP_3;
905 break;
907 case CT_TUNER_STEP_3:
908 state->adc_diff = dib0090_read_reg(state, 0x1d);
910 /* Turns to negative */
911 dib0090_write_reg(state, 0x1f, 0x4);
912 *tune_state = CT_TUNER_STEP_4;
913 break;
915 case CT_TUNER_STEP_4:
916 state->adc_diff -= dib0090_read_reg(state, 0x1d);
917 *tune_state = CT_TUNER_STEP_5;
918 ret = 0;
919 break;
921 default:
922 break;
925 return ret;
928 struct dc_calibration {
929 uint8_t addr;
930 uint8_t offset;
931 uint8_t pga:1;
932 uint16_t bb1;
933 uint8_t i:1;
936 static const struct dc_calibration dc_table[] = {
937 /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
938 {0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1},
939 {0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0},
940 /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
941 {0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1},
942 {0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0},
943 {0},
946 static void dib0090_set_trim(struct dib0090_state *state)
948 u16 *val;
950 if (state->dc->addr == 0x07)
951 val = &state->bb7;
952 else
953 val = &state->bb6;
955 *val &= ~(0x1f << state->dc->offset);
956 *val |= state->step << state->dc->offset;
958 dib0090_write_reg(state, state->dc->addr, *val);
961 static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
963 int ret = 0;
965 switch (*tune_state) {
967 case CT_TUNER_START:
968 /* init */
969 dprintk("Internal DC calibration");
971 /* the LNA is off */
972 dib0090_write_reg(state, 0x24, 0x02ed);
974 /* force vcm2 = 0.8V */
975 state->bb6 = 0;
976 state->bb7 = 0x040d;
978 state->dc = dc_table;
980 *tune_state = CT_TUNER_STEP_0;
982 /* fall through */
984 case CT_TUNER_STEP_0:
985 dib0090_write_reg(state, 0x01, state->dc->bb1);
986 dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
988 state->step = 0;
990 state->min_adc_diff = 1023;
992 *tune_state = CT_TUNER_STEP_1;
993 ret = 50;
994 break;
996 case CT_TUNER_STEP_1:
997 dib0090_set_trim(state);
999 *tune_state = CT_TUNER_STEP_2;
1000 break;
1002 case CT_TUNER_STEP_2:
1003 case CT_TUNER_STEP_3:
1004 case CT_TUNER_STEP_4:
1005 ret = dib0090_get_offset(state, tune_state);
1006 break;
1008 case CT_TUNER_STEP_5: /* found an offset */
1009 dprintk("FE%d: IQC read=%d, current=%x", state->fe->id, (u32) state->adc_diff, state->step);
1011 /* first turn for this frequency */
1012 if (state->step == 0) {
1013 if (state->dc->pga && state->adc_diff < 0)
1014 state->step = 0x10;
1015 if (state->dc->pga == 0 && state->adc_diff > 0)
1016 state->step = 0x10;
1019 state->adc_diff = ABS(state->adc_diff);
1021 if (state->adc_diff < state->min_adc_diff && steps(state->step) < 15) { /* stop search when the delta to 0 is increasing */
1022 state->step++;
1023 state->min_adc_diff = state->adc_diff;
1024 *tune_state = CT_TUNER_STEP_1;
1025 } else {
1027 /* the minimum was what we have seen in the step before */
1028 state->step--;
1029 dib0090_set_trim(state);
1031 dprintk("FE%d: BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->fe->id, state->dc->addr, state->adc_diff,
1032 state->step);
1034 state->dc++;
1035 if (state->dc->addr == 0) /* done */
1036 *tune_state = CT_TUNER_STEP_6;
1037 else
1038 *tune_state = CT_TUNER_STEP_0;
1041 break;
1043 case CT_TUNER_STEP_6:
1044 dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008);
1045 dib0090_write_reg(state, 0x1f, 0x7);
1046 *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1047 state->reset &= ~0x1;
1048 default:
1049 break;
1051 return ret;
1054 static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1056 switch (*tune_state) {
1057 case CT_TUNER_START:
1058 /* WBD-mode=log, Bias=2, Gain=6, Testmode=1, en=1, WBDMUX=1 */
1059 dib0090_write_reg(state, 0x10, 0xdb09 | (1 << 10));
1060 dib0090_write_reg(state, 0x24, EN_UHF & 0x0fff);
1062 *tune_state = CT_TUNER_STEP_0;
1063 return 90; /* wait for the WBDMUX to switch and for the ADC to sample */
1064 case CT_TUNER_STEP_0:
1065 state->wbd_offset = dib0090_read_reg(state, 0x1d);
1066 dprintk("WBD calibration offset = %d", state->wbd_offset);
1068 *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1069 state->reset &= ~0x2;
1070 break;
1071 default:
1072 break;
1074 return 0;
1077 static void dib0090_set_bandwidth(struct dib0090_state *state)
1079 u16 tmp;
1081 if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000)
1082 tmp = (3 << 14);
1083 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000)
1084 tmp = (2 << 14);
1085 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000)
1086 tmp = (1 << 14);
1087 else
1088 tmp = (0 << 14);
1090 state->bb_1_def &= 0x3fff;
1091 state->bb_1_def |= tmp;
1093 dib0090_write_reg(state, 0x01, state->bb_1_def); /* be sure that we have the right bb-filter */
1096 static const struct dib0090_pll dib0090_pll_table[] = {
1097 #ifdef CONFIG_BAND_CBAND
1098 {56000, 0, 9, 48, 6},
1099 {70000, 1, 9, 48, 6},
1100 {87000, 0, 8, 32, 4},
1101 {105000, 1, 8, 32, 4},
1102 {115000, 0, 7, 24, 6},
1103 {140000, 1, 7, 24, 6},
1104 {170000, 0, 6, 16, 4},
1105 #endif
1106 #ifdef CONFIG_BAND_VHF
1107 {200000, 1, 6, 16, 4},
1108 {230000, 0, 5, 12, 6},
1109 {280000, 1, 5, 12, 6},
1110 {340000, 0, 4, 8, 4},
1111 {380000, 1, 4, 8, 4},
1112 {450000, 0, 3, 6, 6},
1113 #endif
1114 #ifdef CONFIG_BAND_UHF
1115 {580000, 1, 3, 6, 6},
1116 {700000, 0, 2, 4, 4},
1117 {860000, 1, 2, 4, 4},
1118 #endif
1119 #ifdef CONFIG_BAND_LBAND
1120 {1800000, 1, 0, 2, 4},
1121 #endif
1122 #ifdef CONFIG_BAND_SBAND
1123 {2900000, 0, 14, 1, 4},
1124 #endif
1127 static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
1129 #ifdef CONFIG_BAND_CBAND
1130 {184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1131 {227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1132 {380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1133 #endif
1134 #ifdef CONFIG_BAND_UHF
1135 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1136 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1137 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1138 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1139 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1140 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1141 #endif
1142 #ifdef CONFIG_BAND_LBAND
1143 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1144 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1145 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1146 #endif
1147 #ifdef CONFIG_BAND_SBAND
1148 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1149 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1150 #endif
1153 static const struct dib0090_tuning dib0090_tuning_table[] = {
1155 #ifdef CONFIG_BAND_CBAND
1156 {170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1157 #endif
1158 #ifdef CONFIG_BAND_VHF
1159 {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1160 {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1161 {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1162 #endif
1163 #ifdef CONFIG_BAND_UHF
1164 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1165 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1166 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1167 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1168 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1169 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1170 #endif
1171 #ifdef CONFIG_BAND_LBAND
1172 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1173 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1174 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1175 #endif
1176 #ifdef CONFIG_BAND_SBAND
1177 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1178 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1179 #endif
1182 #define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */
1183 static int dib0090_tune(struct dvb_frontend *fe)
1185 struct dib0090_state *state = fe->tuner_priv;
1186 const struct dib0090_tuning *tune = state->current_tune_table_index;
1187 const struct dib0090_pll *pll = state->current_pll_table_index;
1188 enum frontend_tune_state *tune_state = &state->tune_state;
1190 u32 rf;
1191 u16 lo4 = 0xe900, lo5, lo6, Den;
1192 u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
1193 u16 tmp, adc;
1194 int8_t step_sign;
1195 int ret = 10; /* 1ms is the default delay most of the time */
1196 u8 c, i;
1198 state->current_band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000);
1199 rf = fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
1200 BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->freq_offset_khz_vhf);
1201 /* in any case we first need to do a reset if needed */
1202 if (state->reset & 0x1)
1203 return dib0090_dc_offset_calibration(state, tune_state);
1204 else if (state->reset & 0x2)
1205 return dib0090_wbd_calibration(state, tune_state);
1207 /************************* VCO ***************************/
1208 /* Default values for FG */
1209 /* from these are needed : */
1210 /* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv */
1212 #ifdef CONFIG_SYS_ISDBT
1213 if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
1214 rf += 850;
1215 #endif
1217 if (state->current_rf != rf) {
1218 state->tuner_is_tuned = 0;
1220 tune = dib0090_tuning_table;
1222 tmp = (state->revision >> 5) & 0x7;
1223 if (tmp == 0x4 || tmp == 0x7) {
1224 /* CBAND tuner version for VHF */
1225 if (state->current_band == BAND_FM || state->current_band == BAND_VHF) {
1226 /* Force CBAND */
1227 state->current_band = BAND_CBAND;
1228 tune = dib0090_tuning_table_fm_vhf_on_cband;
1232 pll = dib0090_pll_table;
1233 /* Look for the interval */
1234 while (rf > tune->max_freq)
1235 tune++;
1236 while (rf > pll->max_freq)
1237 pll++;
1238 state->current_tune_table_index = tune;
1239 state->current_pll_table_index = pll;
1242 if (*tune_state == CT_TUNER_START) {
1244 if (state->tuner_is_tuned == 0)
1245 state->current_rf = 0;
1247 if (state->current_rf != rf) {
1249 dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
1251 /* external loop filter, otherwise:
1252 * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
1253 * lo6 = 0x0e34 */
1254 if (pll->vco_band)
1255 lo5 = 0x049e;
1256 else if (state->config->analog_output)
1257 lo5 = 0x041d;
1258 else
1259 lo5 = 0x041c;
1261 lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7); /* bit 15 is the split to the slave, we do not do it here */
1263 if (!state->config->io.pll_int_loop_filt)
1264 lo6 = 0xff28;
1265 else
1266 lo6 = (state->config->io.pll_int_loop_filt << 3);
1268 VCOF_kHz = (pll->hfdiv * rf) * 2;
1270 FREF = state->config->io.clock_khz;
1272 FBDiv = (VCOF_kHz / pll->topresc / FREF);
1273 Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
1275 if (Rest < LPF)
1276 Rest = 0;
1277 else if (Rest < 2 * LPF)
1278 Rest = 2 * LPF;
1279 else if (Rest > (FREF - LPF)) {
1280 Rest = 0;
1281 FBDiv += 1;
1282 } else if (Rest > (FREF - 2 * LPF))
1283 Rest = FREF - 2 * LPF;
1284 Rest = (Rest * 6528) / (FREF / 10);
1286 Den = 1;
1288 dprintk(" ***** ******* Rest value = %d", Rest);
1290 if (Rest > 0) {
1291 if (state->config->analog_output)
1292 lo6 |= (1 << 2) | 2;
1293 else
1294 lo6 |= (1 << 2) | 1;
1295 Den = 255;
1297 #ifdef CONFIG_BAND_SBAND
1298 if (state->current_band == BAND_SBAND)
1299 lo6 &= 0xfffb;
1300 #endif
1302 dib0090_write_reg(state, 0x15, (u16) FBDiv);
1304 dib0090_write_reg(state, 0x16, (Den << 8) | 1);
1306 dib0090_write_reg(state, 0x17, (u16) Rest);
1308 dib0090_write_reg(state, 0x19, lo5);
1310 dib0090_write_reg(state, 0x1c, lo6);
1312 lo6 = tune->tuner_enable;
1313 if (state->config->analog_output)
1314 lo6 = (lo6 & 0xff9f) | 0x2;
1316 dib0090_write_reg(state, 0x24, lo6 | EN_LO
1317 #ifdef CONFIG_DIB0090_USE_PWM_AGC
1318 | state->config->use_pwm_agc * EN_CRYSTAL
1319 #endif
1322 state->current_rf = rf;
1324 /* prepare a complete captrim */
1325 state->step = state->captrim = state->fcaptrim = 64;
1327 } else { /* we are already tuned to this frequency - the configuration is correct */
1329 /* do a minimal captrim even if the frequency has not changed */
1330 state->step = 4;
1331 state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
1333 state->adc_diff = 3000;
1335 dib0090_write_reg(state, 0x10, 0x2B1);
1337 dib0090_write_reg(state, 0x1e, 0x0032);
1339 ret = 20;
1340 *tune_state = CT_TUNER_STEP_1;
1341 } else if (*tune_state == CT_TUNER_STEP_0) {
1342 /* nothing */
1343 } else if (*tune_state == CT_TUNER_STEP_1) {
1344 state->step /= 2;
1345 dib0090_write_reg(state, 0x18, lo4 | state->captrim);
1346 *tune_state = CT_TUNER_STEP_2;
1347 } else if (*tune_state == CT_TUNER_STEP_2) {
1349 adc = dib0090_read_reg(state, 0x1d);
1350 dprintk("FE %d CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) fe->id, (u32) state->captrim, (u32) adc,
1351 (u32) (adc) * (u32) 1800 / (u32) 1024);
1353 if (adc >= 400) {
1354 adc -= 400;
1355 step_sign = -1;
1356 } else {
1357 adc = 400 - adc;
1358 step_sign = 1;
1361 if (adc < state->adc_diff) {
1362 dprintk("FE %d CAPTRIM=%d is closer to target (%d/%d)", (u32) fe->id, (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
1363 state->adc_diff = adc;
1364 state->fcaptrim = state->captrim;
1368 state->captrim += step_sign * state->step;
1369 if (state->step >= 1)
1370 *tune_state = CT_TUNER_STEP_1;
1371 else
1372 *tune_state = CT_TUNER_STEP_3;
1374 ret = 15;
1375 } else if (*tune_state == CT_TUNER_STEP_3) {
1376 /*write the final cptrim config */
1377 dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
1379 #ifdef CONFIG_TUNER_DIB0090_CAPTRIM_MEMORY
1380 state->memory[state->memory_index].cap = state->fcaptrim;
1381 #endif
1383 *tune_state = CT_TUNER_STEP_4;
1384 } else if (*tune_state == CT_TUNER_STEP_4) {
1385 dib0090_write_reg(state, 0x1e, 0x07ff);
1387 dprintk("FE %d Final Captrim: %d", (u32) fe->id, (u32) state->fcaptrim);
1388 dprintk("FE %d HFDIV code: %d", (u32) fe->id, (u32) pll->hfdiv_code);
1389 dprintk("FE %d VCO = %d", (u32) fe->id, (u32) pll->vco_band);
1390 dprintk("FE %d VCOF in kHz: %d ((%d*%d) << 1))", (u32) fe->id, (u32) ((pll->hfdiv * rf) * 2), (u32) pll->hfdiv, (u32) rf);
1391 dprintk("FE %d REFDIV: %d, FREF: %d", (u32) fe->id, (u32) 1, (u32) state->config->io.clock_khz);
1392 dprintk("FE %d FBDIV: %d, Rest: %d", (u32) fe->id, (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
1393 dprintk("FE %d Num: %d, Den: %d, SD: %d", (u32) fe->id, (u32) dib0090_read_reg(state, 0x17),
1394 (u32) (dib0090_read_reg(state, 0x16) >> 8), (u32) dib0090_read_reg(state, 0x1c) & 0x3);
1396 c = 4;
1397 i = 3;
1398 #if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
1399 if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND)) {
1400 c = 2;
1401 i = 2;
1403 #endif
1404 dib0090_write_reg(state, 0x10, (c << 13) | (i << 11) | (WBD
1405 #ifdef CONFIG_DIB0090_USE_PWM_AGC
1406 | (state->config->use_pwm_agc << 1)
1407 #endif
1409 dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | (tune->lna_bias << 0));
1410 dib0090_write_reg(state, 0x0c, tune->v2i);
1411 dib0090_write_reg(state, 0x0d, tune->mix);
1412 dib0090_write_reg(state, 0x0e, tune->load);
1414 *tune_state = CT_TUNER_STEP_5;
1415 } else if (*tune_state == CT_TUNER_STEP_5) {
1417 /* initialize the lt gain register */
1418 state->rf_lt_def = 0x7c00;
1419 dib0090_write_reg(state, 0x0f, state->rf_lt_def);
1421 dib0090_set_bandwidth(state);
1422 state->tuner_is_tuned = 1;
1423 *tune_state = CT_TUNER_STOP;
1424 } else
1425 ret = FE_CALLBACK_TIME_NEVER;
1426 return ret;
1429 static int dib0090_release(struct dvb_frontend *fe)
1431 kfree(fe->tuner_priv);
1432 fe->tuner_priv = NULL;
1433 return 0;
1436 enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
1438 struct dib0090_state *state = fe->tuner_priv;
1440 return state->tune_state;
1442 EXPORT_SYMBOL(dib0090_get_tune_state);
1444 int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
1446 struct dib0090_state *state = fe->tuner_priv;
1448 state->tune_state = tune_state;
1449 return 0;
1451 EXPORT_SYMBOL(dib0090_set_tune_state);
1453 static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
1455 struct dib0090_state *state = fe->tuner_priv;
1457 *frequency = 1000 * state->current_rf;
1458 return 0;
1461 static int dib0090_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
1463 struct dib0090_state *state = fe->tuner_priv;
1464 uint32_t ret;
1466 state->tune_state = CT_TUNER_START;
1468 do {
1469 ret = dib0090_tune(fe);
1470 if (ret != FE_CALLBACK_TIME_NEVER)
1471 msleep(ret / 10);
1472 else
1473 break;
1474 } while (state->tune_state != CT_TUNER_STOP);
1476 return 0;
1479 static const struct dvb_tuner_ops dib0090_ops = {
1480 .info = {
1481 .name = "DiBcom DiB0090",
1482 .frequency_min = 45000000,
1483 .frequency_max = 860000000,
1484 .frequency_step = 1000,
1486 .release = dib0090_release,
1488 .init = dib0090_wakeup,
1489 .sleep = dib0090_sleep,
1490 .set_params = dib0090_set_params,
1491 .get_frequency = dib0090_get_frequency,
1494 struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
1496 struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
1497 if (st == NULL)
1498 return NULL;
1500 st->config = config;
1501 st->i2c = i2c;
1502 st->fe = fe;
1503 fe->tuner_priv = st;
1505 if (dib0090_reset(fe) != 0)
1506 goto free_mem;
1508 printk(KERN_INFO "DiB0090: successfully identified\n");
1509 memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
1511 return fe;
1512 free_mem:
1513 kfree(st);
1514 fe->tuner_priv = NULL;
1515 return NULL;
1517 EXPORT_SYMBOL(dib0090_register);
1519 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
1520 MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>");
1521 MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
1522 MODULE_LICENSE("GPL");