/*
Driver for Philips tda1004xh OFDM Demodulator
(c) 2003, 2004 Andrew de Quincey & Robert Schlabbach
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 external firmware. Please use the commands
* "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
* "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
* download/extract them, and then copy them to /usr/lib/hotplug/firmware.
*/
#define TDA10045_DEFAULT_FIRMWARE "dvb-fe-tda10045.fw"
#define TDA10046_DEFAULT_FIRMWARE "dvb-fe-tda10046.fw"
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/device.h>
#include "dvb_frontend.h"
#include "tda1004x.h"
enum tda1004x_demod {
TDA1004X_DEMOD_TDA10045,
TDA1004X_DEMOD_TDA10046,
};
struct tda1004x_state {
struct i2c_adapter* i2c;
struct dvb_frontend_ops ops;
const struct tda1004x_config* config;
struct dvb_frontend frontend;
/* private demod data */
u8 initialised;
enum tda1004x_demod demod_type;
};
static int debug;
#define dprintk(args...) \
do { \
if (debug) printk(KERN_DEBUG "tda1004x: " args); \
} while (0)
#define TDA1004X_CHIPID 0x00
#define TDA1004X_AUTO 0x01
#define TDA1004X_IN_CONF1 0x02
#define TDA1004X_IN_CONF2 0x03
#define TDA1004X_OUT_CONF1 0x04
#define TDA1004X_OUT_CONF2 0x05
#define TDA1004X_STATUS_CD 0x06
#define TDA1004X_CONFC4 0x07
#define TDA1004X_DSSPARE2 0x0C
#define TDA10045H_CODE_IN 0x0D
#define TDA10045H_FWPAGE 0x0E
#define TDA1004X_SCAN_CPT 0x10
#define TDA1004X_DSP_CMD 0x11
#define TDA1004X_DSP_ARG 0x12
#define TDA1004X_DSP_DATA1 0x13
#define TDA1004X_DSP_DATA2 0x14
#define TDA1004X_CONFADC1 0x15
#define TDA1004X_CONFC1 0x16
#define TDA10045H_S_AGC 0x1a
#define TDA10046H_AGC_TUN_LEVEL 0x1a
#define TDA1004X_SNR 0x1c
#define TDA1004X_CONF_TS1 0x1e
#define TDA1004X_CONF_TS2 0x1f
#define TDA1004X_CBER_RESET 0x20
#define TDA1004X_CBER_MSB 0x21
#define TDA1004X_CBER_LSB 0x22
#define TDA1004X_CVBER_LUT 0x23
#define TDA1004X_VBER_MSB 0x24
#define TDA1004X_VBER_MID 0x25
#define TDA1004X_VBER_LSB 0x26
#define TDA1004X_UNCOR 0x27
#define TDA10045H_CONFPLL_P 0x2D
#define TDA10045H_CONFPLL_M_MSB 0x2E
#define TDA10045H_CONFPLL_M_LSB 0x2F
#define TDA10045H_CONFPLL_N 0x30
#define TDA10046H_CONFPLL1 0x2D
#define TDA10046H_CONFPLL2 0x2F
#define TDA10046H_CONFPLL3 0x30
#define TDA10046H_TIME_WREF1 0x31
#define TDA10046H_TIME_WREF2 0x32
#define TDA10046H_TIME_WREF3 0x33
#define TDA10046H_TIME_WREF4 0x34
#define TDA10046H_TIME_WREF5 0x35
#define TDA10045H_UNSURW_MSB 0x31
#define TDA10045H_UNSURW_LSB 0x32
#define TDA10045H_WREF_MSB 0x33
#define TDA10045H_WREF_MID 0x34
#define TDA10045H_WREF_LSB 0x35
#define TDA10045H_MUXOUT 0x36
#define TDA1004X_CONFADC2 0x37
#define TDA10045H_IOFFSET 0x38
#define TDA10046H_CONF_TRISTATE1 0x3B
#define TDA10046H_CONF_TRISTATE2 0x3C
#define TDA10046H_CONF_POLARITY 0x3D
#define TDA10046H_FREQ_OFFSET 0x3E
#define TDA10046H_GPIO_OUT_SEL 0x41
#define TDA10046H_GPIO_SELECT 0x42
#define TDA10046H_AGC_CONF 0x43
#define TDA10046H_AGC_THR 0x44
#define TDA10046H_AGC_RENORM 0x45
#define TDA10046H_AGC_GAINS 0x46
#define TDA10046H_AGC_TUN_MIN 0x47
#define TDA10046H_AGC_TUN_MAX 0x48
#define TDA10046H_AGC_IF_MIN 0x49
#define TDA10046H_AGC_IF_MAX 0x4A
#define TDA10046H_FREQ_PHY2_MSB 0x4D
#define TDA10046H_FREQ_PHY2_LSB 0x4E
#define TDA10046H_CVBER_CTRL 0x4F
#define TDA10046H_AGC_IF_LEVEL 0x52
#define TDA10046H_CODE_CPT 0x57
#define TDA10046H_CODE_IN 0x58
static int tda1004x_write_byteI(struct tda1004x_state *state, int reg, int data)
{
int ret;
u8 buf[] = { reg, data };
struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
dprintk("%s: reg=0x%x, data=0x%x\n", __FUNCTION__, reg, data);
msg.addr = state->config->demod_address;
ret = i2c_transfer(state->i2c, &msg, 1);
if (ret != 1)
dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n"