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

📄 alps_tdlb7.c

📁 linux_dvb的驱动程序:linuxtv-dvb-1.1.1.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Driver for Alps TDLB7 Frontend    Copyright (C) 1999 Juergen Peitz    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.*//*    This driver needs a copy of the firmware file 'Sc_main.mc' from the Haupauge    windows driver in the '/usr/lib/DVB/driver/frontends' directory.    You can also pass the complete file name with the module parameter 'firmware_file'.*/#define __KERNEL_SYSCALLS__#include <linux/module.h>#include <linux/init.h>#include <linux/vmalloc.h>#include <linux/fs.h>#include <linux/unistd.h>#include <linux/delay.h>#include "dvb_frontend.h"#include "dvb_functions.h"#ifndef CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION#define CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION "/usr/lib/DVB/driver/frontends/Sc_main.mc"#endifstatic char * firmware_file = CONFIG_ALPS_TDLB7_FIRMWARE_LOCATION;static int debug = 0;#define dprintk	if (debug) printk/* firmware size for sp8870 */#define SP8870_FIRMWARE_SIZE 16382/* starting point for firmware in file 'Sc_main.mc' */#define SP8870_FIRMWARE_OFFSET 0x0Astatic int errno;static struct dvb_frontend_info tdlb7_info = {	name: "Alps TDLB7",	type: FE_OFDM,	frequency_min: 470000000,	frequency_max: 860000000,	frequency_stepsize: 166666,	caps: FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |	      FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |	      FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |	      FE_CAN_HIERARCHY_AUTO |  FE_CAN_RECOVER};static int sp8870_writereg (struct dvb_i2c_bus *i2c, u16 reg, u16 data){        u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff };	struct i2c_msg msg = { addr: 0x71, flags: 0, buf: buf, len: 4 };	int err;        if ((err = i2c->xfer (i2c, &msg, 1)) != 1) {		dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data);		return -EREMOTEIO;	}        return 0;}static u16 sp8870_readreg (struct dvb_i2c_bus *i2c, u16 reg){	int ret;	u8 b0 [] = { reg >> 8 , reg & 0xff };	u8 b1 [] = { 0, 0 };	struct i2c_msg msg [] = { { addr: 0x71, flags: 0, buf: b0, len: 2 },			   { addr: 0x71, flags: I2C_M_RD, buf: b1, len: 2 } };	ret = i2c->xfer (i2c, msg, 2);	if (ret != 2) {		dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);		return -1;	}	return (b1[0] << 8 | b1[1]);}static int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4]){        int ret;        struct i2c_msg msg = { addr: 0x60, flags: 0, buf: data, len: 4 };        ret = i2c->xfer (i2c, &msg, 1);        if (ret != 1)                printk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret);        return (ret != 1) ? -1 : 0;}static void sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq){        u32 div = (freq + 36200000) / 166666;        u8 buf [4];	int pwr;	if (freq <= 782000000)		pwr = 1;	else		pwr = 2;	buf[0] = (div >> 8) & 0x7f;	buf[1] = div & 0xff;	buf[2] = 0x85;	buf[3] = pwr << 6;	/* open i2c gate for PLL message transmission... */	sp8870_writereg(i2c, 0x206, 0x001);	sp5659_write (i2c, buf);	sp8870_writereg(i2c, 0x206, 0x000);}static int sp8870_read_firmware_file (const char *fn, char **fp){        int fd;	loff_t filesize;	char *dp;	fd = open(fn, 0, 0);	if (fd == -1) {                printk("%s: unable to open '%s'.\n", __FUNCTION__, fn);		return -EIO;	}	filesize = lseek(fd, 0L, 2);	if (filesize <= 0 || filesize < SP8870_FIRMWARE_OFFSET + SP8870_FIRMWARE_SIZE) {	        printk("%s: firmware filesize to small '%s'\n", __FUNCTION__, fn);		sys_close(fd);		return -EIO;	}	*fp= dp = vmalloc(SP8870_FIRMWARE_SIZE);	if (dp == NULL)	{		printk("%s: out of memory loading '%s'.\n", __FUNCTION__, fn);		sys_close(fd);		return -EIO;	}	lseek(fd, SP8870_FIRMWARE_OFFSET, 0);	if (read(fd, dp, SP8870_FIRMWARE_SIZE) != SP8870_FIRMWARE_SIZE) {		printk("%s: failed to read '%s'.\n",__FUNCTION__, fn);		vfree(dp);		sys_close(fd);		return -EIO;	}	sys_close(fd);	*fp = dp;	return 0;}static int sp8870_firmware_upload (struct dvb_i2c_bus *i2c){	struct i2c_msg msg;	char *fw_buf = NULL;	int fw_pos;	u8 tx_buf[255];	int tx_len;	int err = 0;	mm_segment_t fs = get_fs();	dprintk ("%s: ...\n", __FUNCTION__);	// system controller stop	sp8870_writereg(i2c, 0x0F00, 0x0000);	// instruction RAM register hiword	sp8870_writereg(i2c, 0x8F08, ((SP8870_FIRMWARE_SIZE / 2) & 0xFFFF));	// instruction RAM MWR	sp8870_writereg(i2c, 0x8F0A, ((SP8870_FIRMWARE_SIZE / 2) >> 16));	// reading firmware file to buffer	set_fs(get_ds());        err = sp8870_read_firmware_file(firmware_file, (char**) &fw_buf);	set_fs(fs);	if (err != 0) {		printk("%s: reading firmware file failed!\n", __FUNCTION__);		return err;	}	// do firmware upload	fw_pos = 0;	while (fw_pos < SP8870_FIRMWARE_SIZE){		tx_len = (fw_pos <= SP8870_FIRMWARE_SIZE - 252) ? 252 : SP8870_FIRMWARE_SIZE - fw_pos;		// write register 0xCF0A		tx_buf[0] = 0xCF;		tx_buf[1] = 0x0A;		memcpy(&tx_buf[2], fw_buf + fw_pos, tx_len);		msg.addr = 0x71;		msg.flags = 0;		msg.buf = tx_buf;		msg.len = tx_len + 2;        	if ((err = i2c->xfer (i2c, &msg, 1)) != 1) {			printk("%s: firmware upload failed!\n", __FUNCTION__);			printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);        		vfree(fw_buf);			return err;		}		fw_pos += tx_len;	}	vfree(fw_buf);	dprintk ("%s: done!\n", __FUNCTION__);	return 0;};static void sp8870_microcontroller_stop (struct dvb_i2c_bus *i2c){	sp8870_writereg(i2c, 0x0F08, 0x000);	sp8870_writereg(i2c, 0x0F09, 0x000);	// microcontroller STOP	sp8870_writereg(i2c, 0x0F00, 0x000);}static void sp8870_microcontroller_start (struct dvb_i2c_bus *i2c){	sp8870_writereg(i2c, 0x0F08, 0x000);	sp8870_writereg(i2c, 0x0F09, 0x000);	// microcontroller START	sp8870_writereg(i2c, 0x0F00, 0x001);	// not documented but if we don't read 0x0D01 out here	// we don't get a correct data valid signal	sp8870_readreg(i2c, 0x0D01);}static int sp8870_init (struct dvb_i2c_bus *i2c){	dprintk ("%s\n", __FUNCTION__);	/* enable TS output and interface pins */	sp8870_writereg(i2c, 0xc18, 0x00d);	// system controller stop	sp8870_microcontroller_stop(i2c);	// ADC mode	sp8870_writereg(i2c, 0x0301, 0x0003);	// Reed Solomon parity bytes passed to output	sp8870_writereg(i2c, 0x0C13, 0x0001);	// MPEG clock is suppressed if no valid data	sp8870_writereg(i2c, 0x0C14, 0x0001);	/* bit 0x010: enable data valid signal */	sp8870_writereg(i2c, 0x0D00, 0x010);	sp8870_writereg(i2c, 0x0D01, 0x000);	return 0;}static int sp8870_read_status (struct dvb_i2c_bus *i2c,  fe_status_t * fe_status){	int status;	int signal;	*fe_status = 0;	status = sp8870_readreg (i2c, 0x0200);	if (status < 0)		return -EIO;	signal = sp8870_readreg (i2c, 0x0303);	if (signal < 0)		return -EIO;	if (signal > 0x0F)		*fe_status |= FE_HAS_SIGNAL;	if (status & 0x08)		*fe_status |= FE_HAS_SYNC;	if (status & 0x04)		*fe_status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_VITERBI;	return 0;}static int sp8870_read_ber (struct dvb_i2c_bus *i2c, u32 * ber){	int ret;	u32 tmp;	*ber = 0;	ret = sp8870_readreg(i2c, 0xC08);	if (ret < 0)		return -EIO;	tmp = ret & 0x3F;	ret = sp8870_readreg(i2c, 0xC07);	if (ret < 0)		return -EIO;	 tmp = ret << 6;	if (tmp >= 0x3FFF0)		tmp = ~0;	*ber = tmp;	return 0;}static int sp8870_read_signal_strength (struct dvb_i2c_bus *i2c,  u16 * signal){	int ret;	u16 tmp;	*signal = 0;	ret = sp8870_readreg (i2c, 0x306);	if (ret < 0)		return -EIO;	tmp = ret << 8;	ret = sp8870_readreg (i2c, 0x303);

⌨️ 快捷键说明

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