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

📄 sp887x.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*   Driver for the Microtune 7202D Frontend*//*   This driver needs a copy of the Avermedia firmware. The version tested   is part of the Avermedia DVB-T 1.3.26.3 Application. If the software is   installed in Windows the file will be in the /Program Files/AVerTV DVB-T/   directory and is called sc_main.mc. Alternatively it can "extracted" from   the install cab files. Copy this file to '/usr/lib/hotplug/firmware/sc_main.mc'.   With this version of the file the first 10 bytes are discarded and the   next 0x4000 loaded. This may change in future versions. */#include <linux/kernel.h>#include <linux/vmalloc.h>#include <linux/module.h>#include <linux/init.h>#include <linux/string.h>#include <linux/slab.h>#include <linux/fs.h>#include <linux/unistd.h>#include <linux/fcntl.h>#include <linux/errno.h>#include <linux/i2c.h>#include <linux/syscalls.h>#include "dvb_frontend.h"#include "dvb_functions.h"#ifndef DVB_SP887X_FIRMWARE_FILE#define DVB_SP887X_FIRMWARE_FILE "/usr/lib/hotplug/firmware/sc_main.mc"#endifstatic char *sp887x_firmware = DVB_SP887X_FIRMWARE_FILE;#if 0#define dprintk(x...) printk(x)#else#define dprintk(x...)#endif#if 0#define LOG(dir,addr,buf,len) 					\	do {							\		int i;						\		printk("%s (%02x):", dir, addr & 0xff);		\		for (i=0; i<len; i++)				\			printk(" 0x%02x,", buf[i] & 0xff);	\		printk("\n");					\	} while (0)#else#define LOG(dir,addr,buf,len)#endifstaticstruct dvb_frontend_info sp887x_info = {	.name = "Microtune MT7202DTF",	.type = FE_OFDM,	.frequency_min =  50500000,	.frequency_max = 858000000,	.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_RECOVER};static int errno;staticint i2c_writebytes (struct dvb_frontend *fe, u8 addr, u8 *buf, u8 len){	struct dvb_i2c_bus *i2c = fe->i2c;	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = len };	int err;	LOG("i2c_writebytes", msg.addr, msg.buf, msg.len);	if ((err = i2c->xfer (i2c, &msg, 1)) != 1) {		printk ("%s: i2c write error (addr %02x, err == %i)\n",			__FUNCTION__, addr, err);		return -EREMOTEIO;	}	return 0;}staticint sp887x_writereg (struct dvb_frontend *fe, u16 reg, u16 data){	struct dvb_i2c_bus *i2c = fe->i2c;	u8 b0 [] = { reg >> 8 , reg & 0xff, data >> 8, data & 0xff };	struct i2c_msg msg = { .addr = 0x70, .flags = 0, .buf = b0, .len = 4 };	int ret;	LOG("sp887x_writereg", msg.addr, msg.buf, msg.len);	if ((ret = i2c->xfer(i2c, &msg, 1)) != 1) {		/**		 *  in case of soft reset we ignore ACK errors...		 */		if (!(reg == 0xf1a && data == 0x000 && 			(ret == -EREMOTEIO || ret == -EFAULT)))		{			printk("%s: writereg error "			       "(reg %03x, data %03x, ret == %i)\n",			       __FUNCTION__, reg & 0xffff, data & 0xffff, ret);			return ret;		}	}	return 0;}staticu16 sp887x_readreg (struct dvb_frontend *fe, u16 reg){	struct dvb_i2c_bus *i2c = fe->i2c;	u8 b0 [] = { reg >> 8 , reg & 0xff };	u8 b1 [2];	int ret;	struct i2c_msg msg[] = {{ .addr = 0x70, .flags = 0, .buf = b0, .len = 2 },		         { .addr = 0x70, .flags = I2C_M_RD, .buf = b1, .len = 2 }};	LOG("sp887x_readreg (w)", msg[0].addr, msg[0].buf, msg[0].len);	LOG("sp887x_readreg (r)", msg[1].addr, msg[1].buf, msg[1].len);	if ((ret = i2c->xfer(i2c, msg, 2)) != 2)		printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);	return (((b1[0] << 8) | b1[1]) & 0xfff);}staticvoid sp887x_microcontroller_stop (struct dvb_frontend *fe){	dprintk("%s\n", __FUNCTION__);	sp887x_writereg(fe, 0xf08, 0x000);	sp887x_writereg(fe, 0xf09, 0x000);			/* microcontroller STOP */	sp887x_writereg(fe, 0xf00, 0x000);}staticvoid sp887x_microcontroller_start (struct dvb_frontend *fe){	dprintk("%s\n", __FUNCTION__);	sp887x_writereg(fe, 0xf08, 0x000);	sp887x_writereg(fe, 0xf09, 0x000);			/* microcontroller START */	sp887x_writereg(fe, 0xf00, 0x001);}staticvoid sp887x_setup_agc (struct dvb_frontend *fe){	/* setup AGC parameters */	dprintk("%s\n", __FUNCTION__);	sp887x_writereg(fe, 0x33c, 0x054);	sp887x_writereg(fe, 0x33b, 0x04c);	sp887x_writereg(fe, 0x328, 0x000);	sp887x_writereg(fe, 0x327, 0x005);	sp887x_writereg(fe, 0x326, 0x001);	sp887x_writereg(fe, 0x325, 0x001);	sp887x_writereg(fe, 0x324, 0x001);	sp887x_writereg(fe, 0x318, 0x050);	sp887x_writereg(fe, 0x317, 0x3fe);	sp887x_writereg(fe, 0x316, 0x001);	sp887x_writereg(fe, 0x313, 0x005);	sp887x_writereg(fe, 0x312, 0x002);	sp887x_writereg(fe, 0x306, 0x000);	sp887x_writereg(fe, 0x303, 0x000);}#define BLOCKSIZE 30/** *  load firmware and setup MPEG interface... */staticint sp887x_initial_setup (struct dvb_frontend *fe){	u8 buf [BLOCKSIZE+2];	unsigned char *firmware = NULL;	int i;	int fd;	int filesize;	int fw_size;	mm_segment_t fs;	dprintk("%s\n", __FUNCTION__);	/* soft reset */	sp887x_writereg(fe, 0xf1a, 0x000);	sp887x_microcontroller_stop (fe);	fs = get_fs();	// Load the firmware	set_fs(get_ds());	fd = sys_open(sp887x_firmware, 0, 0);	if (fd < 0) {		printk(KERN_WARNING "%s: Unable to open firmware %s\n", __FUNCTION__,		       sp887x_firmware);		return -EIO;	}	filesize = sys_lseek(fd, 0L, 2);	if (filesize <= 0) {		printk(KERN_WARNING "%s: Firmware %s is empty\n", __FUNCTION__,		       sp887x_firmware);		sys_close(fd);		return -EIO;	}	fw_size = 0x4000;	// allocate buffer for it	firmware = vmalloc(fw_size);	if (firmware == NULL) {		printk(KERN_WARNING "%s: Out of memory loading firmware\n",		       __FUNCTION__);		sys_close(fd);		return -EIO;	}	// read it!	// read the first 16384 bytes from the file	// ignore the first 10 bytes	sys_lseek(fd, 10, 0);	if (sys_read(fd, firmware, fw_size) != fw_size) {		printk(KERN_WARNING "%s: Failed to read firmware\n", __FUNCTION__);		vfree(firmware);		sys_close(fd);		return -EIO;	}	sys_close(fd);	set_fs(fs);	printk ("%s: firmware upload... ", __FUNCTION__);	/* setup write pointer to -1 (end of memory) */	/* bit 0x8000 in address is set to enable 13bit mode */	sp887x_writereg(fe, 0x8f08, 0x1fff);	/* dummy write (wrap around to start of memory) */	sp887x_writereg(fe, 0x8f0a, 0x0000);	for (i=0; i<fw_size; i+=BLOCKSIZE) {		int c = BLOCKSIZE;		int err;		if (i+c > fw_size)			c = fw_size - i;		/* bit 0x8000 in address is set to enable 13bit mode */		/* bit 0x4000 enables multibyte read/write transfers */		/* write register is 0xf0a */		buf[0] = 0xcf;		buf[1] = 0x0a;		memcpy(&buf[2], firmware + i, c);		if ((err = i2c_writebytes (fe, 0x70, buf, c+2)) < 0) {			printk ("failed.\n");			printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);			vfree(firmware);			return err;		}	}	vfree(firmware);	/* don't write RS bytes between packets */	sp887x_writereg(fe, 0xc13, 0x001);	/* suppress clock if (!data_valid) */	sp887x_writereg(fe, 0xc14, 0x000);	/* setup MPEG interface... */	sp887x_writereg(fe, 0xc1a, 0x872);	sp887x_writereg(fe, 0xc1b, 0x001);	sp887x_writereg(fe, 0xc1c, 0x000); /* parallel mode (serial mode == 1) */	sp887x_writereg(fe, 0xc1a, 0x871);	/* ADC mode, 2 for MT8872, 3 for SP8870/SP8871 */	sp887x_writereg(fe, 0x301, 0x002);	sp887x_setup_agc(fe);	/* bit 0x010: enable data valid signal */	sp887x_writereg(fe, 0xd00, 0x010);	sp887x_writereg(fe, 0x0d1, 0x000);	printk ("done.\n");	return 0;};/** *  returns the actual tuned center frequency which can be used *  to initialise the AFC registers */staticint tsa5060_setup_pll (struct dvb_frontend *fe, int freq){	u8 cfg, cpump, band_select;	u8 buf [4];	u32 div;	div = (36000000 + freq + 83333) / 166666;	cfg = 0x88;	cpump = freq < 175000000 ? 2 : freq < 390000000 ? 1 :		freq < 470000000 ? 2 : freq < 750000000 ? 2 : 3;	band_select = freq < 175000000 ? 0x0e : freq < 470000000 ? 0x05 : 0x03;	buf [0] = (div >> 8) & 0x7f;	buf [1] = div & 0xff;	buf [2] = ((div >> 10) & 0x60) | cfg;	buf [3] = cpump | band_select;	/* open i2c gate for PLL message transmission... */	sp887x_writereg(fe, 0x206, 0x001);	i2c_writebytes(fe, 0x60, buf, 4);	sp887x_writereg(fe, 0x206, 0x000);	return (div * 166666 - 36000000);}staticint configure_reg0xc05 (struct dvb_frontend_parameters *p, u16 *reg0xc05){	int known_parameters = 1;		*reg0xc05 = 0x000;

⌨️ 快捷键说明

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