GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / media / dvb / frontends / dib0090.c
blob65240b7801e83c9dbfed88aa03ec1ea0eb94ff28
1 /*
2 * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
4 * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * This code is more or less generated from another driver, please
23 * excuse some codingstyle oddities.
27 #include <linux/kernel.h>
28 #include <linux/slab.h>
29 #include <linux/i2c.h>
31 #include "dvb_frontend.h"
33 #include "dib0090.h"
34 #include "dibx000_common.h"
36 static int debug;
37 module_param(debug, int, 0644);
38 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
40 #define dprintk(args...) do { \
41 if (debug) { \
42 printk(KERN_DEBUG "DiB0090: "); \
43 printk(args); \
44 printk("\n"); \
45 } \
46 } while (0)
48 #define CONFIG_SYS_ISDBT
49 #define CONFIG_BAND_CBAND
50 #define CONFIG_BAND_VHF
51 #define CONFIG_BAND_UHF
52 #define CONFIG_DIB0090_USE_PWM_AGC
54 #define EN_LNA0 0x8000
55 #define EN_LNA1 0x4000
56 #define EN_LNA2 0x2000
57 #define EN_LNA3 0x1000
58 #define EN_MIX0 0x0800
59 #define EN_MIX1 0x0400
60 #define EN_MIX2 0x0200
61 #define EN_MIX3 0x0100
62 #define EN_IQADC 0x0040
63 #define EN_PLL 0x0020
64 #define EN_TX 0x0010
65 #define EN_BB 0x0008
66 #define EN_LO 0x0004
67 #define EN_BIAS 0x0001
69 #define EN_IQANA 0x0002
70 #define EN_DIGCLK 0x0080 /* not in the 0x24 reg, only in 0x1b */
71 #define EN_CRYSTAL 0x0002
73 #define EN_UHF 0x22E9
74 #define EN_VHF 0x44E9
75 #define EN_LBD 0x11E9
76 #define EN_SBD 0x44E9
77 #define EN_CAB 0x88E9
79 #define pgm_read_word(w) (*w)
81 struct dc_calibration;
83 struct dib0090_tuning {
84 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
85 u8 switch_trim;
86 u8 lna_tune;
87 u8 lna_bias;
88 u16 v2i;
89 u16 mix;
90 u16 load;
91 u16 tuner_enable;
94 struct dib0090_pll {
95 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
96 u8 vco_band;
97 u8 hfdiv_code;
98 u8 hfdiv;
99 u8 topresc;
102 struct dib0090_state {
103 struct i2c_adapter *i2c;
104 struct dvb_frontend *fe;
105 const struct dib0090_config *config;
107 u8 current_band;
108 u16 revision;
109 enum frontend_tune_state tune_state;
110 u32 current_rf;
112 u16 wbd_offset;
113 s16 wbd_target; /* in dB */
115 s16 rf_gain_limit; /* take-over-point: where to split between bb and rf gain */
116 s16 current_gain; /* keeps the currently programmed gain */
117 u8 agc_step; /* new binary search */
119 u16 gain[2]; /* for channel monitoring */
121 const u16 *rf_ramp;
122 const u16 *bb_ramp;
124 /* for the software AGC ramps */
125 u16 bb_1_def;
126 u16 rf_lt_def;
127 u16 gain_reg[4];
129 /* for the captrim/dc-offset search */
130 s8 step;
131 s16 adc_diff;
132 s16 min_adc_diff;
134 s8 captrim;
135 s8 fcaptrim;
137 const struct dc_calibration *dc;
138 u16 bb6, bb7;
140 const struct dib0090_tuning *current_tune_table_index;
141 const struct dib0090_pll *current_pll_table_index;
143 u8 tuner_is_tuned;
144 u8 agc_freeze;
146 u8 reset;
149 static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
151 u8 b[2];
152 struct i2c_msg msg[2] = {
153 {.addr = state->config->i2c_address, .flags = 0, .buf = &reg, .len = 1},
154 {.addr = state->config->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2},
156 if (i2c_transfer(state->i2c, msg, 2) != 2) {
157 printk(KERN_WARNING "DiB0090 I2C read failed\n");
158 return 0;
160 return (b[0] << 8) | b[1];
163 static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
165 u8 b[3] = { reg & 0xff, val >> 8, val & 0xff };
166 struct i2c_msg msg = {.addr = state->config->i2c_address, .flags = 0, .buf = b, .len = 3 };
167 if (i2c_transfer(state->i2c, &msg, 1) != 1) {
168 printk(KERN_WARNING "DiB0090 I2C write failed\n");
169 return -EREMOTEIO;
171 return 0;
174 #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)
175 #define ADC_TARGET -220
176 #define GAIN_ALPHA 5
177 #define WBD_ALPHA 6
178 #define LPF 100
179 static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c)
181 do {
182 dib0090_write_reg(state, r++, *b++);
183 } while (--c);
186 static u16 dib0090_identify(struct dvb_frontend *fe)
188 struct dib0090_state *state = fe->tuner_priv;
189 u16 v;
191 v = dib0090_read_reg(state, 0x1a);
193 #ifdef FIRMWARE_FIREFLY
194 /* pll is not locked locked */
195 if (!(v & 0x800))
196 dprintk("FE%d : Identification : pll is not yet locked", fe->id);
197 #endif
199 /* without PLL lock info */
200 v &= 0x3ff;
201 dprintk("P/V: %04x:", v);
203 if ((v >> 8) & 0xf)
204 dprintk("FE%d : Product ID = 0x%x : KROSUS", fe->id, (v >> 8) & 0xf);
205 else
206 return 0xff;
208 v &= 0xff;
209 if (((v >> 5) & 0x7) == 0x1)
210 dprintk("FE%d : MP001 : 9090/8096", fe->id);
211 else if (((v >> 5) & 0x7) == 0x4)
212 dprintk("FE%d : MP005 : Single Sband", fe->id);
213 else if (((v >> 5) & 0x7) == 0x6)
214 dprintk("FE%d : MP008 : diversity VHF-UHF-LBAND", fe->id);
215 else if (((v >> 5) & 0x7) == 0x7)
216 dprintk("FE%d : MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND", fe->id);
217 else
218 return 0xff;
220 /* revision only */
221 if ((v & 0x1f) == 0x3)
222 dprintk("FE%d : P1-D/E/F detected", fe->id);
223 else if ((v & 0x1f) == 0x1)
224 dprintk("FE%d : P1C detected", fe->id);
225 else if ((v & 0x1f) == 0x0) {
226 #ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
227 dprintk("FE%d : P1-A/B detected: using previous driver - support will be removed soon", fe->id);
228 dib0090_p1b_register(fe);
229 #else
230 dprintk("FE%d : P1-A/B detected: driver is deactivated - not available", fe->id);
231 return 0xff;
232 #endif
235 return v;
238 static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
240 struct dib0090_state *state = fe->tuner_priv;
242 HARD_RESET(state);
244 dib0090_write_reg(state, 0x24, EN_PLL);
245 dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */
247 /* adcClkOutRatio=8->7, release reset */
248 dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
249 if (cfg->clkoutdrive != 0)
250 dib0090_write_reg(state, 0x23,
251 (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 10) | (1 << 9) | (0 << 8) | (cfg->clkoutdrive << 5) | (cfg->
252 clkouttobamse
253 << 4) | (0
256 | (0));
257 else
258 dib0090_write_reg(state, 0x23,
259 (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 10) | (1 << 9) | (0 << 8) | (7 << 5) | (cfg->
260 clkouttobamse << 4) | (0
263 | (0));
265 /* enable pll, de-activate reset, ratio: 2/1 = 60MHz */
266 dib0090_write_reg(state, 0x21,
267 (cfg->io.pll_bypass << 15) | (1 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv));
271 static int dib0090_wakeup(struct dvb_frontend *fe)
273 struct dib0090_state *state = fe->tuner_priv;
274 if (state->config->sleep)
275 state->config->sleep(fe, 0);
276 return 0;
279 static int dib0090_sleep(struct dvb_frontend *fe)
281 struct dib0090_state *state = fe->tuner_priv;
282 if (state->config->sleep)
283 state->config->sleep(fe, 1);
284 return 0;
287 void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
289 struct dib0090_state *state = fe->tuner_priv;
290 if (fast)
291 dib0090_write_reg(state, 0x04, 0);
292 else
293 dib0090_write_reg(state, 0x04, 1);
295 EXPORT_SYMBOL(dib0090_dcc_freq);
297 static const u16 rf_ramp_pwm_cband[] = {
298 0, /* max RF gain in 10th of dB */
299 0, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
300 0, /* ramp_max = maximum X used on the ramp */
301 (0 << 10) | 0, /* 0x2c, LNA 1 = 0dB */
302 (0 << 10) | 0, /* 0x2d, LNA 1 */
303 (0 << 10) | 0, /* 0x2e, LNA 2 = 0dB */
304 (0 << 10) | 0, /* 0x2f, LNA 2 */
305 (0 << 10) | 0, /* 0x30, LNA 3 = 0dB */
306 (0 << 10) | 0, /* 0x31, LNA 3 */
307 (0 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
308 (0 << 10) | 0, /* GAIN_4_2, LNA 4 */
311 static const u16 rf_ramp_vhf[] = {
312 412, /* max RF gain in 10th of dB */
313 132, 307, 127, /* LNA1, 13.2dB */
314 105, 412, 255, /* LNA2, 10.5dB */
315 50, 50, 127, /* LNA3, 5dB */
316 125, 175, 127, /* LNA4, 12.5dB */
317 0, 0, 127, /* CBAND, 0dB */
320 static const u16 rf_ramp_uhf[] = {
321 412, /* max RF gain in 10th of dB */
322 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 */
323 105, 412, 255, /* LNA2 : 10.5 dB */
324 50, 50, 127, /* LNA3 : 5.0 dB */
325 125, 175, 127, /* LNA4 : 12.5 dB */
326 0, 0, 127, /* CBAND : 0.0 dB */
329 static const u16 rf_ramp_cband[] = {
330 332, /* max RF gain in 10th of dB */
331 132, 252, 127, /* LNA1, dB */
332 80, 332, 255, /* LNA2, dB */
333 0, 0, 127, /* LNA3, dB */
334 0, 0, 127, /* LNA4, dB */
335 120, 120, 127, /* LT1 CBAND */
338 static const u16 rf_ramp_pwm_vhf[] = {
339 404, /* max RF gain in 10th of dB */
340 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
341 1011, /* ramp_max = maximum X used on the ramp */
342 (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */
343 (0 << 10) | 756, /* 0x2d, LNA 1 */
344 (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */
345 (0 << 10) | 1011, /* 0x2f, LNA 2 */
346 (16 << 10) | 290, /* 0x30, LNA 3 = 5dB */
347 (0 << 10) | 417, /* 0x31, LNA 3 */
348 (7 << 10) | 0, /* GAIN_4_1, LNA 4 = 12.5dB */
349 (0 << 10) | 290, /* GAIN_4_2, LNA 4 */
352 static const u16 rf_ramp_pwm_uhf[] = {
353 404, /* max RF gain in 10th of dB */
354 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
355 1011, /* ramp_max = maximum X used on the ramp */
356 (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */
357 (0 << 10) | 756, /* 0x2d, LNA 1 */
358 (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */
359 (0 << 10) | 1011, /* 0x2f, LNA 2 */
360 (16 << 10) | 0, /* 0x30, LNA 3 = 5dB */
361 (0 << 10) | 127, /* 0x31, LNA 3 */
362 (7 << 10) | 127, /* GAIN_4_1, LNA 4 = 12.5dB */
363 (0 << 10) | 417, /* GAIN_4_2, LNA 4 */
366 static const u16 bb_ramp_boost[] = {
367 550, /* max BB gain in 10th of dB */
368 260, 260, 26, /* BB1, 26dB */
369 290, 550, 29, /* BB2, 29dB */
372 static const u16 bb_ramp_pwm_normal[] = {
373 500, /* max RF gain in 10th of dB */
374 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x34 */
375 400,
376 (2 << 9) | 0, /* 0x35 = 21dB */
377 (0 << 9) | 168, /* 0x36 */
378 (2 << 9) | 168, /* 0x37 = 29dB */
379 (0 << 9) | 400, /* 0x38 */
382 struct slope {
383 int16_t range;
384 int16_t slope;
386 static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
388 u8 i;
389 u16 rest;
390 u16 ret = 0;
391 for (i = 0; i < num; i++) {
392 if (val > slopes[i].range)
393 rest = slopes[i].range;
394 else
395 rest = val;
396 ret += (rest * slopes[i].slope) / slopes[i].range;
397 val -= rest;
399 return ret;
402 static const struct slope dib0090_wbd_slopes[3] = {
403 {66, 120}, /* -64,-52: offset - 65 */
404 {600, 170}, /* -52,-35: 65 - 665 */
405 {170, 250}, /* -45,-10: 665 - 835 */
408 static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
410 wbd &= 0x3ff;
411 if (wbd < state->wbd_offset)
412 wbd = 0;
413 else
414 wbd -= state->wbd_offset;
415 /* -64dB is the floor */
416 return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd);
419 static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
421 u16 offset = 250;
423 /* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */
425 if (state->current_band == BAND_VHF)
426 offset = 650;
427 #ifndef FIRMWARE_FIREFLY
428 if (state->current_band == BAND_VHF)
429 offset = state->config->wbd_vhf_offset;
430 if (state->current_band == BAND_CBAND)
431 offset = state->config->wbd_cband_offset;
432 #endif
434 state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
435 dprintk("wbd-target: %d dB", (u32) state->wbd_target);
438 static const int gain_reg_addr[4] = {
439 0x08, 0x0a, 0x0f, 0x01
442 static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
444 u16 rf, bb, ref;
445 u16 i, v, gain_reg[4] = { 0 }, gain;
446 const u16 *g;
448 if (top_delta < -511)
449 top_delta = -511;
450 if (top_delta > 511)
451 top_delta = 511;
453 if (force) {
454 top_delta *= (1 << WBD_ALPHA);
455 gain_delta *= (1 << GAIN_ALPHA);
458 if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit)) /* overflow */
459 state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
460 else
461 state->rf_gain_limit += top_delta;
463 if (state->rf_gain_limit < 0) /*underflow */
464 state->rf_gain_limit = 0;
466 /* use gain as a temporary variable and correct current_gain */
467 gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA;
468 if (gain_delta >= ((s16) gain - state->current_gain)) /* overflow */
469 state->current_gain = gain;
470 else
471 state->current_gain += gain_delta;
472 /* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */
473 if (state->current_gain < 0)
474 state->current_gain = 0;
476 /* now split total gain to rf and bb gain */
477 gain = state->current_gain >> GAIN_ALPHA;
479 /* requested gain is bigger than rf gain limit - ACI/WBD adjustment */
480 if (gain > (state->rf_gain_limit >> WBD_ALPHA)) {
481 rf = state->rf_gain_limit >> WBD_ALPHA;
482 bb = gain - rf;
483 if (bb > state->bb_ramp[0])
484 bb = state->bb_ramp[0];
485 } else { /* high signal level -> all gains put on RF */
486 rf = gain;
487 bb = 0;
490 state->gain[0] = rf;
491 state->gain[1] = bb;
493 /* software ramp */
494 /* Start with RF gains */
495 g = state->rf_ramp + 1; /* point on RF LNA1 max gain */
496 ref = rf;
497 for (i = 0; i < 7; i++) { /* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */
498 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 */
499 v = 0; /* force the gain to write for the current amp to be null */
500 else if (ref >= g[1]) /* Gain to set is higher than the high working point of this amp */
501 v = g[2]; /* force this amp to be full gain */
502 else /* compute the value to set to this amp because we are somewhere in his range */
503 v = ((ref - (g[1] - g[0])) * g[2]) / g[0];
505 if (i == 0) /* LNA 1 reg mapping */
506 gain_reg[0] = v;
507 else if (i == 1) /* LNA 2 reg mapping */
508 gain_reg[0] |= v << 7;
509 else if (i == 2) /* LNA 3 reg mapping */
510 gain_reg[1] = v;
511 else if (i == 3) /* LNA 4 reg mapping */
512 gain_reg[1] |= v << 7;
513 else if (i == 4) /* CBAND LNA reg mapping */
514 gain_reg[2] = v | state->rf_lt_def;
515 else if (i == 5) /* BB gain 1 reg mapping */
516 gain_reg[3] = v << 3;
517 else if (i == 6) /* BB gain 2 reg mapping */
518 gain_reg[3] |= v << 8;
520 g += 3; /* go to next gain bloc */
522 /* When RF is finished, start with BB */
523 if (i == 4) {
524 g = state->bb_ramp + 1; /* point on BB gain 1 max gain */
525 ref = bb;
528 gain_reg[3] |= state->bb_1_def;
529 gain_reg[3] |= ((bb % 10) * 100) / 125;
531 #ifdef DEBUG_AGC
532 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,
533 gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]);
534 #endif
536 /* Write the amplifier regs */
537 for (i = 0; i < 4; i++) {
538 v = gain_reg[i];
539 if (force || state->gain_reg[i] != v) {
540 state->gain_reg[i] = v;
541 dib0090_write_reg(state, gain_reg_addr[i], v);
546 static void dib0090_set_boost(struct dib0090_state *state, int onoff)
548 state->bb_1_def &= 0xdfff;
549 state->bb_1_def |= onoff << 13;
552 static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
554 state->rf_ramp = cfg;
557 static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
559 state->rf_ramp = cfg;
561 dib0090_write_reg(state, 0x2a, 0xffff);
563 dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
565 dib0090_write_regs(state, 0x2c, cfg + 3, 6);
566 dib0090_write_regs(state, 0x3e, cfg + 9, 2);
569 static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
571 state->bb_ramp = cfg;
572 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
575 static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
577 state->bb_ramp = cfg;
579 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
581 dib0090_write_reg(state, 0x33, 0xffff);
582 dprintk("total BB gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x33));
583 dib0090_write_regs(state, 0x35, cfg + 3, 4);
586 void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
588 struct dib0090_state *state = fe->tuner_priv;
589 /* reset the AGC */
591 if (state->config->use_pwm_agc) {
592 #ifdef CONFIG_BAND_SBAND
593 if (state->current_band == BAND_SBAND) {
594 dib0090_set_rframp_pwm(state, rf_ramp_pwm_sband);
595 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_boost);
596 } else
597 #endif
598 #ifdef CONFIG_BAND_CBAND
599 if (state->current_band == BAND_CBAND) {
600 dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband);
601 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
602 } else
603 #endif
604 #ifdef CONFIG_BAND_VHF
605 if (state->current_band == BAND_VHF) {
606 dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf);
607 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
608 } else
609 #endif
611 dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf);
612 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
615 if (state->rf_ramp[0] != 0)
616 dib0090_write_reg(state, 0x32, (3 << 11));
617 else
618 dib0090_write_reg(state, 0x32, (0 << 11));
620 dib0090_write_reg(state, 0x39, (1 << 10));
623 EXPORT_SYMBOL(dib0090_pwm_gain_reset);
625 int dib0090_gain_control(struct dvb_frontend *fe)
627 struct dib0090_state *state = fe->tuner_priv;
628 enum frontend_tune_state *tune_state = &state->tune_state;
629 int ret = 10;
631 u16 wbd_val = 0;
632 u8 apply_gain_immediatly = 1;
633 s16 wbd_error = 0, adc_error = 0;
635 if (*tune_state == CT_AGC_START) {
636 state->agc_freeze = 0;
637 dib0090_write_reg(state, 0x04, 0x0);
639 #ifdef CONFIG_BAND_SBAND
640 if (state->current_band == BAND_SBAND) {
641 dib0090_set_rframp(state, rf_ramp_sband);
642 dib0090_set_bbramp(state, bb_ramp_boost);
643 } else
644 #endif
645 #ifdef CONFIG_BAND_VHF
646 if (state->current_band == BAND_VHF) {
647 dib0090_set_rframp(state, rf_ramp_vhf);
648 dib0090_set_bbramp(state, bb_ramp_boost);
649 } else
650 #endif
651 #ifdef CONFIG_BAND_CBAND
652 if (state->current_band == BAND_CBAND) {
653 dib0090_set_rframp(state, rf_ramp_cband);
654 dib0090_set_bbramp(state, bb_ramp_boost);
655 } else
656 #endif
658 dib0090_set_rframp(state, rf_ramp_uhf);
659 dib0090_set_bbramp(state, bb_ramp_boost);
662 dib0090_write_reg(state, 0x32, 0);
663 dib0090_write_reg(state, 0x39, 0);
665 dib0090_wbd_target(state, state->current_rf);
667 state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
668 state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA;
670 *tune_state = CT_AGC_STEP_0;
671 } else if (!state->agc_freeze) {
672 s16 wbd;
674 int adc;
675 wbd_val = dib0090_read_reg(state, 0x1d);
677 /* read and calc the wbd power */
678 wbd = dib0090_wbd_to_db(state, wbd_val);
679 wbd_error = state->wbd_target - wbd;
681 if (*tune_state == CT_AGC_STEP_0) {
682 if (wbd_error < 0 && state->rf_gain_limit > 0) {
683 #ifdef CONFIG_BAND_CBAND
684 /* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */
685 u8 ltg2 = (state->rf_lt_def >> 10) & 0x7;
686 if (state->current_band == BAND_CBAND && ltg2) {
687 ltg2 >>= 1;
688 state->rf_lt_def &= ltg2 << 10; /* reduce in 3 steps from 7 to 0 */
690 #endif
691 } else {
692 state->agc_step = 0;
693 *tune_state = CT_AGC_STEP_1;
695 } else {
696 /* calc the adc power */
697 adc = state->config->get_adc_power(fe);
698 adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21; /* included in [0:-700] */
700 adc_error = (s16) (((s32) ADC_TARGET) - adc);
701 #ifdef CONFIG_STANDARD_DAB
702 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)
703 adc_error += 130;
704 #endif
705 #ifdef CONFIG_STANDARD_DVBT
706 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT &&
707 (state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
708 adc_error += 60;
709 #endif
710 #ifdef CONFIG_SYS_ISDBT
711 if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count >
714 ((state->fe->dtv_property_cache.layer[0].modulation ==
715 QAM_64)
716 || (state->fe->dtv_property_cache.layer[0].
717 modulation == QAM_16)))
719 ((state->fe->dtv_property_cache.layer[1].segment_count >
722 ((state->fe->dtv_property_cache.layer[1].modulation ==
723 QAM_64)
724 || (state->fe->dtv_property_cache.layer[1].
725 modulation == QAM_16)))
727 ((state->fe->dtv_property_cache.layer[2].segment_count >
730 ((state->fe->dtv_property_cache.layer[2].modulation ==
731 QAM_64)
732 || (state->fe->dtv_property_cache.layer[2].
733 modulation == QAM_16)))
736 adc_error += 60;
737 #endif
739 if (*tune_state == CT_AGC_STEP_1) { /* quickly go to the correct range of the ADC power */
740 if (ABS(adc_error) < 50 || state->agc_step++ > 5) {
742 #ifdef CONFIG_STANDARD_DAB
743 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) {
744 dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63)); /* cap value = 63 : narrow BB filter : Fc = 1.8MHz */
745 dib0090_write_reg(state, 0x04, 0x0);
746 } else
747 #endif
749 dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32));
750 dib0090_write_reg(state, 0x04, 0x01); /*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */
753 *tune_state = CT_AGC_STOP;
755 } else {
756 /* everything higher than or equal to CT_AGC_STOP means tracking */
757 ret = 100; /* 10ms interval */
758 apply_gain_immediatly = 0;
761 #ifdef DEBUG_AGC
762 dprintk
763 ("FE: %d, tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
764 (u32) fe->id, (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
765 (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
766 #endif
769 /* apply gain */
770 if (!state->agc_freeze)
771 dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
772 return ret;
774 EXPORT_SYMBOL(dib0090_gain_control);
776 void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
778 struct dib0090_state *state = fe->tuner_priv;
779 if (rf)
780 *rf = state->gain[0];
781 if (bb)
782 *bb = state->gain[1];
783 if (rf_gain_limit)
784 *rf_gain_limit = state->rf_gain_limit;
785 if (rflt)
786 *rflt = (state->rf_lt_def >> 10) & 0x7;
788 EXPORT_SYMBOL(dib0090_get_current_gain);
790 u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner)
792 struct dib0090_state *st = tuner->tuner_priv;
793 return st->wbd_offset;
795 EXPORT_SYMBOL(dib0090_get_wbd_offset);
797 static const u16 dib0090_defaults[] = {
799 25, 0x01,
800 0x0000,
801 0x99a0,
802 0x6008,
803 0x0000,
804 0x8acb,
805 0x0000,
806 0x0405,
807 0x0000,
808 0x0000,
809 0x0000,
810 0xb802,
811 0x0300,
812 0x2d12,
813 0xbac0,
814 0x7c00,
815 0xdbb9,
816 0x0954,
817 0x0743,
818 0x8000,
819 0x0001,
820 0x0040,
821 0x0100,
822 0x0000,
823 0xe910,
824 0x149e,
826 1, 0x1c,
827 0xff2d,
829 1, 0x39,
830 0x0000,
832 1, 0x1b,
833 EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL,
834 2, 0x1e,
835 0x07FF,
836 0x0007,
838 1, 0x24,
839 EN_UHF | EN_CRYSTAL,
841 2, 0x3c,
842 0x3ff,
843 0x111,
847 static int dib0090_reset(struct dvb_frontend *fe)
849 struct dib0090_state *state = fe->tuner_priv;
850 u16 l, r, *n;
852 dib0090_reset_digital(fe, state->config);
853 state->revision = dib0090_identify(fe);
855 /* Revision definition */
856 if (state->revision == 0xff)
857 return -EINVAL;
858 #ifdef EFUSE
859 else if ((state->revision & 0x1f) >= 3) /* Update the efuse : Only available for KROSUS > P1C */
860 dib0090_set_EFUSE(state);
861 #endif
863 #ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
864 if (!(state->revision & 0x1)) /* it is P1B - reset is already done */
865 return 0;
866 #endif
868 /* Upload the default values */
869 n = (u16 *) dib0090_defaults;
870 l = pgm_read_word(n++);
871 while (l) {
872 r = pgm_read_word(n++);
873 do {
874 /* DEBUG_TUNER */
875 /* dprintk("%d, %d, %d", l, r, pgm_read_word(n)); */
876 dib0090_write_reg(state, r, pgm_read_word(n++));
877 r++;
878 } while (--l);
879 l = pgm_read_word(n++);
882 /* Congigure in function of the crystal */
883 if (state->config->io.clock_khz >= 24000)
884 l = 1;
885 else
886 l = 2;
887 dib0090_write_reg(state, 0x14, l);
888 dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
890 state->reset = 3; /* enable iq-offset-calibration and wbd-calibration when tuning next time */
892 return 0;
895 #define steps(u) (((u) > 15) ? ((u)-16) : (u))
896 #define INTERN_WAIT 10
897 static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
899 int ret = INTERN_WAIT * 10;
901 switch (*tune_state) {
902 case CT_TUNER_STEP_2:
903 /* Turns to positive */
904 dib0090_write_reg(state, 0x1f, 0x7);
905 *tune_state = CT_TUNER_STEP_3;
906 break;
908 case CT_TUNER_STEP_3:
909 state->adc_diff = dib0090_read_reg(state, 0x1d);
911 /* Turns to negative */
912 dib0090_write_reg(state, 0x1f, 0x4);
913 *tune_state = CT_TUNER_STEP_4;
914 break;
916 case CT_TUNER_STEP_4:
917 state->adc_diff -= dib0090_read_reg(state, 0x1d);
918 *tune_state = CT_TUNER_STEP_5;
919 ret = 0;
920 break;
922 default:
923 break;
926 return ret;
929 struct dc_calibration {
930 uint8_t addr;
931 uint8_t offset;
932 uint8_t pga:1;
933 uint16_t bb1;
934 uint8_t i:1;
937 static const struct dc_calibration dc_table[] = {
938 /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
939 {0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1},
940 {0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0},
941 /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
942 {0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1},
943 {0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0},
944 {0},
947 static void dib0090_set_trim(struct dib0090_state *state)
949 u16 *val;
951 if (state->dc->addr == 0x07)
952 val = &state->bb7;
953 else
954 val = &state->bb6;
956 *val &= ~(0x1f << state->dc->offset);
957 *val |= state->step << state->dc->offset;
959 dib0090_write_reg(state, state->dc->addr, *val);
962 static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
964 int ret = 0;
966 switch (*tune_state) {
968 case CT_TUNER_START:
969 /* init */
970 dprintk("Internal DC calibration");
972 /* the LNA is off */
973 dib0090_write_reg(state, 0x24, 0x02ed);
975 /* force vcm2 = 0.8V */
976 state->bb6 = 0;
977 state->bb7 = 0x040d;
979 state->dc = dc_table;
981 *tune_state = CT_TUNER_STEP_0;
983 /* fall through */
985 case CT_TUNER_STEP_0:
986 dib0090_write_reg(state, 0x01, state->dc->bb1);
987 dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
989 state->step = 0;
991 state->min_adc_diff = 1023;
993 *tune_state = CT_TUNER_STEP_1;
994 ret = 50;
995 break;
997 case CT_TUNER_STEP_1:
998 dib0090_set_trim(state);
1000 *tune_state = CT_TUNER_STEP_2;
1001 break;
1003 case CT_TUNER_STEP_2:
1004 case CT_TUNER_STEP_3:
1005 case CT_TUNER_STEP_4:
1006 ret = dib0090_get_offset(state, tune_state);
1007 break;
1009 case CT_TUNER_STEP_5: /* found an offset */
1010 dprintk("FE%d: IQC read=%d, current=%x", state->fe->id, (u32) state->adc_diff, state->step);
1012 /* first turn for this frequency */
1013 if (state->step == 0) {
1014 if (state->dc->pga && state->adc_diff < 0)
1015 state->step = 0x10;
1016 if (state->dc->pga == 0 && state->adc_diff > 0)
1017 state->step = 0x10;
1020 state->adc_diff = ABS(state->adc_diff);
1022 if (state->adc_diff < state->min_adc_diff && steps(state->step) < 15) { /* stop search when the delta to 0 is increasing */
1023 state->step++;
1024 state->min_adc_diff = state->adc_diff;
1025 *tune_state = CT_TUNER_STEP_1;
1026 } else {
1028 /* the minimum was what we have seen in the step before */
1029 state->step--;
1030 dib0090_set_trim(state);
1032 dprintk("FE%d: BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->fe->id, state->dc->addr, state->adc_diff,
1033 state->step);
1035 state->dc++;
1036 if (state->dc->addr == 0) /* done */
1037 *tune_state = CT_TUNER_STEP_6;
1038 else
1039 *tune_state = CT_TUNER_STEP_0;
1042 break;
1044 case CT_TUNER_STEP_6:
1045 dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008);
1046 dib0090_write_reg(state, 0x1f, 0x7);
1047 *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1048 state->reset &= ~0x1;
1049 default:
1050 break;
1052 return ret;
1055 static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1057 switch (*tune_state) {
1058 case CT_TUNER_START:
1059 /* WBD-mode=log, Bias=2, Gain=6, Testmode=1, en=1, WBDMUX=1 */
1060 dib0090_write_reg(state, 0x10, 0xdb09 | (1 << 10));
1061 dib0090_write_reg(state, 0x24, EN_UHF & 0x0fff);
1063 *tune_state = CT_TUNER_STEP_0;
1064 return 90; /* wait for the WBDMUX to switch and for the ADC to sample */
1065 case CT_TUNER_STEP_0:
1066 state->wbd_offset = dib0090_read_reg(state, 0x1d);
1067 dprintk("WBD calibration offset = %d", state->wbd_offset);
1069 *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1070 state->reset &= ~0x2;
1071 break;
1072 default:
1073 break;
1075 return 0;
1078 static void dib0090_set_bandwidth(struct dib0090_state *state)
1080 u16 tmp;
1082 if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000)
1083 tmp = (3 << 14);
1084 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000)
1085 tmp = (2 << 14);
1086 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000)
1087 tmp = (1 << 14);
1088 else
1089 tmp = (0 << 14);
1091 state->bb_1_def &= 0x3fff;
1092 state->bb_1_def |= tmp;
1094 dib0090_write_reg(state, 0x01, state->bb_1_def); /* be sure that we have the right bb-filter */
1097 static const struct dib0090_pll dib0090_pll_table[] = {
1098 #ifdef CONFIG_BAND_CBAND
1099 {56000, 0, 9, 48, 6},
1100 {70000, 1, 9, 48, 6},
1101 {87000, 0, 8, 32, 4},
1102 {105000, 1, 8, 32, 4},
1103 {115000, 0, 7, 24, 6},
1104 {140000, 1, 7, 24, 6},
1105 {170000, 0, 6, 16, 4},
1106 #endif
1107 #ifdef CONFIG_BAND_VHF
1108 {200000, 1, 6, 16, 4},
1109 {230000, 0, 5, 12, 6},
1110 {280000, 1, 5, 12, 6},
1111 {340000, 0, 4, 8, 4},
1112 {380000, 1, 4, 8, 4},
1113 {450000, 0, 3, 6, 6},
1114 #endif
1115 #ifdef CONFIG_BAND_UHF
1116 {580000, 1, 3, 6, 6},
1117 {700000, 0, 2, 4, 4},
1118 {860000, 1, 2, 4, 4},
1119 #endif
1120 #ifdef CONFIG_BAND_LBAND
1121 {1800000, 1, 0, 2, 4},
1122 #endif
1123 #ifdef CONFIG_BAND_SBAND
1124 {2900000, 0, 14, 1, 4},
1125 #endif
1128 static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
1130 #ifdef CONFIG_BAND_CBAND
1131 {184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1132 {227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1133 {380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1134 #endif
1135 #ifdef CONFIG_BAND_UHF
1136 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1137 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1138 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1139 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1140 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1141 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1142 #endif
1143 #ifdef CONFIG_BAND_LBAND
1144 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1145 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1146 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1147 #endif
1148 #ifdef CONFIG_BAND_SBAND
1149 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1150 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1151 #endif
1154 static const struct dib0090_tuning dib0090_tuning_table[] = {
1156 #ifdef CONFIG_BAND_CBAND
1157 {170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1158 #endif
1159 #ifdef CONFIG_BAND_VHF
1160 {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1161 {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1162 {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1163 #endif
1164 #ifdef CONFIG_BAND_UHF
1165 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1166 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1167 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1168 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1169 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1170 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1171 #endif
1172 #ifdef CONFIG_BAND_LBAND
1173 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1174 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1175 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1176 #endif
1177 #ifdef CONFIG_BAND_SBAND
1178 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1179 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1180 #endif
1183 #define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */
1184 static int dib0090_tune(struct dvb_frontend *fe)
1186 struct dib0090_state *state = fe->tuner_priv;
1187 const struct dib0090_tuning *tune = state->current_tune_table_index;
1188 const struct dib0090_pll *pll = state->current_pll_table_index;
1189 enum frontend_tune_state *tune_state = &state->tune_state;
1191 u32 rf;
1192 u16 lo4 = 0xe900, lo5, lo6, Den;
1193 u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
1194 u16 tmp, adc;
1195 int8_t step_sign;
1196 int ret = 10; /* 1ms is the default delay most of the time */
1197 u8 c, i;
1199 state->current_band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000);
1200 rf = fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
1201 BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->freq_offset_khz_vhf);
1202 /* in any case we first need to do a reset if needed */
1203 if (state->reset & 0x1)
1204 return dib0090_dc_offset_calibration(state, tune_state);
1205 else if (state->reset & 0x2)
1206 return dib0090_wbd_calibration(state, tune_state);
1208 /************************* VCO ***************************/
1209 /* Default values for FG */
1210 /* from these are needed : */
1211 /* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv */
1213 #ifdef CONFIG_SYS_ISDBT
1214 if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
1215 rf += 850;
1216 #endif
1218 if (state->current_rf != rf) {
1219 state->tuner_is_tuned = 0;
1221 tune = dib0090_tuning_table;
1223 tmp = (state->revision >> 5) & 0x7;
1224 if (tmp == 0x4 || tmp == 0x7) {
1225 /* CBAND tuner version for VHF */
1226 if (state->current_band == BAND_FM || state->current_band == BAND_VHF) {
1227 /* Force CBAND */
1228 state->current_band = BAND_CBAND;
1229 tune = dib0090_tuning_table_fm_vhf_on_cband;
1233 pll = dib0090_pll_table;
1234 /* Look for the interval */
1235 while (rf > tune->max_freq)
1236 tune++;
1237 while (rf > pll->max_freq)
1238 pll++;
1239 state->current_tune_table_index = tune;
1240 state->current_pll_table_index = pll;
1243 if (*tune_state == CT_TUNER_START) {
1245 if (state->tuner_is_tuned == 0)
1246 state->current_rf = 0;
1248 if (state->current_rf != rf) {
1250 dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
1252 /* external loop filter, otherwise:
1253 * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
1254 * lo6 = 0x0e34 */
1255 if (pll->vco_band)
1256 lo5 = 0x049e;
1257 else if (state->config->analog_output)
1258 lo5 = 0x041d;
1259 else
1260 lo5 = 0x041c;
1262 lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7); /* bit 15 is the split to the slave, we do not do it here */
1264 if (!state->config->io.pll_int_loop_filt)
1265 lo6 = 0xff28;
1266 else
1267 lo6 = (state->config->io.pll_int_loop_filt << 3);
1269 VCOF_kHz = (pll->hfdiv * rf) * 2;
1271 FREF = state->config->io.clock_khz;
1273 FBDiv = (VCOF_kHz / pll->topresc / FREF);
1274 Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
1276 if (Rest < LPF)
1277 Rest = 0;
1278 else if (Rest < 2 * LPF)
1279 Rest = 2 * LPF;
1280 else if (Rest > (FREF - LPF)) {
1281 Rest = 0;
1282 FBDiv += 1;
1283 } else if (Rest > (FREF - 2 * LPF))
1284 Rest = FREF - 2 * LPF;
1285 Rest = (Rest * 6528) / (FREF / 10);
1287 Den = 1;
1289 dprintk(" ***** ******* Rest value = %d", Rest);
1291 if (Rest > 0) {
1292 if (state->config->analog_output)
1293 lo6 |= (1 << 2) | 2;
1294 else
1295 lo6 |= (1 << 2) | 1;
1296 Den = 255;
1298 #ifdef CONFIG_BAND_SBAND
1299 if (state->current_band == BAND_SBAND)
1300 lo6 &= 0xfffb;
1301 #endif
1303 dib0090_write_reg(state, 0x15, (u16) FBDiv);
1305 dib0090_write_reg(state, 0x16, (Den << 8) | 1);
1307 dib0090_write_reg(state, 0x17, (u16) Rest);
1309 dib0090_write_reg(state, 0x19, lo5);
1311 dib0090_write_reg(state, 0x1c, lo6);
1313 lo6 = tune->tuner_enable;
1314 if (state->config->analog_output)
1315 lo6 = (lo6 & 0xff9f) | 0x2;
1317 dib0090_write_reg(state, 0x24, lo6 | EN_LO
1318 #ifdef CONFIG_DIB0090_USE_PWM_AGC
1319 | state->config->use_pwm_agc * EN_CRYSTAL
1320 #endif
1323 state->current_rf = rf;
1325 /* prepare a complete captrim */
1326 state->step = state->captrim = state->fcaptrim = 64;
1328 } else { /* we are already tuned to this frequency - the configuration is correct */
1330 /* do a minimal captrim even if the frequency has not changed */
1331 state->step = 4;
1332 state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
1334 state->adc_diff = 3000;
1336 dib0090_write_reg(state, 0x10, 0x2B1);
1338 dib0090_write_reg(state, 0x1e, 0x0032);
1340 ret = 20;
1341 *tune_state = CT_TUNER_STEP_1;
1342 } else if (*tune_state == CT_TUNER_STEP_0) {
1343 /* nothing */
1344 } else if (*tune_state == CT_TUNER_STEP_1) {
1345 state->step /= 2;
1346 dib0090_write_reg(state, 0x18, lo4 | state->captrim);
1347 *tune_state = CT_TUNER_STEP_2;
1348 } else if (*tune_state == CT_TUNER_STEP_2) {
1350 adc = dib0090_read_reg(state, 0x1d);
1351 dprintk("FE %d CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) fe->id, (u32) state->captrim, (u32) adc,
1352 (u32) (adc) * (u32) 1800 / (u32) 1024);
1354 if (adc >= 400) {
1355 adc -= 400;
1356 step_sign = -1;
1357 } else {
1358 adc = 400 - adc;
1359 step_sign = 1;
1362 if (adc < state->adc_diff) {
1363 dprintk("FE %d CAPTRIM=%d is closer to target (%d/%d)", (u32) fe->id, (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
1364 state->adc_diff = adc;
1365 state->fcaptrim = state->captrim;
1369 state->captrim += step_sign * state->step;
1370 if (state->step >= 1)
1371 *tune_state = CT_TUNER_STEP_1;
1372 else
1373 *tune_state = CT_TUNER_STEP_3;
1375 ret = 15;
1376 } else if (*tune_state == CT_TUNER_STEP_3) {
1377 /*write the final cptrim config */
1378 dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
1380 #ifdef CONFIG_TUNER_DIB0090_CAPTRIM_MEMORY
1381 state->memory[state->memory_index].cap = state->fcaptrim;
1382 #endif
1384 *tune_state = CT_TUNER_STEP_4;
1385 } else if (*tune_state == CT_TUNER_STEP_4) {
1386 dib0090_write_reg(state, 0x1e, 0x07ff);
1388 dprintk("FE %d Final Captrim: %d", (u32) fe->id, (u32) state->fcaptrim);
1389 dprintk("FE %d HFDIV code: %d", (u32) fe->id, (u32) pll->hfdiv_code);
1390 dprintk("FE %d VCO = %d", (u32) fe->id, (u32) pll->vco_band);
1391 dprintk("FE %d VCOF in kHz: %d ((%d*%d) << 1))", (u32) fe->id, (u32) ((pll->hfdiv * rf) * 2), (u32) pll->hfdiv, (u32) rf);
1392 dprintk("FE %d REFDIV: %d, FREF: %d", (u32) fe->id, (u32) 1, (u32) state->config->io.clock_khz);
1393 dprintk("FE %d FBDIV: %d, Rest: %d", (u32) fe->id, (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
1394 dprintk("FE %d Num: %d, Den: %d, SD: %d", (u32) fe->id, (u32) dib0090_read_reg(state, 0x17),
1395 (u32) (dib0090_read_reg(state, 0x16) >> 8), (u32) dib0090_read_reg(state, 0x1c) & 0x3);
1397 c = 4;
1398 i = 3;
1399 #if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
1400 if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND)) {
1401 c = 2;
1402 i = 2;
1404 #endif
1405 dib0090_write_reg(state, 0x10, (c << 13) | (i << 11) | (WBD
1406 #ifdef CONFIG_DIB0090_USE_PWM_AGC
1407 | (state->config->use_pwm_agc << 1)
1408 #endif
1410 dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | (tune->lna_bias << 0));
1411 dib0090_write_reg(state, 0x0c, tune->v2i);
1412 dib0090_write_reg(state, 0x0d, tune->mix);
1413 dib0090_write_reg(state, 0x0e, tune->load);
1415 *tune_state = CT_TUNER_STEP_5;
1416 } else if (*tune_state == CT_TUNER_STEP_5) {
1418 /* initialize the lt gain register */
1419 state->rf_lt_def = 0x7c00;
1420 dib0090_write_reg(state, 0x0f, state->rf_lt_def);
1422 dib0090_set_bandwidth(state);
1423 state->tuner_is_tuned = 1;
1424 *tune_state = CT_TUNER_STOP;
1425 } else
1426 ret = FE_CALLBACK_TIME_NEVER;
1427 return ret;
1430 static int dib0090_release(struct dvb_frontend *fe)
1432 kfree(fe->tuner_priv);
1433 fe->tuner_priv = NULL;
1434 return 0;
1437 enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
1439 struct dib0090_state *state = fe->tuner_priv;
1441 return state->tune_state;
1443 EXPORT_SYMBOL(dib0090_get_tune_state);
1445 int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
1447 struct dib0090_state *state = fe->tuner_priv;
1449 state->tune_state = tune_state;
1450 return 0;
1452 EXPORT_SYMBOL(dib0090_set_tune_state);
1454 static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
1456 struct dib0090_state *state = fe->tuner_priv;
1458 *frequency = 1000 * state->current_rf;
1459 return 0;
1462 static int dib0090_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
1464 struct dib0090_state *state = fe->tuner_priv;
1465 uint32_t ret;
1467 state->tune_state = CT_TUNER_START;
1469 do {
1470 ret = dib0090_tune(fe);
1471 if (ret != FE_CALLBACK_TIME_NEVER)
1472 msleep(ret / 10);
1473 else
1474 break;
1475 } while (state->tune_state != CT_TUNER_STOP);
1477 return 0;
1480 static const struct dvb_tuner_ops dib0090_ops = {
1481 .info = {
1482 .name = "DiBcom DiB0090",
1483 .frequency_min = 45000000,
1484 .frequency_max = 860000000,
1485 .frequency_step = 1000,
1487 .release = dib0090_release,
1489 .init = dib0090_wakeup,
1490 .sleep = dib0090_sleep,
1491 .set_params = dib0090_set_params,
1492 .get_frequency = dib0090_get_frequency,
1495 struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
1497 struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
1498 if (st == NULL)
1499 return NULL;
1501 st->config = config;
1502 st->i2c = i2c;
1503 st->fe = fe;
1504 fe->tuner_priv = st;
1506 if (dib0090_reset(fe) != 0)
1507 goto free_mem;
1509 printk(KERN_INFO "DiB0090: successfully identified\n");
1510 memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
1512 return fe;
1513 free_mem:
1514 kfree(st);
1515 fe->tuner_priv = NULL;
1516 return NULL;
1518 EXPORT_SYMBOL(dib0090_register);
1520 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
1521 MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>");
1522 MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
1523 MODULE_LICENSE("GPL");