xref: /linux/drivers/media/dvb-frontends/dib0090.c (revision 34dc1baba215b826e454b8d19e4f24adbeb7d00d)
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 
23 static int debug;
24 module_param(debug, int, 0644);
25 MODULE_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 
95 struct dc_calibration;
96 
97 struct 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 
108 struct 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 
116 struct dib0090_identity {
117 	u8 version;
118 	u8 product;
119 	u8 p1g;
120 	u8 in_soc;
121 };
122 
123 struct 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 
187 struct 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 
200 static 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 
232 static 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 
261 static 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 
288 static 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
320 static 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 
327 static 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 
415 identification_error:
416 	return -EIO;
417 }
418 
419 static 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 
505 identification_error:
506 	return -EIO;
507 }
508 
509 static 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 
576 static 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 
649 static 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 
660 static 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 
668 void 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 
677 EXPORT_SYMBOL(dib0090_dcc_freq);
678 
679 static 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 
689 static 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 
703 static 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 
717 static 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 
731 static 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 
745 static 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 
759 static 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 */
774 static 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 */
786 static 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 
797 static 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 
811 static 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 
825 static 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 */
841 static 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 
856 struct slope {
857 	s16 range;
858 	s16 slope;
859 };
860 static 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 
876 static 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 
882 static 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 
893 static 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 
912 static const int gain_reg_addr[4] = {
913 	0x08, 0x0a, 0x0f, 0x01
914 };
915 
916 static 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 
1020 static 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 
1026 static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
1027 {
1028 	state->rf_ramp = cfg;
1029 }
1030 
1031 static 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 
1043 static 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 
1049 static 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 
1060 void 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 }
1132 EXPORT_SYMBOL(dib0090_pwm_gain_reset);
1133 
1134 void 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 }
1140 EXPORT_SYMBOL(dib0090_set_dc_servo);
1141 
1142 static 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 
1150 int 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 
1311 EXPORT_SYMBOL(dib0090_gain_control);
1312 
1313 void 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 
1326 EXPORT_SYMBOL(dib0090_get_current_gain);
1327 
1328 u16 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 }
1365 EXPORT_SYMBOL(dib0090_get_wbd_target);
1366 
1367 u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
1368 {
1369 	struct dib0090_state *state = fe->tuner_priv;
1370 	return state->wbd_offset;
1371 }
1372 EXPORT_SYMBOL(dib0090_get_wbd_offset);
1373 
1374 int 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 }
1383 EXPORT_SYMBOL(dib0090_set_switch);
1384 
1385 int 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 }
1393 EXPORT_SYMBOL(dib0090_set_vga);
1394 
1395 int 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 }
1414 EXPORT_SYMBOL(dib0090_update_rframp_7090);
1415 
1416 static 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 
1464 static 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 
1479 static 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 
1501 static 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 
1545 static 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
1594 static 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 
1626 struct dc_calibration {
1627 	u8 addr;
1628 	u8 offset;
1629 	u8 pga:1;
1630 	u16 bb1;
1631 	u8 i:1;
1632 };
1633 
1634 static 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 
1644 static 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 
1655 static 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 
1670 static 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 
1776 static 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 
1821 static 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 
1849 static 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 
1880 static 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 
1906 static 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 
1935 static 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 
1964 static 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 
1995 static 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 
2020 static 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 
2029 static 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 
2040 int 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 }
2073 EXPORT_SYMBOL(dib0090_update_tuning_table_7090);
2074 
2075 static 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 
2181 static 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 */
2232 static 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 
2509 static void dib0090_release(struct dvb_frontend *fe)
2510 {
2511 	kfree(fe->tuner_priv);
2512 	fe->tuner_priv = NULL;
2513 }
2514 
2515 enum 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 
2522 EXPORT_SYMBOL(dib0090_get_tune_state);
2523 
2524 int 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 
2532 EXPORT_SYMBOL(dib0090_set_tune_state);
2533 
2534 static 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 
2542 static 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 
2569 static 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 
2584 static 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 
2599 static 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 
2607 struct 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 
2637 EXPORT_SYMBOL_GPL(dib0090_register);
2638 
2639 struct 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;
2658 free_mem:
2659 	kfree(st);
2660 	fe->tuner_priv = NULL;
2661 	return NULL;
2662 }
2663 EXPORT_SYMBOL_GPL(dib0090_fw_register);
2664 
2665 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
2666 MODULE_AUTHOR("Olivier Grenie <olivier.grenie@parrot.com>");
2667 MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
2668 MODULE_LICENSE("GPL");
2669