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