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