📄 or51132.c
字号:
/* * Support for OR51132 (pcHDTV HD-3000) - VSB/QAM * * * Copyright (C) 2007 Trent Piepho <xyzzy@speakeasy.org> * * Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com> * * Based on code from Jack Kelliher (kelliher@xmission.com) * Copyright (C) 2002 & pcHDTV, inc. * * 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 two external firmware files. Please copy * "dvb-fe-or51132-vsb.fw" and "dvb-fe-or51132-qam.fw" to * /usr/lib/hotplug/firmware/ or /lib/firmware/ * (depending on configuration of firmware hotplug). */#define OR51132_VSB_FIRMWARE "dvb-fe-or51132-vsb.fw"#define OR51132_QAM_FIRMWARE "dvb-fe-or51132-qam.fw"#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/string.h>#include <linux/slab.h>#include <asm/byteorder.h>#include "dvb_math.h"#include "dvb_frontend.h"#include "or51132.h"static int debug;#define dprintk(args...) \ do { \ if (debug) printk(KERN_DEBUG "or51132: " args); \ } while (0)struct or51132_state{ struct i2c_adapter* i2c; /* Configuration settings */ const struct or51132_config* config; struct dvb_frontend frontend; /* Demodulator private data */ fe_modulation_t current_modulation; u32 snr; /* Result of last SNR calculation */ /* Tuner private data */ u32 current_frequency;};/* Write buffer to demod */static int or51132_writebuf(struct or51132_state *state, const u8 *buf, int len){ int err; struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = (u8*)buf, .len = len }; /* msleep(20); */ /* doesn't appear to be necessary */ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { printk(KERN_WARNING "or51132: I2C write (addr 0x%02x len %d) error: %d\n", msg.addr, msg.len, err); return -EREMOTEIO; } return 0;}/* Write constant bytes, e.g. or51132_writebytes(state, 0x04, 0x42, 0x00); Less code and more efficient that loading a buffer on the stack with the bytes to send and then calling or51132_writebuf() on that. */#define or51132_writebytes(state, data...) \ ({ static const u8 _data[] = {data}; \ or51132_writebuf(state, _data, sizeof(_data)); })/* Read data from demod into buffer. Returns 0 on success. */static int or51132_readbuf(struct or51132_state *state, u8 *buf, int len){ int err; struct i2c_msg msg = { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len }; /* msleep(20); */ /* doesn't appear to be necessary */ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { printk(KERN_WARNING "or51132: I2C read (addr 0x%02x len %d) error: %d\n", msg.addr, msg.len, err); return -EREMOTEIO; } return 0;}/* Reads a 16-bit demod register. Returns <0 on error. */static int or51132_readreg(struct or51132_state *state, u8 reg){ u8 buf[2] = { 0x04, reg }; struct i2c_msg msg[2] = { {.addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }, {.addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = 2 }}; int err; if ((err = i2c_transfer(state->i2c, msg, 2)) != 2) { printk(KERN_WARNING "or51132: I2C error reading register %d: %d\n", reg, err); return -EREMOTEIO; } return buf[0] | (buf[1] << 8);}static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware *fw){ struct or51132_state* state = fe->demodulator_priv; static const u8 run_buf[] = {0x7F,0x01}; u8 rec_buf[8]; u32 firmwareAsize, firmwareBsize; int i,ret; dprintk("Firmware is %Zd bytes\n",fw->size); /* Get size of firmware A and B */ firmwareAsize = le32_to_cpu(*((__le32*)fw->data)); dprintk("FirmwareA is %i bytes\n",firmwareAsize); firmwareBsize = le32_to_cpu(*((__le32*)(fw->data+4))); dprintk("FirmwareB is %i bytes\n",firmwareBsize); /* Upload firmware */ if ((ret = or51132_writebuf(state, &fw->data[8], firmwareAsize))) { printk(KERN_WARNING "or51132: load_firmware error 1\n"); return ret; } if ((ret = or51132_writebuf(state, &fw->data[8+firmwareAsize], firmwareBsize))) { printk(KERN_WARNING "or51132: load_firmware error 2\n"); return ret; } if ((ret = or51132_writebuf(state, run_buf, 2))) { printk(KERN_WARNING "or51132: load_firmware error 3\n"); return ret; } if ((ret = or51132_writebuf(state, run_buf, 2))) { printk(KERN_WARNING "or51132: load_firmware error 4\n"); return ret; } /* 50ms for operation to begin */ msleep(50); /* Read back ucode version to besure we loaded correctly and are really up and running */ /* Get uCode version */ if ((ret = or51132_writebytes(state, 0x10, 0x10, 0x00))) { printk(KERN_WARNING "or51132: load_firmware error a\n"); return ret; } if ((ret = or51132_writebytes(state, 0x04, 0x17))) { printk(KERN_WARNING "or51132: load_firmware error b\n"); return ret; } if ((ret = or51132_writebytes(state, 0x00, 0x00))) { printk(KERN_WARNING "or51132: load_firmware error c\n"); return ret; } for (i=0;i<4;i++) { /* Once upon a time, this command might have had something to do with getting the firmware version, but it's not used anymore: {0x04,0x00,0x30,0x00,i+1} */ /* Read 8 bytes, two bytes at a time */ if ((ret = or51132_readbuf(state, &rec_buf[i*2], 2))) { printk(KERN_WARNING "or51132: load_firmware error d - %d\n",i); return ret; } } printk(KERN_WARNING "or51132: Version: %02X%02X%02X%02X-%02X%02X%02X%02X (%02X%01X-%01X-%02X%01X-%01X)\n", rec_buf[1],rec_buf[0],rec_buf[3],rec_buf[2], rec_buf[5],rec_buf[4],rec_buf[7],rec_buf[6], rec_buf[3],rec_buf[2]>>4,rec_buf[2]&0x0f, rec_buf[5],rec_buf[4]>>4,rec_buf[4]&0x0f); if ((ret = or51132_writebytes(state, 0x10, 0x00, 0x00))) { printk(KERN_WARNING "or51132: load_firmware error e\n"); return ret; } return 0;};static int or51132_init(struct dvb_frontend* fe){ return 0;}static int or51132_read_ber(struct dvb_frontend* fe, u32* ber){ *ber = 0; return 0;}static int or51132_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks){ *ucblocks = 0; return 0;}static int or51132_sleep(struct dvb_frontend* fe){ return 0;}static int or51132_setmode(struct dvb_frontend* fe){ struct or51132_state* state = fe->demodulator_priv; u8 cmd_buf1[3] = {0x04, 0x01, 0x5f}; u8 cmd_buf2[3] = {0x1c, 0x00, 0 }; dprintk("setmode %d\n",(int)state->current_modulation); switch (state->current_modulation) { case VSB_8: /* Auto CH, Auto NTSC rej, MPEGser, MPEG2tr, phase noise-high */ cmd_buf1[2] = 0x50; /* REC MODE inv IF spectrum, Normal */ cmd_buf2[1] = 0x03; /* Channel MODE ATSC/VSB8 */ cmd_buf2[2] = 0x06; break; /* All QAM modes are: Auto-deinterleave; MPEGser, MPEG2tr, phase noise-high REC MODE Normal Carrier Lock */ case QAM_AUTO: /* Channel MODE Auto QAM64/256 */ cmd_buf2[2] = 0x4f; break; case QAM_256: /* Channel MODE QAM256 */ cmd_buf2[2] = 0x45; break; case QAM_64: /* Channel MODE QAM64 */ cmd_buf2[2] = 0x43; break; default: printk(KERN_WARNING "or51132: setmode: Modulation set to unsupported value (%d)\n", state->current_modulation); return -EINVAL; } /* Set Receiver 1 register */ if (or51132_writebuf(state, cmd_buf1, 3)) { printk(KERN_WARNING "or51132: set_mode error 1\n"); return -EREMOTEIO; } dprintk("set #1 to %02x\n", cmd_buf1[2]); /* Set operation mode in Receiver 6 register */ if (or51132_writebuf(state, cmd_buf2, 3)) { printk(KERN_WARNING "or51132: set_mode error 2\n"); return -EREMOTEIO; } dprintk("set #6 to 0x%02x%02x\n", cmd_buf2[1], cmd_buf2[2]); return 0;}/* Some modulations use the same firmware. This classifies modulations by the firmware they use. */#define MOD_FWCLASS_UNKNOWN 0#define MOD_FWCLASS_VSB 1#define MOD_FWCLASS_QAM 2static int modulation_fw_class(fe_modulation_t modulation){ switch(modulation) { case VSB_8: return MOD_FWCLASS_VSB; case QAM_AUTO: case QAM_64: case QAM_256: return MOD_FWCLASS_QAM; default: return MOD_FWCLASS_UNKNOWN; }}static int or51132_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_parameters *param){ int ret; struct or51132_state* state = fe->demodulator_priv;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -