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

📄 af9015.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver * * Copyright (C) 2007 Antti Palosaari <crope@iki.fi> * * Thanks to Afatech who kindly provided information. * *    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 "af9015.h"#include "af9013.h"#include "mt2060.h"#include "qt1010.h"#include "tda18271.h"#include "mxl5005s.h"#if 0 /* keep */#include "mc44s80x.h"#endifint dvb_usb_af9015_debug;module_param_named(debug, dvb_usb_af9015_debug, int, 0644);MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);int dvb_usb_af9015_remote;module_param_named(remote, dvb_usb_af9015_remote, int, 0644);MODULE_PARM_DESC(remote, "select remote");int dvb_usb_af9015_dual_mode;module_param_named(dual_mode, dvb_usb_af9015_dual_mode, int, 0644);MODULE_PARM_DESC(dual_mode, "enable dual mode");DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);static DEFINE_MUTEX(af9015_usb_mutex);static struct af9015_config af9015_config;static struct dvb_usb_device_properties af9015_properties[2];int af9015_properties_count = ARRAY_SIZE(af9015_properties);static struct af9013_config af9015_af9013_config[] = {	{		.demod_address = AF9015_I2C_DEMOD,		.output_mode = AF9013_OUTPUT_MODE_USB,		.api_version = { 0, 1, 9, 0 },		.gpio[0] = AF9013_GPIO_HI,		.gpio[3] = AF9013_GPIO_TUNER_ON,	}, {		.output_mode = AF9013_OUTPUT_MODE_SERIAL,		.api_version = { 0, 1, 9, 0 },		.gpio[0] = AF9013_GPIO_TUNER_ON,		.gpio[1] = AF9013_GPIO_LO,	}};static int af9015_rw_udev(struct usb_device *udev, struct req_t *req){	int act_len, ret;	u8 buf[64];	u8 write = 1;	u8 msg_len = 8;	static u8 seq; /* packet sequence number */	if (mutex_lock_interruptible(&af9015_usb_mutex) < 0)		return -EAGAIN;	buf[0] = req->cmd;	buf[1] = seq++;	buf[2] = req->i2c_addr;	buf[3] = req->addr >> 8;	buf[4] = req->addr & 0xff;	buf[5] = req->mbox;	buf[6] = req->addr_len;	buf[7] = req->data_len;	switch (req->cmd) {	case GET_CONFIG:	case BOOT:	case READ_MEMORY:	case RECONNECT_USB:	case GET_IR_CODE:		write = 0;		break;	case READ_I2C:		write = 0;		buf[2] |= 0x01; /* set I2C direction */	case WRITE_I2C:		buf[0] = READ_WRITE_I2C;		break;	case WRITE_MEMORY:		if (((req->addr & 0xff00) == 0xff00) ||		    ((req->addr & 0xae00) == 0xae00))			buf[0] = WRITE_VIRTUAL_MEMORY;	case WRITE_VIRTUAL_MEMORY:	case COPY_FIRMWARE:	case DOWNLOAD_FIRMWARE:		break;	default:		err("unknown command:%d", req->cmd);		ret = -1;		goto error_unlock;	}	/* write requested */	if (write) {		memcpy(&buf[8], req->data, req->data_len);		msg_len += req->data_len;	}	deb_xfer(">>> ");	debug_dump(buf, msg_len, deb_xfer);	/* send req */	ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len,	&act_len, AF9015_USB_TIMEOUT);	if (ret)		err("bulk message failed:%d (%d/%d)", ret, msg_len, act_len);	else		if (act_len != msg_len)			ret = -1; /* all data is not send */	if (ret)		goto error_unlock;	/* no ack for those packets */	if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB)		goto exit_unlock;	/* receive ack and data if read req */	msg_len = 1 + 1 + req->data_len;  /* seq + status + data len */	ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len,			   &act_len, AF9015_USB_TIMEOUT);	if (ret) {		err("recv bulk message failed:%d", ret);		ret = -1;		goto error_unlock;	}	deb_xfer("<<< ");	debug_dump(buf, act_len, deb_xfer);	/* remote controller query status is 1 if remote code is not received */	if (req->cmd == GET_IR_CODE && buf[1] == 1) {		buf[1] = 0; /* clear command "error" status */		memset(&buf[2], 0, req->data_len);		buf[3] = 1; /* no remote code received mark */	}	/* check status */	if (buf[1]) {		err("command failed:%d", buf[1]);		ret = -1;		goto error_unlock;	}	/* read request, copy returned data to return buf */	if (!write)		memcpy(req->data, &buf[2], req->data_len);error_unlock:exit_unlock:	mutex_unlock(&af9015_usb_mutex);	return ret;}static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req){	return af9015_rw_udev(d->udev, req);}static int af9015_write_regs(struct dvb_usb_device *d, u16 addr, u8 *val,	u8 len){	struct req_t req = {WRITE_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len,		val};	return af9015_ctrl_msg(d, &req);}static int af9015_write_reg(struct dvb_usb_device *d, u16 addr, u8 val){	return af9015_write_regs(d, addr, &val, 1);}static int af9015_read_reg(struct dvb_usb_device *d, u16 addr, u8 *val){	struct req_t req = {READ_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, 1, val};	return af9015_ctrl_msg(d, &req);}static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,	u8 val){	struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val};	if (addr == af9015_af9013_config[0].demod_address ||	    addr == af9015_af9013_config[1].demod_address)		req.addr_len = 3;	return af9015_ctrl_msg(d, &req);}static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,	u8 *val){	struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val};	if (addr == af9015_af9013_config[0].demod_address ||	    addr == af9015_af9013_config[1].demod_address)		req.addr_len = 3;	return af9015_ctrl_msg(d, &req);}static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],	int num){	struct dvb_usb_device *d = i2c_get_adapdata(adap);	int ret = 0, i = 0;	u16 addr;	u8 mbox, addr_len;	struct req_t req;/* TODO: implement bus lockThe bus lock is needed because there is two tuners both using same I2C-address.Due to that the only way to select correct tuner is use demodulator I2C-gate.................................................. AF9015 includes integrated AF9013 demodulator.. ____________                   ____________  .                ____________.|     uC     |                 |   demod    | .               |    tuner   |.|------------|                 |------------| .               |------------|.|   AF9015   |                 |  AF9013/5  | .               |   MXL5003  |.|            |--+----I2C-------|-----/ -----|-.-----I2C-------|            |.|            |  |              | addr 0x38  | .               |  addr 0xc6 |.|____________|  |              |____________| .               |____________|.................|..............................		 |               ____________                   ____________		 |              |   demod    |                 |    tuner   |		 |              |------------|                 |------------|		 |              |   AF9013   |                 |   MXL5003  |		 +----I2C-------|-----/ -----|-------I2C-------|            |				| addr 0x3a  |                 |  addr 0xc6 |				|____________|                 |____________|*/	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)		return -EAGAIN;	while (i < num) {		if (msg[i].addr == af9015_af9013_config[0].demod_address ||		    msg[i].addr == af9015_af9013_config[1].demod_address) {			addr = msg[i].buf[0] << 8;			addr += msg[i].buf[1];			mbox = msg[i].buf[2];			addr_len = 3;		} else {			addr = msg[i].buf[0];			addr_len = 1;			mbox = 0;		}		if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {			if (msg[i].addr ==				af9015_af9013_config[0].demod_address)				req.cmd = READ_MEMORY;			else				req.cmd = READ_I2C;			req.i2c_addr = msg[i].addr;			req.addr = addr;			req.mbox = mbox;			req.addr_len = addr_len;			req.data_len = msg[i+1].len;			req.data = &msg[i+1].buf[0];			ret = af9015_ctrl_msg(d, &req);			i += 2;		} else {			if (msg[i].addr ==				af9015_af9013_config[0].demod_address)				req.cmd = WRITE_MEMORY;			else				req.cmd = WRITE_I2C;			req.i2c_addr = msg[i].addr;			req.addr = addr;			req.mbox = mbox;			req.addr_len = addr_len;			req.data_len = msg[i].len-addr_len;			req.data = &msg[i].buf[addr_len];			ret = af9015_ctrl_msg(d, &req);			i += 1;		}		if (ret)			goto error;	}	ret = i;error:	mutex_unlock(&d->i2c_mutex);	return ret;}static u32 af9015_i2c_func(struct i2c_adapter *adapter){	return I2C_FUNC_I2C;}static struct i2c_algorithm af9015_i2c_algo = {	.master_xfer = af9015_i2c_xfer,	.functionality = af9015_i2c_func,};static int af9015_do_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit, u8 op){	int ret;	u8 val, mask = 0x01;	ret = af9015_read_reg(d, addr, &val);	if (ret)		return ret;	mask <<= bit;	if (op) {		/* set bit */		val |= mask;	} else {		/* clear bit */		mask ^= 0xff;		val &= mask;	}	return af9015_write_reg(d, addr, val);}static int af9015_set_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit){	return af9015_do_reg_bit(d, addr, bit, 1);}static int af9015_clear_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit){	return af9015_do_reg_bit(d, addr, bit, 0);}static int af9015_init_endpoint(struct dvb_usb_device *d){	int ret;	u16 frame_size;	u8  packet_size;	deb_info("%s: USB speed:%d\n", __func__, d->udev->speed);#define TS_PACKET_SIZE            188#define TS_USB20_PACKET_COUNT     348#define TS_USB20_FRAME_SIZE       (TS_PACKET_SIZE*TS_USB20_PACKET_COUNT)#define TS_USB11_PACKET_COUNT      21#define TS_USB11_FRAME_SIZE       (TS_PACKET_SIZE*TS_USB11_PACKET_COUNT)#define TS_USB20_MAX_PACKET_SIZE  512#define TS_USB11_MAX_PACKET_SIZE   64	if (d->udev->speed == USB_SPEED_FULL) {		frame_size = TS_USB11_FRAME_SIZE/4;		packet_size = TS_USB11_MAX_PACKET_SIZE/4;	} else {		frame_size = TS_USB20_FRAME_SIZE/4;		packet_size = TS_USB20_MAX_PACKET_SIZE/4;	}	ret = af9015_set_reg_bit(d, 0xd507, 2); /* assert EP4 reset */	if (ret)		goto error;	ret = af9015_set_reg_bit(d, 0xd50b, 1); /* assert EP5 reset */	if (ret)		goto error;	ret = af9015_clear_reg_bit(d, 0xdd11, 5); /* disable EP4 */	if (ret)		goto error;	ret = af9015_clear_reg_bit(d, 0xdd11, 6); /* disable EP5 */	if (ret)		goto error;	ret = af9015_set_reg_bit(d, 0xdd11, 5); /* enable EP4 */	if (ret)		goto error;	if (af9015_config.dual_mode) {		ret = af9015_set_reg_bit(d, 0xdd11, 6); /* enable EP5 */		if (ret)			goto error;	}	ret = af9015_clear_reg_bit(d, 0xdd13, 5); /* disable EP4 NAK */	if (ret)		goto error;	if (af9015_config.dual_mode) {		ret = af9015_clear_reg_bit(d, 0xdd13, 6); /* disable EP5 NAK */		if (ret)			goto error;	}	/* EP4 xfer length */	ret = af9015_write_reg(d, 0xdd88, frame_size & 0xff);	if (ret)		goto error;	ret = af9015_write_reg(d, 0xdd89, frame_size >> 8);	if (ret)		goto error;	/* EP5 xfer length */	ret = af9015_write_reg(d, 0xdd8a, frame_size & 0xff);	if (ret)		goto error;	ret = af9015_write_reg(d, 0xdd8b, frame_size >> 8);	if (ret)		goto error;	ret = af9015_write_reg(d, 0xdd0c, packet_size); /* EP4 packet size */	if (ret)		goto error;	ret = af9015_write_reg(d, 0xdd0d, packet_size); /* EP5 packet size */	if (ret)		goto error;	ret = af9015_clear_reg_bit(d, 0xd507, 2); /* negate EP4 reset */	if (ret)		goto error;	if (af9015_config.dual_mode) {		ret = af9015_clear_reg_bit(d, 0xd50b, 1); /* negate EP5 reset */		if (ret)			goto error;	}	/* enable / disable mp2if2 */	if (af9015_config.dual_mode)		ret = af9015_set_reg_bit(d, 0xd50b, 0);	else		ret = af9015_clear_reg_bit(d, 0xd50b, 0);error:	if (ret)		err("endpoint init failed:%d", ret);	return ret;}static int af9015_copy_firmware(struct dvb_usb_device *d){	int ret;	u8 fw_params[4];	u8 val, i;	struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params),		fw_params };	deb_info("%s:\n", __func__);	fw_params[0] = af9015_config.firmware_size >> 8;	fw_params[1] = af9015_config.firmware_size & 0xff;	fw_params[2] = af9015_config.firmware_checksum >> 8;	fw_params[3] = af9015_config.firmware_checksum & 0xff;	/* wait 2nd demodulator ready */	msleep(100);	ret = af9015_read_reg_i2c(d, 0x3a, 0x98be, &val);	if (ret)		goto error;	else		deb_info("%s: firmware status:%02x\n", __func__, val);	if (val == 0x0c) /* fw is running, no need for download */		goto exit;	/* set I2C master clock to fast (to speed up firmware copy) */	ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */	if (ret)		goto error;	msleep(50);	/* copy firmware */	ret = af9015_ctrl_msg(d, &req);	if (ret)		err("firmware copy cmd failed:%d", ret);	deb_info("%s: firmware copy done\n", __func__);	/* set I2C master clock back to normal */	ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */	if (ret)		goto error;	/* request boot firmware */

⌨️ 快捷键说明

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