[go: nahoru, domu]

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#include <linux/mutex.h>
31
32#include "dvb_frontend.h"
33
34#include "dib0090.h"
35#include "dibx000_common.h"
36
37static int debug;
38module_param(debug, int, 0644);
39MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
40
41#define dprintk(args...) do { \
42	if (debug) { \
43		printk(KERN_DEBUG "DiB0090: "); \
44		printk(args); \
45		printk("\n"); \
46	} \
47} while (0)
48
49#define CONFIG_SYS_DVBT
50#define CONFIG_SYS_ISDBT
51#define CONFIG_BAND_CBAND
52#define CONFIG_BAND_VHF
53#define CONFIG_BAND_UHF
54#define CONFIG_DIB0090_USE_PWM_AGC
55
56#define EN_LNA0      0x8000
57#define EN_LNA1      0x4000
58#define EN_LNA2      0x2000
59#define EN_LNA3      0x1000
60#define EN_MIX0      0x0800
61#define EN_MIX1      0x0400
62#define EN_MIX2      0x0200
63#define EN_MIX3      0x0100
64#define EN_IQADC     0x0040
65#define EN_PLL       0x0020
66#define EN_TX        0x0010
67#define EN_BB        0x0008
68#define EN_LO        0x0004
69#define EN_BIAS      0x0001
70
71#define EN_IQANA     0x0002
72#define EN_DIGCLK    0x0080	/* not in the 0x24 reg, only in 0x1b */
73#define EN_CRYSTAL   0x0002
74
75#define EN_UHF		 0x22E9
76#define EN_VHF		 0x44E9
77#define EN_LBD		 0x11E9
78#define EN_SBD		 0x44E9
79#define EN_CAB		 0x88E9
80
81/* Calibration defines */
82#define      DC_CAL 0x1
83#define     WBD_CAL 0x2
84#define    TEMP_CAL 0x4
85#define CAPTRIM_CAL 0x8
86
87#define KROSUS_PLL_LOCKED   0x800
88#define KROSUS              0x2
89
90/* Use those defines to identify SOC version */
91#define SOC               0x02
92#define SOC_7090_P1G_11R1 0x82
93#define SOC_7090_P1G_21R1 0x8a
94#define SOC_8090_P1G_11R1 0x86
95#define SOC_8090_P1G_21R1 0x8e
96
97/* else use thos ones to check */
98#define P1A_B      0x0
99#define P1C	   0x1
100#define P1D_E_F    0x3
101#define P1G	   0x7
102#define P1G_21R2   0xf
103
104#define MP001 0x1		/* Single 9090/8096 */
105#define MP005 0x4		/* Single Sband */
106#define MP008 0x6		/* Dual diversity VHF-UHF-LBAND */
107#define MP009 0x7		/* Dual diversity 29098 CBAND-UHF-LBAND-SBAND */
108
109#define pgm_read_word(w) (*w)
110
111struct dc_calibration;
112
113struct dib0090_tuning {
114	u32 max_freq;		/* for every frequency less than or equal to that field: this information is correct */
115	u8 switch_trim;
116	u8 lna_tune;
117	u16 lna_bias;
118	u16 v2i;
119	u16 mix;
120	u16 load;
121	u16 tuner_enable;
122};
123
124struct dib0090_pll {
125	u32 max_freq;		/* for every frequency less than or equal to that field: this information is correct */
126	u8 vco_band;
127	u8 hfdiv_code;
128	u8 hfdiv;
129	u8 topresc;
130};
131
132struct dib0090_identity {
133	u8 version;
134	u8 product;
135	u8 p1g;
136	u8 in_soc;
137};
138
139struct dib0090_state {
140	struct i2c_adapter *i2c;
141	struct dvb_frontend *fe;
142	const struct dib0090_config *config;
143
144	u8 current_band;
145	enum frontend_tune_state tune_state;
146	u32 current_rf;
147
148	u16 wbd_offset;
149	s16 wbd_target;		/* in dB */
150
151	s16 rf_gain_limit;	/* take-over-point: where to split between bb and rf gain */
152	s16 current_gain;	/* keeps the currently programmed gain */
153	u8 agc_step;		/* new binary search */
154
155	u16 gain[2];		/* for channel monitoring */
156
157	const u16 *rf_ramp;
158	const u16 *bb_ramp;
159
160	/* for the software AGC ramps */
161	u16 bb_1_def;
162	u16 rf_lt_def;
163	u16 gain_reg[4];
164
165	/* for the captrim/dc-offset search */
166	s8 step;
167	s16 adc_diff;
168	s16 min_adc_diff;
169
170	s8 captrim;
171	s8 fcaptrim;
172
173	const struct dc_calibration *dc;
174	u16 bb6, bb7;
175
176	const struct dib0090_tuning *current_tune_table_index;
177	const struct dib0090_pll *current_pll_table_index;
178
179	u8 tuner_is_tuned;
180	u8 agc_freeze;
181
182	struct dib0090_identity identity;
183
184	u32 rf_request;
185	u8 current_standard;
186
187	u8 calibrate;
188	u32 rest;
189	u16 bias;
190	s16 temperature;
191
192	u8 wbd_calibration_gain;
193	const struct dib0090_wbd_slope *current_wbd_table;
194	u16 wbdmux;
195
196	/* for the I2C transfer */
197	struct i2c_msg msg[2];
198	u8 i2c_write_buffer[3];
199	u8 i2c_read_buffer[2];
200	struct mutex i2c_buffer_lock;
201};
202
203struct dib0090_fw_state {
204	struct i2c_adapter *i2c;
205	struct dvb_frontend *fe;
206	struct dib0090_identity identity;
207	const struct dib0090_config *config;
208
209	/* for the I2C transfer */
210	struct i2c_msg msg;
211	u8 i2c_write_buffer[2];
212	u8 i2c_read_buffer[2];
213	struct mutex i2c_buffer_lock;
214};
215
216static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
217{
218	u16 ret;
219
220	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
221		dprintk("could not acquire lock");
222		return 0;
223	}
224
225	state->i2c_write_buffer[0] = reg;
226
227	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
228	state->msg[0].addr = state->config->i2c_address;
229	state->msg[0].flags = 0;
230	state->msg[0].buf = state->i2c_write_buffer;
231	state->msg[0].len = 1;
232	state->msg[1].addr = state->config->i2c_address;
233	state->msg[1].flags = I2C_M_RD;
234	state->msg[1].buf = state->i2c_read_buffer;
235	state->msg[1].len = 2;
236
237	if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
238		printk(KERN_WARNING "DiB0090 I2C read failed\n");
239		ret = 0;
240	} else
241		ret = (state->i2c_read_buffer[0] << 8)
242			| state->i2c_read_buffer[1];
243
244	mutex_unlock(&state->i2c_buffer_lock);
245	return ret;
246}
247
248static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
249{
250	int ret;
251
252	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
253		dprintk("could not acquire lock");
254		return -EINVAL;
255	}
256
257	state->i2c_write_buffer[0] = reg & 0xff;
258	state->i2c_write_buffer[1] = val >> 8;
259	state->i2c_write_buffer[2] = val & 0xff;
260
261	memset(state->msg, 0, sizeof(struct i2c_msg));
262	state->msg[0].addr = state->config->i2c_address;
263	state->msg[0].flags = 0;
264	state->msg[0].buf = state->i2c_write_buffer;
265	state->msg[0].len = 3;
266
267	if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
268		printk(KERN_WARNING "DiB0090 I2C write failed\n");
269		ret = -EREMOTEIO;
270	} else
271		ret = 0;
272
273	mutex_unlock(&state->i2c_buffer_lock);
274	return ret;
275}
276
277static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
278{
279	u16 ret;
280
281	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
282		dprintk("could not acquire lock");
283		return 0;
284	}
285
286	state->i2c_write_buffer[0] = reg;
287
288	memset(&state->msg, 0, sizeof(struct i2c_msg));
289	state->msg.addr = reg;
290	state->msg.flags = I2C_M_RD;
291	state->msg.buf = state->i2c_read_buffer;
292	state->msg.len = 2;
293	if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
294		printk(KERN_WARNING "DiB0090 I2C read failed\n");
295		ret = 0;
296	} else
297		ret = (state->i2c_read_buffer[0] << 8)
298			| state->i2c_read_buffer[1];
299
300	mutex_unlock(&state->i2c_buffer_lock);
301	return ret;
302}
303
304static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
305{
306	int ret;
307
308	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
309		dprintk("could not acquire lock");
310		return -EINVAL;
311	}
312
313	state->i2c_write_buffer[0] = val >> 8;
314	state->i2c_write_buffer[1] = val & 0xff;
315
316	memset(&state->msg, 0, sizeof(struct i2c_msg));
317	state->msg.addr = reg;
318	state->msg.flags = 0;
319	state->msg.buf = state->i2c_write_buffer;
320	state->msg.len = 2;
321	if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
322		printk(KERN_WARNING "DiB0090 I2C write failed\n");
323		ret = -EREMOTEIO;
324	} else
325		ret = 0;
326
327	mutex_unlock(&state->i2c_buffer_lock);
328	return ret;
329}
330
331#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)
332#define ADC_TARGET -220
333#define GAIN_ALPHA 5
334#define WBD_ALPHA 6
335#define LPF	100
336static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c)
337{
338	do {
339		dib0090_write_reg(state, r++, *b++);
340	} while (--c);
341}
342
343static int dib0090_identify(struct dvb_frontend *fe)
344{
345	struct dib0090_state *state = fe->tuner_priv;
346	u16 v;
347	struct dib0090_identity *identity = &state->identity;
348
349	v = dib0090_read_reg(state, 0x1a);
350
351	identity->p1g = 0;
352	identity->in_soc = 0;
353
354	dprintk("Tuner identification (Version = 0x%04x)", v);
355
356	/* without PLL lock info */
357	v &= ~KROSUS_PLL_LOCKED;
358
359	identity->version = v & 0xff;
360	identity->product = (v >> 8) & 0xf;
361
362	if (identity->product != KROSUS)
363		goto identification_error;
364
365	if ((identity->version & 0x3) == SOC) {
366		identity->in_soc = 1;
367		switch (identity->version) {
368		case SOC_8090_P1G_11R1:
369			dprintk("SOC 8090 P1-G11R1 Has been detected");
370			identity->p1g = 1;
371			break;
372		case SOC_8090_P1G_21R1:
373			dprintk("SOC 8090 P1-G21R1 Has been detected");
374			identity->p1g = 1;
375			break;
376		case SOC_7090_P1G_11R1:
377			dprintk("SOC 7090 P1-G11R1 Has been detected");
378			identity->p1g = 1;
379			break;
380		case SOC_7090_P1G_21R1:
381			dprintk("SOC 7090 P1-G21R1 Has been detected");
382			identity->p1g = 1;
383			break;
384		default:
385			goto identification_error;
386		}
387	} else {
388		switch ((identity->version >> 5) & 0x7) {
389		case MP001:
390			dprintk("MP001 : 9090/8096");
391			break;
392		case MP005:
393			dprintk("MP005 : Single Sband");
394			break;
395		case MP008:
396			dprintk("MP008 : diversity VHF-UHF-LBAND");
397			break;
398		case MP009:
399			dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND");
400			break;
401		default:
402			goto identification_error;
403		}
404
405		switch (identity->version & 0x1f) {
406		case P1G_21R2:
407			dprintk("P1G_21R2 detected");
408			identity->p1g = 1;
409			break;
410		case P1G:
411			dprintk("P1G detected");
412			identity->p1g = 1;
413			break;
414		case P1D_E_F:
415			dprintk("P1D/E/F detected");
416			break;
417		case P1C:
418			dprintk("P1C detected");
419			break;
420		case P1A_B:
421			dprintk("P1-A/B detected: driver is deactivated - not available");
422			goto identification_error;
423			break;
424		default:
425			goto identification_error;
426		}
427	}
428
429	return 0;
430
431identification_error:
432	return -EIO;
433}
434
435static int dib0090_fw_identify(struct dvb_frontend *fe)
436{
437	struct dib0090_fw_state *state = fe->tuner_priv;
438	struct dib0090_identity *identity = &state->identity;
439
440	u16 v = dib0090_fw_read_reg(state, 0x1a);
441	identity->p1g = 0;
442	identity->in_soc = 0;
443
444	dprintk("FE: Tuner identification (Version = 0x%04x)", v);
445
446	/* without PLL lock info */
447	v &= ~KROSUS_PLL_LOCKED;
448
449	identity->version = v & 0xff;
450	identity->product = (v >> 8) & 0xf;
451
452	if (identity->product != KROSUS)
453		goto identification_error;
454
455	if ((identity->version & 0x3) == SOC) {
456		identity->in_soc = 1;
457		switch (identity->version) {
458		case SOC_8090_P1G_11R1:
459			dprintk("SOC 8090 P1-G11R1 Has been detected");
460			identity->p1g = 1;
461			break;
462		case SOC_8090_P1G_21R1:
463			dprintk("SOC 8090 P1-G21R1 Has been detected");
464			identity->p1g = 1;
465			break;
466		case SOC_7090_P1G_11R1:
467			dprintk("SOC 7090 P1-G11R1 Has been detected");
468			identity->p1g = 1;
469			break;
470		case SOC_7090_P1G_21R1:
471			dprintk("SOC 7090 P1-G21R1 Has been detected");
472			identity->p1g = 1;
473			break;
474		default:
475			goto identification_error;
476		}
477	} else {
478		switch ((identity->version >> 5) & 0x7) {
479		case MP001:
480			dprintk("MP001 : 9090/8096");
481			break;
482		case MP005:
483			dprintk("MP005 : Single Sband");
484			break;
485		case MP008:
486			dprintk("MP008 : diversity VHF-UHF-LBAND");
487			break;
488		case MP009:
489			dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND");
490			break;
491		default:
492			goto identification_error;
493		}
494
495		switch (identity->version & 0x1f) {
496		case P1G_21R2:
497			dprintk("P1G_21R2 detected");
498			identity->p1g = 1;
499			break;
500		case P1G:
501			dprintk("P1G detected");
502			identity->p1g = 1;
503			break;
504		case P1D_E_F:
505			dprintk("P1D/E/F detected");
506			break;
507		case P1C:
508			dprintk("P1C detected");
509			break;
510		case P1A_B:
511			dprintk("P1-A/B detected: driver is deactivated - not available");
512			goto identification_error;
513			break;
514		default:
515			goto identification_error;
516		}
517	}
518
519	return 0;
520
521identification_error:
522	return -EIO;
523}
524
525static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
526{
527	struct dib0090_state *state = fe->tuner_priv;
528	u16 PllCfg, i, v;
529
530	HARD_RESET(state);
531	dib0090_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
532	if (cfg->in_soc)
533		return;
534
535	dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL);	/* PLL, DIG_CLK and CRYSTAL remain */
536	/* adcClkOutRatio=8->7, release reset */
537	dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
538	if (cfg->clkoutdrive != 0)
539		dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
540				| (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
541	else
542		dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
543				| (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
544
545	/* Read Pll current config * */
546	PllCfg = dib0090_read_reg(state, 0x21);
547
548	/** Reconfigure PLL if current setting is different from default setting **/
549	if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && (!cfg->in_soc)
550			&& !cfg->io.pll_bypass) {
551
552		/* Set Bypass mode */
553		PllCfg |= (1 << 15);
554		dib0090_write_reg(state, 0x21, PllCfg);
555
556		/* Set Reset Pll */
557		PllCfg &= ~(1 << 13);
558		dib0090_write_reg(state, 0x21, PllCfg);
559
560	/*** Set new Pll configuration in bypass and reset state ***/
561		PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
562		dib0090_write_reg(state, 0x21, PllCfg);
563
564		/* Remove Reset Pll */
565		PllCfg |= (1 << 13);
566		dib0090_write_reg(state, 0x21, PllCfg);
567
568	/*** Wait for PLL lock ***/
569		i = 100;
570		do {
571			v = !!(dib0090_read_reg(state, 0x1a) & 0x800);
572			if (v)
573				break;
574		} while (--i);
575
576		if (i == 0) {
577			dprintk("Pll: Unable to lock Pll");
578			return;
579		}
580
581		/* Finally Remove Bypass mode */
582		PllCfg &= ~(1 << 15);
583		dib0090_write_reg(state, 0x21, PllCfg);
584	}
585
586	if (cfg->io.pll_bypass) {
587		PllCfg |= (cfg->io.pll_bypass << 15);
588		dib0090_write_reg(state, 0x21, PllCfg);
589	}
590}
591
592static int dib0090_fw_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
593{
594	struct dib0090_fw_state *state = fe->tuner_priv;
595	u16 PllCfg;
596	u16 v;
597	int i;
598
599	dprintk("fw reset digital");
600	HARD_RESET(state);
601
602	dib0090_fw_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
603	dib0090_fw_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL);	/* PLL, DIG_CLK and CRYSTAL remain */
604
605	dib0090_fw_write_reg(state, 0x20,
606			((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (cfg->data_tx_drv << 4) | cfg->ls_cfg_pad_drv);
607
608	v = (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 9) | (0 << 8) | (cfg->clkouttobamse << 4) | (0 << 2) | (0);
609	if (cfg->clkoutdrive != 0)
610		v |= cfg->clkoutdrive << 5;
611	else
612		v |= 7 << 5;
613
614	v |= 2 << 10;
615	dib0090_fw_write_reg(state, 0x23, v);
616
617	/* Read Pll current config * */
618	PllCfg = dib0090_fw_read_reg(state, 0x21);
619
620	/** Reconfigure PLL if current setting is different from default setting **/
621	if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && !cfg->io.pll_bypass) {
622
623		/* Set Bypass mode */
624		PllCfg |= (1 << 15);
625		dib0090_fw_write_reg(state, 0x21, PllCfg);
626
627		/* Set Reset Pll */
628		PllCfg &= ~(1 << 13);
629		dib0090_fw_write_reg(state, 0x21, PllCfg);
630
631	/*** Set new Pll configuration in bypass and reset state ***/
632		PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
633		dib0090_fw_write_reg(state, 0x21, PllCfg);
634
635		/* Remove Reset Pll */
636		PllCfg |= (1 << 13);
637		dib0090_fw_write_reg(state, 0x21, PllCfg);
638
639	/*** Wait for PLL lock ***/
640		i = 100;
641		do {
642			v = !!(dib0090_fw_read_reg(state, 0x1a) & 0x800);
643			if (v)
644				break;
645		} while (--i);
646
647		if (i == 0) {
648			dprintk("Pll: Unable to lock Pll");
649			return -EIO;
650		}
651
652		/* Finally Remove Bypass mode */
653		PllCfg &= ~(1 << 15);
654		dib0090_fw_write_reg(state, 0x21, PllCfg);
655	}
656
657	if (cfg->io.pll_bypass) {
658		PllCfg |= (cfg->io.pll_bypass << 15);
659		dib0090_fw_write_reg(state, 0x21, PllCfg);
660	}
661
662	return dib0090_fw_identify(fe);
663}
664
665static int dib0090_wakeup(struct dvb_frontend *fe)
666{
667	struct dib0090_state *state = fe->tuner_priv;
668	if (state->config->sleep)
669		state->config->sleep(fe, 0);
670
671	/* enable dataTX in case we have been restarted in the wrong moment */
672	dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
673	return 0;
674}
675
676static int dib0090_sleep(struct dvb_frontend *fe)
677{
678	struct dib0090_state *state = fe->tuner_priv;
679	if (state->config->sleep)
680		state->config->sleep(fe, 1);
681	return 0;
682}
683
684void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
685{
686	struct dib0090_state *state = fe->tuner_priv;
687	if (fast)
688		dib0090_write_reg(state, 0x04, 0);
689	else
690		dib0090_write_reg(state, 0x04, 1);
691}
692
693EXPORT_SYMBOL(dib0090_dcc_freq);
694
695static const u16 bb_ramp_pwm_normal_socs[] = {
696	550, /* max BB gain in 10th of dB */
697	(1<<9) | 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
698	440,
699	(4  << 9) | 0, /* BB_RAMP3 = 26dB */
700	(0  << 9) | 208, /* BB_RAMP4 */
701	(4  << 9) | 208, /* BB_RAMP5 = 29dB */
702	(0  << 9) | 440, /* BB_RAMP6 */
703};
704
705static const u16 rf_ramp_pwm_cband_7090p[] = {
706	280, /* max RF gain in 10th of dB */
707	18, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
708	504, /* ramp_max = maximum X used on the ramp */
709	(29 << 10) | 364, /* RF_RAMP5, LNA 1 = 8dB */
710	(0  << 10) | 504, /* RF_RAMP6, LNA 1 */
711	(60 << 10) | 228, /* RF_RAMP7, LNA 2 = 7.7dB */
712	(0  << 10) | 364, /* RF_RAMP8, LNA 2 */
713	(34 << 10) | 109, /* GAIN_4_1, LNA 3 = 6.8dB */
714	(0  << 10) | 228, /* GAIN_4_2, LNA 3 */
715	(37 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */
716	(0  << 10) | 109, /* RF_RAMP4, LNA 4 */
717};
718
719static const u16 rf_ramp_pwm_cband_7090e_sensitivity[] = {
720	186, /* max RF gain in 10th of dB */
721	40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
722	746, /* ramp_max = maximum X used on the ramp */
723	(10 << 10) | 345, /* RF_RAMP5, LNA 1 = 10dB */
724	(0  << 10) | 746, /* RF_RAMP6, LNA 1 */
725	(0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */
726	(0  << 10) | 0, /* RF_RAMP8, LNA 2 */
727	(28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */
728	(0  << 10) | 345, /* GAIN_4_2, LNA 3 */
729	(20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */
730	(0  << 10) | 200, /* RF_RAMP4, LNA 4 */
731};
732
733static const u16 rf_ramp_pwm_cband_7090e_aci[] = {
734	86, /* max RF gain in 10th of dB */
735	40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
736	345, /* ramp_max = maximum X used on the ramp */
737	(0 << 10) | 0, /* RF_RAMP5, LNA 1 = 8dB */ /* 7.47 dB */
738	(0 << 10) | 0, /* RF_RAMP6, LNA 1 */
739	(0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */
740	(0 << 10) | 0, /* RF_RAMP8, LNA 2 */
741	(28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */
742	(0  << 10) | 345, /* GAIN_4_2, LNA 3 */
743	(20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */
744	(0  << 10) | 200, /* RF_RAMP4, LNA 4 */
745};
746
747static const u16 rf_ramp_pwm_cband_8090[] = {
748	345, /* max RF gain in 10th of dB */
749	29, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
750	1000, /* ramp_max = maximum X used on the ramp */
751	(35 << 10) | 772, /* RF_RAMP3, LNA 1 = 8dB */
752	(0  << 10) | 1000, /* RF_RAMP4, LNA 1 */
753	(58 << 10) | 496, /* RF_RAMP5, LNA 2 = 9.5dB */
754	(0  << 10) | 772, /* RF_RAMP6, LNA 2 */
755	(27 << 10) | 200, /* RF_RAMP7, LNA 3 = 10.5dB */
756	(0  << 10) | 496, /* RF_RAMP8, LNA 3 */
757	(40 << 10) | 0, /* GAIN_4_1, LNA 4 = 7dB */
758	(0  << 10) | 200, /* GAIN_4_2, LNA 4 */
759};
760
761static const u16 rf_ramp_pwm_uhf_7090[] = {
762	407, /* max RF gain in 10th of dB */
763	13, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
764	529, /* ramp_max = maximum X used on the ramp */
765	(23 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
766	(0  << 10) | 176, /* RF_RAMP4, LNA 1 */
767	(63 << 10) | 400, /* RF_RAMP5, LNA 2 = 8dB */
768	(0  << 10) | 529, /* RF_RAMP6, LNA 2 */
769	(48 << 10) | 316, /* RF_RAMP7, LNA 3 = 6.8dB */
770	(0  << 10) | 400, /* RF_RAMP8, LNA 3 */
771	(29 << 10) | 176, /* GAIN_4_1, LNA 4 = 11.5dB */
772	(0  << 10) | 316, /* GAIN_4_2, LNA 4 */
773};
774
775static const u16 rf_ramp_pwm_uhf_8090[] = {
776	388, /* max RF gain in 10th of dB */
777	26, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
778	1008, /* ramp_max = maximum X used on the ramp */
779	(11 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
780	(0  << 10) | 369, /* RF_RAMP4, LNA 1 */
781	(41 << 10) | 809, /* RF_RAMP5, LNA 2 = 8dB */
782	(0  << 10) | 1008, /* RF_RAMP6, LNA 2 */
783	(27 << 10) | 659, /* RF_RAMP7, LNA 3 = 6dB */
784	(0  << 10) | 809, /* RF_RAMP8, LNA 3 */
785	(14 << 10) | 369, /* GAIN_4_1, LNA 4 = 11.5dB */
786	(0  << 10) | 659, /* GAIN_4_2, LNA 4 */
787};
788
789/* GENERAL PWM ramp definition for all other Krosus */
790static const u16 bb_ramp_pwm_normal[] = {
791	500, /* max BB gain in 10th of dB */
792	8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
793	400,
794	(2  << 9) | 0, /* BB_RAMP3 = 21dB */
795	(0  << 9) | 168, /* BB_RAMP4 */
796	(2  << 9) | 168, /* BB_RAMP5 = 29dB */
797	(0  << 9) | 400, /* BB_RAMP6 */
798};
799
800static const u16 bb_ramp_pwm_boost[] = {
801	550, /* max BB gain in 10th of dB */
802	8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
803	440,
804	(2  << 9) | 0, /* BB_RAMP3 = 26dB */
805	(0  << 9) | 208, /* BB_RAMP4 */
806	(2  << 9) | 208, /* BB_RAMP5 = 29dB */
807	(0  << 9) | 440, /* BB_RAMP6 */
808};
809
810static const u16 rf_ramp_pwm_cband[] = {
811	314, /* max RF gain in 10th of dB */
812	33, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
813	1023, /* ramp_max = maximum X used on the ramp */
814	(8  << 10) | 743, /* RF_RAMP3, LNA 1 = 0dB */
815	(0  << 10) | 1023, /* RF_RAMP4, LNA 1 */
816	(15 << 10) | 469, /* RF_RAMP5, LNA 2 = 0dB */
817	(0  << 10) | 742, /* RF_RAMP6, LNA 2 */
818	(9  << 10) | 234, /* RF_RAMP7, LNA 3 = 0dB */
819	(0  << 10) | 468, /* RF_RAMP8, LNA 3 */
820	(9  << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
821	(0  << 10) | 233, /* GAIN_4_2, LNA 4 */
822};
823
824static const u16 rf_ramp_pwm_vhf[] = {
825	398, /* max RF gain in 10th of dB */
826	24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
827	954, /* ramp_max = maximum X used on the ramp */
828	(7  << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */
829	(0  << 10) | 290, /* RF_RAMP4, LNA 1 */
830	(16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */
831	(0  << 10) | 954, /* RF_RAMP6, LNA 2 */
832	(17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */
833	(0  << 10) | 699, /* RF_RAMP8, LNA 3 */
834	(7  << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */
835	(0  << 10) | 580, /* GAIN_4_2, LNA 4 */
836};
837
838static const u16 rf_ramp_pwm_uhf[] = {
839	398, /* max RF gain in 10th of dB */
840	24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
841	954, /* ramp_max = maximum X used on the ramp */
842	(7  << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */
843	(0  << 10) | 290, /* RF_RAMP4, LNA 1 */
844	(16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */
845	(0  << 10) | 954, /* RF_RAMP6, LNA 2 */
846	(17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */
847	(0  << 10) | 699, /* RF_RAMP8, LNA 3 */
848	(7  << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */
849	(0  << 10) | 580, /* GAIN_4_2, LNA 4 */
850};
851
852static const u16 rf_ramp_pwm_sband[] = {
853	253, /* max RF gain in 10th of dB */
854	38, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
855	961,
856	(4  << 10) | 0, /* RF_RAMP3, LNA 1 = 14.1dB */
857	(0  << 10) | 508, /* RF_RAMP4, LNA 1 */
858	(9  << 10) | 508, /* RF_RAMP5, LNA 2 = 11.2dB */
859	(0  << 10) | 961, /* RF_RAMP6, LNA 2 */
860	(0  << 10) | 0, /* RF_RAMP7, LNA 3 = 0dB */
861	(0  << 10) | 0, /* RF_RAMP8, LNA 3 */
862	(0  << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
863	(0  << 10) | 0, /* GAIN_4_2, LNA 4 */
864};
865
866struct slope {
867	s16 range;
868	s16 slope;
869};
870static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
871{
872	u8 i;
873	u16 rest;
874	u16 ret = 0;
875	for (i = 0; i < num; i++) {
876		if (val > slopes[i].range)
877			rest = slopes[i].range;
878		else
879			rest = val;
880		ret += (rest * slopes[i].slope) / slopes[i].range;
881		val -= rest;
882	}
883	return ret;
884}
885
886static const struct slope dib0090_wbd_slopes[3] = {
887	{66, 120},		/* -64,-52: offset -   65 */
888	{600, 170},		/* -52,-35: 65     -  665 */
889	{170, 250},		/* -45,-10: 665    - 835 */
890};
891
892static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
893{
894	wbd &= 0x3ff;
895	if (wbd < state->wbd_offset)
896		wbd = 0;
897	else
898		wbd -= state->wbd_offset;
899	/* -64dB is the floor */
900	return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd);
901}
902
903static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
904{
905	u16 offset = 250;
906
907	/* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */
908
909	if (state->current_band == BAND_VHF)
910		offset = 650;
911#ifndef FIRMWARE_FIREFLY
912	if (state->current_band == BAND_VHF)
913		offset = state->config->wbd_vhf_offset;
914	if (state->current_band == BAND_CBAND)
915		offset = state->config->wbd_cband_offset;
916#endif
917
918	state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
919	dprintk("wbd-target: %d dB", (u32) state->wbd_target);
920}
921
922static const int gain_reg_addr[4] = {
923	0x08, 0x0a, 0x0f, 0x01
924};
925
926static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
927{
928	u16 rf, bb, ref;
929	u16 i, v, gain_reg[4] = { 0 }, gain;
930	const u16 *g;
931
932	if (top_delta < -511)
933		top_delta = -511;
934	if (top_delta > 511)
935		top_delta = 511;
936
937	if (force) {
938		top_delta *= (1 << WBD_ALPHA);
939		gain_delta *= (1 << GAIN_ALPHA);
940	}
941
942	if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit))	/* overflow */
943		state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
944	else
945		state->rf_gain_limit += top_delta;
946
947	if (state->rf_gain_limit < 0)	/*underflow */
948		state->rf_gain_limit = 0;
949
950	/* use gain as a temporary variable and correct current_gain */
951	gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA;
952	if (gain_delta >= ((s16) gain - state->current_gain))	/* overflow */
953		state->current_gain = gain;
954	else
955		state->current_gain += gain_delta;
956	/* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */
957	if (state->current_gain < 0)
958		state->current_gain = 0;
959
960	/* now split total gain to rf and bb gain */
961	gain = state->current_gain >> GAIN_ALPHA;
962
963	/* requested gain is bigger than rf gain limit - ACI/WBD adjustment */
964	if (gain > (state->rf_gain_limit >> WBD_ALPHA)) {
965		rf = state->rf_gain_limit >> WBD_ALPHA;
966		bb = gain - rf;
967		if (bb > state->bb_ramp[0])
968			bb = state->bb_ramp[0];
969	} else {		/* high signal level -> all gains put on RF */
970		rf = gain;
971		bb = 0;
972	}
973
974	state->gain[0] = rf;
975	state->gain[1] = bb;
976
977	/* software ramp */
978	/* Start with RF gains */
979	g = state->rf_ramp + 1;	/* point on RF LNA1 max gain */
980	ref = rf;
981	for (i = 0; i < 7; i++) {	/* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */
982		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 */
983			v = 0;	/* force the gain to write for the current amp to be null */
984		else if (ref >= g[1])	/* Gain to set is higher than the high working point of this amp */
985			v = g[2];	/* force this amp to be full gain */
986		else		/* compute the value to set to this amp because we are somewhere in his range */
987			v = ((ref - (g[1] - g[0])) * g[2]) / g[0];
988
989		if (i == 0)	/* LNA 1 reg mapping */
990			gain_reg[0] = v;
991		else if (i == 1)	/* LNA 2 reg mapping */
992			gain_reg[0] |= v << 7;
993		else if (i == 2)	/* LNA 3 reg mapping */
994			gain_reg[1] = v;
995		else if (i == 3)	/* LNA 4 reg mapping */
996			gain_reg[1] |= v << 7;
997		else if (i == 4)	/* CBAND LNA reg mapping */
998			gain_reg[2] = v | state->rf_lt_def;
999		else if (i == 5)	/* BB gain 1 reg mapping */
1000			gain_reg[3] = v << 3;
1001		else if (i == 6)	/* BB gain 2 reg mapping */
1002			gain_reg[3] |= v << 8;
1003
1004		g += 3;		/* go to next gain bloc */
1005
1006		/* When RF is finished, start with BB */
1007		if (i == 4) {
1008			g = state->bb_ramp + 1;	/* point on BB gain 1 max gain */
1009			ref = bb;
1010		}
1011	}
1012	gain_reg[3] |= state->bb_1_def;
1013	gain_reg[3] |= ((bb % 10) * 100) / 125;
1014
1015#ifdef DEBUG_AGC
1016	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,
1017		gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]);
1018#endif
1019
1020	/* Write the amplifier regs */
1021	for (i = 0; i < 4; i++) {
1022		v = gain_reg[i];
1023		if (force || state->gain_reg[i] != v) {
1024			state->gain_reg[i] = v;
1025			dib0090_write_reg(state, gain_reg_addr[i], v);
1026		}
1027	}
1028}
1029
1030static void dib0090_set_boost(struct dib0090_state *state, int onoff)
1031{
1032	state->bb_1_def &= 0xdfff;
1033	state->bb_1_def |= onoff << 13;
1034}
1035
1036static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
1037{
1038	state->rf_ramp = cfg;
1039}
1040
1041static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
1042{
1043	state->rf_ramp = cfg;
1044
1045	dib0090_write_reg(state, 0x2a, 0xffff);
1046
1047	dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
1048
1049	dib0090_write_regs(state, 0x2c, cfg + 3, 6);
1050	dib0090_write_regs(state, 0x3e, cfg + 9, 2);
1051}
1052
1053static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
1054{
1055	state->bb_ramp = cfg;
1056	dib0090_set_boost(state, cfg[0] > 500);	/* we want the boost if the gain is higher that 50dB */
1057}
1058
1059static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
1060{
1061	state->bb_ramp = cfg;
1062
1063	dib0090_set_boost(state, cfg[0] > 500);	/* we want the boost if the gain is higher that 50dB */
1064
1065	dib0090_write_reg(state, 0x33, 0xffff);
1066	dprintk("total BB gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x33));
1067	dib0090_write_regs(state, 0x35, cfg + 3, 4);
1068}
1069
1070void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
1071{
1072	struct dib0090_state *state = fe->tuner_priv;
1073	u16 *bb_ramp = (u16 *)&bb_ramp_pwm_normal; /* default baseband config */
1074	u16 *rf_ramp = NULL;
1075	u8 en_pwm_rf_mux = 1;
1076
1077	/* reset the AGC */
1078	if (state->config->use_pwm_agc) {
1079		if (state->current_band == BAND_CBAND) {
1080			if (state->identity.in_soc) {
1081				bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
1082				if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1083					rf_ramp = (u16 *)&rf_ramp_pwm_cband_8090;
1084				else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1) {
1085					if (state->config->is_dib7090e) {
1086						if (state->rf_ramp == NULL)
1087							rf_ramp = (u16 *)&rf_ramp_pwm_cband_7090e_sensitivity;
1088						else
1089							rf_ramp = (u16 *)state->rf_ramp;
1090					} else
1091						rf_ramp = (u16 *)&rf_ramp_pwm_cband_7090p;
1092				}
1093			} else
1094				rf_ramp = (u16 *)&rf_ramp_pwm_cband;
1095		} else
1096
1097			if (state->current_band == BAND_VHF) {
1098				if (state->identity.in_soc) {
1099					bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
1100					/* rf_ramp = &rf_ramp_pwm_vhf_socs; */ /* TODO */
1101				} else
1102					rf_ramp = (u16 *)&rf_ramp_pwm_vhf;
1103			} else if (state->current_band == BAND_UHF) {
1104				if (state->identity.in_soc) {
1105					bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
1106					if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
1107						rf_ramp = (u16 *)&rf_ramp_pwm_uhf_8090;
1108					else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1109						rf_ramp = (u16 *)&rf_ramp_pwm_uhf_7090;
1110				} else
1111					rf_ramp = (u16 *)&rf_ramp_pwm_uhf;
1112			}
1113		if (rf_ramp)
1114			dib0090_set_rframp_pwm(state, rf_ramp);
1115		dib0090_set_bbramp_pwm(state, bb_ramp);
1116
1117		/* activate the ramp generator using PWM control */
1118		dprintk("ramp RF gain = %d BAND = %s version = %d", state->rf_ramp[0], (state->current_band == BAND_CBAND) ? "CBAND" : "NOT CBAND", state->identity.version & 0x1f);
1119
1120		if ((state->rf_ramp[0] == 0) || (state->current_band == BAND_CBAND && (state->identity.version & 0x1f) <= P1D_E_F)) {
1121			dprintk("DE-Engage mux for direct gain reg control");
1122			en_pwm_rf_mux = 0;
1123		} else
1124			dprintk("Engage mux for PWM control");
1125
1126		dib0090_write_reg(state, 0x32, (en_pwm_rf_mux << 12) | (en_pwm_rf_mux << 11));
1127
1128		/* Set fast servo cutoff to start AGC; 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast*/
1129		if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
1130			dib0090_write_reg(state, 0x04, 3);
1131		else
1132			dib0090_write_reg(state, 0x04, 1);
1133		dib0090_write_reg(state, 0x39, (1 << 10)); /* 0 gain by default */
1134	}
1135}
1136EXPORT_SYMBOL(dib0090_pwm_gain_reset);
1137
1138void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff)
1139{
1140	struct dib0090_state *state = fe->tuner_priv;
1141	if (DC_servo_cutoff < 4)
1142		dib0090_write_reg(state, 0x04, DC_servo_cutoff);
1143}
1144EXPORT_SYMBOL(dib0090_set_dc_servo);
1145
1146static u32 dib0090_get_slow_adc_val(struct dib0090_state *state)
1147{
1148	u16 adc_val = dib0090_read_reg(state, 0x1d);
1149	if (state->identity.in_soc)
1150		adc_val >>= 2;
1151	return adc_val;
1152}
1153
1154int dib0090_gain_control(struct dvb_frontend *fe)
1155{
1156	struct dib0090_state *state = fe->tuner_priv;
1157	enum frontend_tune_state *tune_state = &state->tune_state;
1158	int ret = 10;
1159
1160	u16 wbd_val = 0;
1161	u8 apply_gain_immediatly = 1;
1162	s16 wbd_error = 0, adc_error = 0;
1163
1164	if (*tune_state == CT_AGC_START) {
1165		state->agc_freeze = 0;
1166		dib0090_write_reg(state, 0x04, 0x0);
1167
1168#ifdef CONFIG_BAND_SBAND
1169		if (state->current_band == BAND_SBAND) {
1170			dib0090_set_rframp(state, rf_ramp_sband);
1171			dib0090_set_bbramp(state, bb_ramp_boost);
1172		} else
1173#endif
1174#ifdef CONFIG_BAND_VHF
1175		if (state->current_band == BAND_VHF && !state->identity.p1g) {
1176			dib0090_set_rframp(state, rf_ramp_pwm_vhf);
1177			dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1178		} else
1179#endif
1180#ifdef CONFIG_BAND_CBAND
1181		if (state->current_band == BAND_CBAND && !state->identity.p1g) {
1182			dib0090_set_rframp(state, rf_ramp_pwm_cband);
1183			dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1184		} else
1185#endif
1186		if ((state->current_band == BAND_CBAND || state->current_band == BAND_VHF) && state->identity.p1g) {
1187			dib0090_set_rframp(state, rf_ramp_pwm_cband_7090p);
1188			dib0090_set_bbramp(state, bb_ramp_pwm_normal_socs);
1189		} else {
1190			dib0090_set_rframp(state, rf_ramp_pwm_uhf);
1191			dib0090_set_bbramp(state, bb_ramp_pwm_normal);
1192		}
1193
1194		dib0090_write_reg(state, 0x32, 0);
1195		dib0090_write_reg(state, 0x39, 0);
1196
1197		dib0090_wbd_target(state, state->current_rf);
1198
1199		state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
1200		state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA;
1201
1202		*tune_state = CT_AGC_STEP_0;
1203	} else if (!state->agc_freeze) {
1204		s16 wbd = 0, i, cnt;
1205
1206		int adc;
1207		wbd_val = dib0090_get_slow_adc_val(state);
1208
1209		if (*tune_state == CT_AGC_STEP_0)
1210			cnt = 5;
1211		else
1212			cnt = 1;
1213
1214		for (i = 0; i < cnt; i++) {
1215			wbd_val = dib0090_get_slow_adc_val(state);
1216			wbd += dib0090_wbd_to_db(state, wbd_val);
1217		}
1218		wbd /= cnt;
1219		wbd_error = state->wbd_target - wbd;
1220
1221		if (*tune_state == CT_AGC_STEP_0) {
1222			if (wbd_error < 0 && state->rf_gain_limit > 0 && !state->identity.p1g) {
1223#ifdef CONFIG_BAND_CBAND
1224				/* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */
1225				u8 ltg2 = (state->rf_lt_def >> 10) & 0x7;
1226				if (state->current_band == BAND_CBAND && ltg2) {
1227					ltg2 >>= 1;
1228					state->rf_lt_def &= ltg2 << 10;	/* reduce in 3 steps from 7 to 0 */
1229				}
1230#endif
1231			} else {
1232				state->agc_step = 0;
1233				*tune_state = CT_AGC_STEP_1;
1234			}
1235		} else {
1236			/* calc the adc power */
1237			adc = state->config->get_adc_power(fe);
1238			adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21;	/* included in [0:-700] */
1239
1240			adc_error = (s16) (((s32) ADC_TARGET) - adc);
1241#ifdef CONFIG_STANDARD_DAB
1242			if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)
1243				adc_error -= 10;
1244#endif
1245#ifdef CONFIG_STANDARD_DVBT
1246			if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT &&
1247					(state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
1248				adc_error += 60;
1249#endif
1250#ifdef CONFIG_SYS_ISDBT
1251			if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count >
1252								0)
1253							&&
1254							((state->fe->dtv_property_cache.layer[0].modulation ==
1255							  QAM_64)
1256							 || (state->fe->dtv_property_cache.
1257								 layer[0].modulation == QAM_16)))
1258						||
1259						((state->fe->dtv_property_cache.layer[1].segment_count >
1260						  0)
1261						 &&
1262						 ((state->fe->dtv_property_cache.layer[1].modulation ==
1263						   QAM_64)
1264						  || (state->fe->dtv_property_cache.
1265							  layer[1].modulation == QAM_16)))
1266						||
1267						((state->fe->dtv_property_cache.layer[2].segment_count >
1268						  0)
1269						 &&
1270						 ((state->fe->dtv_property_cache.layer[2].modulation ==
1271						   QAM_64)
1272						  || (state->fe->dtv_property_cache.
1273							  layer[2].modulation == QAM_16)))
1274						)
1275				)
1276				adc_error += 60;
1277#endif
1278
1279			if (*tune_state == CT_AGC_STEP_1) {	/* quickly go to the correct range of the ADC power */
1280				if (ABS(adc_error) < 50 || state->agc_step++ > 5) {
1281
1282#ifdef CONFIG_STANDARD_DAB
1283					if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) {
1284						dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63));	/* cap value = 63 : narrow BB filter : Fc = 1.8MHz */
1285						dib0090_write_reg(state, 0x04, 0x0);
1286					} else
1287#endif
1288					{
1289						dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32));
1290						dib0090_write_reg(state, 0x04, 0x01);	/*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */
1291					}
1292
1293					*tune_state = CT_AGC_STOP;
1294				}
1295			} else {
1296				/* everything higher than or equal to CT_AGC_STOP means tracking */
1297				ret = 100;	/* 10ms interval */
1298				apply_gain_immediatly = 0;
1299			}
1300		}
1301#ifdef DEBUG_AGC
1302		dprintk
1303			("tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
1304			 (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
1305			 (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
1306#endif
1307	}
1308
1309	/* apply gain */
1310	if (!state->agc_freeze)
1311		dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
1312	return ret;
1313}
1314
1315EXPORT_SYMBOL(dib0090_gain_control);
1316
1317void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
1318{
1319	struct dib0090_state *state = fe->tuner_priv;
1320	if (rf)
1321		*rf = state->gain[0];
1322	if (bb)
1323		*bb = state->gain[1];
1324	if (rf_gain_limit)
1325		*rf_gain_limit = state->rf_gain_limit;
1326	if (rflt)
1327		*rflt = (state->rf_lt_def >> 10) & 0x7;
1328}
1329
1330EXPORT_SYMBOL(dib0090_get_current_gain);
1331
1332u16 dib0090_get_wbd_target(struct dvb_frontend *fe)
1333{
1334	struct dib0090_state *state = fe->tuner_priv;
1335	u32 f_MHz = state->fe->dtv_property_cache.frequency / 1000000;
1336	s32 current_temp = state->temperature;
1337	s32 wbd_thot, wbd_tcold;
1338	const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1339
1340	while (f_MHz > wbd->max_freq)
1341		wbd++;
1342
1343	dprintk("using wbd-table-entry with max freq %d", wbd->max_freq);
1344
1345	if (current_temp < 0)
1346		current_temp = 0;
1347	if (current_temp > 128)
1348		current_temp = 128;
1349
1350	state->wbdmux &= ~(7 << 13);
1351	if (wbd->wbd_gain != 0)
1352		state->wbdmux |= (wbd->wbd_gain << 13);
1353	else
1354		state->wbdmux |= (4 << 13);
1355
1356	dib0090_write_reg(state, 0x10, state->wbdmux);
1357
1358	wbd_thot = wbd->offset_hot - (((u32) wbd->slope_hot * f_MHz) >> 6);
1359	wbd_tcold = wbd->offset_cold - (((u32) wbd->slope_cold * f_MHz) >> 6);
1360
1361	wbd_tcold += ((wbd_thot - wbd_tcold) * current_temp) >> 7;
1362
1363	state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + wbd_tcold);
1364	dprintk("wbd-target: %d dB", (u32) state->wbd_target);
1365	dprintk("wbd offset applied is %d", wbd_tcold);
1366
1367	return state->wbd_offset + wbd_tcold;
1368}
1369EXPORT_SYMBOL(dib0090_get_wbd_target);
1370
1371u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
1372{
1373	struct dib0090_state *state = fe->tuner_priv;
1374	return state->wbd_offset;
1375}
1376EXPORT_SYMBOL(dib0090_get_wbd_offset);
1377
1378int dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3)
1379{
1380	struct dib0090_state *state = fe->tuner_priv;
1381
1382	dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xfff8)
1383			| ((sw3 & 1) << 2) | ((sw2 & 1) << 1) | (sw1 & 1));
1384
1385	return 0;
1386}
1387EXPORT_SYMBOL(dib0090_set_switch);
1388
1389int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff)
1390{
1391	struct dib0090_state *state = fe->tuner_priv;
1392
1393	dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x7fff)
1394			| ((onoff & 1) << 15));
1395	return 0;
1396}
1397EXPORT_SYMBOL(dib0090_set_vga);
1398
1399int dib0090_update_rframp_7090(struct dvb_frontend *fe, u8 cfg_sensitivity)
1400{
1401	struct dib0090_state *state = fe->tuner_priv;
1402
1403	if ((!state->identity.p1g) || (!state->identity.in_soc)
1404			|| ((state->identity.version != SOC_7090_P1G_21R1)
1405				&& (state->identity.version != SOC_7090_P1G_11R1))) {
1406		dprintk("%s() function can only be used for dib7090P", __func__);
1407		return -ENODEV;
1408	}
1409
1410	if (cfg_sensitivity)
1411		state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_sensitivity;
1412	else
1413		state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_aci;
1414	dib0090_pwm_gain_reset(fe);
1415
1416	return 0;
1417}
1418EXPORT_SYMBOL(dib0090_update_rframp_7090);
1419
1420static const u16 dib0090_defaults[] = {
1421
1422	25, 0x01,
1423	0x0000,
1424	0x99a0,
1425	0x6008,
1426	0x0000,
1427	0x8bcb,
1428	0x0000,
1429	0x0405,
1430	0x0000,
1431	0x0000,
1432	0x0000,
1433	0xb802,
1434	0x0300,
1435	0x2d12,
1436	0xbac0,
1437	0x7c00,
1438	0xdbb9,
1439	0x0954,
1440	0x0743,
1441	0x8000,
1442	0x0001,
1443	0x0040,
1444	0x0100,
1445	0x0000,
1446	0xe910,
1447	0x149e,
1448
1449	1, 0x1c,
1450	0xff2d,
1451
1452	1, 0x39,
1453	0x0000,
1454
1455	2, 0x1e,
1456	0x07FF,
1457	0x0007,
1458
1459	1, 0x24,
1460	EN_UHF | EN_CRYSTAL,
1461
1462	2, 0x3c,
1463	0x3ff,
1464	0x111,
1465	0
1466};
1467
1468static const u16 dib0090_p1g_additionnal_defaults[] = {
1469	1, 0x05,
1470	0xabcd,
1471
1472	1, 0x11,
1473	0x00b4,
1474
1475	1, 0x1c,
1476	0xfffd,
1477
1478	1, 0x40,
1479	0x108,
1480	0
1481};
1482
1483static void dib0090_set_default_config(struct dib0090_state *state, const u16 * n)
1484{
1485	u16 l, r;
1486
1487	l = pgm_read_word(n++);
1488	while (l) {
1489		r = pgm_read_word(n++);
1490		do {
1491			dib0090_write_reg(state, r, pgm_read_word(n++));
1492			r++;
1493		} while (--l);
1494		l = pgm_read_word(n++);
1495	}
1496}
1497
1498#define CAP_VALUE_MIN (u8)  9
1499#define CAP_VALUE_MAX (u8) 40
1500#define HR_MIN	      (u8) 25
1501#define HR_MAX	      (u8) 40
1502#define POLY_MIN      (u8)  0
1503#define POLY_MAX      (u8)  8
1504
1505static void dib0090_set_EFUSE(struct dib0090_state *state)
1506{
1507	u8 c, h, n;
1508	u16 e2, e4;
1509	u16 cal;
1510
1511	e2 = dib0090_read_reg(state, 0x26);
1512	e4 = dib0090_read_reg(state, 0x28);
1513
1514	if ((state->identity.version == P1D_E_F) ||
1515			(state->identity.version == P1G) || (e2 == 0xffff)) {
1516
1517		dib0090_write_reg(state, 0x22, 0x10);
1518		cal = (dib0090_read_reg(state, 0x22) >> 6) & 0x3ff;
1519
1520		if ((cal < 670) || (cal == 1023))
1521			cal = 850;
1522		n = 165 - ((cal * 10)>>6) ;
1523		e2 = e4 = (3<<12) | (34<<6) | (n);
1524	}
1525
1526	if (e2 != e4)
1527		e2 &= e4; /* Remove the redundancy  */
1528
1529	if (e2 != 0xffff) {
1530		c = e2 & 0x3f;
1531		n = (e2 >> 12) & 0xf;
1532		h = (e2 >> 6) & 0x3f;
1533
1534		if ((c >= CAP_VALUE_MAX) || (c <= CAP_VALUE_MIN))
1535			c = 32;
1536		else
1537			c += 14;
1538		if ((h >= HR_MAX) || (h <= HR_MIN))
1539			h = 34;
1540		if ((n >= POLY_MAX) || (n <= POLY_MIN))
1541			n = 3;
1542
1543		dib0090_write_reg(state, 0x13, (h << 10));
1544		e2 = (n << 11) | ((h >> 2)<<6) | c;
1545		dib0090_write_reg(state, 0x2, e2); /* Load the BB_2 */
1546	}
1547}
1548
1549static int dib0090_reset(struct dvb_frontend *fe)
1550{
1551	struct dib0090_state *state = fe->tuner_priv;
1552
1553	dib0090_reset_digital(fe, state->config);
1554	if (dib0090_identify(fe) < 0)
1555		return -EIO;
1556
1557#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
1558	if (!(state->identity.version & 0x1))	/* it is P1B - reset is already done */
1559		return 0;
1560#endif
1561
1562	if (!state->identity.in_soc) {
1563		if ((dib0090_read_reg(state, 0x1a) >> 5) & 0x2)
1564			dib0090_write_reg(state, 0x1b, (EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1565		else
1566			dib0090_write_reg(state, 0x1b, (EN_DIGCLK | EN_PLL | EN_CRYSTAL));
1567	}
1568
1569	dib0090_set_default_config(state, dib0090_defaults);
1570
1571	if (state->identity.in_soc)
1572		dib0090_write_reg(state, 0x18, 0x2910);  /* charge pump current = 0 */
1573
1574	if (state->identity.p1g)
1575		dib0090_set_default_config(state, dib0090_p1g_additionnal_defaults);
1576
1577	/* Update the efuse : Only available for KROSUS > P1C  and SOC as well*/
1578	if (((state->identity.version & 0x1f) >= P1D_E_F) || (state->identity.in_soc))
1579		dib0090_set_EFUSE(state);
1580
1581	/* Congigure in function of the crystal */
1582	if (state->config->force_crystal_mode != 0)
1583		dib0090_write_reg(state, 0x14,
1584				state->config->force_crystal_mode & 3);
1585	else if (state->config->io.clock_khz >= 24000)
1586		dib0090_write_reg(state, 0x14, 1);
1587	else
1588		dib0090_write_reg(state, 0x14, 2);
1589	dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
1590
1591	state->calibrate = DC_CAL | WBD_CAL | TEMP_CAL;	/* enable iq-offset-calibration and wbd-calibration when tuning next time */
1592
1593	return 0;
1594}
1595
1596#define steps(u) (((u) > 15) ? ((u)-16) : (u))
1597#define INTERN_WAIT 10
1598static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1599{
1600	int ret = INTERN_WAIT * 10;
1601
1602	switch (*tune_state) {
1603	case CT_TUNER_STEP_2:
1604		/* Turns to positive */
1605		dib0090_write_reg(state, 0x1f, 0x7);
1606		*tune_state = CT_TUNER_STEP_3;
1607		break;
1608
1609	case CT_TUNER_STEP_3:
1610		state->adc_diff = dib0090_read_reg(state, 0x1d);
1611
1612		/* Turns to negative */
1613		dib0090_write_reg(state, 0x1f, 0x4);
1614		*tune_state = CT_TUNER_STEP_4;
1615		break;
1616
1617	case CT_TUNER_STEP_4:
1618		state->adc_diff -= dib0090_read_reg(state, 0x1d);
1619		*tune_state = CT_TUNER_STEP_5;
1620		ret = 0;
1621		break;
1622
1623	default:
1624		break;
1625	}
1626
1627	return ret;
1628}
1629
1630struct dc_calibration {
1631	u8 addr;
1632	u8 offset;
1633	u8 pga:1;
1634	u16 bb1;
1635	u8 i:1;
1636};
1637
1638static const struct dc_calibration dc_table[] = {
1639	/* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
1640	{0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1},
1641	{0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0},
1642	/* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
1643	{0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1},
1644	{0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0},
1645	{0},
1646};
1647
1648static const struct dc_calibration dc_p1g_table[] = {
1649	/* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
1650	/* addr ; trim reg offset ; pga ; CTRL_BB1 value ; i or q */
1651	{0x06, 5, 1, (1 << 13) | (0 << 8) | (15 << 3), 1},
1652	{0x07, 11, 1, (1 << 13) | (0 << 8) | (15 << 3), 0},
1653	/* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
1654	{0x06, 0, 0, (1 << 13) | (29 << 8) | (15 << 3), 1},
1655	{0x06, 10, 0, (1 << 13) | (29 << 8) | (15 << 3), 0},
1656	{0},
1657};
1658
1659static void dib0090_set_trim(struct dib0090_state *state)
1660{
1661	u16 *val;
1662
1663	if (state->dc->addr == 0x07)
1664		val = &state->bb7;
1665	else
1666		val = &state->bb6;
1667
1668	*val &= ~(0x1f << state->dc->offset);
1669	*val |= state->step << state->dc->offset;
1670
1671	dib0090_write_reg(state, state->dc->addr, *val);
1672}
1673
1674static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1675{
1676	int ret = 0;
1677	u16 reg;
1678
1679	switch (*tune_state) {
1680	case CT_TUNER_START:
1681		dprintk("Start DC offset calibration");
1682
1683		/* force vcm2 = 0.8V */
1684		state->bb6 = 0;
1685		state->bb7 = 0x040d;
1686
1687		/* the LNA AND LO are off */
1688		reg = dib0090_read_reg(state, 0x24) & 0x0ffb;	/* shutdown lna and lo */
1689		dib0090_write_reg(state, 0x24, reg);
1690
1691		state->wbdmux = dib0090_read_reg(state, 0x10);
1692		dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x7 << 3) | 0x3);
1693		dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
1694
1695		state->dc = dc_table;
1696
1697		if (state->identity.p1g)
1698			state->dc = dc_p1g_table;
1699		*tune_state = CT_TUNER_STEP_0;
1700
1701		/* fall through */
1702
1703	case CT_TUNER_STEP_0:
1704		dprintk("Sart/continue DC calibration for %s path", (state->dc->i == 1) ? "I" : "Q");
1705		dib0090_write_reg(state, 0x01, state->dc->bb1);
1706		dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
1707
1708		state->step = 0;
1709		state->min_adc_diff = 1023;
1710		*tune_state = CT_TUNER_STEP_1;
1711		ret = 50;
1712		break;
1713
1714	case CT_TUNER_STEP_1:
1715		dib0090_set_trim(state);
1716		*tune_state = CT_TUNER_STEP_2;
1717		break;
1718
1719	case CT_TUNER_STEP_2:
1720	case CT_TUNER_STEP_3:
1721	case CT_TUNER_STEP_4:
1722		ret = dib0090_get_offset(state, tune_state);
1723		break;
1724
1725	case CT_TUNER_STEP_5:	/* found an offset */
1726		dprintk("adc_diff = %d, current step= %d", (u32) state->adc_diff, state->step);
1727		if (state->step == 0 && state->adc_diff < 0) {
1728			state->min_adc_diff = -1023;
1729			dprintk("Change of sign of the minimum adc diff");
1730		}
1731
1732		dprintk("adc_diff = %d, min_adc_diff = %d current_step = %d", state->adc_diff, state->min_adc_diff, state->step);
1733
1734		/* first turn for this frequency */
1735		if (state->step == 0) {
1736			if (state->dc->pga && state->adc_diff < 0)
1737				state->step = 0x10;
1738			if (state->dc->pga == 0 && state->adc_diff > 0)
1739				state->step = 0x10;
1740		}
1741
1742		/* Look for a change of Sign in the Adc_diff.min_adc_diff is used to STORE the setp N-1 */
1743		if ((state->adc_diff & 0x8000) == (state->min_adc_diff & 0x8000) && steps(state->step) < 15) {
1744			/* stop search when the delta the sign is changing and Steps =15 and Step=0 is force for continuance */
1745			state->step++;
1746			state->min_adc_diff = state->adc_diff;
1747			*tune_state = CT_TUNER_STEP_1;
1748		} else {
1749			/* the minimum was what we have seen in the step before */
1750			if (ABS(state->adc_diff) > ABS(state->min_adc_diff)) {
1751				dprintk("Since adc_diff N = %d  > adc_diff step N-1 = %d, Come back one step", state->adc_diff, state->min_adc_diff);
1752				state->step--;
1753			}
1754
1755			dib0090_set_trim(state);
1756			dprintk("BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->dc->addr, state->adc_diff, state->step);
1757
1758			state->dc++;
1759			if (state->dc->addr == 0)	/* done */
1760				*tune_state = CT_TUNER_STEP_6;
1761			else
1762				*tune_state = CT_TUNER_STEP_0;
1763
1764		}
1765		break;
1766
1767	case CT_TUNER_STEP_6:
1768		dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008);
1769		dib0090_write_reg(state, 0x1f, 0x7);
1770		*tune_state = CT_TUNER_START;	/* reset done -> real tuning can now begin */
1771		state->calibrate &= ~DC_CAL;
1772	default:
1773		break;
1774	}
1775	return ret;
1776}
1777
1778static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1779{
1780	u8 wbd_gain;
1781	const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1782
1783	switch (*tune_state) {
1784	case CT_TUNER_START:
1785		while (state->current_rf / 1000 > wbd->max_freq)
1786			wbd++;
1787		if (wbd->wbd_gain != 0)
1788			wbd_gain = wbd->wbd_gain;
1789		else {
1790			wbd_gain = 4;
1791#if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
1792			if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND))
1793				wbd_gain = 2;
1794#endif
1795		}
1796
1797		if (wbd_gain == state->wbd_calibration_gain) {	/* the WBD calibration has already been done */
1798			*tune_state = CT_TUNER_START;
1799			state->calibrate &= ~WBD_CAL;
1800			return 0;
1801		}
1802
1803		dib0090_write_reg(state, 0x10, 0x1b81 | (1 << 10) | (wbd_gain << 13) | (1 << 3));
1804
1805		dib0090_write_reg(state, 0x24, ((EN_UHF & 0x0fff) | (1 << 1)));
1806		*tune_state = CT_TUNER_STEP_0;
1807		state->wbd_calibration_gain = wbd_gain;
1808		return 90;	/* wait for the WBDMUX to switch and for the ADC to sample */
1809
1810	case CT_TUNER_STEP_0:
1811		state->wbd_offset = dib0090_get_slow_adc_val(state);
1812		dprintk("WBD calibration offset = %d", state->wbd_offset);
1813		*tune_state = CT_TUNER_START;	/* reset done -> real tuning can now begin */
1814		state->calibrate &= ~WBD_CAL;
1815		break;
1816
1817	default:
1818		break;
1819	}
1820	return 0;
1821}
1822
1823static void dib0090_set_bandwidth(struct dib0090_state *state)
1824{
1825	u16 tmp;
1826
1827	if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000)
1828		tmp = (3 << 14);
1829	else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000)
1830		tmp = (2 << 14);
1831	else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000)
1832		tmp = (1 << 14);
1833	else
1834		tmp = (0 << 14);
1835
1836	state->bb_1_def &= 0x3fff;
1837	state->bb_1_def |= tmp;
1838
1839	dib0090_write_reg(state, 0x01, state->bb_1_def);	/* be sure that we have the right bb-filter */
1840
1841	dib0090_write_reg(state, 0x03, 0x6008);	/* = 0x6008 : vcm3_trim = 1 ; filter2_gm1_trim = 8 ; filter2_cutoff_freq = 0 */
1842	dib0090_write_reg(state, 0x04, 0x1);	/* 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast */
1843	if (state->identity.in_soc) {
1844		dib0090_write_reg(state, 0x05, 0x9bcf); /* attenuator_ibias_tri = 2 ; input_stage_ibias_tr = 1 ; nc = 11 ; ext_gm_trim = 1 ; obuf_ibias_trim = 4 ; filter13_gm2_ibias_t = 15 */
1845	} else {
1846		dib0090_write_reg(state, 0x02, (5 << 11) | (8 << 6) | (22 & 0x3f));	/* 22 = cap_value */
1847		dib0090_write_reg(state, 0x05, 0xabcd);	/* = 0xabcd : attenuator_ibias_tri = 2 ; input_stage_ibias_tr = 2 ; nc = 11 ; ext_gm_trim = 1 ; obuf_ibias_trim = 4 ; filter13_gm2_ibias_t = 13 */
1848	}
1849}
1850
1851static const struct dib0090_pll dib0090_pll_table[] = {
1852#ifdef CONFIG_BAND_CBAND
1853	{56000, 0, 9, 48, 6},
1854	{70000, 1, 9, 48, 6},
1855	{87000, 0, 8, 32, 4},
1856	{105000, 1, 8, 32, 4},
1857	{115000, 0, 7, 24, 6},
1858	{140000, 1, 7, 24, 6},
1859	{170000, 0, 6, 16, 4},
1860#endif
1861#ifdef CONFIG_BAND_VHF
1862	{200000, 1, 6, 16, 4},
1863	{230000, 0, 5, 12, 6},
1864	{280000, 1, 5, 12, 6},
1865	{340000, 0, 4, 8, 4},
1866	{380000, 1, 4, 8, 4},
1867	{450000, 0, 3, 6, 6},
1868#endif
1869#ifdef CONFIG_BAND_UHF
1870	{580000, 1, 3, 6, 6},
1871	{700000, 0, 2, 4, 4},
1872	{860000, 1, 2, 4, 4},
1873#endif
1874#ifdef CONFIG_BAND_LBAND
1875	{1800000, 1, 0, 2, 4},
1876#endif
1877#ifdef CONFIG_BAND_SBAND
1878	{2900000, 0, 14, 1, 4},
1879#endif
1880};
1881
1882static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
1883
1884#ifdef CONFIG_BAND_CBAND
1885	{184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1886	{227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1887	{380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1888#endif
1889#ifdef CONFIG_BAND_UHF
1890	{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1891	{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1892	{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1893	{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1894	{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1895	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1896#endif
1897#ifdef CONFIG_BAND_LBAND
1898	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1899	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1900	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1901#endif
1902#ifdef CONFIG_BAND_SBAND
1903	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1904	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1905#endif
1906};
1907
1908static const struct dib0090_tuning dib0090_tuning_table[] = {
1909
1910#ifdef CONFIG_BAND_CBAND
1911	{170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1912#endif
1913#ifdef CONFIG_BAND_VHF
1914	{184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1915	{227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1916	{380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1917#endif
1918#ifdef CONFIG_BAND_UHF
1919	{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1920	{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1921	{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1922	{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1923	{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1924	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1925#endif
1926#ifdef CONFIG_BAND_LBAND
1927	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1928	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1929	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1930#endif
1931#ifdef CONFIG_BAND_SBAND
1932	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1933	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1934#endif
1935};
1936
1937static const struct dib0090_tuning dib0090_p1g_tuning_table[] = {
1938#ifdef CONFIG_BAND_CBAND
1939	{170000, 4, 1, 0x820f, 0x300, 0x2d22, 0x82cb, EN_CAB},
1940#endif
1941#ifdef CONFIG_BAND_VHF
1942	{184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1943	{227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1944	{380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1945#endif
1946#ifdef CONFIG_BAND_UHF
1947	{510000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1948	{540000, 2, 1, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1949	{600000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1950	{630000, 2, 4, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1951	{680000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1952	{720000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1953	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1954#endif
1955#ifdef CONFIG_BAND_LBAND
1956	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1957	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1958	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1959#endif
1960#ifdef CONFIG_BAND_SBAND
1961	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1962	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1963#endif
1964};
1965
1966static const struct dib0090_pll dib0090_p1g_pll_table[] = {
1967#ifdef CONFIG_BAND_CBAND
1968	{57000, 0, 11, 48, 6},
1969	{70000, 1, 11, 48, 6},
1970	{86000, 0, 10, 32, 4},
1971	{105000, 1, 10, 32, 4},
1972	{115000, 0, 9, 24, 6},
1973	{140000, 1, 9, 24, 6},
1974	{170000, 0, 8, 16, 4},
1975#endif
1976#ifdef CONFIG_BAND_VHF
1977	{200000, 1, 8, 16, 4},
1978	{230000, 0, 7, 12, 6},
1979	{280000, 1, 7, 12, 6},
1980	{340000, 0, 6, 8, 4},
1981	{380000, 1, 6, 8, 4},
1982	{455000, 0, 5, 6, 6},
1983#endif
1984#ifdef CONFIG_BAND_UHF
1985	{580000, 1, 5, 6, 6},
1986	{680000, 0, 4, 4, 4},
1987	{860000, 1, 4, 4, 4},
1988#endif
1989#ifdef CONFIG_BAND_LBAND
1990	{1800000, 1, 2, 2, 4},
1991#endif
1992#ifdef CONFIG_BAND_SBAND
1993	{2900000, 0, 1, 1, 6},
1994#endif
1995};
1996
1997static const struct dib0090_tuning dib0090_p1g_tuning_table_fm_vhf_on_cband[] = {
1998#ifdef CONFIG_BAND_CBAND
1999	{184000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
2000	{227000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
2001	{380000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
2002#endif
2003#ifdef CONFIG_BAND_UHF
2004	{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2005	{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2006	{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2007	{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2008	{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2009	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2010#endif
2011#ifdef CONFIG_BAND_LBAND
2012	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2013	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2014	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2015#endif
2016#ifdef CONFIG_BAND_SBAND
2017	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
2018	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
2019#endif
2020};
2021
2022static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = {
2023#ifdef CONFIG_BAND_CBAND
2024	{300000, 4, 3, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2025	{380000, 4, 10, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2026	{570000, 4, 10, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2027	{858000, 4, 5, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2028#endif
2029};
2030
2031static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_sensitivity[] = {
2032#ifdef CONFIG_BAND_CBAND
2033	{ 300000,  0 ,  3,  0x8105, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2034	{ 380000,  0 ,  10, 0x810F, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2035	{ 600000,  0 ,  10, 0x815E, 0x280, 0x2d12, 0xb84e, EN_CAB },
2036	{ 660000,  0 ,  5,  0x85E3, 0x280, 0x2d12, 0xb84e, EN_CAB },
2037	{ 720000,  0 ,  5,  0x852E, 0x280, 0x2d12, 0xb84e, EN_CAB },
2038	{ 860000,  0 ,  4,  0x85E5, 0x280, 0x2d12, 0xb84e, EN_CAB },
2039#endif
2040};
2041
2042int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
2043		u8 cfg_sensitivity)
2044{
2045	struct dib0090_state *state = fe->tuner_priv;
2046	const struct dib0090_tuning *tune =
2047		dib0090_tuning_table_cband_7090e_sensitivity;
2048	const struct dib0090_tuning dib0090_tuning_table_cband_7090e_aci[] = {
2049		{ 300000,  0 ,  3,  0x8165, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2050		{ 650000,  0 ,  4,  0x815B, 0x280, 0x2d12, 0xb84e, EN_CAB },
2051		{ 860000,  0 ,  5,  0x84EF, 0x280, 0x2d12, 0xb84e, EN_CAB },
2052	};
2053
2054	if ((!state->identity.p1g) || (!state->identity.in_soc)
2055			|| ((state->identity.version != SOC_7090_P1G_21R1)
2056				&& (state->identity.version != SOC_7090_P1G_11R1))) {
2057		dprintk("%s() function can only be used for dib7090", __func__);
2058		return -ENODEV;
2059	}
2060
2061	if (cfg_sensitivity)
2062		tune = dib0090_tuning_table_cband_7090e_sensitivity;
2063	else
2064		tune = dib0090_tuning_table_cband_7090e_aci;
2065
2066	while (state->rf_request > tune->max_freq)
2067		tune++;
2068
2069	dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x8000)
2070			| (tune->lna_bias & 0x7fff));
2071	dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xf83f)
2072			| ((tune->lna_tune << 6) & 0x07c0));
2073	return 0;
2074}
2075EXPORT_SYMBOL(dib0090_update_tuning_table_7090);
2076
2077static int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2078{
2079	int ret = 0;
2080	u16 lo4 = 0xe900;
2081
2082	s16 adc_target;
2083	u16 adc;
2084	s8 step_sign;
2085	u8 force_soft_search = 0;
2086
2087	if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
2088		force_soft_search = 1;
2089
2090	if (*tune_state == CT_TUNER_START) {
2091		dprintk("Start Captrim search : %s", (force_soft_search == 1) ? "FORCE SOFT SEARCH" : "AUTO");
2092		dib0090_write_reg(state, 0x10, 0x2B1);
2093		dib0090_write_reg(state, 0x1e, 0x0032);
2094
2095		if (!state->tuner_is_tuned) {
2096			/* prepare a complete captrim */
2097			if (!state->identity.p1g || force_soft_search)
2098				state->step = state->captrim = state->fcaptrim = 64;
2099
2100			state->current_rf = state->rf_request;
2101		} else {	/* we are already tuned to this frequency - the configuration is correct  */
2102			if (!state->identity.p1g || force_soft_search) {
2103				/* do a minimal captrim even if the frequency has not changed */
2104				state->step = 4;
2105				state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
2106			}
2107		}
2108		state->adc_diff = 3000;
2109		*tune_state = CT_TUNER_STEP_0;
2110
2111	} else if (*tune_state == CT_TUNER_STEP_0) {
2112		if (state->identity.p1g && !force_soft_search) {
2113			u8 ratio = 31;
2114
2115			dib0090_write_reg(state, 0x40, (3 << 7) | (ratio << 2) | (1 << 1) | 1);
2116			dib0090_read_reg(state, 0x40);
2117			ret = 50;
2118		} else {
2119			state->step /= 2;
2120			dib0090_write_reg(state, 0x18, lo4 | state->captrim);
2121
2122			if (state->identity.in_soc)
2123				ret = 25;
2124		}
2125		*tune_state = CT_TUNER_STEP_1;
2126
2127	} else if (*tune_state == CT_TUNER_STEP_1) {
2128		if (state->identity.p1g && !force_soft_search) {
2129			dib0090_write_reg(state, 0x40, 0x18c | (0 << 1) | 0);
2130			dib0090_read_reg(state, 0x40);
2131
2132			state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7F;
2133			dprintk("***Final Captrim= 0x%x", state->fcaptrim);
2134			*tune_state = CT_TUNER_STEP_3;
2135
2136		} else {
2137			/* MERGE for all krosus before P1G */
2138			adc = dib0090_get_slow_adc_val(state);
2139			dprintk("CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) state->captrim, (u32) adc, (u32) (adc) * (u32) 1800 / (u32) 1024);
2140
2141			if (state->rest == 0 || state->identity.in_soc) {	/* Just for 8090P SOCS where auto captrim HW bug : TO CHECK IN ACI for SOCS !!! if 400 for 8090p SOC => tune issue !!! */
2142				adc_target = 200;
2143			} else
2144				adc_target = 400;
2145
2146			if (adc >= adc_target) {
2147				adc -= adc_target;
2148				step_sign = -1;
2149			} else {
2150				adc = adc_target - adc;
2151				step_sign = 1;
2152			}
2153
2154			if (adc < state->adc_diff) {
2155				dprintk("CAPTRIM=%d is closer to target (%d/%d)", (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
2156				state->adc_diff = adc;
2157				state->fcaptrim = state->captrim;
2158			}
2159
2160			state->captrim += step_sign * state->step;
2161			if (state->step >= 1)
2162				*tune_state = CT_TUNER_STEP_0;
2163			else
2164				*tune_state = CT_TUNER_STEP_2;
2165
2166			ret = 25;
2167		}
2168	} else if (*tune_state == CT_TUNER_STEP_2) {	/* this step is only used by krosus < P1G */
2169		/*write the final cptrim config */
2170		dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
2171
2172		*tune_state = CT_TUNER_STEP_3;
2173
2174	} else if (*tune_state == CT_TUNER_STEP_3) {
2175		state->calibrate &= ~CAPTRIM_CAL;
2176		*tune_state = CT_TUNER_STEP_0;
2177	}
2178
2179	return ret;
2180}
2181
2182static int dib0090_get_temperature(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2183{
2184	int ret = 15;
2185	s16 val;
2186
2187	switch (*tune_state) {
2188	case CT_TUNER_START:
2189		state->wbdmux = dib0090_read_reg(state, 0x10);
2190		dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x8 << 3));
2191
2192		state->bias = dib0090_read_reg(state, 0x13);
2193		dib0090_write_reg(state, 0x13, state->bias | (0x3 << 8));
2194
2195		*tune_state = CT_TUNER_STEP_0;
2196		/* wait for the WBDMUX to switch and for the ADC to sample */
2197		break;
2198
2199	case CT_TUNER_STEP_0:
2200		state->adc_diff = dib0090_get_slow_adc_val(state);
2201		dib0090_write_reg(state, 0x13, (state->bias & ~(0x3 << 8)) | (0x2 << 8));
2202		*tune_state = CT_TUNER_STEP_1;
2203		break;
2204
2205	case CT_TUNER_STEP_1:
2206		val = dib0090_get_slow_adc_val(state);
2207		state->temperature = ((s16) ((val - state->adc_diff) * 180) >> 8) + 55;
2208
2209		dprintk("temperature: %d C", state->temperature - 30);
2210
2211		*tune_state = CT_TUNER_STEP_2;
2212		break;
2213
2214	case CT_TUNER_STEP_2:
2215		dib0090_write_reg(state, 0x13, state->bias);
2216		dib0090_write_reg(state, 0x10, state->wbdmux);	/* write back original WBDMUX */
2217
2218		*tune_state = CT_TUNER_START;
2219		state->calibrate &= ~TEMP_CAL;
2220		if (state->config->analog_output == 0)
2221			dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2222
2223		break;
2224
2225	default:
2226		ret = 0;
2227		break;
2228	}
2229	return ret;
2230}
2231
2232#define WBD     0x781		/* 1 1 1 1 0000 0 0 1 */
2233static int dib0090_tune(struct dvb_frontend *fe)
2234{
2235	struct dib0090_state *state = fe->tuner_priv;
2236	const struct dib0090_tuning *tune = state->current_tune_table_index;
2237	const struct dib0090_pll *pll = state->current_pll_table_index;
2238	enum frontend_tune_state *tune_state = &state->tune_state;
2239
2240	u16 lo5, lo6, Den, tmp;
2241	u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
2242	int ret = 10;		/* 1ms is the default delay most of the time */
2243	u8 c, i;
2244
2245	/************************* VCO ***************************/
2246	/* Default values for FG                                 */
2247	/* from these are needed :                               */
2248	/* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv             */
2249
2250	/* in any case we first need to do a calibration if needed */
2251	if (*tune_state == CT_TUNER_START) {
2252		/* deactivate DataTX before some calibrations */
2253		if (state->calibrate & (DC_CAL | TEMP_CAL | WBD_CAL))
2254			dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
2255		else
2256			/* Activate DataTX in case a calibration has been done before */
2257			if (state->config->analog_output == 0)
2258				dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2259	}
2260
2261	if (state->calibrate & DC_CAL)
2262		return dib0090_dc_offset_calibration(state, tune_state);
2263	else if (state->calibrate & WBD_CAL) {
2264		if (state->current_rf == 0)
2265			state->current_rf = state->fe->dtv_property_cache.frequency / 1000;
2266		return dib0090_wbd_calibration(state, tune_state);
2267	} else if (state->calibrate & TEMP_CAL)
2268		return dib0090_get_temperature(state, tune_state);
2269	else if (state->calibrate & CAPTRIM_CAL)
2270		return dib0090_captrim_search(state, tune_state);
2271
2272	if (*tune_state == CT_TUNER_START) {
2273		/* if soc and AGC pwm control, disengage mux to be able to R/W access to 0x01 register to set the right filter (cutoff_freq_select) during the tune sequence, otherwise, SOC SERPAR error when accessing to 0x01 */
2274		if (state->config->use_pwm_agc && state->identity.in_soc) {
2275			tmp = dib0090_read_reg(state, 0x39);
2276			if ((tmp >> 10) & 0x1)
2277				dib0090_write_reg(state, 0x39, tmp & ~(1 << 10));
2278		}
2279
2280		state->current_band = (u8) BAND_OF_FREQUENCY(state->fe->dtv_property_cache.frequency / 1000);
2281		state->rf_request =
2282			state->fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
2283					BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->
2284					freq_offset_khz_vhf);
2285
2286		/* in ISDB-T 1seg we shift tuning frequency */
2287		if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1
2288					&& state->fe->dtv_property_cache.isdbt_partial_reception == 0)) {
2289			const struct dib0090_low_if_offset_table *LUT_offset = state->config->low_if;
2290			u8 found_offset = 0;
2291			u32 margin_khz = 100;
2292
2293			if (LUT_offset != NULL) {
2294				while (LUT_offset->RF_freq != 0xffff) {
2295					if (((state->rf_request > (LUT_offset->RF_freq - margin_khz))
2296								&& (state->rf_request < (LUT_offset->RF_freq + margin_khz)))
2297							&& LUT_offset->std == state->fe->dtv_property_cache.delivery_system) {
2298						state->rf_request += LUT_offset->offset_khz;
2299						found_offset = 1;
2300						break;
2301					}
2302					LUT_offset++;
2303				}
2304			}
2305
2306			if (found_offset == 0)
2307				state->rf_request += 400;
2308		}
2309		if (state->current_rf != state->rf_request || (state->current_standard != state->fe->dtv_property_cache.delivery_system)) {
2310			state->tuner_is_tuned = 0;
2311			state->current_rf = 0;
2312			state->current_standard = 0;
2313
2314			tune = dib0090_tuning_table;
2315			if (state->identity.p1g)
2316				tune = dib0090_p1g_tuning_table;
2317
2318			tmp = (state->identity.version >> 5) & 0x7;
2319
2320			if (state->identity.in_soc) {
2321				if (state->config->force_cband_input) {	/* Use the CBAND input for all band */
2322					if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF
2323							|| state->current_band & BAND_UHF) {
2324						state->current_band = BAND_CBAND;
2325						if (state->config->is_dib7090e)
2326							tune = dib0090_tuning_table_cband_7090e_sensitivity;
2327						else
2328							tune = dib0090_tuning_table_cband_7090;
2329					}
2330				} else {	/* Use the CBAND input for all band under UHF */
2331					if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) {
2332						state->current_band = BAND_CBAND;
2333						if (state->config->is_dib7090e)
2334							tune = dib0090_tuning_table_cband_7090e_sensitivity;
2335						else
2336							tune = dib0090_tuning_table_cband_7090;
2337					}
2338				}
2339			} else
2340			 if (tmp == 0x4 || tmp == 0x7) {
2341				/* CBAND tuner version for VHF */
2342				if (state->current_band == BAND_FM || state->current_band == BAND_CBAND || state->current_band == BAND_VHF) {
2343					state->current_band = BAND_CBAND;	/* Force CBAND */
2344
2345					tune = dib0090_tuning_table_fm_vhf_on_cband;
2346					if (state->identity.p1g)
2347						tune = dib0090_p1g_tuning_table_fm_vhf_on_cband;
2348				}
2349			}
2350
2351			pll = dib0090_pll_table;
2352			if (state->identity.p1g)
2353				pll = dib0090_p1g_pll_table;
2354
2355			/* Look for the interval */
2356			while (state->rf_request > tune->max_freq)
2357				tune++;
2358			while (state->rf_request > pll->max_freq)
2359				pll++;
2360
2361			state->current_tune_table_index = tune;
2362			state->current_pll_table_index = pll;
2363
2364			dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
2365
2366			VCOF_kHz = (pll->hfdiv * state->rf_request) * 2;
2367
2368			FREF = state->config->io.clock_khz;
2369			if (state->config->fref_clock_ratio != 0)
2370				FREF /= state->config->fref_clock_ratio;
2371
2372			FBDiv = (VCOF_kHz / pll->topresc / FREF);
2373			Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
2374
2375			if (Rest < LPF)
2376				Rest = 0;
2377			else if (Rest < 2 * LPF)
2378				Rest = 2 * LPF;
2379			else if (Rest > (FREF - LPF)) {
2380				Rest = 0;
2381				FBDiv += 1;
2382			} else if (Rest > (FREF - 2 * LPF))
2383				Rest = FREF - 2 * LPF;
2384			Rest = (Rest * 6528) / (FREF / 10);
2385			state->rest = Rest;
2386
2387			/* external loop filter, otherwise:
2388			 * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
2389			 * lo6 = 0x0e34 */
2390
2391			if (Rest == 0) {
2392				if (pll->vco_band)
2393					lo5 = 0x049f;
2394				else
2395					lo5 = 0x041f;
2396			} else {
2397				if (pll->vco_band)
2398					lo5 = 0x049e;
2399				else if (state->config->analog_output)
2400					lo5 = 0x041d;
2401				else
2402					lo5 = 0x041c;
2403			}
2404
2405			if (state->identity.p1g) {	/* Bias is done automatically in P1G */
2406				if (state->identity.in_soc) {
2407					if (state->identity.version == SOC_8090_P1G_11R1)
2408						lo5 = 0x46f;
2409					else
2410						lo5 = 0x42f;
2411				} else
2412					lo5 = 0x42c;
2413			}
2414
2415			lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7);	/* bit 15 is the split to the slave, we do not do it here */
2416
2417			if (!state->config->io.pll_int_loop_filt) {
2418				if (state->identity.in_soc)
2419					lo6 = 0xff98;
2420				else if (state->identity.p1g || (Rest == 0))
2421					lo6 = 0xfff8;
2422				else
2423					lo6 = 0xff28;
2424			} else
2425				lo6 = (state->config->io.pll_int_loop_filt << 3);
2426
2427			Den = 1;
2428
2429			if (Rest > 0) {
2430				if (state->config->analog_output)
2431					lo6 |= (1 << 2) | 2;
2432				else {
2433					if (state->identity.in_soc)
2434						lo6 |= (1 << 2) | 2;
2435					else
2436						lo6 |= (1 << 2) | 2;
2437				}
2438				Den = 255;
2439			}
2440			dib0090_write_reg(state, 0x15, (u16) FBDiv);
2441			if (state->config->fref_clock_ratio != 0)
2442				dib0090_write_reg(state, 0x16, (Den << 8) | state->config->fref_clock_ratio);
2443			else
2444				dib0090_write_reg(state, 0x16, (Den << 8) | 1);
2445			dib0090_write_reg(state, 0x17, (u16) Rest);
2446			dib0090_write_reg(state, 0x19, lo5);
2447			dib0090_write_reg(state, 0x1c, lo6);
2448
2449			lo6 = tune->tuner_enable;
2450			if (state->config->analog_output)
2451				lo6 = (lo6 & 0xff9f) | 0x2;
2452
2453			dib0090_write_reg(state, 0x24, lo6 | EN_LO | state->config->use_pwm_agc * EN_CRYSTAL);
2454
2455		}
2456
2457		state->current_rf = state->rf_request;
2458		state->current_standard = state->fe->dtv_property_cache.delivery_system;
2459
2460		ret = 20;
2461		state->calibrate = CAPTRIM_CAL;	/* captrim serach now */
2462	}
2463
2464	else if (*tune_state == CT_TUNER_STEP_0) {	/* Warning : because of captrim cal, if you change this step, change it also in _cal.c file because it is the step following captrim cal state machine */
2465		const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
2466
2467		while (state->current_rf / 1000 > wbd->max_freq)
2468			wbd++;
2469
2470		dib0090_write_reg(state, 0x1e, 0x07ff);
2471		dprintk("Final Captrim: %d", (u32) state->fcaptrim);
2472		dprintk("HFDIV code: %d", (u32) pll->hfdiv_code);
2473		dprintk("VCO = %d", (u32) pll->vco_band);
2474		dprintk("VCOF in kHz: %d ((%d*%d) << 1))", (u32) ((pll->hfdiv * state->rf_request) * 2), (u32) pll->hfdiv, (u32) state->rf_request);
2475		dprintk("REFDIV: %d, FREF: %d", (u32) 1, (u32) state->config->io.clock_khz);
2476		dprintk("FBDIV: %d, Rest: %d", (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
2477		dprintk("Num: %d, Den: %d, SD: %d", (u32) dib0090_read_reg(state, 0x17), (u32) (dib0090_read_reg(state, 0x16) >> 8),
2478			(u32) dib0090_read_reg(state, 0x1c) & 0x3);
2479
2480#define WBD     0x781		/* 1 1 1 1 0000 0 0 1 */
2481		c = 4;
2482		i = 3;
2483
2484		if (wbd->wbd_gain != 0)
2485			c = wbd->wbd_gain;
2486
2487		state->wbdmux = (c << 13) | (i << 11) | (WBD | (state->config->use_pwm_agc << 1));
2488		dib0090_write_reg(state, 0x10, state->wbdmux);
2489
2490		if ((tune->tuner_enable == EN_CAB) && state->identity.p1g) {
2491			dprintk("P1G : The cable band is selected and lna_tune = %d", tune->lna_tune);
2492			dib0090_write_reg(state, 0x09, tune->lna_bias);
2493			dib0090_write_reg(state, 0x0b, 0xb800 | (tune->lna_tune << 6) | (tune->switch_trim));
2494		} else
2495			dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | tune->lna_bias);
2496
2497		dib0090_write_reg(state, 0x0c, tune->v2i);
2498		dib0090_write_reg(state, 0x0d, tune->mix);
2499		dib0090_write_reg(state, 0x0e, tune->load);
2500		*tune_state = CT_TUNER_STEP_1;
2501
2502	} else if (*tune_state == CT_TUNER_STEP_1) {
2503		/* initialize the lt gain register */
2504		state->rf_lt_def = 0x7c00;
2505
2506		dib0090_set_bandwidth(state);
2507		state->tuner_is_tuned = 1;
2508
2509		state->calibrate |= WBD_CAL;
2510		state->calibrate |= TEMP_CAL;
2511		*tune_state = CT_TUNER_STOP;
2512	} else
2513		ret = FE_CALLBACK_TIME_NEVER;
2514	return ret;
2515}
2516
2517static int dib0090_release(struct dvb_frontend *fe)
2518{
2519	kfree(fe->tuner_priv);
2520	fe->tuner_priv = NULL;
2521	return 0;
2522}
2523
2524enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
2525{
2526	struct dib0090_state *state = fe->tuner_priv;
2527
2528	return state->tune_state;
2529}
2530
2531EXPORT_SYMBOL(dib0090_get_tune_state);
2532
2533int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
2534{
2535	struct dib0090_state *state = fe->tuner_priv;
2536
2537	state->tune_state = tune_state;
2538	return 0;
2539}
2540
2541EXPORT_SYMBOL(dib0090_set_tune_state);
2542
2543static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
2544{
2545	struct dib0090_state *state = fe->tuner_priv;
2546
2547	*frequency = 1000 * state->current_rf;
2548	return 0;
2549}
2550
2551static int dib0090_set_params(struct dvb_frontend *fe)
2552{
2553	struct dib0090_state *state = fe->tuner_priv;
2554	u32 ret;
2555
2556	state->tune_state = CT_TUNER_START;
2557
2558	do {
2559		ret = dib0090_tune(fe);
2560		if (ret == FE_CALLBACK_TIME_NEVER)
2561			break;
2562
2563		/*
2564		 * Despite dib0090_tune returns time at a 0.1 ms range,
2565		 * the actual sleep time depends on CONFIG_HZ. The worse case
2566		 * is when CONFIG_HZ=100. In such case, the minimum granularity
2567		 * is 10ms. On some real field tests, the tuner sometimes don't
2568		 * lock when this timer is lower than 10ms. So, enforce a 10ms
2569		 * granularity and use usleep_range() instead of msleep().
2570		 */
2571		ret = 10 * (ret + 99)/100;
2572		usleep_range(ret * 1000, (ret + 1) * 1000);
2573	} while (state->tune_state != CT_TUNER_STOP);
2574
2575	return 0;
2576}
2577
2578static const struct dvb_tuner_ops dib0090_ops = {
2579	.info = {
2580		 .name = "DiBcom DiB0090",
2581		 .frequency_min = 45000000,
2582		 .frequency_max = 860000000,
2583		 .frequency_step = 1000,
2584		 },
2585	.release = dib0090_release,
2586
2587	.init = dib0090_wakeup,
2588	.sleep = dib0090_sleep,
2589	.set_params = dib0090_set_params,
2590	.get_frequency = dib0090_get_frequency,
2591};
2592
2593static const struct dvb_tuner_ops dib0090_fw_ops = {
2594	.info = {
2595		 .name = "DiBcom DiB0090",
2596		 .frequency_min = 45000000,
2597		 .frequency_max = 860000000,
2598		 .frequency_step = 1000,
2599		 },
2600	.release = dib0090_release,
2601
2602	.init = NULL,
2603	.sleep = NULL,
2604	.set_params = NULL,
2605	.get_frequency = NULL,
2606};
2607
2608static const struct dib0090_wbd_slope dib0090_wbd_table_default[] = {
2609	{470, 0, 250, 0, 100, 4},
2610	{860, 51, 866, 21, 375, 4},
2611	{1700, 0, 800, 0, 850, 4},
2612	{2900, 0, 250, 0, 100, 6},
2613	{0xFFFF, 0, 0, 0, 0, 0},
2614};
2615
2616struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2617{
2618	struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
2619	if (st == NULL)
2620		return NULL;
2621
2622	st->config = config;
2623	st->i2c = i2c;
2624	st->fe = fe;
2625	mutex_init(&st->i2c_buffer_lock);
2626	fe->tuner_priv = st;
2627
2628	if (config->wbd == NULL)
2629		st->current_wbd_table = dib0090_wbd_table_default;
2630	else
2631		st->current_wbd_table = config->wbd;
2632
2633	if (dib0090_reset(fe) != 0)
2634		goto free_mem;
2635
2636	printk(KERN_INFO "DiB0090: successfully identified\n");
2637	memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
2638
2639	return fe;
2640 free_mem:
2641	kfree(st);
2642	fe->tuner_priv = NULL;
2643	return NULL;
2644}
2645
2646EXPORT_SYMBOL(dib0090_register);
2647
2648struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2649{
2650	struct dib0090_fw_state *st = kzalloc(sizeof(struct dib0090_fw_state), GFP_KERNEL);
2651	if (st == NULL)
2652		return NULL;
2653
2654	st->config = config;
2655	st->i2c = i2c;
2656	st->fe = fe;
2657	mutex_init(&st->i2c_buffer_lock);
2658	fe->tuner_priv = st;
2659
2660	if (dib0090_fw_reset_digital(fe, st->config) != 0)
2661		goto free_mem;
2662
2663	dprintk("DiB0090 FW: successfully identified");
2664	memcpy(&fe->ops.tuner_ops, &dib0090_fw_ops, sizeof(struct dvb_tuner_ops));
2665
2666	return fe;
2667free_mem:
2668	kfree(st);
2669	fe->tuner_priv = NULL;
2670	return NULL;
2671}
2672EXPORT_SYMBOL(dib0090_fw_register);
2673
2674MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
2675MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>");
2676MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
2677MODULE_LICENSE("GPL");
2678