• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/media/dvb/frontends/
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/slab.h>
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] = {
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},
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 };
166	struct i2c_msg msg = {.addr = state->config->i2c_address, .flags = 0, .buf = b, .len = 3 };
167	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
168		printk(KERN_WARNING "DiB0090 I2C write failed\n");
169		return -EREMOTEIO;
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
287void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
288{
289	struct dib0090_state *state = fe->tuner_priv;
290	if (fast)
291		dib0090_write_reg(state, 0x04, 0);
292	else
293		dib0090_write_reg(state, 0x04, 1);
294}
295EXPORT_SYMBOL(dib0090_dcc_freq);
296
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
620		dib0090_write_reg(state, 0x39, (1 << 10));
621	}
622}
623EXPORT_SYMBOL(dib0090_pwm_gain_reset);
624
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",
764		     (u32) fe->id, (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
765		     (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
766#endif
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}
774EXPORT_SYMBOL(dib0090_gain_control);
775
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}
788EXPORT_SYMBOL(dib0090_get_current_gain);
789
790u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner)
791{
792	struct dib0090_state *st = tuner->tuner_priv;
793	return st->wbd_offset;
794}
795EXPORT_SYMBOL(dib0090_get_wbd_offset);
796
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
895#define steps(u) (((u) > 15) ? ((u)-16) : (u))
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}
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}
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}
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");
1524