⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 si21xx.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* DVB compliant Linux driver for the DVB-S si2109/2110 demodulator** Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)**	This program is free software; you can redistribute it and/or modify*	it under the terms of the GNU General Public License as published by*	the Free Software Foundation; either version 2 of the License, or*	(at your option) any later version.**/#include <linux/version.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/string.h>#include <linux/slab.h>#include <linux/jiffies.h>#include <asm/div64.h>#include "dvb_frontend.h"#include "si21xx.h"#define	REVISION_REG			0x00#define	SYSTEM_MODE_REG			0x01#define	TS_CTRL_REG_1			0x02#define	TS_CTRL_REG_2			0x03#define	PIN_CTRL_REG_1			0x04#define	PIN_CTRL_REG_2			0x05#define	LOCK_STATUS_REG_1		0x0f#define	LOCK_STATUS_REG_2		0x10#define	ACQ_STATUS_REG			0x11#define	ACQ_CTRL_REG_1			0x13#define	ACQ_CTRL_REG_2			0x14#define	PLL_DIVISOR_REG			0x15#define	COARSE_TUNE_REG			0x16#define	FINE_TUNE_REG_L			0x17#define	FINE_TUNE_REG_H			0x18#define	ANALOG_AGC_POWER_LEVEL_REG	0x28#define	CFO_ESTIMATOR_CTRL_REG_1	0x29#define	CFO_ESTIMATOR_CTRL_REG_2	0x2a#define	CFO_ESTIMATOR_CTRL_REG_3	0x2b#define	SYM_RATE_ESTIMATE_REG_L		0x31#define	SYM_RATE_ESTIMATE_REG_M		0x32#define	SYM_RATE_ESTIMATE_REG_H		0x33#define	CFO_ESTIMATOR_OFFSET_REG_L	0x36#define	CFO_ESTIMATOR_OFFSET_REG_H	0x37#define	CFO_ERROR_REG_L			0x38#define	CFO_ERROR_REG_H			0x39#define	SYM_RATE_ESTIMATOR_CTRL_REG	0x3a#define	SYM_RATE_REG_L			0x3f#define	SYM_RATE_REG_M			0x40#define	SYM_RATE_REG_H			0x41#define	SYM_RATE_ESTIMATOR_MAXIMUM_REG	0x42#define	SYM_RATE_ESTIMATOR_MINIMUM_REG	0x43#define	C_N_ESTIMATOR_CTRL_REG		0x7c#define	C_N_ESTIMATOR_THRSHLD_REG	0x7d#define	C_N_ESTIMATOR_LEVEL_REG_L	0x7e#define	C_N_ESTIMATOR_LEVEL_REG_H	0x7f#define	BLIND_SCAN_CTRL_REG		0x80#define	LSA_CTRL_REG_1			0x8D#define	SPCTRM_TILT_CORR_THRSHLD_REG	0x8f#define	ONE_DB_BNDWDTH_THRSHLD_REG	0x90#define	TWO_DB_BNDWDTH_THRSHLD_REG	0x91#define	THREE_DB_BNDWDTH_THRSHLD_REG	0x92#define	INBAND_POWER_THRSHLD_REG	0x93#define	REF_NOISE_LVL_MRGN_THRSHLD_REG	0x94#define	VIT_SRCH_CTRL_REG_1		0xa0#define	VIT_SRCH_CTRL_REG_2		0xa1#define	VIT_SRCH_CTRL_REG_3		0xa2#define	VIT_SRCH_STATUS_REG		0xa3#define	VITERBI_BER_COUNT_REG_L		0xab#define	REED_SOLOMON_CTRL_REG		0xb0#define	REED_SOLOMON_ERROR_COUNT_REG_L	0xb1#define	PRBS_CTRL_REG			0xb5#define	LNB_CTRL_REG_1			0xc0#define	LNB_CTRL_REG_2			0xc1#define	LNB_CTRL_REG_3			0xc2#define	LNB_CTRL_REG_4			0xc3#define	LNB_CTRL_STATUS_REG		0xc4#define	LNB_FIFO_REGS_0			0xc5#define	LNB_FIFO_REGS_1			0xc6#define	LNB_FIFO_REGS_2			0xc7#define	LNB_FIFO_REGS_3			0xc8#define	LNB_FIFO_REGS_4			0xc9#define	LNB_FIFO_REGS_5			0xca#define	LNB_SUPPLY_CTRL_REG_1		0xcb#define	LNB_SUPPLY_CTRL_REG_2		0xcc#define	LNB_SUPPLY_CTRL_REG_3		0xcd#define	LNB_SUPPLY_CTRL_REG_4		0xce#define	LNB_SUPPLY_STATUS_REG		0xcf#define FALSE	0#define TRUE	1#define FAIL	-1#define PASS	0#define ALLOWABLE_FS_COUNT	10#define STATUS_BER		0#define STATUS_UCBLOCKS		1static int debug;#define dprintk(args...) \	do { \		if (debug) \			printk(KERN_DEBUG "si21xx: " args); \	} while (0)enum {	ACTIVE_HIGH,	ACTIVE_LOW};enum {	BYTE_WIDE,	BIT_WIDE};enum {	CLK_GAPPED_MODE,	CLK_CONTINUOUS_MODE};enum {	RISING_EDGE,	FALLING_EDGE};enum {	MSB_FIRST,	LSB_FIRST};enum {	SERIAL,	PARALLEL};struct si21xx_state {	struct i2c_adapter *i2c;	const struct si21xx_config *config;	struct dvb_frontend frontend;	u8 initialised:1;	int errmode;	int fs;			/*Sampling rate of the ADC in MHz*/};/*	register default initialization */static u8 serit_sp1511lhb_inittab[] = {	0x01, 0x28,	/* set i2c_inc_disable */	0x20, 0x03,	0x27, 0x20,	0xe0, 0x45,	0xe1, 0x08,	0xfe, 0x01,	0x01, 0x28,	0x89, 0x09,	0x04, 0x80,	0x05, 0x01,	0x06, 0x00,	0x20, 0x03,	0x24, 0x88,	0x29, 0x09,	0x2a, 0x0f,	0x2c, 0x10,	0x2d, 0x19,	0x2e, 0x08,	0x2f, 0x10,	0x30, 0x19,	0x34, 0x20,	0x35, 0x03,	0x45, 0x02,	0x46, 0x45,	0x47, 0xd0,	0x48, 0x00,	0x49, 0x40,	0x4a, 0x03,	0x4c, 0xfd,	0x4f, 0x2e,	0x50, 0x2e,	0x51, 0x10,	0x52, 0x10,	0x56, 0x92,	0x59, 0x00,	0x5a, 0x2d,	0x5b, 0x33,	0x5c, 0x1f,	0x5f, 0x76,	0x62, 0xc0,	0x63, 0xc0,	0x64, 0xf3,	0x65, 0xf3,	0x79, 0x40,	0x6a, 0x40,	0x6b, 0x0a,	0x6c, 0x80,	0x6d, 0x27,	0x71, 0x06,	0x75, 0x60,	0x78, 0x00,	0x79, 0xb5,	0x7c, 0x05,	0x7d, 0x1a,	0x87, 0x55,	0x88, 0x72,	0x8f, 0x08,	0x90, 0xe0,	0x94, 0x40,	0xa0, 0x3f,	0xa1, 0xc0,	0xa4, 0xcc,	0xa5, 0x66,	0xa6, 0x66,	0xa7, 0x7b,	0xa8, 0x7b,	0xa9, 0x7b,	0xaa, 0x9a,	0xed, 0x04,	0xad, 0x00,	0xae, 0x03,	0xcc, 0xab,	0x01, 0x08,	0xff, 0xff};/*	low level read/writes */static int si21_writeregs(struct si21xx_state *state, u8 reg1,							u8 *data, int len){	int ret;	u8 buf[60];/* = { reg1, data };*/	struct i2c_msg msg = {				.addr = state->config->demod_address,				.flags = 0,				.buf = buf,				.len = len + 1	};	msg.buf[0] =  reg1;	memcpy(msg.buf + 1, data, len);	ret = i2c_transfer(state->i2c, &msg, 1);	if (ret != 1)		dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, "			"ret == %i)\n", __func__, reg1, data[0], ret);	return (ret != 1) ? -EREMOTEIO : 0;}static int si21_writereg(struct si21xx_state *state, u8 reg, u8 data){	int ret;	u8 buf[] = { reg, data };	struct i2c_msg msg = {				.addr = state->config->demod_address,				.flags = 0,				.buf = buf,				.len = 2	};	ret = i2c_transfer(state->i2c, &msg, 1);	if (ret != 1)		dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, "			"ret == %i)\n", __func__, reg, data, ret);	return (ret != 1) ? -EREMOTEIO : 0;}static int si21_write(struct dvb_frontend *fe, u8 *buf, int len){	struct si21xx_state *state = fe->demodulator_priv;	if (len != 2)		return -EINVAL;	return si21_writereg(state, buf[0], buf[1]);}static u8 si21_readreg(struct si21xx_state *state, u8 reg){	int ret;	u8 b0[] = { reg };	u8 b1[] = { 0 };	struct i2c_msg msg[] = {		{			.addr = state->config->demod_address,			.flags = 0,			.buf = b0,			.len = 1		}, {			.addr = state->config->demod_address,			.flags = I2C_M_RD,			.buf = b1,			.len = 1		}	};	ret = i2c_transfer(state->i2c, msg, 2);	if (ret != 2)		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",			__func__, reg, ret);	return b1[0];}static int si21_readregs(struct si21xx_state *state, u8 reg1, u8 *b, u8 len){	int ret;	struct i2c_msg msg[] = {		{			.addr = state->config->demod_address,			.flags = 0,			.buf = &reg1,			.len = 1		}, {			.addr = state->config->demod_address,			.flags = I2C_M_RD,			.buf = b,			.len = len		}	};	ret = i2c_transfer(state->i2c, msg, 2);	if (ret != 2)		dprintk("%s: readreg error (ret == %i)\n", __func__, ret);	return ret == 2 ? 0 : -1;}#if 0static int si21xx_wait_diseqc_fifo(struct si21xx_state *state, int timeout){	unsigned long start = jiffies;	dprintk("%s\n", __func__);	while (((si21_readreg(state, 0xc4) >> 7) & 1) == 0) {		if (jiffies - start > timeout) {			dprintk("%s: timeout!!\n", __func__);			return -ETIMEDOUT;		}		msleep(10);	};	return 0;}#endifstatic int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout){	unsigned long start = jiffies;	dprintk("%s\n", __func__);	while ((si21_readreg(state, LNB_CTRL_REG_1) & 0x8) == 8) {		if (jiffies - start > timeout) {			dprintk("%s: timeout!!\n", __func__);			return -ETIMEDOUT;		}		msleep(10);	};	return 0;}static int si21xx_set_symbolrate(struct dvb_frontend *fe, u32 srate){	struct si21xx_state *state = fe->demodulator_priv;	u32 sym_rate, data_rate;	int i;	u8 sym_rate_bytes[3];	dprintk("%s : srate = %i\n", __func__ , srate);	if ((srate < 1000000) || (srate > 45000000))		return -EINVAL;	data_rate = srate;	sym_rate = 0;	for (i = 0; i < 4; ++i) {		sym_rate /= 100;		sym_rate = sym_rate + ((data_rate % 100) * 0x800000) /								state->fs;		data_rate /= 100;	}	for (i = 0; i < 3; ++i)		sym_rate_bytes[i] = (u8)((sym_rate >> (i * 8)) & 0xff);	si21_writeregs(state, SYM_RATE_REG_L, sym_rate_bytes, 0x03);	return 0;}static int si21xx_send_diseqc_msg(struct dvb_frontend *fe,					struct dvb_diseqc_master_cmd *m){	struct si21xx_state *state = fe->demodulator_priv;#if 0	u8 val;	int i;		if (si21xx_wait_diseqc_idle(state, 100) < 0)			return -ETIMEDOUT;		val = si21_readreg(state, 0x08);		/* DiSEqC mode */		if (si21_writereg(state, 0x08, (val & ~0x7) | 0x6))			return -EREMOTEIO;		for (i = 0; i < m->msg_len; i++) {			if (si21xx_wait_diseqc_fifo(state, 100) < 0)				return -ETIMEDOUT;			if (si21_writereg(state, 0x09, m->msg[i]))				return -EREMOTEIO;		}		if (si21xx_wait_diseqc_idle(state, 100) < 0)			return -ETIMEDOUT;		return 0;	}int si21xx_set_lnb_msg(state, lnb_cmd){#endif	u8 lnb_status;	u8 LNB_CTRL_1;	int status;	dprintk("%s\n", __func__);	status = PASS;	LNB_CTRL_1 = 0;	status |= si21_readregs(state, LNB_CTRL_STATUS_REG, &lnb_status, 0x01);	status |= si21_readregs(state, LNB_CTRL_REG_1, &lnb_status, 0x01);	/*fill the FIFO*/	status |= si21_writeregs(state, LNB_FIFO_REGS_0, m->msg, m->msg_len);	LNB_CTRL_1 = (lnb_status & 0x70);#if 0	LNB_CTRL_1 |= voltage << 6;	/*voltage select*/	LNB_CTRL_1 |= tone << 5;	/*continuous tone selection*/	LNB_CTRL_1 |= burst << 4;	/*tone burst selection*/	LNB_CTRL_1 |= mmsg << 3;	/*more messages indicator*/#endif	LNB_CTRL_1 |= m->msg_len;	LNB_CTRL_1 |= 0x80;	/* begin LNB signaling */	status |= si21_writeregs(state, LNB_CTRL_REG_1, &LNB_CTRL_1, 0x01);	return status;}static int si21xx_send_diseqc_burst(struct dvb_frontend *fe,						fe_sec_mini_cmd_t burst){	struct si21xx_state *state = fe->demodulator_priv;	u8 val;	dprintk("%s\n", __func__);	if (si21xx_wait_diseqc_idle(state, 100) < 0)		return -ETIMEDOUT;	val = (0x80 | si21_readreg(state, 0xc1));#if 0	/* burst mode */	if (si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x10))		return -EREMOTEIO;#endif	if (si21_writereg(state, LNB_CTRL_REG_1,			burst == SEC_MINI_A ? (val & ~0x10) : (val | 0x10)))		return -EREMOTEIO;	if (si21xx_wait_diseqc_idle(state, 100) < 0)		return -ETIMEDOUT;	if (si21_writereg(state, LNB_CTRL_REG_1, val))		return -EREMOTEIO;	return 0;}/*	30.06.2008 */static int si21xx_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone){	struct si21xx_state *state = fe->demodulator_priv;	u8 val;	dprintk("%s\n", __func__);#if 0	if (si21xx_wait_diseqc_idle(state, 100) < 0)		return -ETIMEDOUT;#endif	val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));	switch (tone) {	case SEC_TONE_ON:		return si21_writereg(state, LNB_CTRL_REG_1, val | 0x20);	case SEC_TONE_OFF:		return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x20));	default:		return -EINVAL;	}}static int si21xx_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt){	struct si21xx_state *state = fe->demodulator_priv;	u8 val;	dprintk("%s: %s\n", __func__,		volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -