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

📄 dst.c

📁 linux_dvb的驱动程序:linuxtv-dvb-1.1.1.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
/*     Frontend-driver for TwinHan DST Frontend    Copyright (C) 2003 Jamie Honan    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/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/string.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/delay.h>#include <asm/div64.h>#include "dvb_frontend.h"#include "dvb_functions.h"#include "dst-bt878.h"unsigned int dst_debug = 0;unsigned int dst_verbose = 0;MODULE_PARM(dst_verbose, "i");MODULE_PARM_DESC(dst_verbose,		 "verbose startup messages, default is 1 (yes)");MODULE_PARM(dst_debug, "i");MODULE_PARM_DESC(dst_debug, "debug messages, default is 0 (no)");#define DST_MAX_CARDS	6unsigned int dst_cur_no = 0;unsigned int dst_type[DST_MAX_CARDS] = { [0 ... (DST_MAX_CARDS-1)] = (-1U)};unsigned int dst_type_flags[DST_MAX_CARDS] = { [0 ... (DST_MAX_CARDS-1)] = (-1U)};MODULE_PARM(dst_type, "1-" __stringify(DST_MAX_CARDS) "i");MODULE_PARM_DESC(dst_type,		"Type of DST card, 0 Satellite, 1 terrestial TV, 2 Cable, default driver determined");MODULE_PARM(dst_type_flags, "1-" __stringify(DST_MAX_CARDS) "i");MODULE_PARM_DESC(dst_type_flags,		"Type flags of DST card, bitfield 1=10 byte tuner, 2=TS is 204, 4=symdiv");#define dprintk	if (dst_debug) printk#define DST_TYPE_IS_SAT		0#define DST_TYPE_IS_TERR	1#define DST_TYPE_IS_CABLE	2#define DST_TYPE_HAS_NEWTUNE	1#define DST_TYPE_HAS_TS204	2#define DST_TYPE_HAS_SYMDIV	4#define HAS_LOCK	1#define ATTEMPT_TUNE	2#define HAS_POWER	4struct dst_data {	u8	tx_tuna[10];	u8	rx_tuna[10];	u8	rxbuffer[10];	u8	diseq_flags;	u8	dst_type;	u32	type_flags;	u32 frequency;     /* intermediate frequency in kHz for QPSK */        fe_spectral_inversion_t inversion;        u32   symbol_rate;  /* symbol rate in Symbols per second */	fe_code_rate_t  fec;	fe_sec_voltage_t voltage;	fe_sec_tone_mode_t tone;	u32 decode_freq;	u8  decode_lock;	u16 decode_strength;	u16 decode_snr;	unsigned long cur_jiff;	u8  k22;	fe_bandwidth_t bandwidth;	struct bt878 *bt;	struct dvb_i2c_bus *i2c;} ;static struct dvb_frontend_info dst_info_sat = {	.name 			= "DST SAT",	.type 			= FE_QPSK,	.frequency_min 		= 950000,	.frequency_max 		= 2150000,	.frequency_stepsize 	= 1000,           /* kHz for QPSK frontends */	.frequency_tolerance 	= 29500,	.symbol_rate_min	= 1000000,	.symbol_rate_max	= 45000000,/*     . symbol_rate_tolerance	= 	???,*/	.notifier_delay		= 50,                /* 1/20 s */	.caps = FE_CAN_FEC_AUTO |		FE_CAN_QPSK};static struct dvb_frontend_info dst_info_cable = {	.name 			= "DST CABLE",	.type 			= FE_QAM,        .frequency_stepsize 	= 62500,	.frequency_min 		= 51000000,	.frequency_max 		= 858000000,	.symbol_rate_min	= 1000000,	.symbol_rate_max	= 45000000,/*     . symbol_rate_tolerance	= 	???,*/	.notifier_delay		= 50,                /* 1/20 s */	.caps = FE_CAN_FEC_AUTO |		FE_CAN_QAM_AUTO};static struct dvb_frontend_info dst_info_tv = {	.name 			= "DST TERR",	.type 			= FE_OFDM,	.frequency_min 		= 137000000,	.frequency_max 		= 858000000,	.frequency_stepsize 	= 166667,	.caps = FE_CAN_FEC_AUTO |	    FE_CAN_QAM_AUTO |	    FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO};static void dst_packsize(struct dst_data *dst, int psize){	union dst_gpio_packet bits;	bits.psize = psize;	bt878_device_control(dst->bt, DST_IG_TS, &bits);}static int dst_gpio_outb(struct dst_data *dst, u32 mask, u32 enbb, u32 outhigh){	union dst_gpio_packet enb;	union dst_gpio_packet bits;	int err;	enb.enb.mask = mask;	enb.enb.enable = enbb;        if ((err = bt878_device_control(dst->bt, DST_IG_ENABLE, &enb)) < 0) {		dprintk ("%s: dst_gpio_enb error (err == %i, mask == 0x%02x, enb == 0x%02x)\n", __FUNCTION__, err, mask, enbb);		return -EREMOTEIO;	}	/* because complete disabling means no output, no need to do	 * output packet */	if (enbb == 0)		return 0;	bits.outp.mask = enbb;	bits.outp.highvals = outhigh;        if ((err = bt878_device_control(dst->bt, DST_IG_WRITE, &bits)) < 0) {		dprintk ("%s: dst_gpio_outb error (err == %i, enbb == 0x%02x, outhigh == 0x%02x)\n", __FUNCTION__, err, enbb, outhigh);		return -EREMOTEIO;	}        return 0;}static int dst_gpio_inb(struct dst_data *dst, u8 *result){	union dst_gpio_packet rd_packet;	int err;	*result = 0;        if ((err = bt878_device_control(dst->bt, DST_IG_READ, &rd_packet)) < 0) {		dprintk ("%s: dst_gpio_inb error (err == %i)\n", __FUNCTION__, err);		return -EREMOTEIO;	}	*result = (u8)rd_packet.rd.value;        return 0;}#define DST_I2C_ENABLE	1#define DST_8820  	2static intdst_reset8820(struct dst_data *dst){int retval;	/* pull 8820 gpio pin low, wait, high, wait, then low */	// dprintk ("%s: reset 8820\n", __FUNCTION__);	retval = dst_gpio_outb(dst, DST_8820, DST_8820, 0);	if (retval < 0)		return retval;	dvb_delay(10);	retval = dst_gpio_outb(dst, DST_8820, DST_8820, DST_8820);	if (retval < 0)		return retval;	/* wait for more feedback on what works here *	dvb_delay(10);	retval = dst_gpio_outb(dst, DST_8820, DST_8820, 0);	if (retval < 0)		return retval;	*/	return 0;}static intdst_i2c_enable(struct dst_data *dst){int retval;	/* pull I2C enable gpio pin low, wait */	// dprintk ("%s: i2c enable\n", __FUNCTION__);	retval = dst_gpio_outb(dst, ~0, DST_I2C_ENABLE, 0);	if (retval < 0)		return retval;	// dprintk ("%s: i2c enable delay\n", __FUNCTION__);	dvb_delay(33);	return 0;}static intdst_i2c_disable(struct dst_data *dst){int retval;	/* release I2C enable gpio pin, wait */	// dprintk ("%s: i2c disable\n", __FUNCTION__);	retval = dst_gpio_outb(dst, ~0, 0, 0);	if (retval < 0)		return retval;	// dprintk ("%s: i2c disable delay\n", __FUNCTION__);	dvb_delay(33);	return 0;}static intdst_wait_dst_ready(struct dst_data *dst){u8 reply;int retval;int i;	for (i = 0; i < 200; i++) {		retval = dst_gpio_inb(dst, &reply);		if (retval < 0)			return retval;		if ((reply & DST_I2C_ENABLE) == 0) {			dprintk ("%s: dst wait ready after %d\n", __FUNCTION__, i);			return 1;		}		dvb_delay(5);	}	dprintk ("%s: dst wait NOT ready after %d\n", __FUNCTION__, i);	return 0;}#define DST_I2C_ADDR 0x55static int write_dst (struct dst_data *dst, u8 *data, u8 len){	struct i2c_msg msg = {		.addr = DST_I2C_ADDR, .flags = 0, .buf = data, .len = len };	int err;	int cnt;	if (dst_debug && dst_verbose) {		u8 i;		dprintk("%s writing",__FUNCTION__);		for (i = 0 ; i < len ; i++) {			dprintk(" 0x%02x", data[i]);		}		dprintk("\n");	}	dvb_delay(30);	for (cnt = 0; cnt < 4; cnt++) {		if ((err = dst->i2c->xfer (dst->i2c, &msg, 1)) < 0) {			dprintk ("%s: write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, data[0]);			dst_i2c_disable(dst);			dvb_delay(500);			dst_i2c_enable(dst);			dvb_delay(500);			continue;		} else			break;	}	if (cnt >= 4)		return -EREMOTEIO;        return 0;}static int read_dst (struct dst_data *dst, u8 *ret, u8 len){	struct i2c_msg msg = 		{ .addr = DST_I2C_ADDR, .flags = I2C_M_RD, .buf = ret, .len = len };	int err;	int cnt;	for (cnt = 0; cnt < 4; cnt++) {		if ((err = dst->i2c->xfer (dst->i2c, &msg, 1)) < 0) {			dprintk ("%s: read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, ret[0]);			dst_i2c_disable(dst);			dst_i2c_enable(dst);			continue;		} else			break;	}	if (cnt >= 4)		return -EREMOTEIO;	dprintk("%s reply is 0x%x\n", __FUNCTION__, ret[0]);	if (dst_debug && dst_verbose) {		for (err = 1; err < len; err++)			dprintk(" 0x%x", ret[err]);		if (err > 1)			dprintk("\n");	}	return 0;}static int dst_set_freq(struct dst_data *dst, u32 freq){	u8 *val;	dst->frequency = freq;	// dprintk("%s: set frequency %u\n", __FUNCTION__, freq);	if (dst->dst_type == DST_TYPE_IS_SAT) {		freq = freq / 1000;		if (freq < 950 || freq > 2150)			return -EINVAL;		val = &dst->tx_tuna[0];		val[2] = (freq >> 8) & 0x7f;		val[3] = (u8)freq;		val[4] = 1;		val[8] &= ~4;		if (freq < 1531)			val[8] |= 4;	} else if (dst->dst_type == DST_TYPE_IS_TERR) {		freq = freq / 1000;		if (freq < 137000 || freq > 858000)			return -EINVAL;		val = &dst->tx_tuna[0];		val[2] = (freq >> 16) & 0xff;		val[3] = (freq >> 8) & 0xff;		val[4] = (u8)freq;		val[5] = 0;		switch (dst->bandwidth) {		case BANDWIDTH_6_MHZ:			val[6] = 6;			break;		case BANDWIDTH_7_MHZ:		case BANDWIDTH_AUTO:			val[6] = 7;			break;		case BANDWIDTH_8_MHZ:			val[6] = 8;			break;		}		val[7] = 0;		val[8] = 0;	} else if (dst->dst_type == DST_TYPE_IS_CABLE) {		/* guess till will get one */		freq = freq / 1000;		val = &dst->tx_tuna[0];		val[2] = (freq >> 16) & 0xff;		val[3] = (freq >> 8) & 0xff;		val[4] = (u8)freq;	} else		return -EINVAL;	return 0;}static int dst_set_bandwidth(struct dst_data *dst, fe_bandwidth_t bandwidth){	u8 *val;	dst->bandwidth = bandwidth;	if (dst->dst_type != DST_TYPE_IS_TERR)		return 0;	val = &dst->tx_tuna[0];        switch (bandwidth) {	case BANDWIDTH_6_MHZ:		val[6] = 6;		break;	case BANDWIDTH_7_MHZ:		val[6] = 7;		break;	case BANDWIDTH_8_MHZ:		val[6] = 8;		break;	default:		return -EINVAL;	}	return 0;}static int dst_set_inversion (struct dst_data *dst, fe_spectral_inversion_t inversion){	u8 *val;	dst->inversion = inversion;	val = &dst->tx_tuna[0];	val[8] &= ~0x80;	switch (inversion) {	case INVERSION_OFF:		break;	case INVERSION_ON:		val[8] |= 0x80;		break;	default:		return -EINVAL;	}	return 0;}static int dst_set_fec (struct dst_data *dst, fe_code_rate_t fec){	dst->fec = fec;	return 0;}static fe_code_rate_t dst_get_fec (struct dst_data *dst){	return dst->fec;}static int dst_set_symbolrate (struct dst_data *dst, u32 srate){	u8 *val;	u32 symcalc;	u64 sval;	dst->symbol_rate = srate;	if (dst->dst_type == DST_TYPE_IS_TERR) {		return 0;	}	// dprintk("%s: set srate %u\n", __FUNCTION__, srate);	srate /= 1000;	val = &dst->tx_tuna[0];	if (dst->type_flags & DST_TYPE_HAS_SYMDIV) {		sval = srate;		sval <<= 20;		do_div(sval, 88000);	        symcalc = (u32)sval;		// dprintk("%s: set symcalc %u\n", __FUNCTION__, symcalc);		val[5] = (u8)(symcalc >> 12);		val[6] = (u8)(symcalc >> 4);		val[7] = (u8)(symcalc << 4);	} else {		val[5] = (u8)(srate >> 16) & 0x7f;		val[6] = (u8)(srate >> 8);		val[7] = (u8)srate;	}	val[8] &= ~0x20;	if (srate > 8000)		val[8] |= 0x20;	return 0;}static u8 dst_check_sum(u8 *buf, u32 len){	u32 i;	u8  val = 0;	if (!len)		return 0;	for (i = 0; i < len; i++) {		val += buf[i];	}	return ((~val) + 1);}typedef struct dst_types {	char	*mstr;	int	offs;	u8	dst_type;	u32	type_flags;} DST_TYPES;struct dst_types dst_tlist[] = {	{ "DST-020", 0,  DST_TYPE_IS_SAT,    DST_TYPE_HAS_SYMDIV },	{ "DST-030", 0,  DST_TYPE_IS_SAT,    DST_TYPE_HAS_TS204|DST_TYPE_HAS_NEWTUNE },	{ "DST-03T", 0,  DST_TYPE_IS_SAT,    DST_TYPE_HAS_SYMDIV|DST_TYPE_HAS_TS204},	{ "DST-MOT", 0,  DST_TYPE_IS_SAT,    DST_TYPE_HAS_SYMDIV },	{ "DST-CI",  1,  DST_TYPE_IS_SAT,    DST_TYPE_HAS_TS204|DST_TYPE_HAS_NEWTUNE },	{ "DSTMCI",  1,  DST_TYPE_IS_SAT,    DST_TYPE_HAS_NEWTUNE },	{ "DSTFCI",  1,  DST_TYPE_IS_SAT,    DST_TYPE_HAS_NEWTUNE },	{ "DCTNEW",  1,  DST_TYPE_IS_CABLE,  DST_TYPE_HAS_NEWTUNE },	{ "DCT_CI",  1,  DST_TYPE_IS_CABLE,  DST_TYPE_HAS_NEWTUNE|DST_TYPE_HAS_TS204 },	{ "DTTDIG" , 1,  DST_TYPE_IS_TERR,   0} };/* DCTNEW and DCT-CI are guesses */static void dst_type_flags_print(u32 type_flags){	printk("DST type flags :");	if (type_flags & DST_TYPE_HAS_NEWTUNE)		printk(" 0x%x newtuner", DST_TYPE_HAS_NEWTUNE);	if (type_flags & DST_TYPE_HAS_TS204)		printk(" 0x%x ts204", DST_TYPE_HAS_TS204);	if (type_flags & DST_TYPE_HAS_SYMDIV)		printk(" 0x%x symdiv", DST_TYPE_HAS_SYMDIV);	printk("\n");}static int dst_type_print(u8 type){	char *otype;	switch (type) {		case DST_TYPE_IS_SAT:			otype = "satellite";			break;		case DST_TYPE_IS_TERR:			otype = "terrestial TV";			break;		case DST_TYPE_IS_CABLE:			otype = "terrestial TV";			break;		default:			printk("%s: invalid dst type %d\n",				__FUNCTION__, type);			return -EINVAL;	}	printk("DST type : %s\n", otype);	return 0;}static int dst_check_ci (struct dst_data *dst){	u8 txbuf[8];	u8 rxbuf[8];	int retval;	int i;	struct dst_types *dsp;	u8 use_dst_type;	u32 use_type_flags;	memset(txbuf, 0, sizeof(txbuf));	txbuf[1] = 6;	txbuf[7] = dst_check_sum (txbuf, 7); 	dst_i2c_enable(dst);	dst_reset8820(dst);	retval = write_dst (dst, txbuf, 8);	if (retval < 0) {		dst_i2c_disable(dst);		dprintk("%s: write not successful, maybe no card?\n", __FUNCTION__);		return retval;	}	dvb_delay(3);	retval = read_dst (dst, rxbuf, 1);	dst_i2c_disable(dst);	if (retval < 0) {		dprintk("%s: read not successful, maybe no card?\n", __FUNCTION__);		return retval;	}	if (rxbuf[0] != 0xff) {		dprintk("%s: write reply not 0xff, not ci (%02x)\n", __FUNCTION__, rxbuf[0]);		return retval;	}	if (!dst_wait_dst_ready(dst))		return 0;	// dst_i2c_enable(i2c); Dimitri	retval = read_dst (dst, rxbuf, 8);	dst_i2c_disable(dst);	if (retval < 0) {		dprintk("%s: read not successful\n", __FUNCTION__);		return retval;	}	if (rxbuf[7] != dst_check_sum (rxbuf, 7)) {		dprintk("%s: checksum failure\n", __FUNCTION__);		return retval;	}	rxbuf[7] = '\0';	for (i = 0, dsp = &dst_tlist[0]; i < sizeof(dst_tlist) / sizeof(dst_tlist[0]); i++, dsp++) {		if (!strncmp(&rxbuf[dsp->offs],				dsp->mstr,				strlen(dsp->mstr))) {			use_type_flags = dsp->type_flags;

⌨️ 快捷键说明

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