cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dib0090.c (77694B)


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