brintos

brintos / linux-shallow public Read only

0
0
Text · 75.9 KiB · c958bcf Raw
2669 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*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, please8 * excuse some codingstyle oddities.9 */10 11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt12 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_DVBT34#define CONFIG_SYS_ISDBT35#define CONFIG_BAND_CBAND36#define CONFIG_BAND_VHF37#define CONFIG_BAND_UHF38#define CONFIG_DIB0090_USE_PWM_AGC39 40#define EN_LNA0      0x800041#define EN_LNA1      0x400042#define EN_LNA2      0x200043#define EN_LNA3      0x100044#define EN_MIX0      0x080045#define EN_MIX1      0x040046#define EN_MIX2      0x020047#define EN_MIX3      0x010048#define EN_IQADC     0x004049#define EN_PLL       0x002050#define EN_TX        0x001051#define EN_BB        0x000852#define EN_LO        0x000453#define EN_BIAS      0x000154 55#define EN_IQANA     0x000256#define EN_DIGCLK    0x0080	/* not in the 0x24 reg, only in 0x1b */57#define EN_CRYSTAL   0x000258 59#define EN_UHF		 0x22E960#define EN_VHF		 0x44E961#define EN_LBD		 0x11E962#define EN_SBD		 0x44E963#define EN_CAB		 0x88E964 65/* Calibration defines */66#define      DC_CAL 0x167#define     WBD_CAL 0x268#define    TEMP_CAL 0x469#define CAPTRIM_CAL 0x870 71#define KROSUS_PLL_LOCKED   0x80072#define KROSUS              0x273 74/* Use those defines to identify SOC version */75#define SOC               0x0276#define SOC_7090_P1G_11R1 0x8277#define SOC_7090_P1G_21R1 0x8a78#define SOC_8090_P1G_11R1 0x8679#define SOC_8090_P1G_21R1 0x8e80 81/* else use thos ones to check */82#define P1A_B      0x083#define P1C	   0x184#define P1D_E_F    0x385#define P1G	   0x786#define P1G_21R2   0xf87 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	} else225		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	} else255		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	} else281		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	} else309		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 -220317#define GAIN_ALPHA 5318#define WBD_ALPHA 6319#define LPF	100320static 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	else526		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	else596		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	else674		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 0785/* 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#endif796 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 0840/* 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#endif855 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		else869			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	else888		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_FIREFLY902	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#endif907 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, 0x01914};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	else935		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	else945		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_AGC1006	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#endif1009 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						else1079							rf_ramp = state->rf_ramp;1080					} else1081						rf_ramp = rf_ramp_pwm_cband_7090p;1082				}1083			} else1084				rf_ramp = rf_ramp_pwm_cband;1085		} else1086 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				} else1092					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				} else1101					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		} else1120			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		else1128			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_SBAND1165		if (state->current_band == BAND_SBAND) {1166			dib0090_set_rframp(state, rf_ramp_sband);1167			dib0090_set_bbramp(state, bb_ramp_boost);1168		} else1169#endif1170#ifdef CONFIG_BAND_VHF1171		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		} else1175#endif1176#ifdef CONFIG_BAND_CBAND1177		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		} else1181#endif1182		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		else1208			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_CBAND1220				/* 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#endif1227			} 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_DAB1238			if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)1239				adc_error -= 10;1240#endif1241#ifdef CONFIG_STANDARD_DVBT1242			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#endif1246#ifdef CONFIG_SYS_ISDBT1247			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#endif1274 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_DAB1279					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					} else1283#endif1284					{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_AGC1298		dprintk1299			("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#endif1303	}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	else1350		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	else1409		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	01462};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	01477};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)  91495#define CAP_VALUE_MAX (u8) 401496#define HR_MIN	      (u8) 251497#define HR_MAX	      (u8) 401498#define POLY_MIN      (u8)  01499#define POLY_MAX      (u8)  81500 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		else1533			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_SUPPORT1554	if (!(state->identity.version & 0x1))	/* it is P1B - reset is already done */1555		return 0;1556#endif1557 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		else1562			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	else1584		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 101594static 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	else1662		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			else1758				*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#endif1793		}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	else1832		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_CBAND1851	{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#endif1859#ifdef CONFIG_BAND_VHF1860	{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#endif1867#ifdef CONFIG_BAND_UHF1868	{580000, 1, 3, 6, 6},1869	{700000, 0, 2, 4, 4},1870	{860000, 1, 2, 4, 4},1871#endif1872#ifdef CONFIG_BAND_LBAND1873	{1800000, 1, 0, 2, 4},1874#endif1875#ifdef CONFIG_BAND_SBAND1876	{2900000, 0, 14, 1, 4},1877#endif1878};1879 1880static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {1881 1882#ifdef CONFIG_BAND_CBAND1883	{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#endif1887#ifdef CONFIG_BAND_UHF1888	{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#endif1895#ifdef CONFIG_BAND_LBAND1896	{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#endif1900#ifdef CONFIG_BAND_SBAND1901	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},1902	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},1903#endif1904};1905 1906static const struct dib0090_tuning dib0090_tuning_table[] = {1907 1908#ifdef CONFIG_BAND_CBAND1909	{170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},1910#endif1911#ifdef CONFIG_BAND_VHF1912	{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#endif1916#ifdef CONFIG_BAND_UHF1917	{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#endif1924#ifdef CONFIG_BAND_LBAND1925	{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#endif1929#ifdef CONFIG_BAND_SBAND1930	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},1931	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},1932#endif1933};1934 1935static const struct dib0090_tuning dib0090_p1g_tuning_table[] = {1936#ifdef CONFIG_BAND_CBAND1937	{170000, 4, 1, 0x820f, 0x300, 0x2d22, 0x82cb, EN_CAB},1938#endif1939#ifdef CONFIG_BAND_VHF1940	{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#endif1944#ifdef CONFIG_BAND_UHF1945	{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#endif1953#ifdef CONFIG_BAND_LBAND1954	{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#endif1958#ifdef CONFIG_BAND_SBAND1959	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},1960	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},1961#endif1962};1963 1964static const struct dib0090_pll dib0090_p1g_pll_table[] = {1965#ifdef CONFIG_BAND_CBAND1966	{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#endif1974#ifdef CONFIG_BAND_VHF1975	{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#endif1982#ifdef CONFIG_BAND_UHF1983	{580000, 1, 5, 6, 6},1984	{680000, 0, 4, 4, 4},1985	{860000, 1, 4, 4, 4},1986#endif1987#ifdef CONFIG_BAND_LBAND1988	{1800000, 1, 2, 2, 4},1989#endif1990#ifdef CONFIG_BAND_SBAND1991	{2900000, 0, 1, 1, 6},1992#endif1993};1994 1995static const struct dib0090_tuning dib0090_p1g_tuning_table_fm_vhf_on_cband[] = {1996#ifdef CONFIG_BAND_CBAND1997	{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#endif2001#ifdef CONFIG_BAND_UHF2002	{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#endif2009#ifdef CONFIG_BAND_LBAND2010	{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#endif2014#ifdef CONFIG_BAND_SBAND2015	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},2016	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},2017#endif2018};2019 2020static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = {2021#ifdef CONFIG_BAND_CBAND2022	{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#endif2027};2028 2029static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_sensitivity[] = {2030#ifdef CONFIG_BAND_CBAND2031	{ 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#endif2038};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	else2062		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			} else2143				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			else2163				*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		else2255			/* 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 == 12287					&& 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_VHF2322							|| 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						else2327							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						else2335							tune = dib0090_tuning_table_cband_7090;2336					}2337				}2338			} else2339			 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				else2394					lo5 = 0x041f;2395			} else {2396				if (pll->vco_band)2397					lo5 = 0x049e;2398				else if (state->config->analog_output)2399					lo5 = 0x041d;2400				else2401					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					else2409						lo5 = 0x42f;2410				} else2411					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				else2422					lo6 = 0xff28;2423			} else2424				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			else2436				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		} else2487			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	} else2505		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 case2557		 * is when CONFIG_HZ=100. In such case, the minimum granularity2558		 * is 10ms. On some real field tests, the tuner sometimes don't2559		 * lock when this timer is lower than 10ms. So, enforce a 10ms2560		 * 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	else2622		st->current_wbd_table = config->wbd;2623 2624	if (dib0090_reset(fe) != 0)2625		goto free_mem;2626 2627	pr_info("DiB0090: successfully identified\n");2628	memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));2629 2630	return fe;2631 free_mem:2632	kfree(st);2633	fe->tuner_priv = NULL;2634	return NULL;2635}2636 2637EXPORT_SYMBOL_GPL(dib0090_register);2638 2639struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)2640{2641	struct dib0090_fw_state *st = kzalloc(sizeof(struct dib0090_fw_state), GFP_KERNEL);2642	if (st == NULL)2643		return NULL;2644 2645	st->config = config;2646	st->i2c = i2c;2647	st->fe = fe;2648	mutex_init(&st->i2c_buffer_lock);2649	fe->tuner_priv = st;2650 2651	if (dib0090_fw_reset_digital(fe, st->config) != 0)2652		goto free_mem;2653 2654	dprintk("DiB0090 FW: successfully identified\n");2655	memcpy(&fe->ops.tuner_ops, &dib0090_fw_ops, sizeof(struct dvb_tuner_ops));2656 2657	return fe;2658free_mem:2659	kfree(st);2660	fe->tuner_priv = NULL;2661	return NULL;2662}2663EXPORT_SYMBOL_GPL(dib0090_fw_register);2664 2665MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");2666MODULE_AUTHOR("Olivier Grenie <olivier.grenie@parrot.com>");2667MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");2668MODULE_LICENSE("GPL");2669