aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/dib0090.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/frontends/dib0090.c')
-rw-r--r--drivers/media/dvb/frontends/dib0090.c1525
1 files changed, 1525 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c
new file mode 100644
index 000000000000..e37d32dbd5c5
--- /dev/null
+++ b/drivers/media/dvb/frontends/dib0090.c
@@ -0,0 +1,1525 @@
1/*
2 * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
3 *
4 * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
5 *
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.
10 *
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
14 *
15 * GNU General Public License for more details.
16 *
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.
20 *
21 *
22 * This code is more or less generated from another driver, please
23 * excuse some codingstyle oddities.
24 *
25 */
26
27#include <linux/kernel.h>
28#include <linux/i2c.h>
29
30#include "dvb_frontend.h"
31
32#include "dib0090.h"
33#include "dibx000_common.h"
34
35static int debug;
36module_param(debug, int, 0644);
37MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
38
39#define dprintk(args...) do { \
40 if (debug) { \
41 printk(KERN_DEBUG "DiB0090: "); \
42 printk(args); \
43 printk("\n"); \
44 } \
45} while (0)
46
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
52
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
67
68#define EN_IQANA 0x0002
69#define EN_DIGCLK 0x0080 /* not in the 0x24 reg, only in 0x1b */
70#define EN_CRYSTAL 0x0002
71
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
77
78#define pgm_read_word(w) (*w)
79
80struct dc_calibration;
81
82struct 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;
91};
92
93struct 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;
99};
100
101struct dib0090_state {
102 struct i2c_adapter *i2c;
103 struct dvb_frontend *fe;
104 const struct dib0090_config *config;
105
106 u8 current_band;
107 u16 revision;
108 enum frontend_tune_state tune_state;
109 u32 current_rf;
110
111 u16 wbd_offset;
112 s16 wbd_target; /* in dB */
113
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 */
117
118 u16 gain[2]; /* for channel monitoring */
119
120 const u16 *rf_ramp;
121 const u16 *bb_ramp;
122
123 /* for the software AGC ramps */
124 u16 bb_1_def;
125 u16 rf_lt_def;
126 u16 gain_reg[4];
127
128 /* for the captrim/dc-offset search */
129 s8 step;
130 s16 adc_diff;
131 s16 min_adc_diff;
132
133 s8 captrim;
134 s8 fcaptrim;
135
136 const struct dc_calibration *dc;
137 u16 bb6, bb7;
138
139 const struct dib0090_tuning *current_tune_table_index;
140 const struct dib0090_pll *current_pll_table_index;
141
142 u8 tuner_is_tuned;
143 u8 agc_freeze;
144
145 u8 reset;
146};
147
148static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
149{
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},
154 };
155 if (i2c_transfer(state->i2c, msg, 2) != 2) {
156 printk(KERN_WARNING "DiB0090 I2C read failed\n");
157 return 0;
158 }
159 return (b[0] << 8) | b[1];
160}
161
162static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
163{
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;
169 }
170 return 0;
171}
172
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
178static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c)
179{
180 do {
181 dib0090_write_reg(state, r++, *b++);
182 } while (--c);
183}
184
185static u16 dib0090_identify(struct dvb_frontend *fe)
186{
187 struct dib0090_state *state = fe->tuner_priv;
188 u16 v;
189
190 v = dib0090_read_reg(state, 0x1a);
191
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
197
198 /* without PLL lock info */
199 v &= 0x3ff;
200 dprintk("P/V: %04x:", v);
201
202 if ((v >> 8) & 0xf)
203 dprintk("FE%d : Product ID = 0x%x : KROSUS", fe->id, (v >> 8) & 0xf);
204 else
205 return 0xff;
206
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;
218
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
232 }
233
234 return v;
235}
236
237static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
238{
239 struct dib0090_state *state = fe->tuner_priv;
240
241 HARD_RESET(state);
242
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 */
245
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
253 <<
254 2)
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
260 <<
261 2)
262 | (0));
263
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));
267
268}
269
270static int dib0090_wakeup(struct dvb_frontend *fe)
271{
272 struct dib0090_state *state = fe->tuner_priv;
273 if (state->config->sleep)
274 state->config->sleep(fe, 0);
275 return 0;
276}
277
278static int dib0090_sleep(struct dvb_frontend *fe)
279{
280 struct dib0090_state *state = fe->tuner_priv;
281 if (state->config->sleep)
282 state->config->sleep(fe, 1);
283 return 0;
284}
285
286extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
287{
288 struct dib0090_state *state = fe->tuner_priv;
289 if (fast)
290 dib0090_write_reg(state, 0x04, 0); //1kHz
291 else
292 dib0090_write_reg(state, 0x04, 1); //almost frozen
293}
294
295EXPORT_SYMBOL(dib0090_dcc_freq);
296static 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 */
308};
309
310static 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 */
317};
318
319static 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 */
326};
327
328static 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 */
335};
336
337static 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 */
349};
350
351static 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 */
363};
364
365static 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 */
369};
370
371static 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 */
379};
380
381struct slope {
382 int16_t range;
383 int16_t slope;
384};
385static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
386{
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;
397 }
398 return ret;
399}
400
401static 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 */
405};
406
407static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
408{
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);
416}
417
418static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
419{
420 u16 offset = 250;
421
422 /* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */
423
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
432
433 state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
434 dprintk("wbd-target: %d dB", (u32) state->wbd_target);
435}
436
437static const int gain_reg_addr[4] = {
438 0x08, 0x0a, 0x0f, 0x01
439};
440
441static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
442{
443 u16 rf, bb, ref;
444 u16 i, v, gain_reg[4] = { 0 }, gain;
445 const u16 *g;
446
447 if (top_delta < -511)
448 top_delta = -511;
449 if (top_delta > 511)
450 top_delta = 511;
451
452 if (force) {
453 top_delta *= (1 << WBD_ALPHA);
454 gain_delta *= (1 << GAIN_ALPHA);
455 }
456
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;
461
462 if (state->rf_gain_limit < 0) /*underflow */
463 state->rf_gain_limit = 0;
464
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;
474
475 /* now split total gain to rf and bb gain */
476 gain = state->current_gain >> GAIN_ALPHA;
477
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;
487 }
488
489 state->gain[0] = rf;
490 state->gain[1] = bb;
491
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];
503
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;
518
519 g += 3; /* go to next gain bloc */
520
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;
525 }
526 }
527 gain_reg[3] |= state->bb_1_def;
528 gain_reg[3] |= ((bb % 10) * 100) / 125;
529
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
534
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);
541 }
542 }
543}
544
545static void dib0090_set_boost(struct dib0090_state *state, int onoff)
546{
547 state->bb_1_def &= 0xdfff;
548 state->bb_1_def |= onoff << 13;
549}
550
551static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
552{
553 state->rf_ramp = cfg;
554}
555
556static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
557{
558 state->rf_ramp = cfg;
559
560 dib0090_write_reg(state, 0x2a, 0xffff);
561
562 dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
563
564 dib0090_write_regs(state, 0x2c, cfg + 3, 6);
565 dib0090_write_regs(state, 0x3e, cfg + 9, 2);
566}
567
568static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
569{
570 state->bb_ramp = cfg;
571 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
572}
573
574static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
575{
576 state->bb_ramp = cfg;
577
578 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
579
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);
583}
584
585void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
586{
587 struct dib0090_state *state = fe->tuner_priv;
588 /* reset the AGC */
589
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
609 {
610 dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf);
611 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
612 }
613
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));
618
619 dib0090_write_reg(state, 0x39, (1 << 10)); // 0 gain by default
620 }
621}
622
623EXPORT_SYMBOL(dib0090_pwm_gain_reset);
624int dib0090_gain_control(struct dvb_frontend *fe)
625{
626 struct dib0090_state *state = fe->tuner_priv;
627 enum frontend_tune_state *tune_state = &state->tune_state;
628 int ret = 10;
629
630 u16 wbd_val = 0;
631 u8 apply_gain_immediatly = 1;
632 s16 wbd_error = 0, adc_error = 0;
633
634 if (*tune_state == CT_AGC_START) {
635 state->agc_freeze = 0;
636 dib0090_write_reg(state, 0x04, 0x0);
637
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
656 {
657 dib0090_set_rframp(state, rf_ramp_uhf);
658 dib0090_set_bbramp(state, bb_ramp_boost);
659 }
660
661 dib0090_write_reg(state, 0x32, 0);
662 dib0090_write_reg(state, 0x39, 0);
663
664 dib0090_wbd_target(state, state->current_rf);
665
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;
668
669 *tune_state = CT_AGC_STEP_0;
670 } else if (!state->agc_freeze) {
671 s16 wbd;
672
673 int adc;
674 wbd_val = dib0090_read_reg(state, 0x1d);
675
676 /* read and calc the wbd power */
677 wbd = dib0090_wbd_to_db(state, wbd_val);
678 wbd_error = state->wbd_target - wbd;
679
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 */
688 }
689#endif
690 } else {
691 state->agc_step = 0;
692 *tune_state = CT_AGC_STEP_1;
693 }
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] */
698
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 >
711 0)
712 &&
713 ((state->fe->dtv_property_cache.layer[0].modulation ==
714 QAM_64)
715 || (state->fe->dtv_property_cache.layer[0].
716 modulation == QAM_16)))
717 ||
718 ((state->fe->dtv_property_cache.layer[1].segment_count >
719 0)
720 &&
721 ((state->fe->dtv_property_cache.layer[1].modulation ==
722 QAM_64)
723 || (state->fe->dtv_property_cache.layer[1].
724 modulation == QAM_16)))
725 ||
726 ((state->fe->dtv_property_cache.layer[2].segment_count >
727 0)
728 &&
729 ((state->fe->dtv_property_cache.layer[2].modulation ==
730 QAM_64)
731 || (state->fe->dtv_property_cache.layer[2].
732 modulation == QAM_16)))
733 )
734 )
735 adc_error += 60;
736#endif
737
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) {
740
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
747 {
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 */
750 }
751
752 *tune_state = CT_AGC_STOP;
753 }
754 } else {
755 /* everything higher than or equal to CT_AGC_STOP means tracking */
756 ret = 100; /* 10ms interval */
757 apply_gain_immediatly = 0;
758 }
759 }
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
766 }
767
768 /* apply gain */
769 if (!state->agc_freeze)
770 dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
771 return ret;
772}
773
774EXPORT_SYMBOL(dib0090_gain_control);
775void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
776{
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;
786}
787
788EXPORT_SYMBOL(dib0090_get_current_gain);
789u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner)
790{
791 struct dib0090_state *st = tuner->tuner_priv;
792 return st->wbd_offset;
793}
794
795EXPORT_SYMBOL(dib0090_get_wbd_offset);
796static const u16 dib0090_defaults[] = {
797
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,
824
825 1, 0x1c,
826 0xff2d,
827
828 1, 0x39,
829 0x0000,
830
831 1, 0x1b,
832 EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL,
833 2, 0x1e,
834 0x07FF,
835 0x0007,
836
837 1, 0x24,
838 EN_UHF | EN_CRYSTAL,
839
840 2, 0x3c,
841 0x3ff,
842 0x111,
843 0
844};
845
846static int dib0090_reset(struct dvb_frontend *fe)
847{
848 struct dib0090_state *state = fe->tuner_priv;
849 u16 l, r, *n;
850
851 dib0090_reset_digital(fe, state->config);
852 state->revision = dib0090_identify(fe);
853
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
861
862#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
863 if (!(state->revision & 0x1)) /* it is P1B - reset is already done */
864 return 0;
865#endif
866
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++);
879 }
880
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);
888
889 state->reset = 3; /* enable iq-offset-calibration and wbd-calibration when tuning next time */
890
891 return 0;
892}
893
894#define steps(u) (((u)>15)?((u)-16):(u))
895#define INTERN_WAIT 10
896static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
897{
898 int ret = INTERN_WAIT * 10;
899
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;
906
907 case CT_TUNER_STEP_3:
908 state->adc_diff = dib0090_read_reg(state, 0x1d);
909
910 /* Turns to negative */
911 dib0090_write_reg(state, 0x1f, 0x4);
912 *tune_state = CT_TUNER_STEP_4;
913 break;
914
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;
920
921 default:
922 break;
923 }
924
925 return ret;
926}
927
928struct dc_calibration {
929 uint8_t addr;
930 uint8_t offset;
931 uint8_t pga:1;
932 uint16_t bb1;
933 uint8_t i:1;
934};
935
936static 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},
944};
945
946static void dib0090_set_trim(struct dib0090_state *state)
947{
948 u16 *val;
949
950 if (state->dc->addr == 0x07)
951 val = &state->bb7;
952 else
953 val = &state->bb6;
954
955 *val &= ~(0x1f << state->dc->offset);
956 *val |= state->step << state->dc->offset;
957
958 dib0090_write_reg(state, state->dc->addr, *val);
959}
960
961static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
962{
963 int ret = 0;
964
965 switch (*tune_state) {
966
967 case CT_TUNER_START:
968 /* init */
969 dprintk("Internal DC calibration");
970
971 /* the LNA is off */
972 dib0090_write_reg(state, 0x24, 0x02ed);
973
974 /* force vcm2 = 0.8V */
975 state->bb6 = 0;
976 state->bb7 = 0x040d;
977
978 state->dc = dc_table;
979
980 *tune_state = CT_TUNER_STEP_0;
981
982 /* fall through */
983
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));
987
988 state->step = 0;
989
990 state->min_adc_diff = 1023;
991
992 *tune_state = CT_TUNER_STEP_1;
993 ret = 50;
994 break;
995
996 case CT_TUNER_STEP_1:
997 dib0090_set_trim(state);
998
999 *tune_state = CT_TUNER_STEP_2;
1000 break;
1001
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;
1007
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);
1010
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;
1017 }
1018
1019 state->adc_diff = ABS(state->adc_diff);
1020
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 {
1026
1027 /* the minimum was what we have seen in the step before */
1028 state->step--;
1029 dib0090_set_trim(state);
1030
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);
1033
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;
1039
1040 }
1041 break;
1042
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;
1050 }
1051 return ret;
1052}
1053
1054static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1055{
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);
1061
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);
1067
1068 *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1069 state->reset &= ~0x2;
1070 break;
1071 default:
1072 break;
1073 }
1074 return 0;
1075}
1076
1077static void dib0090_set_bandwidth(struct dib0090_state *state)
1078{
1079 u16 tmp;
1080
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);
1089
1090 state->bb_1_def &= 0x3fff;
1091 state->bb_1_def |= tmp;
1092
1093 dib0090_write_reg(state, 0x01, state->bb_1_def); /* be sure that we have the right bb-filter */
1094}
1095
1096static 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
1125};
1126
1127static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
1128
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
1151};
1152
1153static const struct dib0090_tuning dib0090_tuning_table[] = {
1154
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
1180};
1181
1182#define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */
1183static int dib0090_tune(struct dvb_frontend *fe)
1184{
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;
1189
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;
1197
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);
1206
1207 /************************* VCO ***************************/
1208 /* Default values for FG */
1209 /* from these are needed : */
1210 /* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv */
1211
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
1216
1217 if (state->current_rf != rf) {
1218 state->tuner_is_tuned = 0;
1219
1220 tune = dib0090_tuning_table;
1221
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;
1229 }
1230 }
1231
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;
1240 }
1241
1242 if (*tune_state == CT_TUNER_START) {
1243
1244 if (state->tuner_is_tuned == 0)
1245 state->current_rf = 0;
1246
1247 if (state->current_rf != rf) {
1248
1249 dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
1250
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;
1260
1261 lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7); /* bit 15 is the split to the slave, we do not do it here */
1262
1263 if (!state->config->io.pll_int_loop_filt)
1264 lo6 = 0xff28;
1265 else
1266 lo6 = (state->config->io.pll_int_loop_filt << 3);
1267
1268 VCOF_kHz = (pll->hfdiv * rf) * 2;
1269
1270 FREF = state->config->io.clock_khz;
1271
1272 FBDiv = (VCOF_kHz / pll->topresc / FREF);
1273 Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
1274
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);
1285
1286 Den = 1;
1287
1288 dprintk(" ***** ******* Rest value = %d", Rest);
1289
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;
1296 }
1297#ifdef CONFIG_BAND_SBAND
1298 if (state->current_band == BAND_SBAND)
1299 lo6 &= 0xfffb;
1300#endif
1301
1302 dib0090_write_reg(state, 0x15, (u16) FBDiv);
1303
1304 dib0090_write_reg(state, 0x16, (Den << 8) | 1);
1305
1306 dib0090_write_reg(state, 0x17, (u16) Rest);
1307
1308 dib0090_write_reg(state, 0x19, lo5);
1309
1310 dib0090_write_reg(state, 0x1c, lo6);
1311
1312 lo6 = tune->tuner_enable;
1313 if (state->config->analog_output)
1314 lo6 = (lo6 & 0xff9f) | 0x2;
1315
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
1320 );
1321
1322 state->current_rf = rf;
1323
1324 /* prepare a complete captrim */
1325 state->step = state->captrim = state->fcaptrim = 64;
1326
1327 } else { /* we are already tuned to this frequency - the configuration is correct */
1328
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;
1332 }
1333 state->adc_diff = 3000;
1334
1335 dib0090_write_reg(state, 0x10, 0x2B1);
1336
1337 dib0090_write_reg(state, 0x1e, 0x0032);
1338
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) {
1348
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);
1352
1353 if (adc >= 400) {
1354 adc -= 400;
1355 step_sign = -1;
1356 } else {
1357 adc = 400 - adc;
1358 step_sign = 1;
1359 }
1360
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;
1365
1366 }
1367
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;
1373
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);
1378
1379#ifdef CONFIG_TUNER_DIB0090_CAPTRIM_MEMORY
1380 state->memory[state->memory_index].cap = state->fcaptrim;
1381#endif
1382
1383 *tune_state = CT_TUNER_STEP_4;
1384 } else if (*tune_state == CT_TUNER_STEP_4) {
1385 dib0090_write_reg(state, 0x1e, 0x07ff);
1386
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);
1395
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;
1402 }
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
1408 ));
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);
1413
1414 *tune_state = CT_TUNER_STEP_5;
1415 } else if (*tune_state == CT_TUNER_STEP_5) {
1416
1417 /* initialize the lt gain register */
1418 state->rf_lt_def = 0x7c00;
1419 dib0090_write_reg(state, 0x0f, state->rf_lt_def);
1420
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;
1427}
1428
1429static int dib0090_release(struct dvb_frontend *fe)
1430{
1431 kfree(fe->tuner_priv);
1432 fe->tuner_priv = NULL;
1433 return 0;
1434}
1435
1436enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
1437{
1438 struct dib0090_state *state = fe->tuner_priv;
1439
1440 return state->tune_state;
1441}
1442
1443EXPORT_SYMBOL(dib0090_get_tune_state);
1444
1445int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
1446{
1447 struct dib0090_state *state = fe->tuner_priv;
1448
1449 state->tune_state = tune_state;
1450 return 0;
1451}
1452
1453EXPORT_SYMBOL(dib0090_set_tune_state);
1454
1455static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
1456{
1457 struct dib0090_state *state = fe->tuner_priv;
1458
1459 *frequency = 1000 * state->current_rf;
1460 return 0;
1461}
1462
1463static int dib0090_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
1464{
1465 struct dib0090_state *state = fe->tuner_priv;
1466 uint32_t ret;
1467
1468 state->tune_state = CT_TUNER_START;
1469
1470 do {
1471 ret = dib0090_tune(fe);
1472 if (ret != FE_CALLBACK_TIME_NEVER)
1473 msleep(ret / 10);
1474 else
1475 break;
1476 } while (state->tune_state != CT_TUNER_STOP);
1477
1478 return 0;
1479}
1480
1481static const struct dvb_tuner_ops dib0090_ops = {
1482 .info = {
1483 .name = "DiBcom DiB0090",
1484 .frequency_min = 45000000,
1485 .frequency_max = 860000000,
1486 .frequency_step = 1000,
1487 },
1488 .release = dib0090_release,
1489
1490 .init = dib0090_wakeup,
1491 .sleep = dib0090_sleep,
1492 .set_params = dib0090_set_params,
1493 .get_frequency = dib0090_get_frequency,
1494};
1495
1496struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
1497{
1498 struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
1499 if (st == NULL)
1500 return NULL;
1501
1502 st->config = config;
1503 st->i2c = i2c;
1504 st->fe = fe;
1505 fe->tuner_priv = st;
1506
1507 if (dib0090_reset(fe) != 0)
1508 goto free_mem;
1509
1510 printk(KERN_INFO "DiB0090: successfully identified\n");
1511 memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
1512
1513 return fe;
1514 free_mem:
1515 kfree(st);
1516 fe->tuner_priv = NULL;
1517 return NULL;
1518}
1519
1520EXPORT_SYMBOL(dib0090_register);
1521
1522MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
1523MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>");
1524MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
1525MODULE_LICENSE("GPL");