]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/media/dvb/frontends/dib0090.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[net-next-2.6.git] / drivers / media / dvb / frontends / dib0090.c
CommitLineData
03245a5e
OG
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>
5a0e3ad6 28#include <linux/slab.h>
03245a5e
OG
29#include <linux/i2c.h>
30
31#include "dvb_frontend.h"
32
33#include "dib0090.h"
34#include "dibx000_common.h"
35
36static int debug;
37module_param(debug, int, 0644);
38MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
39
40#define dprintk(args...) do { \
41 if (debug) { \
42 printk(KERN_DEBUG "DiB0090: "); \
43 printk(args); \
44 printk("\n"); \
45 } \
46} while (0)
47
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
53
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
68
69#define EN_IQANA 0x0002
70#define EN_DIGCLK 0x0080 /* not in the 0x24 reg, only in 0x1b */
71#define EN_CRYSTAL 0x0002
72
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
78
79#define pgm_read_word(w) (*w)
80
81struct dc_calibration;
82
83struct 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;
92};
93
94struct 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;
100};
101
102struct dib0090_state {
103 struct i2c_adapter *i2c;
104 struct dvb_frontend *fe;
105 const struct dib0090_config *config;
106
107 u8 current_band;
108 u16 revision;
109 enum frontend_tune_state tune_state;
110 u32 current_rf;
111
112 u16 wbd_offset;
113 s16 wbd_target; /* in dB */
114
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 */
118
119 u16 gain[2]; /* for channel monitoring */
120
121 const u16 *rf_ramp;
122 const u16 *bb_ramp;
123
124 /* for the software AGC ramps */
125 u16 bb_1_def;
126 u16 rf_lt_def;
127 u16 gain_reg[4];
128
129 /* for the captrim/dc-offset search */
130 s8 step;
131 s16 adc_diff;
132 s16 min_adc_diff;
133
134 s8 captrim;
135 s8 fcaptrim;
136
137 const struct dc_calibration *dc;
138 u16 bb6, bb7;
139
140 const struct dib0090_tuning *current_tune_table_index;
141 const struct dib0090_pll *current_pll_table_index;
142
143 u8 tuner_is_tuned;
144 u8 agc_freeze;
145
146 u8 reset;
147};
148
149static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
150{
151 u8 b[2];
152 struct i2c_msg msg[2] = {
9c783036
OG
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},
03245a5e
OG
155 };
156 if (i2c_transfer(state->i2c, msg, 2) != 2) {
157 printk(KERN_WARNING "DiB0090 I2C read failed\n");
158 return 0;
159 }
160 return (b[0] << 8) | b[1];
161}
162
163static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
164{
165 u8 b[3] = { reg & 0xff, val >> 8, val & 0xff };
9c783036 166 struct i2c_msg msg = {.addr = state->config->i2c_address, .flags = 0, .buf = b, .len = 3 };
03245a5e
OG
167 if (i2c_transfer(state->i2c, &msg, 1) != 1) {
168 printk(KERN_WARNING "DiB0090 I2C write failed\n");
169 return -EREMOTEIO;
170 }
171 return 0;
172}
173
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
179static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c)
180{
181 do {
182 dib0090_write_reg(state, r++, *b++);
183 } while (--c);
184}
185
186static u16 dib0090_identify(struct dvb_frontend *fe)
187{
188 struct dib0090_state *state = fe->tuner_priv;
189 u16 v;
190
191 v = dib0090_read_reg(state, 0x1a);
192
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
198
199 /* without PLL lock info */
200 v &= 0x3ff;
201 dprintk("P/V: %04x:", v);
202
203 if ((v >> 8) & 0xf)
204 dprintk("FE%d : Product ID = 0x%x : KROSUS", fe->id, (v >> 8) & 0xf);
205 else
206 return 0xff;
207
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;
219
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
233 }
234
235 return v;
236}
237
238static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
239{
240 struct dib0090_state *state = fe->tuner_priv;
241
242 HARD_RESET(state);
243
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 */
246
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
254 <<
255 2)
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
261 <<
262 2)
263 | (0));
264
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));
268
269}
270
271static int dib0090_wakeup(struct dvb_frontend *fe)
272{
273 struct dib0090_state *state = fe->tuner_priv;
274 if (state->config->sleep)
275 state->config->sleep(fe, 0);
276 return 0;
277}
278
279static int dib0090_sleep(struct dvb_frontend *fe)
280{
281 struct dib0090_state *state = fe->tuner_priv;
282 if (state->config->sleep)
283 state->config->sleep(fe, 1);
284 return 0;
285}
286
43e3e6d9 287void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
03245a5e
OG
288{
289 struct dib0090_state *state = fe->tuner_priv;
290 if (fast)
9c783036 291 dib0090_write_reg(state, 0x04, 0);
03245a5e 292 else
9c783036 293 dib0090_write_reg(state, 0x04, 1);
03245a5e 294}
03245a5e 295EXPORT_SYMBOL(dib0090_dcc_freq);
9c783036 296
03245a5e
OG
297static 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 */
309};
310
311static 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 */
318};
319
320static 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 */
327};
328
329static 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 */
336};
337
338static 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 */
350};
351
352static 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 */
364};
365
366static 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 */
370};
371
372static 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 */
380};
381
382struct slope {
383 int16_t range;
384 int16_t slope;
385};
386static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
387{
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;
398 }
399 return ret;
400}
401
402static 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 */
406};
407
408static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
409{
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);
417}
418
419static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
420{
421 u16 offset = 250;
422
423 /* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */
424
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
433
434 state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
435 dprintk("wbd-target: %d dB", (u32) state->wbd_target);
436}
437
438static const int gain_reg_addr[4] = {
439 0x08, 0x0a, 0x0f, 0x01
440};
441
442static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
443{
444 u16 rf, bb, ref;
445 u16 i, v, gain_reg[4] = { 0 }, gain;
446 const u16 *g;
447
448 if (top_delta < -511)
449 top_delta = -511;
450 if (top_delta > 511)
451 top_delta = 511;
452
453 if (force) {
454 top_delta *= (1 << WBD_ALPHA);
455 gain_delta *= (1 << GAIN_ALPHA);
456 }
457
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;
462
463 if (state->rf_gain_limit < 0) /*underflow */
464 state->rf_gain_limit = 0;
465
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;
475
476 /* now split total gain to rf and bb gain */
477 gain = state->current_gain >> GAIN_ALPHA;
478
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;
488 }
489
490 state->gain[0] = rf;
491 state->gain[1] = bb;
492
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];
504
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;
519
520 g += 3; /* go to next gain bloc */
521
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;
526 }
527 }
528 gain_reg[3] |= state->bb_1_def;
529 gain_reg[3] |= ((bb % 10) * 100) / 125;
530
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
535
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);
542 }
543 }
544}
545
546static void dib0090_set_boost(struct dib0090_state *state, int onoff)
547{
548 state->bb_1_def &= 0xdfff;
549 state->bb_1_def |= onoff << 13;
550}
551
552static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
553{
554 state->rf_ramp = cfg;
555}
556
557static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
558{
559 state->rf_ramp = cfg;
560
561 dib0090_write_reg(state, 0x2a, 0xffff);
562
563 dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
564
565 dib0090_write_regs(state, 0x2c, cfg + 3, 6);
566 dib0090_write_regs(state, 0x3e, cfg + 9, 2);
567}
568
569static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
570{
571 state->bb_ramp = cfg;
572 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
573}
574
575static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
576{
577 state->bb_ramp = cfg;
578
579 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
580
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);
584}
585
586void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
587{
588 struct dib0090_state *state = fe->tuner_priv;
589 /* reset the AGC */
590
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
610 {
611 dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf);
612 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
613 }
614
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));
619
9c783036 620 dib0090_write_reg(state, 0x39, (1 << 10));
03245a5e
OG
621 }
622}
03245a5e 623EXPORT_SYMBOL(dib0090_pwm_gain_reset);
9c783036 624
03245a5e
OG
625int dib0090_gain_control(struct dvb_frontend *fe)
626{
627 struct dib0090_state *state = fe->tuner_priv;
628 enum frontend_tune_state *tune_state = &state->tune_state;
629 int ret = 10;
630
631 u16 wbd_val = 0;
632 u8 apply_gain_immediatly = 1;
633 s16 wbd_error = 0, adc_error = 0;
634
635 if (*tune_state == CT_AGC_START) {
636 state->agc_freeze = 0;
637 dib0090_write_reg(state, 0x04, 0x0);
638
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
657 {
658 dib0090_set_rframp(state, rf_ramp_uhf);
659 dib0090_set_bbramp(state, bb_ramp_boost);
660 }
661
662 dib0090_write_reg(state, 0x32, 0);
663 dib0090_write_reg(state, 0x39, 0);
664
665 dib0090_wbd_target(state, state->current_rf);
666
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;
669
670 *tune_state = CT_AGC_STEP_0;
671 } else if (!state->agc_freeze) {
672 s16 wbd;
673
674 int adc;
675 wbd_val = dib0090_read_reg(state, 0x1d);
676
677 /* read and calc the wbd power */
678 wbd = dib0090_wbd_to_db(state, wbd_val);
679 wbd_error = state->wbd_target - wbd;
680
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 */
689 }
690#endif
691 } else {
692 state->agc_step = 0;
693 *tune_state = CT_AGC_STEP_1;
694 }
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] */
699
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 >
712 0)
713 &&
714 ((state->fe->dtv_property_cache.layer[0].modulation ==
715 QAM_64)
716 || (state->fe->dtv_property_cache.layer[0].
717 modulation == QAM_16)))
718 ||
719 ((state->fe->dtv_property_cache.layer[1].segment_count >
720 0)
721 &&
722 ((state->fe->dtv_property_cache.layer[1].modulation ==
723 QAM_64)
724 || (state->fe->dtv_property_cache.layer[1].
725 modulation == QAM_16)))
726 ||
727 ((state->fe->dtv_property_cache.layer[2].segment_count >
728 0)
729 &&
730 ((state->fe->dtv_property_cache.layer[2].modulation ==
731 QAM_64)
732 || (state->fe->dtv_property_cache.layer[2].
733 modulation == QAM_16)))
734 )
735 )
736 adc_error += 60;
737#endif
738
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) {
741
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
748 {
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 */
751 }
752
753 *tune_state = CT_AGC_STOP;
754 }
755 } else {
756 /* everything higher than or equal to CT_AGC_STOP means tracking */
757 ret = 100; /* 10ms interval */
758 apply_gain_immediatly = 0;
759 }
760 }
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",
9c783036 764 (u32) fe->id, (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
03245a5e
OG
765 (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
766#endif
767 }
768
769 /* apply gain */
770 if (!state->agc_freeze)
771 dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
772 return ret;
773}
03245a5e 774EXPORT_SYMBOL(dib0090_gain_control);
9c783036 775
03245a5e
OG
776void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
777{
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;
787}
03245a5e 788EXPORT_SYMBOL(dib0090_get_current_gain);
9c783036 789
03245a5e
OG
790u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner)
791{
792 struct dib0090_state *st = tuner->tuner_priv;
793 return st->wbd_offset;
794}
03245a5e 795EXPORT_SYMBOL(dib0090_get_wbd_offset);
9c783036 796
03245a5e
OG
797static const u16 dib0090_defaults[] = {
798
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,
825
826 1, 0x1c,
827 0xff2d,
828
829 1, 0x39,
830 0x0000,
831
832 1, 0x1b,
833 EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL,
834 2, 0x1e,
835 0x07FF,
836 0x0007,
837
838 1, 0x24,
839 EN_UHF | EN_CRYSTAL,
840
841 2, 0x3c,
842 0x3ff,
843 0x111,
844 0
845};
846
847static int dib0090_reset(struct dvb_frontend *fe)
848{
849 struct dib0090_state *state = fe->tuner_priv;
850 u16 l, r, *n;
851
852 dib0090_reset_digital(fe, state->config);
853 state->revision = dib0090_identify(fe);
854
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
862
863#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
864 if (!(state->revision & 0x1)) /* it is P1B - reset is already done */
865 return 0;
866#endif
867
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++);
880 }
881
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);
889
890 state->reset = 3; /* enable iq-offset-calibration and wbd-calibration when tuning next time */
891
892 return 0;
893}
894
9c783036 895#define steps(u) (((u) > 15) ? ((u)-16) : (u))
03245a5e
OG
896#define INTERN_WAIT 10
897static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
898{
899 int ret = INTERN_WAIT * 10;
900
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;
907
908 case CT_TUNER_STEP_3:
909 state->adc_diff = dib0090_read_reg(state, 0x1d);
910
911 /* Turns to negative */
912 dib0090_write_reg(state, 0x1f, 0x4);
913 *tune_state = CT_TUNER_STEP_4;
914 break;
915
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;
921
922 default:
923 break;
924 }
925
926 return ret;
927}
928
929struct dc_calibration {
930 uint8_t addr;
931 uint8_t offset;
932 uint8_t pga:1;
933 uint16_t bb1;
934 uint8_t i:1;
935};
936
937static 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},
945};
946
947static void dib0090_set_trim(struct dib0090_state *state)
948{
949 u16 *val;
950
951 if (state->dc->addr == 0x07)
952 val = &state->bb7;
953 else
954 val = &state->bb6;
955
956 *val &= ~(0x1f << state->dc->offset);
957 *val |= state->step << state->dc->offset;
958
959 dib0090_write_reg(state, state->dc->addr, *val);
960}
961
962static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
963{
964 int ret = 0;
965
966 switch (*tune_state) {
967
968 case CT_TUNER_START:
969 /* init */
970 dprintk("Internal DC calibration");
971
972 /* the LNA is off */
973 dib0090_write_reg(state, 0x24, 0x02ed);
974
975 /* force vcm2 = 0.8V */
976 state->bb6 = 0;
977 state->bb7 = 0x040d;
978
979 state->dc = dc_table;
980
981 *tune_state = CT_TUNER_STEP_0;
982
983 /* fall through */
984
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));
988
989 state->step = 0;
990
991 state->min_adc_diff = 1023;
992
993 *tune_state = CT_TUNER_STEP_1;
994 ret = 50;
995 break;
996
997 case CT_TUNER_STEP_1:
998 dib0090_set_trim(state);
999
1000 *tune_state = CT_TUNER_STEP_2;
1001 break;
1002
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;
1008
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);
1011
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;
1018 }
1019
1020 state->adc_diff = ABS(state->adc_diff);
1021
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 {
1027
1028 /* the minimum was what we have seen in the step before */
1029 state->step--;
1030 dib0090_set_trim(state);
1031
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);
1034
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;
1040
1041 }
1042 break;
1043
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;
1051 }
1052 return ret;
1053}
1054
1055static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1056{
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);
1062
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);
1068
1069 *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1070 state->reset &= ~0x2;
1071 break;
1072 default:
1073 break;
1074 }
1075 return 0;
1076}
1077
1078static void dib0090_set_bandwidth(struct dib0090_state *state)
1079{
1080 u16 tmp;
1081
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);
1090
1091 state->bb_1_def &= 0x3fff;
1092 state->bb_1_def |= tmp;
1093
1094 dib0090_write_reg(state, 0x01, state->bb_1_def); /* be sure that we have the right bb-filter */
1095}
1096
1097static 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
1126};
1127
1128static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
1129
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
1152};
1153
1154static const struct dib0090_tuning dib0090_tuning_table[] = {
1155
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
1181};
1182
1183#define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */
1184static int dib0090_tune(struct dvb_frontend *fe)
1185{
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;
1190
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;
1198
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);
1207
1208 /************************* VCO ***************************/
1209 /* Default values for FG */
1210 /* from these are needed : */
1211 /* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv */
1212
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
1217
1218 if (state->current_rf != rf) {
1219 state->tuner_is_tuned = 0;
1220
1221 tune = dib0090_tuning_table;
1222
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;
1230 }
1231 }
1232
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;
1241 }
1242
1243 if (*tune_state == CT_TUNER_START) {
1244
1245 if (state->tuner_is_tuned == 0)
1246 state->current_rf = 0;
1247
1248 if (state->current_rf != rf) {
1249
1250 dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
1251
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;
1261
1262 lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7); /* bit 15 is the split to the slave, we do not do it here */
1263
1264 if (!state->config->io.pll_int_loop_filt)
1265 lo6 = 0xff28;
1266 else
1267 lo6 = (state->config->io.pll_int_loop_filt << 3);
1268
1269 VCOF_kHz = (pll->hfdiv * rf) * 2;
1270
1271 FREF = state->config->io.clock_khz;
1272
1273 FBDiv = (VCOF_kHz / pll->topresc / FREF);
1274 Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
1275
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);
1286
1287 Den = 1;
1288
1289 dprintk(" ***** ******* Rest value = %d", Rest);
1290
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;
1297 }
1298#ifdef CONFIG_BAND_SBAND
1299 if (state->current_band == BAND_SBAND)
1300 lo6 &= 0xfffb;
1301#endif
1302
1303 dib0090_write_reg(state, 0x15, (u16) FBDiv);
1304
1305 dib0090_write_reg(state, 0x16, (Den << 8) | 1);
1306
1307 dib0090_write_reg(state, 0x17, (u16) Rest);
1308
1309 dib0090_write_reg(state, 0x19, lo5);
1310
1311 dib0090_write_reg(state, 0x1c, lo6);
1312
1313 lo6 = tune->tuner_enable;
1314 if (state->config->analog_output)
1315 lo6 = (lo6 & 0xff9f) | 0x2;
1316
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
1321 );
1322
1323 state->current_rf = rf;
1324
1325 /* prepare a complete captrim */
1326 state->step = state->captrim = state->fcaptrim = 64;
1327
1328 } else { /* we are already tuned to this frequency - the configuration is correct */
1329
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;
1333 }
1334 state->adc_diff = 3000;
1335
1336 dib0090_write_reg(state, 0x10, 0x2B1);
1337
1338 dib0090_write_reg(state, 0x1e, 0x0032);
1339
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) {
1349
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);
1353
1354 if (adc >= 400) {
1355 adc -= 400;
1356 step_sign = -1;
1357 } else {
1358 adc = 400 - adc;
1359 step_sign = 1;
1360 }
1361
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;
1366
1367 }
1368
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;
1374
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);
1379
1380#ifdef CONFIG_TUNER_DIB0090_CAPTRIM_MEMORY
1381 state->memory[state->memory_index].cap = state->fcaptrim;
1382#endif
1383
1384 *tune_state = CT_TUNER_STEP_4;
1385 } else if (*tune_state == CT_TUNER_STEP_4) {
1386 dib0090_write_reg(state, 0x1e, 0x07ff);
1387
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);
1396
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;
1403 }
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
1409 ));
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);
1414
1415 *tune_state = CT_TUNER_STEP_5;
1416 } else if (*tune_state == CT_TUNER_STEP_5) {
1417
1418 /* initialize the lt gain register */
1419 state->rf_lt_def = 0x7c00;
1420 dib0090_write_reg(state, 0x0f, state->rf_lt_def);
1421
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;
1428}
1429
1430static int dib0090_release(struct dvb_frontend *fe)
1431{
1432 kfree(fe->tuner_priv);
1433 fe->tuner_priv = NULL;
1434 return 0;
1435}
1436
1437enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
1438{
1439 struct dib0090_state *state = fe->tuner_priv;
1440
1441 return state->tune_state;
1442}
03245a5e
OG
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}
03245a5e
OG
1452EXPORT_SYMBOL(dib0090_set_tune_state);
1453
1454static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
1455{
1456 struct dib0090_state *state = fe->tuner_priv;
1457
1458 *frequency = 1000 * state->current_rf;
1459 return 0;
1460}
1461
1462static int dib0090_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
1463{
1464 struct dib0090_state *state = fe->tuner_priv;
1465 uint32_t ret;
1466
1467 state->tune_state = CT_TUNER_START;
1468
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);
1476
1477 return 0;
1478}
1479
1480static 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,
1486 },
1487 .release = dib0090_release,
1488
1489 .init = dib0090_wakeup,
1490 .sleep = dib0090_sleep,
1491 .set_params = dib0090_set_params,
1492 .get_frequency = dib0090_get_frequency,
1493};
1494
1495struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
1496{
1497 struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
1498 if (st == NULL)
1499 return NULL;
1500
1501 st->config = config;
1502 st->i2c = i2c;
1503 st->fe = fe;
1504 fe->tuner_priv = st;
1505
1506 if (dib0090_reset(fe) != 0)
1507 goto free_mem;
1508
1509 printk(KERN_INFO "DiB0090: successfully identified\n");
1510 memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
1511
1512 return fe;
1513 free_mem:
1514 kfree(st);
1515 fe->tuner_priv = NULL;
1516 return NULL;
1517}
03245a5e
OG
1518EXPORT_SYMBOL(dib0090_register);
1519
1520MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
1521MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>");
1522MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
1523MODULE_LICENSE("GPL");