brintos

brintos / linux-shallow public Read only

0
0
Text · 20.5 KiB · 210ccd3 Raw
948 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/* DVB compliant Linux driver for the DVB-S si2109/2110 demodulator3*4* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)5*/6#include <linux/init.h>7#include <linux/kernel.h>8#include <linux/module.h>9#include <linux/string.h>10#include <linux/slab.h>11#include <linux/jiffies.h>12#include <asm/div64.h>13 14#include <media/dvb_frontend.h>15#include "si21xx.h"16 17#define	REVISION_REG			0x0018#define	SYSTEM_MODE_REG			0x0119#define	TS_CTRL_REG_1			0x0220#define	TS_CTRL_REG_2			0x0321#define	PIN_CTRL_REG_1			0x0422#define	PIN_CTRL_REG_2			0x0523#define	LOCK_STATUS_REG_1		0x0f24#define	LOCK_STATUS_REG_2		0x1025#define	ACQ_STATUS_REG			0x1126#define	ACQ_CTRL_REG_1			0x1327#define	ACQ_CTRL_REG_2			0x1428#define	PLL_DIVISOR_REG			0x1529#define	COARSE_TUNE_REG			0x1630#define	FINE_TUNE_REG_L			0x1731#define	FINE_TUNE_REG_H			0x1832 33#define	ANALOG_AGC_POWER_LEVEL_REG	0x2834#define	CFO_ESTIMATOR_CTRL_REG_1	0x2935#define	CFO_ESTIMATOR_CTRL_REG_2	0x2a36#define	CFO_ESTIMATOR_CTRL_REG_3	0x2b37 38#define	SYM_RATE_ESTIMATE_REG_L		0x3139#define	SYM_RATE_ESTIMATE_REG_M		0x3240#define	SYM_RATE_ESTIMATE_REG_H		0x3341 42#define	CFO_ESTIMATOR_OFFSET_REG_L	0x3643#define	CFO_ESTIMATOR_OFFSET_REG_H	0x3744#define	CFO_ERROR_REG_L			0x3845#define	CFO_ERROR_REG_H			0x3946#define	SYM_RATE_ESTIMATOR_CTRL_REG	0x3a47 48#define	SYM_RATE_REG_L			0x3f49#define	SYM_RATE_REG_M			0x4050#define	SYM_RATE_REG_H			0x4151#define	SYM_RATE_ESTIMATOR_MAXIMUM_REG	0x4252#define	SYM_RATE_ESTIMATOR_MINIMUM_REG	0x4353 54#define	C_N_ESTIMATOR_CTRL_REG		0x7c55#define	C_N_ESTIMATOR_THRSHLD_REG	0x7d56#define	C_N_ESTIMATOR_LEVEL_REG_L	0x7e57#define	C_N_ESTIMATOR_LEVEL_REG_H	0x7f58 59#define	BLIND_SCAN_CTRL_REG		0x8060 61#define	LSA_CTRL_REG_1			0x8D62#define	SPCTRM_TILT_CORR_THRSHLD_REG	0x8f63#define	ONE_DB_BNDWDTH_THRSHLD_REG	0x9064#define	TWO_DB_BNDWDTH_THRSHLD_REG	0x9165#define	THREE_DB_BNDWDTH_THRSHLD_REG	0x9266#define	INBAND_POWER_THRSHLD_REG	0x9367#define	REF_NOISE_LVL_MRGN_THRSHLD_REG	0x9468 69#define	VIT_SRCH_CTRL_REG_1		0xa070#define	VIT_SRCH_CTRL_REG_2		0xa171#define	VIT_SRCH_CTRL_REG_3		0xa272#define	VIT_SRCH_STATUS_REG		0xa373#define	VITERBI_BER_COUNT_REG_L		0xab74#define	REED_SOLOMON_CTRL_REG		0xb075#define	REED_SOLOMON_ERROR_COUNT_REG_L	0xb176#define	PRBS_CTRL_REG			0xb577 78#define	LNB_CTRL_REG_1			0xc079#define	LNB_CTRL_REG_2			0xc180#define	LNB_CTRL_REG_3			0xc281#define	LNB_CTRL_REG_4			0xc382#define	LNB_CTRL_STATUS_REG		0xc483#define	LNB_FIFO_REGS_0			0xc584#define	LNB_FIFO_REGS_1			0xc685#define	LNB_FIFO_REGS_2			0xc786#define	LNB_FIFO_REGS_3			0xc887#define	LNB_FIFO_REGS_4			0xc988#define	LNB_FIFO_REGS_5			0xca89#define	LNB_SUPPLY_CTRL_REG_1		0xcb90#define	LNB_SUPPLY_CTRL_REG_2		0xcc91#define	LNB_SUPPLY_CTRL_REG_3		0xcd92#define	LNB_SUPPLY_CTRL_REG_4		0xce93#define	LNB_SUPPLY_STATUS_REG		0xcf94 95#define FAIL	-196#define PASS	097 98#define ALLOWABLE_FS_COUNT	1099#define STATUS_BER		0100#define STATUS_UCBLOCKS		1101 102static int debug;103#define dprintk(args...) \104	do { \105		if (debug) \106			printk(KERN_DEBUG "si21xx: " args); \107	} while (0)108 109enum {110	ACTIVE_HIGH,111	ACTIVE_LOW112};113enum {114	BYTE_WIDE,115	BIT_WIDE116};117enum {118	CLK_GAPPED_MODE,119	CLK_CONTINUOUS_MODE120};121enum {122	RISING_EDGE,123	FALLING_EDGE124};125enum {126	MSB_FIRST,127	LSB_FIRST128};129enum {130	SERIAL,131	PARALLEL132};133 134struct si21xx_state {135	struct i2c_adapter *i2c;136	const struct si21xx_config *config;137	struct dvb_frontend frontend;138	u8 initialised:1;139	int errmode;140	int fs;			/*Sampling rate of the ADC in MHz*/141};142 143/*	register default initialization */144static u8 serit_sp1511lhb_inittab[] = {145	0x01, 0x28,	/* set i2c_inc_disable */146	0x20, 0x03,147	0x27, 0x20,148	0xe0, 0x45,149	0xe1, 0x08,150	0xfe, 0x01,151	0x01, 0x28,152	0x89, 0x09,153	0x04, 0x80,154	0x05, 0x01,155	0x06, 0x00,156	0x20, 0x03,157	0x24, 0x88,158	0x29, 0x09,159	0x2a, 0x0f,160	0x2c, 0x10,161	0x2d, 0x19,162	0x2e, 0x08,163	0x2f, 0x10,164	0x30, 0x19,165	0x34, 0x20,166	0x35, 0x03,167	0x45, 0x02,168	0x46, 0x45,169	0x47, 0xd0,170	0x48, 0x00,171	0x49, 0x40,172	0x4a, 0x03,173	0x4c, 0xfd,174	0x4f, 0x2e,175	0x50, 0x2e,176	0x51, 0x10,177	0x52, 0x10,178	0x56, 0x92,179	0x59, 0x00,180	0x5a, 0x2d,181	0x5b, 0x33,182	0x5c, 0x1f,183	0x5f, 0x76,184	0x62, 0xc0,185	0x63, 0xc0,186	0x64, 0xf3,187	0x65, 0xf3,188	0x79, 0x40,189	0x6a, 0x40,190	0x6b, 0x0a,191	0x6c, 0x80,192	0x6d, 0x27,193	0x71, 0x06,194	0x75, 0x60,195	0x78, 0x00,196	0x79, 0xb5,197	0x7c, 0x05,198	0x7d, 0x1a,199	0x87, 0x55,200	0x88, 0x72,201	0x8f, 0x08,202	0x90, 0xe0,203	0x94, 0x40,204	0xa0, 0x3f,205	0xa1, 0xc0,206	0xa4, 0xcc,207	0xa5, 0x66,208	0xa6, 0x66,209	0xa7, 0x7b,210	0xa8, 0x7b,211	0xa9, 0x7b,212	0xaa, 0x9a,213	0xed, 0x04,214	0xad, 0x00,215	0xae, 0x03,216	0xcc, 0xab,217	0x01, 0x08,218	0xff, 0xff219};220 221/*	low level read/writes */222static int si21_writeregs(struct si21xx_state *state, u8 reg1,223							u8 *data, int len)224{225	int ret;226	u8 buf[60];/* = { reg1, data };*/227	struct i2c_msg msg = {228				.addr = state->config->demod_address,229				.flags = 0,230				.buf = buf,231				.len = len + 1232	};233 234	if (len > sizeof(buf) - 1)235		return -EINVAL;236 237	msg.buf[0] =  reg1;238	memcpy(msg.buf + 1, data, len);239 240	ret = i2c_transfer(state->i2c, &msg, 1);241 242	if (ret != 1)243		dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, ret == %i)\n",244			__func__, reg1, data[0], ret);245 246	return (ret != 1) ? -EREMOTEIO : 0;247}248 249static int si21_writereg(struct si21xx_state *state, u8 reg, u8 data)250{251	int ret;252	u8 buf[] = { reg, data };253	struct i2c_msg msg = {254				.addr = state->config->demod_address,255				.flags = 0,256				.buf = buf,257				.len = 2258	};259 260	ret = i2c_transfer(state->i2c, &msg, 1);261 262	if (ret != 1)263		dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, ret == %i)\n",264			__func__, reg, data, ret);265 266	return (ret != 1) ? -EREMOTEIO : 0;267}268 269static int si21_write(struct dvb_frontend *fe, const u8 buf[], int len)270{271	struct si21xx_state *state = fe->demodulator_priv;272 273	if (len != 2)274		return -EINVAL;275 276	return si21_writereg(state, buf[0], buf[1]);277}278 279static u8 si21_readreg(struct si21xx_state *state, u8 reg)280{281	int ret;282	u8 b0[] = { reg };283	u8 b1[] = { 0 };284	struct i2c_msg msg[] = {285		{286			.addr = state->config->demod_address,287			.flags = 0,288			.buf = b0,289			.len = 1290		}, {291			.addr = state->config->demod_address,292			.flags = I2C_M_RD,293			.buf = b1,294			.len = 1295		}296	};297 298	ret = i2c_transfer(state->i2c, msg, 2);299 300	if (ret != 2)301		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",302			__func__, reg, ret);303 304	return b1[0];305}306 307static int si21_readregs(struct si21xx_state *state, u8 reg1, u8 *b, u8 len)308{309	int ret;310	struct i2c_msg msg[] = {311		{312			.addr = state->config->demod_address,313			.flags = 0,314			.buf = &reg1,315			.len = 1316		}, {317			.addr = state->config->demod_address,318			.flags = I2C_M_RD,319			.buf = b,320			.len = len321		}322	};323 324	ret = i2c_transfer(state->i2c, msg, 2);325 326	if (ret != 2)327		dprintk("%s: readreg error (ret == %i)\n", __func__, ret);328 329	return ret == 2 ? 0 : -1;330}331 332static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout)333{334	unsigned long start = jiffies;335 336	dprintk("%s\n", __func__);337 338	while ((si21_readreg(state, LNB_CTRL_REG_1) & 0x8) == 8) {339		if (time_is_before_jiffies(start + timeout)) {340			dprintk("%s: timeout!!\n", __func__);341			return -ETIMEDOUT;342		}343		msleep(10);344	}345 346	return 0;347}348 349static int si21xx_set_symbolrate(struct dvb_frontend *fe, u32 srate)350{351	struct si21xx_state *state = fe->demodulator_priv;352	u32 sym_rate, data_rate;353	int i;354	u8 sym_rate_bytes[3];355 356	dprintk("%s : srate = %i\n", __func__ , srate);357 358	if ((srate < 1000000) || (srate > 45000000))359		return -EINVAL;360 361	data_rate = srate;362	sym_rate = 0;363 364	for (i = 0; i < 4; ++i) {365		sym_rate /= 100;366		sym_rate = sym_rate + ((data_rate % 100) * 0x800000) /367								state->fs;368		data_rate /= 100;369	}370	for (i = 0; i < 3; ++i)371		sym_rate_bytes[i] = (u8)((sym_rate >> (i * 8)) & 0xff);372 373	si21_writeregs(state, SYM_RATE_REG_L, sym_rate_bytes, 0x03);374 375	return 0;376}377 378static int si21xx_send_diseqc_msg(struct dvb_frontend *fe,379					struct dvb_diseqc_master_cmd *m)380{381	struct si21xx_state *state = fe->demodulator_priv;382	u8 lnb_status;383	u8 LNB_CTRL_1;384	int status;385 386	dprintk("%s\n", __func__);387 388	status = PASS;389	LNB_CTRL_1 = 0;390 391	status |= si21_readregs(state, LNB_CTRL_STATUS_REG, &lnb_status, 0x01);392	status |= si21_readregs(state, LNB_CTRL_REG_1, &lnb_status, 0x01);393 394	/*fill the FIFO*/395	status |= si21_writeregs(state, LNB_FIFO_REGS_0, m->msg, m->msg_len);396 397	LNB_CTRL_1 = (lnb_status & 0x70);398	LNB_CTRL_1 |= m->msg_len;399 400	LNB_CTRL_1 |= 0x80;	/* begin LNB signaling */401 402	status |= si21_writeregs(state, LNB_CTRL_REG_1, &LNB_CTRL_1, 0x01);403 404	return status;405}406 407static int si21xx_send_diseqc_burst(struct dvb_frontend *fe,408				    enum fe_sec_mini_cmd burst)409{410	struct si21xx_state *state = fe->demodulator_priv;411	u8 val;412 413	dprintk("%s\n", __func__);414 415	if (si21xx_wait_diseqc_idle(state, 100) < 0)416		return -ETIMEDOUT;417 418	val = (0x80 | si21_readreg(state, 0xc1));419	if (si21_writereg(state, LNB_CTRL_REG_1,420			burst == SEC_MINI_A ? (val & ~0x10) : (val | 0x10)))421		return -EREMOTEIO;422 423	if (si21xx_wait_diseqc_idle(state, 100) < 0)424		return -ETIMEDOUT;425 426	if (si21_writereg(state, LNB_CTRL_REG_1, val))427		return -EREMOTEIO;428 429	return 0;430}431/*	30.06.2008 */432static int si21xx_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone)433{434	struct si21xx_state *state = fe->demodulator_priv;435	u8 val;436 437	dprintk("%s\n", __func__);438	val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));439 440	switch (tone) {441	case SEC_TONE_ON:442		return si21_writereg(state, LNB_CTRL_REG_1, val | 0x20);443 444	case SEC_TONE_OFF:445		return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x20));446 447	default:448		return -EINVAL;449	}450}451 452static int si21xx_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage volt)453{454	struct si21xx_state *state = fe->demodulator_priv;455 456	u8 val;457	dprintk("%s: %s\n", __func__,458		volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :459		volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");460 461 462	val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));463 464	switch (volt) {465	case SEC_VOLTAGE_18:466		return si21_writereg(state, LNB_CTRL_REG_1, val | 0x40);467	case SEC_VOLTAGE_13:468		return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x40));469	default:470		return -EINVAL;471	}472}473 474static int si21xx_init(struct dvb_frontend *fe)475{476	struct si21xx_state *state = fe->demodulator_priv;477	int i;478	int status = 0;479	u8 reg1;480	u8 val;481	u8 reg2[2];482 483	dprintk("%s\n", __func__);484 485	for (i = 0; ; i += 2) {486		reg1 = serit_sp1511lhb_inittab[i];487		val = serit_sp1511lhb_inittab[i+1];488		if (reg1 == 0xff && val == 0xff)489			break;490		si21_writeregs(state, reg1, &val, 1);491	}492 493	/*DVB QPSK SYSTEM MODE REG*/494	reg1 = 0x08;495	si21_writeregs(state, SYSTEM_MODE_REG, &reg1, 0x01);496 497	/*transport stream config*/498	/*499	mode = PARALLEL;500	sdata_form = LSB_FIRST;501	clk_edge = FALLING_EDGE;502	clk_mode = CLK_GAPPED_MODE;503	strt_len = BYTE_WIDE;504	sync_pol = ACTIVE_HIGH;505	val_pol = ACTIVE_HIGH;506	err_pol = ACTIVE_HIGH;507	sclk_rate = 0x00;508	parity = 0x00 ;509	data_delay = 0x00;510	clk_delay = 0x00;511	pclk_smooth = 0x00;512	*/513	reg2[0] =514		PARALLEL + (LSB_FIRST << 1)515		+ (FALLING_EDGE << 2) + (CLK_GAPPED_MODE << 3)516		+ (BYTE_WIDE << 4) + (ACTIVE_HIGH << 5)517		+ (ACTIVE_HIGH << 6) + (ACTIVE_HIGH << 7);518 519	reg2[1] = 0;520	/*	sclk_rate + (parity << 2)521		+ (data_delay << 3) + (clk_delay << 4)522		+ (pclk_smooth << 5);523	*/524	status |= si21_writeregs(state, TS_CTRL_REG_1, reg2, 0x02);525	if (status != 0)526		dprintk(" %s : TS Set Error\n", __func__);527 528	return 0;529 530}531 532static int si21_read_status(struct dvb_frontend *fe, enum fe_status *status)533{534	struct si21xx_state *state = fe->demodulator_priv;535	u8 regs_read[2];536	u8 reg_read;537	u8 i;538	u8 lock;539	u8 signal = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG);540 541	si21_readregs(state, LOCK_STATUS_REG_1, regs_read, 0x02);542	reg_read = 0;543 544	for (i = 0; i < 7; ++i)545		reg_read |= ((regs_read[0] >> i) & 0x01) << (6 - i);546 547	lock = ((reg_read & 0x7f) | (regs_read[1] & 0x80));548 549	dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, lock);550	*status = 0;551 552	if (signal > 10)553		*status |= FE_HAS_SIGNAL;554 555	if (lock & 0x2)556		*status |= FE_HAS_CARRIER;557 558	if (lock & 0x20)559		*status |= FE_HAS_VITERBI;560 561	if (lock & 0x40)562		*status |= FE_HAS_SYNC;563 564	if ((lock & 0x7b) == 0x7b)565		*status |= FE_HAS_LOCK;566 567	return 0;568}569 570static int si21_read_signal_strength(struct dvb_frontend *fe, u16 *strength)571{572	struct si21xx_state *state = fe->demodulator_priv;573 574	/*status = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG,575						(u8*)agclevel, 0x01);*/576 577	u16 signal = (3 * si21_readreg(state, 0x27) *578					si21_readreg(state, 0x28));579 580	dprintk("%s : AGCPWR: 0x%02x%02x, signal=0x%04x\n", __func__,581		si21_readreg(state, 0x27),582		si21_readreg(state, 0x28), (int) signal);583 584	signal  <<= 4;585	*strength = signal;586 587	return 0;588}589 590static int si21_read_ber(struct dvb_frontend *fe, u32 *ber)591{592	struct si21xx_state *state = fe->demodulator_priv;593 594	dprintk("%s\n", __func__);595 596	if (state->errmode != STATUS_BER)597		return 0;598 599	*ber = (si21_readreg(state, 0x1d) << 8) |600				si21_readreg(state, 0x1e);601 602	return 0;603}604 605static int si21_read_snr(struct dvb_frontend *fe, u16 *snr)606{607	struct si21xx_state *state = fe->demodulator_priv;608 609	s32 xsnr = 0xffff - ((si21_readreg(state, 0x24) << 8) |610					si21_readreg(state, 0x25));611	xsnr = 3 * (xsnr - 0xa100);612	*snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr;613 614	dprintk("%s\n", __func__);615 616	return 0;617}618 619static int si21_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)620{621	struct si21xx_state *state = fe->demodulator_priv;622 623	dprintk("%s\n", __func__);624 625	if (state->errmode != STATUS_UCBLOCKS)626		*ucblocks = 0;627	else628		*ucblocks = (si21_readreg(state, 0x1d) << 8) |629					si21_readreg(state, 0x1e);630 631	return 0;632}633 634/*	initiates a channel acquisition sequence635	using the specified symbol rate and code rate */636static int si21xx_setacquire(struct dvb_frontend *fe, int symbrate,637			     enum fe_code_rate crate)638{639 640	struct si21xx_state *state = fe->demodulator_priv;641	u8 coderates[] = {642				0x0, 0x01, 0x02, 0x04, 0x00,643				0x8, 0x10, 0x20, 0x00, 0x3f644	};645 646	u8 coderate_ptr;647	int status;648	u8 start_acq = 0x80;649	u8 reg, regs[3];650 651	dprintk("%s\n", __func__);652 653	status = PASS;654	coderate_ptr = coderates[crate];655 656	si21xx_set_symbolrate(fe, symbrate);657 658	/* write code rates to use in the Viterbi search */659	status |= si21_writeregs(state,660				VIT_SRCH_CTRL_REG_1,661				&coderate_ptr, 0x01);662 663	/* clear acq_start bit */664	status |= si21_readregs(state, ACQ_CTRL_REG_2, &reg, 0x01);665	reg &= ~start_acq;666	status |= si21_writeregs(state, ACQ_CTRL_REG_2, &reg, 0x01);667 668	/* use new Carrier Frequency Offset Estimator (QuickLock) */669	regs[0] = 0xCB;670	regs[1] = 0x40;671	regs[2] = 0xCB;672 673	status |= si21_writeregs(state,674				TWO_DB_BNDWDTH_THRSHLD_REG,675				&regs[0], 0x03);676	reg = 0x56;677	status |= si21_writeregs(state,678				LSA_CTRL_REG_1, &reg, 1);679	reg = 0x05;680	status |= si21_writeregs(state,681				BLIND_SCAN_CTRL_REG, &reg, 1);682	/* start automatic acq */683	status |= si21_writeregs(state,684				ACQ_CTRL_REG_2, &start_acq, 0x01);685 686	return status;687}688 689static int si21xx_set_frontend(struct dvb_frontend *fe)690{691	struct si21xx_state *state = fe->demodulator_priv;692	struct dtv_frontend_properties *c = &fe->dtv_property_cache;693 694	/* freq		Channel carrier frequency in KHz (i.e. 1550000 KHz)695	 datarate	Channel symbol rate in Sps (i.e. 22500000 Sps)*/696 697	/* in MHz */698	unsigned char coarse_tune_freq;699	int fine_tune_freq;700	unsigned char sample_rate = 0;701	/* boolean */702	bool inband_interferer_ind;703 704	/* INTERMEDIATE VALUES */705	int icoarse_tune_freq; /* MHz */706	int ifine_tune_freq; /* MHz */707	unsigned int band_high;708	unsigned int band_low;709	unsigned int x1;710	unsigned int x2;711	int i;712	bool inband_interferer_div2[ALLOWABLE_FS_COUNT];713	bool inband_interferer_div4[ALLOWABLE_FS_COUNT];714	int status = 0;715 716	/* allowable sample rates for ADC in MHz */717	int afs[ALLOWABLE_FS_COUNT] = { 200, 192, 193, 194, 195,718					196, 204, 205, 206, 207719	};720	/* in MHz */721	int if_limit_high;722	int if_limit_low;723	int lnb_lo;724	int lnb_uncertanity;725 726	int rf_freq;727	int data_rate;728	unsigned char regs[4];729 730	dprintk("%s : FE_SET_FRONTEND\n", __func__);731 732	if (c->delivery_system != SYS_DVBS) {733			dprintk("%s: unsupported delivery system selected (%d)\n",734				__func__, c->delivery_system);735			return -EOPNOTSUPP;736	}737 738	for (i = 0; i < ALLOWABLE_FS_COUNT; ++i)739		inband_interferer_div2[i] = inband_interferer_div4[i] = false;740 741	if_limit_high = -700000;742	if_limit_low = -100000;743	/* in MHz */744	lnb_lo = 0;745	lnb_uncertanity = 0;746 747	rf_freq = 10 * c->frequency ;748	data_rate = c->symbol_rate / 100;749 750	band_low = (rf_freq - lnb_lo) - ((lnb_uncertanity * 200)751					+ (data_rate * 135)) / 200;752 753	band_high = (rf_freq - lnb_lo) + ((lnb_uncertanity * 200)754					+ (data_rate * 135)) / 200;755 756 757	icoarse_tune_freq = 100000 *758				(((rf_freq - lnb_lo) -759					(if_limit_low + if_limit_high) / 2)760								/ 100000);761 762	ifine_tune_freq = (rf_freq - lnb_lo) - icoarse_tune_freq ;763 764	for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {765		x1 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *766					(afs[i] * 2500) + afs[i] * 2500;767 768		x2 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *769							(afs[i] * 2500);770 771		if (((band_low < x1) && (x1 < band_high)) ||772					((band_low < x2) && (x2 < band_high)))773					inband_interferer_div4[i] = true;774 775	}776 777	for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {778		x1 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *779					(afs[i] * 5000) + afs[i] * 5000;780 781		x2 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *782					(afs[i] * 5000);783 784		if (((band_low < x1) && (x1 < band_high)) ||785					((band_low < x2) && (x2 < band_high)))786					inband_interferer_div2[i] = true;787	}788 789	inband_interferer_ind = true;790	for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {791		if (inband_interferer_div2[i] || inband_interferer_div4[i]) {792			inband_interferer_ind = false;793			break;794		}795	}796 797	if (inband_interferer_ind) {798		for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {799			if (!inband_interferer_div2[i]) {800				sample_rate = (u8) afs[i];801				break;802			}803		}804	} else {805		for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {806			if ((inband_interferer_div2[i] ||807			     !inband_interferer_div4[i])) {808				sample_rate = (u8) afs[i];809				break;810			}811		}812 813	}814 815	if (sample_rate > 207 || sample_rate < 192)816		sample_rate = 200;817 818	fine_tune_freq = ((0x4000 * (ifine_tune_freq / 10)) /819					((sample_rate) * 1000));820 821	coarse_tune_freq = (u8)(icoarse_tune_freq / 100000);822 823	regs[0] = sample_rate;824	regs[1] = coarse_tune_freq;825	regs[2] = fine_tune_freq & 0xFF;826	regs[3] = fine_tune_freq >> 8 & 0xFF;827 828	status |= si21_writeregs(state, PLL_DIVISOR_REG, &regs[0], 0x04);829 830	state->fs = sample_rate;/*ADC MHz*/831	si21xx_setacquire(fe, c->symbol_rate, c->fec_inner);832 833	if (status)834		return -EREMOTEIO;835 836	return 0;837}838 839static int si21xx_sleep(struct dvb_frontend *fe)840{841	struct si21xx_state *state = fe->demodulator_priv;842	u8 regdata;843 844	dprintk("%s\n", __func__);845 846	si21_readregs(state, SYSTEM_MODE_REG, &regdata, 0x01);847	regdata |= 1 << 6;848	si21_writeregs(state, SYSTEM_MODE_REG, &regdata, 0x01);849	state->initialised = 0;850 851	return 0;852}853 854static void si21xx_release(struct dvb_frontend *fe)855{856	struct si21xx_state *state = fe->demodulator_priv;857 858	dprintk("%s\n", __func__);859 860	kfree(state);861}862 863static const struct dvb_frontend_ops si21xx_ops = {864	.delsys = { SYS_DVBS },865	.info = {866		.name			= "SL SI21XX DVB-S",867		.frequency_min_hz	=  950 * MHz,868		.frequency_max_hz	= 2150 * MHz,869		.frequency_stepsize_hz	=  125 * kHz,870		.symbol_rate_min	= 1000000,871		.symbol_rate_max	= 45000000,872		.symbol_rate_tolerance	= 500,	/* ppm */873		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |874		FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |875		FE_CAN_QPSK |876		FE_CAN_FEC_AUTO877	},878 879	.release = si21xx_release,880	.init = si21xx_init,881	.sleep = si21xx_sleep,882	.write = si21_write,883	.read_status = si21_read_status,884	.read_ber = si21_read_ber,885	.read_signal_strength = si21_read_signal_strength,886	.read_snr = si21_read_snr,887	.read_ucblocks = si21_read_ucblocks,888	.diseqc_send_master_cmd = si21xx_send_diseqc_msg,889	.diseqc_send_burst = si21xx_send_diseqc_burst,890	.set_tone = si21xx_set_tone,891	.set_voltage = si21xx_set_voltage,892 893	.set_frontend = si21xx_set_frontend,894};895 896struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,897						struct i2c_adapter *i2c)898{899	struct si21xx_state *state = NULL;900	int id;901 902	dprintk("%s\n", __func__);903 904	/* allocate memory for the internal state */905	state = kzalloc(sizeof(struct si21xx_state), GFP_KERNEL);906	if (state == NULL)907		goto error;908 909	/* setup the state */910	state->config = config;911	state->i2c = i2c;912	state->initialised = 0;913	state->errmode = STATUS_BER;914 915	/* check if the demod is there */916	id = si21_readreg(state, SYSTEM_MODE_REG);917	si21_writereg(state, SYSTEM_MODE_REG, id | 0x40); /* standby off */918	msleep(200);919	id = si21_readreg(state, 0x00);920 921	/* register 0x00 contains:922		0x34 for SI2107923		0x24 for SI2108924		0x14 for SI2109925		0x04 for SI2110926	*/927	if (id != 0x04 && id != 0x14)928		goto error;929 930	/* create dvb_frontend */931	memcpy(&state->frontend.ops, &si21xx_ops,932					sizeof(struct dvb_frontend_ops));933	state->frontend.demodulator_priv = state;934	return &state->frontend;935 936error:937	kfree(state);938	return NULL;939}940EXPORT_SYMBOL_GPL(si21xx_attach);941 942module_param(debug, int, 0644);943MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");944 945MODULE_DESCRIPTION("SL SI21XX DVB Demodulator driver");946MODULE_AUTHOR("Igor M. Liplianin");947MODULE_LICENSE("GPL");948