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

📄 stv0297.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Driver for STV0297 demodulator    Copyright (C) 2004 Andrew de Quincey <adq_dvb@lidskialf.net>    Copyright (C) 2003-2004 Dennis Noermann <dennis.noermann@noernet.de>    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.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <linux/init.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/string.h>#include <linux/delay.h>#include <linux/jiffies.h>#include <linux/slab.h>#include "dvb_frontend.h"#include "stv0297.h"struct stv0297_state {	struct i2c_adapter *i2c;	struct dvb_frontend_ops ops;	const struct stv0297_config *config;	struct dvb_frontend frontend;	unsigned long base_freq;};#if 1#define dprintk(x...) printk(x)#else#define dprintk(x...)#endif#define STV0297_CLOCK_KHZ   28900static int stv0297_writereg(struct stv0297_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, val == 0x%02x, "			"ret == %i)\n", __FUNCTION__, reg, data, ret);	return (ret != 1) ? -1 : 0;}static int stv0297_readreg(struct stv0297_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}	};	// this device needs a STOP between the register and data	if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);		return -1;	}	if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);		return -1;	}	return b1[0];}static int stv0297_writereg_mask(struct stv0297_state *state, u8 reg, u8 mask, u8 data){	int val;	val = stv0297_readreg(state, reg);	val &= ~mask;	val |= (data & mask);	stv0297_writereg(state, reg, val);	return 0;}static int stv0297_readregs(struct stv0297_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}	};	// this device needs a STOP between the register and data	if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);		return -1;	}	if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);		return -1;	}	return 0;}static u32 stv0297_get_symbolrate(struct stv0297_state *state){	u64 tmp;	tmp = stv0297_readreg(state, 0x55);	tmp |= stv0297_readreg(state, 0x56) << 8;	tmp |= stv0297_readreg(state, 0x57) << 16;	tmp |= stv0297_readreg(state, 0x58) << 24;	tmp *= STV0297_CLOCK_KHZ;	tmp >>= 32;	return (u32) tmp;}static void stv0297_set_symbolrate(struct stv0297_state *state, u32 srate){	long tmp;	tmp = 131072L * srate;	/* 131072 = 2^17  */	tmp = tmp / (STV0297_CLOCK_KHZ / 4);	/* 1/4 = 2^-2 */	tmp = tmp * 8192L;	/* 8192 = 2^13 */	stv0297_writereg(state, 0x55, (unsigned char) (tmp & 0xFF));	stv0297_writereg(state, 0x56, (unsigned char) (tmp >> 8));	stv0297_writereg(state, 0x57, (unsigned char) (tmp >> 16));	stv0297_writereg(state, 0x58, (unsigned char) (tmp >> 24));}static void stv0297_set_sweeprate(struct stv0297_state *state, short fshift, long symrate){	long tmp;	tmp = (long) fshift *262144L;	/* 262144 = 2*18 */	tmp /= symrate;	tmp *= 1024;		/* 1024 = 2*10   */	// adjust	if (tmp >= 0) {		tmp += 500000;	} else {		tmp -= 500000;	}	tmp /= 1000000;	stv0297_writereg(state, 0x60, tmp & 0xFF);	stv0297_writereg_mask(state, 0x69, 0xF0, (tmp >> 4) & 0xf0);}static void stv0297_set_carrieroffset(struct stv0297_state *state, long offset){	long tmp;	/* symrate is hardcoded to 10000 */	tmp = offset * 26844L;	/* (2**28)/10000 */	if (tmp < 0)		tmp += 0x10000000;	tmp &= 0x0FFFFFFF;	stv0297_writereg(state, 0x66, (unsigned char) (tmp & 0xFF));	stv0297_writereg(state, 0x67, (unsigned char) (tmp >> 8));	stv0297_writereg(state, 0x68, (unsigned char) (tmp >> 16));	stv0297_writereg_mask(state, 0x69, 0x0F, (tmp >> 24) & 0x0f);}/*static long stv0297_get_carrieroffset(struct stv0297_state *state){	s64 tmp;	stv0297_writereg(state, 0x6B, 0x00);	tmp = stv0297_readreg(state, 0x66);	tmp |= (stv0297_readreg(state, 0x67) << 8);	tmp |= (stv0297_readreg(state, 0x68) << 16);	tmp |= (stv0297_readreg(state, 0x69) & 0x0F) << 24;	tmp *= stv0297_get_symbolrate(state);	tmp >>= 28;	return (s32) tmp;}*/static void stv0297_set_initialdemodfreq(struct stv0297_state *state, long freq){	s32 tmp;	if (freq > 10000)		freq -= STV0297_CLOCK_KHZ;	tmp = (STV0297_CLOCK_KHZ * 1000) / (1 << 16);	tmp = (freq * 1000) / tmp;	if (tmp > 0xffff)		tmp = 0xffff;	stv0297_writereg_mask(state, 0x25, 0x80, 0x80);	stv0297_writereg(state, 0x21, tmp >> 8);	stv0297_writereg(state, 0x20, tmp);}static int stv0297_set_qam(struct stv0297_state *state, fe_modulation_t modulation){	int val = 0;	switch (modulation) {	case QAM_16:		val = 0;		break;	case QAM_32:		val = 1;		break;	case QAM_64:		val = 4;		break;	case QAM_128:		val = 2;		break;	case QAM_256:		val = 3;		break;	default:		return -EINVAL;	}	stv0297_writereg_mask(state, 0x00, 0x70, val << 4);	return 0;}static int stv0297_set_inversion(struct stv0297_state *state, fe_spectral_inversion_t inversion){	int val = 0;	switch (inversion) {	case INVERSION_OFF:		val = 0;		break;	case INVERSION_ON:		val = 1;		break;	default:		return -EINVAL;	}	stv0297_writereg_mask(state, 0x83, 0x08, val << 3);	return 0;}int stv0297_enable_plli2c(struct dvb_frontend *fe){	struct stv0297_state *state = fe->demodulator_priv;	stv0297_writereg(state, 0x87, 0x78);	stv0297_writereg(state, 0x86, 0xc8);	return 0;}static int stv0297_init(struct dvb_frontend *fe){	struct stv0297_state *state = fe->demodulator_priv;	int i;	/* load init table */	for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2)		stv0297_writereg(state, state->config->inittab[i], state->config->inittab[i+1]);	msleep(200);	if (state->config->pll_init)		state->config->pll_init(fe);	return 0;}static int stv0297_sleep(struct dvb_frontend *fe){	struct stv0297_state *state = fe->demodulator_priv;	stv0297_writereg_mask(state, 0x80, 1, 1);	return 0;}static int stv0297_read_status(struct dvb_frontend *fe, fe_status_t * status){	struct stv0297_state *state = fe->demodulator_priv;	u8 sync = stv0297_readreg(state, 0xDF);	*status = 0;	if (sync & 0x80)		*status |=			FE_HAS_SYNC | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK;	return 0;}static int stv0297_read_ber(struct dvb_frontend *fe, u32 * ber){	struct stv0297_state *state = fe->demodulator_priv;	u8 BER[3];	stv0297_writereg(state, 0xA0, 0x80);	// Start Counting bit errors for 4096 Bytes	mdelay(25);		// Hopefully got 4096 Bytes	stv0297_readregs(state, 0xA0, BER, 3);	mdelay(25);	*ber = (BER[2] << 8 | BER[1]) / (8 * 4096);	return 0;}static int stv0297_read_signal_strength(struct dvb_frontend *fe, u16 * strength){	struct stv0297_state *state = fe->demodulator_priv;	u8 STRENGTH[2];

⌨️ 快捷键说明

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