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

📄 dst.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	Frontend/Card driver for TwinHan DST Frontend	Copyright (C) 2003 Jamie Honan	Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)	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 "dst_priv.h"#include "dst_common.h"static unsigned int verbose = 1;module_param(verbose, int, 0644);MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");static unsigned int dst_addons;module_param(dst_addons, int, 0644);MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");#define HAS_LOCK		1#define ATTEMPT_TUNE		2#define HAS_POWER		4#define DST_ERROR		0#define DST_NOTICE		1#define DST_INFO		2#define DST_DEBUG		3#define dprintk(x, y, z, format, arg...) do {						\	if (z) {									\		if	((x > DST_ERROR) && (x > y))					\			printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg);	\		else if	((x > DST_NOTICE) && (x > y))					\			printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg);	\		else if ((x > DST_INFO) && (x > y))					\			printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg);	\		else if ((x > DST_DEBUG) && (x > y))					\			printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg);	\	} else {									\		if (x > y)								\			printk(format, ##arg);						\	}										\} while(0)static void dst_packsize(struct dst_state *state, int psize){	union dst_gpio_packet bits;	bits.psize = psize;	bt878_device_control(state->bt, DST_IG_TS, &bits);}int dst_gpio_outb(struct dst_state *state, u32 mask, u32 enbb, u32 outhigh, int delay){	union dst_gpio_packet enb;	union dst_gpio_packet bits;	int err;	enb.enb.mask = mask;	enb.enb.enable = enbb;	dprintk(verbose, DST_INFO, 1, "mask=[%04x], enbb=[%04x], outhigh=[%04x]", mask, enbb, outhigh);	if ((err = bt878_device_control(state->bt, DST_IG_ENABLE, &enb)) < 0) {		dprintk(verbose, DST_INFO, 1, "dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)", err, mask, enbb);		return -EREMOTEIO;	}	udelay(1000);	/* because complete disabling means no output, no need to do output packet */	if (enbb == 0)		return 0;	if (delay)		msleep(10);	bits.outp.mask = enbb;	bits.outp.highvals = outhigh;	if ((err = bt878_device_control(state->bt, DST_IG_WRITE, &bits)) < 0) {		dprintk(verbose, DST_INFO, 1, "dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)", err, enbb, outhigh);		return -EREMOTEIO;	}	return 0;}EXPORT_SYMBOL(dst_gpio_outb);int dst_gpio_inb(struct dst_state *state, u8 *result){	union dst_gpio_packet rd_packet;	int err;	*result = 0;	if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) {		dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)\n", err);		return -EREMOTEIO;	}	*result = (u8) rd_packet.rd.value;	return 0;}EXPORT_SYMBOL(dst_gpio_inb);int rdc_reset_state(struct dst_state *state){	dprintk(verbose, DST_INFO, 1, "Resetting state machine");	if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, 0, NO_DELAY) < 0) {		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");		return -1;	}	msleep(10);	if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, RDC_8820_INT, NO_DELAY) < 0) {		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");		msleep(10);		return -1;	}	return 0;}EXPORT_SYMBOL(rdc_reset_state);int rdc_8820_reset(struct dst_state *state){	dprintk(verbose, DST_DEBUG, 1, "Resetting DST");	if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 0, NO_DELAY) < 0) {		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");		return -1;	}	udelay(1000);	if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, RDC_8820_RESET, DELAY) < 0) {		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");		return -1;	}	return 0;}EXPORT_SYMBOL(rdc_8820_reset);int dst_pio_enable(struct dst_state *state){	if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_ENABLE, 0, NO_DELAY) < 0) {		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");		return -1;	}	udelay(1000);	return 0;}EXPORT_SYMBOL(dst_pio_enable);int dst_pio_disable(struct dst_state *state){	if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_DISABLE, RDC_8820_PIO_0_DISABLE, NO_DELAY) < 0) {		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");		return -1;	}	if (state->type_flags & DST_TYPE_HAS_FW_1)		udelay(1000);	return 0;}EXPORT_SYMBOL(dst_pio_disable);int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode){	u8 reply;	int i;	for (i = 0; i < 200; i++) {		if (dst_gpio_inb(state, &reply) < 0) {			dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb ERROR !");			return -1;		}		if ((reply & RDC_8820_PIO_0_ENABLE) == 0) {			dprintk(verbose, DST_INFO, 1, "dst wait ready after %d", i);			return 1;		}		msleep(10);	}	dprintk(verbose, DST_NOTICE, 1, "dst wait NOT ready after %d", i);	return 0;}EXPORT_SYMBOL(dst_wait_dst_ready);int dst_error_recovery(struct dst_state *state){	dprintk(verbose, DST_NOTICE, 1, "Trying to return from previous errors.");	dst_pio_disable(state);	msleep(10);	dst_pio_enable(state);	msleep(10);	return 0;}EXPORT_SYMBOL(dst_error_recovery);int dst_error_bailout(struct dst_state *state){	dprintk(verbose, DST_INFO, 1, "Trying to bailout from previous error.");	rdc_8820_reset(state);	dst_pio_disable(state);	msleep(10);	return 0;}EXPORT_SYMBOL(dst_error_bailout);int dst_comm_init(struct dst_state *state){	dprintk(verbose, DST_INFO, 1, "Initializing DST.");	if ((dst_pio_enable(state)) < 0) {		dprintk(verbose, DST_ERROR, 1, "PIO Enable Failed");		return -1;	}	if ((rdc_reset_state(state)) < 0) {		dprintk(verbose, DST_ERROR, 1, "RDC 8820 State RESET Failed.");		return -1;	}	if (state->type_flags & DST_TYPE_HAS_FW_1)		msleep(100);	else		msleep(5);	return 0;}EXPORT_SYMBOL(dst_comm_init);int write_dst(struct dst_state *state, u8 *data, u8 len){	struct i2c_msg msg = {		.addr = state->config->demod_address,		.flags = 0,		.buf = data,		.len = len	};	int err;	u8 cnt, i;	dprintk(verbose, DST_NOTICE, 0, "writing [ ");	for (i = 0; i < len; i++)		dprintk(verbose, DST_NOTICE, 0, "%02x ", data[i]);	dprintk(verbose, DST_NOTICE, 0, "]\n");	for (cnt = 0; cnt < 2; cnt++) {		if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {			dprintk(verbose, DST_INFO, 1, "_write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)", err, len, data[0]);			dst_error_recovery(state);			continue;		} else			break;	}	if (cnt >= 2) {		dprintk(verbose, DST_INFO, 1, "RDC 8820 RESET");		dst_error_bailout(state);		return -1;	}	return 0;}EXPORT_SYMBOL(write_dst);int read_dst(struct dst_state *state, u8 *ret, u8 len){	struct i2c_msg msg = {		.addr = state->config->demod_address,		.flags = I2C_M_RD,		.buf = ret,		.len = len	};	int err;	int cnt;	for (cnt = 0; cnt < 2; cnt++) {		if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {			dprintk(verbose, DST_INFO, 1, "read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)", err, len, ret[0]);			dst_error_recovery(state);			continue;		} else			break;	}	if (cnt >= 2) {		dprintk(verbose, DST_INFO, 1, "RDC 8820 RESET");		dst_error_bailout(state);		return -1;	}	dprintk(verbose, DST_DEBUG, 1, "reply is 0x%x", ret[0]);	for (err = 1; err < len; err++)		dprintk(verbose, DST_DEBUG, 0, " 0x%x", ret[err]);	if (err > 1)		dprintk(verbose, DST_DEBUG, 0, "\n");	return 0;}EXPORT_SYMBOL(read_dst);static int dst_set_polarization(struct dst_state *state){	switch (state->voltage) {	case SEC_VOLTAGE_13:	/*	Vertical	*/		dprintk(verbose, DST_INFO, 1, "Polarization=[Vertical]");		state->tx_tuna[8] &= ~0x40;		break;	case SEC_VOLTAGE_18:	/*	Horizontal	*/		dprintk(verbose, DST_INFO, 1, "Polarization=[Horizontal]");		state->tx_tuna[8] |= 0x40;		break;	case SEC_VOLTAGE_OFF:		break;	}	return 0;}static int dst_set_freq(struct dst_state *state, u32 freq){	state->frequency = freq;	dprintk(verbose, DST_INFO, 1, "set Frequency %u", freq);	if (state->dst_type == DST_TYPE_IS_SAT) {		freq = freq / 1000;		if (freq < 950 || freq > 2150)			return -EINVAL;		state->tx_tuna[2] = (freq >> 8);		state->tx_tuna[3] = (u8) freq;		state->tx_tuna[4] = 0x01;		state->tx_tuna[8] &= ~0x04;		if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {			if (freq < 1531)				state->tx_tuna[8] |= 0x04;		}	} else if (state->dst_type == DST_TYPE_IS_TERR) {		freq = freq / 1000;		if (freq < 137000 || freq > 858000)			return -EINVAL;		state->tx_tuna[2] = (freq >> 16) & 0xff;		state->tx_tuna[3] = (freq >> 8) & 0xff;		state->tx_tuna[4] = (u8) freq;	} else if (state->dst_type == DST_TYPE_IS_CABLE) {		freq = freq / 1000;		state->tx_tuna[2] = (freq >> 16) & 0xff;		state->tx_tuna[3] = (freq >> 8) & 0xff;		state->tx_tuna[4] = (u8) freq;	} else		return -EINVAL;	return 0;}static int dst_set_bandwidth(struct dst_state *state, fe_bandwidth_t bandwidth){	state->bandwidth = bandwidth;	if (state->dst_type != DST_TYPE_IS_TERR)		return 0;	switch (bandwidth) {	case BANDWIDTH_6_MHZ:		if (state->dst_hw_cap & DST_TYPE_HAS_CA)			state->tx_tuna[7] = 0x06;		else {			state->tx_tuna[6] = 0x06;			state->tx_tuna[7] = 0x00;		}		break;	case BANDWIDTH_7_MHZ:		if (state->dst_hw_cap & DST_TYPE_HAS_CA)			state->tx_tuna[7] = 0x07;		else {			state->tx_tuna[6] = 0x07;			state->tx_tuna[7] = 0x00;		}		break;	case BANDWIDTH_8_MHZ:		if (state->dst_hw_cap & DST_TYPE_HAS_CA)			state->tx_tuna[7] = 0x08;		else {			state->tx_tuna[6] = 0x08;			state->tx_tuna[7] = 0x00;		}		break;	default:		return -EINVAL;	}	return 0;}static int dst_set_inversion(struct dst_state *state, fe_spectral_inversion_t inversion){	state->inversion = inversion;	switch (inversion) {	case INVERSION_OFF:	/*	Inversion = Normal	*/		state->tx_tuna[8] &= ~0x80;		break;	case INVERSION_ON:		state->tx_tuna[8] |= 0x80;		break;	default:		return -EINVAL;	}	return 0;}static int dst_set_fec(struct dst_state *state, fe_code_rate_t fec){	state->fec = fec;	return 0;}static fe_code_rate_t dst_get_fec(struct dst_state *state){	return state->fec;}static int dst_set_symbolrate(struct dst_state *state, u32 srate){	u32 symcalc;	u64 sval;	state->symbol_rate = srate;	if (state->dst_type == DST_TYPE_IS_TERR) {		return 0;	}	dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);	srate /= 1000;	if (state->type_flags & DST_TYPE_HAS_SYMDIV) {		sval = srate;		sval <<= 20;		do_div(sval, 88000);		symcalc = (u32) sval;		dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);		state->tx_tuna[5] = (u8) (symcalc >> 12);		state->tx_tuna[6] = (u8) (symcalc >> 4);		state->tx_tuna[7] = (u8) (symcalc << 4);	} else {		state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;		state->tx_tuna[6] = (u8) (srate >> 8);		state->tx_tuna[7] = (u8) srate;	}	state->tx_tuna[8] &= ~0x20;	if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {		if (srate > 8000)			state->tx_tuna[8] |= 0x20;	}	return 0;}static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation){	if (state->dst_type != DST_TYPE_IS_CABLE)		return 0;	state->modulation = modulation;	switch (modulation) {	case QAM_16:		state->tx_tuna[8] = 0x10;		break;	case QAM_32:		state->tx_tuna[8] = 0x20;		break;	case QAM_64:		state->tx_tuna[8] = 0x40;		break;	case QAM_128:		state->tx_tuna[8] = 0x80;		break;	case QAM_256:		state->tx_tuna[8] = 0x00;		break;	case QPSK:	case QAM_AUTO:	case VSB_8:	case VSB_16:	default:		return -EINVAL;	}

⌨️ 快捷键说明

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