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		break;
1769
1770	default:
1771		break;
1772	}
1773	return ret;
1774}
1775
1776static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1777{
1778	u8 wbd_gain;
1779	const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
1780
1781	switch (*tune_state) {
1782	case CT_TUNER_START:
1783		while (state->current_rf / 1000 > wbd->max_freq)
1784			wbd++;
1785		if (wbd->wbd_gain != 0)
1786			wbd_gain = wbd->wbd_gain;
1787		else {
1788			wbd_gain = 4;
1789#if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
1790			if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND))
1791				wbd_gain = 2;
1792#endif
1793		}
1794
1795		if (wbd_gain == state->wbd_calibration_gain) {	/* the WBD calibration has already been done */
1796			*tune_state = CT_TUNER_START;
1797			state->calibrate &= ~WBD_CAL;
1798			return 0;
1799		}
1800
1801		dib0090_write_reg(state, 0x10, 0x1b81 | (1 << 10) | (wbd_gain << 13) | (1 << 3));
1802
1803		dib0090_write_reg(state, 0x24, ((EN_UHF & 0x0fff) | (1 << 1)));
1804		*tune_state = CT_TUNER_STEP_0;
1805		state->wbd_calibration_gain = wbd_gain;
1806		return 90;	/* wait for the WBDMUX to switch and for the ADC to sample */
1807
1808	case CT_TUNER_STEP_0:
1809		state->wbd_offset = dib0090_get_slow_adc_val(state);
1810		dprintk("WBD calibration offset = %d\n", state->wbd_offset);
1811		*tune_state = CT_TUNER_START;	/* reset done -> real tuning can now begin */
1812		state->calibrate &= ~WBD_CAL;
1813		break;
1814
1815	default:
1816		break;
1817	}
1818	return 0;
1819}
1820
1821static void dib0090_set_bandwidth(struct dib0090_state *state)
1822{
1823	u16 tmp;
1824
1825	if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000)
1826		tmp = (3 << 14);
1827	else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000)
1828		tmp = (2 << 14);
1829	else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000)
1830		tmp = (1 << 14);
1831	else
1832		tmp = (0 << 14);
1833
1834	state->bb_1_def &= 0x3fff;
1835	state->bb_1_def |= tmp;
1836
1837	dib0090_write_reg(state, 0x01, state->bb_1_def);	/* be sure that we have the right bb-filter */
1838
1839	dib0090_write_reg(state, 0x03, 0x6008);	/* = 0x6008 : vcm3_trim = 1 ; filter2_gm1_trim = 8 ; filter2_cutoff_freq = 0 */
1840	dib0090_write_reg(state, 0x04, 0x1);	/* 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast */
1841	if (state->identity.in_soc) {
1842		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 */
1843	} else {
1844		dib0090_write_reg(state, 0x02, (5 << 11) | (8 << 6) | (22 & 0x3f));	/* 22 = cap_value */
1845		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 */
1846	}
1847}
1848
1849static const struct dib0090_pll dib0090_pll_table[] = {
1850#ifdef CONFIG_BAND_CBAND
1851	{56000, 0, 9, 48, 6},
1852	{70000, 1, 9, 48, 6},
1853	{87000, 0, 8, 32, 4},
1854	{105000, 1, 8, 32, 4},
1855	{115000, 0, 7, 24, 6},
1856	{140000, 1, 7, 24, 6},
1857	{170000, 0, 6, 16, 4},
1858#endif
1859#ifdef CONFIG_BAND_VHF
1860	{200000, 1, 6, 16, 4},
1861	{230000, 0, 5, 12, 6},
1862	{280000, 1, 5, 12, 6},
1863	{340000, 0, 4, 8, 4},
1864	{380000, 1, 4, 8, 4},
1865	{450000, 0, 3, 6, 6},
1866#endif
1867#ifdef CONFIG_BAND_UHF
1868	{580000, 1, 3, 6, 6},
1869	{700000, 0, 2, 4, 4},
1870	{860000, 1, 2, 4, 4},
1871#endif
1872#ifdef CONFIG_BAND_LBAND
1873	{1800000, 1, 0, 2, 4},
1874#endif
1875#ifdef CONFIG_BAND_SBAND
1876	{2900000, 0, 14, 1, 4},
1877#endif
1878};
1879
1880static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
1881
1882#ifdef CONFIG_BAND_CBAND
1883	{184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1884	{227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1885	{380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1886#endif
1887#ifdef CONFIG_BAND_UHF
1888	{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1889	{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1890	{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1891	{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1892	{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1893	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1894#endif
1895#ifdef CONFIG_BAND_LBAND
1896	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1897	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1898	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1899#endif
1900#ifdef CONFIG_BAND_SBAND
1901	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1902	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1903#endif
1904};
1905
1906static const struct dib0090_tuning dib0090_tuning_table[] = {
1907
1908#ifdef CONFIG_BAND_CBAND
1909	{170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1910#endif
1911#ifdef CONFIG_BAND_VHF
1912	{184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1913	{227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1914	{380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1915#endif
1916#ifdef CONFIG_BAND_UHF
1917	{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1918	{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1919	{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1920	{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1921	{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1922	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1923#endif
1924#ifdef CONFIG_BAND_LBAND
1925	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1926	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1927	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1928#endif
1929#ifdef CONFIG_BAND_SBAND
1930	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1931	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1932#endif
1933};
1934
1935static const struct dib0090_tuning dib0090_p1g_tuning_table[] = {
1936#ifdef CONFIG_BAND_CBAND
1937	{170000, 4, 1, 0x820f, 0x300, 0x2d22, 0x82cb, EN_CAB},
1938#endif
1939#ifdef CONFIG_BAND_VHF
1940	{184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1941	{227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1942	{380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1943#endif
1944#ifdef CONFIG_BAND_UHF
1945	{510000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1946	{540000, 2, 1, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1947	{600000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1948	{630000, 2, 4, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1949	{680000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1950	{720000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1951	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1952#endif
1953#ifdef CONFIG_BAND_LBAND
1954	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1955	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1956	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1957#endif
1958#ifdef CONFIG_BAND_SBAND
1959	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1960	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1961#endif
1962};
1963
1964static const struct dib0090_pll dib0090_p1g_pll_table[] = {
1965#ifdef CONFIG_BAND_CBAND
1966	{57000, 0, 11, 48, 6},
1967	{70000, 1, 11, 48, 6},
1968	{86000, 0, 10, 32, 4},
1969	{105000, 1, 10, 32, 4},
1970	{115000, 0, 9, 24, 6},
1971	{140000, 1, 9, 24, 6},
1972	{170000, 0, 8, 16, 4},
1973#endif
1974#ifdef CONFIG_BAND_VHF
1975	{200000, 1, 8, 16, 4},
1976	{230000, 0, 7, 12, 6},
1977	{280000, 1, 7, 12, 6},
1978	{340000, 0, 6, 8, 4},
1979	{380000, 1, 6, 8, 4},
1980	{455000, 0, 5, 6, 6},
1981#endif
1982#ifdef CONFIG_BAND_UHF
1983	{580000, 1, 5, 6, 6},
1984	{680000, 0, 4, 4, 4},
1985	{860000, 1, 4, 4, 4},
1986#endif
1987#ifdef CONFIG_BAND_LBAND
1988	{1800000, 1, 2, 2, 4},
1989#endif
1990#ifdef CONFIG_BAND_SBAND
1991	{2900000, 0, 1, 1, 6},
1992#endif
1993};
1994
1995static const struct dib0090_tuning dib0090_p1g_tuning_table_fm_vhf_on_cband[] = {
1996#ifdef CONFIG_BAND_CBAND
1997	{184000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
1998	{227000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
1999	{380000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
2000#endif
2001#ifdef CONFIG_BAND_UHF
2002	{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2003	{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2004	{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2005	{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2006	{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2007	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
2008#endif
2009#ifdef CONFIG_BAND_LBAND
2010	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2011	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2012	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
2013#endif
2014#ifdef CONFIG_BAND_SBAND
2015	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
2016	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
2017#endif
2018};
2019
2020static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = {
2021#ifdef CONFIG_BAND_CBAND
2022	{300000, 4, 3, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2023	{380000, 4, 10, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2024	{570000, 4, 10, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2025	{858000, 4, 5, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
2026#endif
2027};
2028
2029static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_sensitivity[] = {
2030#ifdef CONFIG_BAND_CBAND
2031	{ 300000,  0 ,  3,  0x8105, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2032	{ 380000,  0 ,  10, 0x810F, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2033	{ 600000,  0 ,  10, 0x815E, 0x280, 0x2d12, 0xb84e, EN_CAB },
2034	{ 660000,  0 ,  5,  0x85E3, 0x280, 0x2d12, 0xb84e, EN_CAB },
2035	{ 720000,  0 ,  5,  0x852E, 0x280, 0x2d12, 0xb84e, EN_CAB },
2036	{ 860000,  0 ,  4,  0x85E5, 0x280, 0x2d12, 0xb84e, EN_CAB },
2037#endif
2038};
2039
2040int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
2041		u8 cfg_sensitivity)
2042{
2043	struct dib0090_state *state = fe->tuner_priv;
2044	const struct dib0090_tuning *tune =
2045		dib0090_tuning_table_cband_7090e_sensitivity;
2046	static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_aci[] = {
2047		{ 300000,  0 ,  3,  0x8165, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
2048		{ 650000,  0 ,  4,  0x815B, 0x280, 0x2d12, 0xb84e, EN_CAB },
2049		{ 860000,  0 ,  5,  0x84EF, 0x280, 0x2d12, 0xb84e, EN_CAB },
2050	};
2051
2052	if ((!state->identity.p1g) || (!state->identity.in_soc)
2053			|| ((state->identity.version != SOC_7090_P1G_21R1)
2054				&& (state->identity.version != SOC_7090_P1G_11R1))) {
2055		dprintk("%s() function can only be used for dib7090\n", __func__);
2056		return -ENODEV;
2057	}
2058
2059	if (cfg_sensitivity)
2060		tune = dib0090_tuning_table_cband_7090e_sensitivity;
2061	else
2062		tune = dib0090_tuning_table_cband_7090e_aci;
2063
2064	while (state->rf_request > tune->max_freq)
2065		tune++;
2066
2067	dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x8000)
2068			| (tune->lna_bias & 0x7fff));
2069	dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xf83f)
2070			| ((tune->lna_tune << 6) & 0x07c0));
2071	return 0;
2072}
2073EXPORT_SYMBOL(dib0090_update_tuning_table_7090);
2074
2075static int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2076{
2077	int ret = 0;
2078	u16 lo4 = 0xe900;
2079
2080	s16 adc_target;
2081	u16 adc;
2082	s8 step_sign;
2083	u8 force_soft_search = 0;
2084
2085	if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
2086		force_soft_search = 1;
2087
2088	if (*tune_state == CT_TUNER_START) {
2089		dprintk("Start Captrim search : %s\n",
2090			(force_soft_search == 1) ? "FORCE SOFT SEARCH" : "AUTO");
2091		dib0090_write_reg(state, 0x10, 0x2B1);
2092		dib0090_write_reg(state, 0x1e, 0x0032);
2093
2094		if (!state->tuner_is_tuned) {
2095			/* prepare a complete captrim */
2096			if (!state->identity.p1g || force_soft_search)
2097				state->step = state->captrim = state->fcaptrim = 64;
2098
2099			state->current_rf = state->rf_request;
2100		} else {	/* we are already tuned to this frequency - the configuration is correct  */
2101			if (!state->identity.p1g || force_soft_search) {
2102				/* do a minimal captrim even if the frequency has not changed */
2103				state->step = 4;
2104				state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
2105			}
2106		}
2107		state->adc_diff = 3000;
2108		*tune_state = CT_TUNER_STEP_0;
2109
2110	} else if (*tune_state == CT_TUNER_STEP_0) {
2111		if (state->identity.p1g && !force_soft_search) {
2112			u8 ratio = 31;
2113
2114			dib0090_write_reg(state, 0x40, (3 << 7) | (ratio << 2) | (1 << 1) | 1);
2115			dib0090_read_reg(state, 0x40);
2116			ret = 50;
2117		} else {
2118			state->step /= 2;
2119			dib0090_write_reg(state, 0x18, lo4 | state->captrim);
2120
2121			if (state->identity.in_soc)
2122				ret = 25;
2123		}
2124		*tune_state = CT_TUNER_STEP_1;
2125
2126	} else if (*tune_state == CT_TUNER_STEP_1) {
2127		if (state->identity.p1g && !force_soft_search) {
2128			dib0090_write_reg(state, 0x40, 0x18c | (0 << 1) | 0);
2129			dib0090_read_reg(state, 0x40);
2130
2131			state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7F;
2132			dprintk("***Final Captrim= 0x%x\n", state->fcaptrim);
2133			*tune_state = CT_TUNER_STEP_3;
2134
2135		} else {
2136			/* MERGE for all krosus before P1G */
2137			adc = dib0090_get_slow_adc_val(state);
2138			dprintk("CAPTRIM=%d; ADC = %d (ADC) & %dmV\n", (u32) state->captrim, (u32) adc, (u32) (adc) * (u32) 1800 / (u32) 1024);
2139
2140			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 !!! */
2141				adc_target = 200;
2142			} else
2143				adc_target = 400;
2144
2145			if (adc >= adc_target) {
2146				adc -= adc_target;
2147				step_sign = -1;
2148			} else {
2149				adc = adc_target - adc;
2150				step_sign = 1;
2151			}
2152
2153			if (adc < state->adc_diff) {
2154				dprintk("CAPTRIM=%d is closer to target (%d/%d)\n", (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
2155				state->adc_diff = adc;
2156				state->fcaptrim = state->captrim;
2157			}
2158
2159			state->captrim += step_sign * state->step;
2160			if (state->step >= 1)
2161				*tune_state = CT_TUNER_STEP_0;
2162			else
2163				*tune_state = CT_TUNER_STEP_2;
2164
2165			ret = 25;
2166		}
2167	} else if (*tune_state == CT_TUNER_STEP_2) {	/* this step is only used by krosus < P1G */
2168		/*write the final cptrim config */
2169		dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
2170
2171		*tune_state = CT_TUNER_STEP_3;
2172
2173	} else if (*tune_state == CT_TUNER_STEP_3) {
2174		state->calibrate &= ~CAPTRIM_CAL;
2175		*tune_state = CT_TUNER_STEP_0;
2176	}
2177
2178	return ret;
2179}
2180
2181static int dib0090_get_temperature(struct dib0090_state *state, enum frontend_tune_state *tune_state)
2182{
2183	int ret = 15;
2184	s16 val;
2185
2186	switch (*tune_state) {
2187	case CT_TUNER_START:
2188		state->wbdmux = dib0090_read_reg(state, 0x10);
2189		dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x8 << 3));
2190
2191		state->bias = dib0090_read_reg(state, 0x13);
2192		dib0090_write_reg(state, 0x13, state->bias | (0x3 << 8));
2193
2194		*tune_state = CT_TUNER_STEP_0;
2195		/* wait for the WBDMUX to switch and for the ADC to sample */
2196		break;
2197
2198	case CT_TUNER_STEP_0:
2199		state->adc_diff = dib0090_get_slow_adc_val(state);
2200		dib0090_write_reg(state, 0x13, (state->bias & ~(0x3 << 8)) | (0x2 << 8));
2201		*tune_state = CT_TUNER_STEP_1;
2202		break;
2203
2204	case CT_TUNER_STEP_1:
2205		val = dib0090_get_slow_adc_val(state);
2206		state->temperature = ((s16) ((val - state->adc_diff) * 180) >> 8) + 55;
2207
2208		dprintk("temperature: %d C\n", state->temperature - 30);
2209
2210		*tune_state = CT_TUNER_STEP_2;
2211		break;
2212
2213	case CT_TUNER_STEP_2:
2214		dib0090_write_reg(state, 0x13, state->bias);
2215		dib0090_write_reg(state, 0x10, state->wbdmux);	/* write back original WBDMUX */
2216
2217		*tune_state = CT_TUNER_START;
2218		state->calibrate &= ~TEMP_CAL;
2219		if (state->config->analog_output == 0)
2220			dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2221
2222		break;
2223
2224	default:
2225		ret = 0;
2226		break;
2227	}
2228	return ret;
2229}
2230
2231#define WBD     0x781		/* 1 1 1 1 0000 0 0 1 */
2232static int dib0090_tune(struct dvb_frontend *fe)
2233{
2234	struct dib0090_state *state = fe->tuner_priv;
2235	const struct dib0090_tuning *tune = state->current_tune_table_index;
2236	const struct dib0090_pll *pll = state->current_pll_table_index;
2237	enum frontend_tune_state *tune_state = &state->tune_state;
2238
2239	u16 lo5, lo6, Den, tmp;
2240	u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
2241	int ret = 10;		/* 1ms is the default delay most of the time */
2242	u8 c, i;
2243
2244	/************************* VCO ***************************/
2245	/* Default values for FG                                 */
2246	/* from these are needed :                               */
2247	/* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv             */
2248
2249	/* in any case we first need to do a calibration if needed */
2250	if (*tune_state == CT_TUNER_START) {
2251		/* deactivate DataTX before some calibrations */
2252		if (state->calibrate & (DC_CAL | TEMP_CAL | WBD_CAL))
2253			dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
2254		else
2255			/* Activate DataTX in case a calibration has been done before */
2256			if (state->config->analog_output == 0)
2257				dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
2258	}
2259
2260	if (state->calibrate & DC_CAL)
2261		return dib0090_dc_offset_calibration(state, tune_state);
2262	else if (state->calibrate & WBD_CAL) {
2263		if (state->current_rf == 0)
2264			state->current_rf = state->fe->dtv_property_cache.frequency / 1000;
2265		return dib0090_wbd_calibration(state, tune_state);
2266	} else if (state->calibrate & TEMP_CAL)
2267		return dib0090_get_temperature(state, tune_state);
2268	else if (state->calibrate & CAPTRIM_CAL)
2269		return dib0090_captrim_search(state, tune_state);
2270
2271	if (*tune_state == CT_TUNER_START) {
2272		/* 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 */
2273		if (state->config->use_pwm_agc && state->identity.in_soc) {
2274			tmp = dib0090_read_reg(state, 0x39);
2275			if ((tmp >> 10) & 0x1)
2276				dib0090_write_reg(state, 0x39, tmp & ~(1 << 10));
2277		}
2278
2279		state->current_band = (u8) BAND_OF_FREQUENCY(state->fe->dtv_property_cache.frequency / 1000);
2280		state->rf_request =
2281			state->fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
2282					BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->
2283					freq_offset_khz_vhf);
2284
2285		/* in ISDB-T 1seg we shift tuning frequency */
2286		if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1
2287					&& state->fe->dtv_property_cache.isdbt_partial_reception == 0)) {
2288			const struct dib0090_low_if_offset_table *LUT_offset = state->config->low_if;
2289			u8 found_offset = 0;
2290			u32 margin_khz = 100;
2291
2292			if (LUT_offset != NULL) {
2293				while (LUT_offset->RF_freq != 0xffff) {
2294					if (((state->rf_request > (LUT_offset->RF_freq - margin_khz))
2295								&& (state->rf_request < (LUT_offset->RF_freq + margin_khz)))
2296							&& LUT_offset->std == state->fe->dtv_property_cache.delivery_system) {
2297						state->rf_request += LUT_offset->offset_khz;
2298						found_offset = 1;
2299						break;
2300					}
2301					LUT_offset++;
2302				}
2303			}
2304
2305			if (found_offset == 0)
2306				state->rf_request += 400;
2307		}
2308		if (state->current_rf != state->rf_request || (state->current_standard != state->fe->dtv_property_cache.delivery_system)) {
2309			state->tuner_is_tuned = 0;
2310			state->current_rf = 0;
2311			state->current_standard = 0;
2312
2313			tune = dib0090_tuning_table;
2314			if (state->identity.p1g)
2315				tune = dib0090_p1g_tuning_table;
2316
2317			tmp = (state->identity.version >> 5) & 0x7;
2318
2319			if (state->identity.in_soc) {
2320				if (state->config->force_cband_input) {	/* Use the CBAND input for all band */
2321					if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF
2322							|| state->current_band & BAND_UHF) {
2323						state->current_band = BAND_CBAND;
2324						if (state->config->is_dib7090e)
2325							tune = dib0090_tuning_table_cband_7090e_sensitivity;
2326						else
2327							tune = dib0090_tuning_table_cband_7090;
2328					}
2329				} else {	/* Use the CBAND input for all band under UHF */
2330					if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) {
2331						state->current_band = BAND_CBAND;
2332						if (state->config->is_dib7090e)
2333							tune = dib0090_tuning_table_cband_7090e_sensitivity;
2334						else
2335							tune = dib0090_tuning_table_cband_7090;
2336					}
2337				}
2338			} else
2339			 if (tmp == 0x4 || tmp == 0x7) {
2340				/* CBAND tuner version for VHF */
2341				if (state->current_band == BAND_FM || state->current_band == BAND_CBAND || state->current_band == BAND_VHF) {
2342					state->current_band = BAND_CBAND;	/* Force CBAND */
2343
2344					tune = dib0090_tuning_table_fm_vhf_on_cband;
2345					if (state->identity.p1g)
2346						tune = dib0090_p1g_tuning_table_fm_vhf_on_cband;
2347				}
2348			}
2349
2350			pll = dib0090_pll_table;
2351			if (state->identity.p1g)
2352				pll = dib0090_p1g_pll_table;
2353
2354			/* Look for the interval */
2355			while (state->rf_request > tune->max_freq)
2356				tune++;
2357			while (state->rf_request > pll->max_freq)
2358				pll++;
2359
2360			state->current_tune_table_index = tune;
2361			state->current_pll_table_index = pll;
2362
2363			dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
2364
2365			VCOF_kHz = (pll->hfdiv * state->rf_request) * 2;
2366
2367			FREF = state->config->io.clock_khz;
2368			if (state->config->fref_clock_ratio != 0)
2369				FREF /= state->config->fref_clock_ratio;
2370
2371			FBDiv = (VCOF_kHz / pll->topresc / FREF);
2372			Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
2373
2374			if (Rest < LPF)
2375				Rest = 0;
2376			else if (Rest < 2 * LPF)
2377				Rest = 2 * LPF;
2378			else if (Rest > (FREF - LPF)) {
2379				Rest = 0;
2380				FBDiv += 1;
2381			} else if (Rest > (FREF - 2 * LPF))
2382				Rest = FREF - 2 * LPF;
2383			Rest = (Rest * 6528) / (FREF / 10);
2384			state->rest = Rest;
2385
2386			/* external loop filter, otherwise:
2387			 * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
2388			 * lo6 = 0x0e34 */
2389
2390			if (Rest == 0) {
2391				if (pll->vco_band)
2392					lo5 = 0x049f;
2393				else
2394					lo5 = 0x041f;
2395			} else {
2396				if (pll->vco_band)
2397					lo5 = 0x049e;
2398				else if (state->config->analog_output)
2399					lo5 = 0x041d;
2400				else
2401					lo5 = 0x041c;
2402			}
2403
2404			if (state->identity.p1g) {	/* Bias is done automatically in P1G */
2405				if (state->identity.in_soc) {
2406					if (state->identity.version == SOC_8090_P1G_11R1)
2407						lo5 = 0x46f;
2408					else
2409						lo5 = 0x42f;
2410				} else
2411					lo5 = 0x42c;
2412			}
2413
2414			lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7);	/* bit 15 is the split to the slave, we do not do it here */
2415
2416			if (!state->config->io.pll_int_loop_filt) {
2417				if (state->identity.in_soc)
2418					lo6 = 0xff98;
2419				else if (state->identity.p1g || (Rest == 0))
2420					lo6 = 0xfff8;
2421				else
2422					lo6 = 0xff28;
2423			} else
2424				lo6 = (state->config->io.pll_int_loop_filt << 3);
2425
2426			Den = 1;
2427
2428			if (Rest > 0) {
2429				lo6 |= (1 << 2) | 2;
2430				Den = 255;
2431			}
2432			dib0090_write_reg(state, 0x15, (u16) FBDiv);
2433			if (state->config->fref_clock_ratio != 0)
2434				dib0090_write_reg(state, 0x16, (Den << 8) | state->config->fref_clock_ratio);
2435			else
2436				dib0090_write_reg(state, 0x16, (Den << 8) | 1);
2437			dib0090_write_reg(state, 0x17, (u16) Rest);
2438			dib0090_write_reg(state, 0x19, lo5);
2439			dib0090_write_reg(state, 0x1c, lo6);
2440
2441			lo6 = tune->tuner_enable;
2442			if (state->config->analog_output)
2443				lo6 = (lo6 & 0xff9f) | 0x2;
2444
2445			dib0090_write_reg(state, 0x24, lo6 | EN_LO | state->config->use_pwm_agc * EN_CRYSTAL);
2446
2447		}
2448
2449		state->current_rf = state->rf_request;
2450		state->current_standard = state->fe->dtv_property_cache.delivery_system;
2451
2452		ret = 20;
2453		state->calibrate = CAPTRIM_CAL;	/* captrim search now */
2454	}
2455
2456	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 */
2457		const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
2458
2459		while (state->current_rf / 1000 > wbd->max_freq)
2460			wbd++;
2461
2462		dib0090_write_reg(state, 0x1e, 0x07ff);
2463		dprintk("Final Captrim: %d\n", (u32) state->fcaptrim);
2464		dprintk("HFDIV code: %d\n", (u32) pll->hfdiv_code);
2465		dprintk("VCO = %d\n", (u32) pll->vco_band);
2466		dprintk("VCOF in kHz: %d ((%d*%d) << 1))\n", (u32) ((pll->hfdiv * state->rf_request) * 2), (u32) pll->hfdiv, (u32) state->rf_request);
2467		dprintk("REFDIV: %d, FREF: %d\n", (u32) 1, (u32) state->config->io.clock_khz);
2468		dprintk("FBDIV: %d, Rest: %d\n", (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
2469		dprintk("Num: %d, Den: %d, SD: %d\n", (u32) dib0090_read_reg(state, 0x17), (u32) (dib0090_read_reg(state, 0x16) >> 8),
2470			(u32) dib0090_read_reg(state, 0x1c) & 0x3);
2471
2472#define WBD     0x781		/* 1 1 1 1 0000 0 0 1 */
2473		c = 4;
2474		i = 3;
2475
2476		if (wbd->wbd_gain != 0)
2477			c = wbd->wbd_gain;
2478
2479		state->wbdmux = (c << 13) | (i << 11) | (WBD | (state->config->use_pwm_agc << 1));
2480		dib0090_write_reg(state, 0x10, state->wbdmux);
2481
2482		if ((tune->tuner_enable == EN_CAB) && state->identity.p1g) {
2483			dprintk("P1G : The cable band is selected and lna_tune = %d\n", tune->lna_tune);
2484			dib0090_write_reg(state, 0x09, tune->lna_bias);
2485			dib0090_write_reg(state, 0x0b, 0xb800 | (tune->lna_tune << 6) | (tune->switch_trim));
2486		} else
2487			dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | tune->lna_bias);
2488
2489		dib0090_write_reg(state, 0x0c, tune->v2i);
2490		dib0090_write_reg(state, 0x0d, tune->mix);
2491		dib0090_write_reg(state, 0x0e, tune->load);
2492		*tune_state = CT_TUNER_STEP_1;
2493
2494	} else if (*tune_state == CT_TUNER_STEP_1) {
2495		/* initialize the lt gain register */
2496		state->rf_lt_def = 0x7c00;
2497
2498		dib0090_set_bandwidth(state);
2499		state->tuner_is_tuned = 1;
2500
2501		state->calibrate |= WBD_CAL;
2502		state->calibrate |= TEMP_CAL;
2503		*tune_state = CT_TUNER_STOP;
2504	} else
2505		ret = FE_CALLBACK_TIME_NEVER;
2506	return ret;
2507}
2508
2509static void dib0090_release(struct dvb_frontend *fe)
2510{
2511	kfree(fe->tuner_priv);
2512	fe->tuner_priv = NULL;
2513}
2514
2515enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
2516{
2517	struct dib0090_state *state = fe->tuner_priv;
2518
2519	return state->tune_state;
2520}
2521
2522EXPORT_SYMBOL(dib0090_get_tune_state);
2523
2524int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
2525{
2526	struct dib0090_state *state = fe->tuner_priv;
2527
2528	state->tune_state = tune_state;
2529	return 0;
2530}
2531
2532EXPORT_SYMBOL(dib0090_set_tune_state);
2533
2534static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
2535{
2536	struct dib0090_state *state = fe->tuner_priv;
2537
2538	*frequency = 1000 * state->current_rf;
2539	return 0;
2540}
2541
2542static int dib0090_set_params(struct dvb_frontend *fe)
2543{
2544	struct dib0090_state *state = fe->tuner_priv;
2545	u32 ret;
2546
2547	state->tune_state = CT_TUNER_START;
2548
2549	do {
2550		ret = dib0090_tune(fe);
2551		if (ret == FE_CALLBACK_TIME_NEVER)
2552			break;
2553
2554		/*
2555		 * Despite dib0090_tune returns time at a 0.1 ms range,
2556		 * the actual sleep time depends on CONFIG_HZ. The worse case
2557		 * is when CONFIG_HZ=100. In such case, the minimum granularity
2558		 * is 10ms. On some real field tests, the tuner sometimes don't
2559		 * lock when this timer is lower than 10ms. So, enforce a 10ms
2560		 * granularity and use usleep_range() instead of msleep().
2561		 */
2562		ret = 10 * (ret + 99)/100;
2563		usleep_range(ret * 1000, (ret + 1) * 1000);
2564	} while (state->tune_state != CT_TUNER_STOP);
2565
2566	return 0;
2567}
2568
2569static const struct dvb_tuner_ops dib0090_ops = {
2570	.info = {
2571		 .name = "DiBcom DiB0090",
2572		 .frequency_min_hz  =  45 * MHz,
2573		 .frequency_max_hz  = 860 * MHz,
2574		 .frequency_step_hz =   1 * kHz,
2575		 },
2576	.release = dib0090_release,
2577
2578	.init = dib0090_wakeup,
2579	.sleep = dib0090_sleep,
2580	.set_params = dib0090_set_params,
2581	.get_frequency = dib0090_get_frequency,
2582};
2583
2584static const struct dvb_tuner_ops dib0090_fw_ops = {
2585	.info = {
2586		 .name = "DiBcom DiB0090",
2587		 .frequency_min_hz  =  45 * MHz,
2588		 .frequency_max_hz  = 860 * MHz,
2589		 .frequency_step_hz =   1 * kHz,
2590		 },
2591	.release = dib0090_release,
2592
2593	.init = NULL,
2594	.sleep = NULL,
2595	.set_params = NULL,
2596	.get_frequency = NULL,
2597};
2598
2599static const struct dib0090_wbd_slope dib0090_wbd_table_default[] = {
2600	{470, 0, 250, 0, 100, 4},
2601	{860, 51, 866, 21, 375, 4},
2602	{1700, 0, 800, 0, 850, 4},
2603	{2900, 0, 250, 0, 100, 6},
2604	{0xFFFF, 0, 0, 0, 0, 0},
2605};
2606
2607struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2608{
2609	struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
2610	if (st == NULL)
2611		return NULL;
2612
2613	st->config = config;
2614	st->i2c = i2c;
2615	st->fe = fe;
2616	mutex_init(&st->i2c_buffer_lock);
2617	fe->tuner_priv = st;
2618
2619	if (config->wbd == NULL)
2620		st->current_wbd_table = dib0090_wbd_table_default;
2621	else
2622		st->current_wbd_table = config->wbd;
2623
2624	if (dib0090_reset(fe) != 0)
2625		goto free_mem;
2626
2627	pr_info("DiB0090: successfully identified\n");
2628	memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
2629
2630	return fe;
2631 free_mem:
2632	kfree(st);
2633	fe->tuner_priv = NULL;
2634	return NULL;
2635}
2636
2637EXPORT_SYMBOL_GPL(dib0090_register);
2638
2639struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
2640{
2641	struct dib0090_fw_state *st = kzalloc(sizeof(struct dib0090_fw_state), GFP_KERNEL);
2642	if (st == NULL)
2643		return NULL;
2644
2645	st->config = config;
2646	st->i2c = i2c;
2647	st->fe = fe;
2648	mutex_init(&st->i2c_buffer_lock);
2649	fe->tuner_priv = st;
2650
2651	if (dib0090_fw_reset_digital(fe, st->config) != 0)
2652		goto free_mem;
2653
2654	dprintk("DiB0090 FW: successfully identified\n");
2655	memcpy(&fe->ops.tuner_ops, &dib0090_fw_ops, sizeof(struct dvb_tuner_ops));
2656
2657	return fe;
2658free_mem:
2659	kfree(st);
2660	fe->tuner_priv = NULL;
2661	return NULL;
2662}
2663EXPORT_SYMBOL_GPL(dib0090_fw_register);
2664
2665MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
2666MODULE_AUTHOR("Olivier Grenie <olivier.grenie@parrot.com>");
2667MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
2668MODULE_LICENSE("GPL");
2669