/*
Auvitek AU8522 QAM/8VSB demodulator driver
Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
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 <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/delay.h>
#include "dvb_frontend.h"
#include "au8522.h"
#include "au8522_priv.h"
static int debug;
/* Despite the name "hybrid_tuner", the framework works just as well for
hybrid demodulators as well... */
static LIST_HEAD(hybrid_tuner_instance_list);
static DEFINE_MUTEX(au8522_list_mutex);
#define dprintk(arg...)\
do { if (debug)\
printk(arg);\
} while (0)
/* 16 bit registers, 8 bit values */
int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
{
int ret;
u8 buf[] = { (reg >> 8) | 0x80, reg & 0xff, data };
struct i2c_msg msg = { .addr = state->config->demod_address,
.flags = 0, .buf = buf, .len = 3 };
ret = i2c_transfer(state->i2c, &msg, 1);
if (ret != 1)
printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
"ret == %i)\n", __func__, reg, data, ret);
return (ret != 1) ? -1 : 0;
}
u8 au8522_readreg(struct au8522_state *state, u16 reg)
{
int ret;
u8 b0[] = { (reg >> 8) | 0x40, reg & 0xff };
u8 b1[] = { 0 };
struct i2c_msg msg[] = {
{ .addr = state->config->demod_address, .flags = 0,
.buf = b0, .len = 2 },
{ .addr = state->config->demod_address, .flags = I2C_M_RD,
.buf = b1, .len = 1 } };
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2)
printk(KERN_ERR "%s: readreg error (ret == %i)\n",
__func__, ret);
return b1[0];
}
static int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
{
struct au8522_state *state = fe->demodulator_priv;
dprintk("%s(%d)\n", __func__, enable);
if (enable)
return au8522_writereg(state, 0x106, 1);
else
return au8522_writereg(state, 0x106, 0);
}
struct mse2snr_tab {
u16 val;
u16 data;
};
/* VSB SNR lookup table */
static struct mse2snr_tab vsb_mse2snr_tab[] = {
{ 0, 270 },
{ 2, 250 },
{ 3, 240 },
{ 5, 230 },
{ 7, 220 },
{ 9, 210 },
{ 12, 200 },
{ 13, 195 },
{ 15, 190 },
{ 17, 185 },
{ 19, 180 },
{ 21, 175 },
{ 24, 170 },
{ 27, 165 },
{ 31, 160 },
{ 32, 158 },
{ 33, 156 },
{ 36, 152 },
{ 37, 150 },
{ 39, 148 },
{ 40, 146 },
{ 41, 144 },
{ 43, 142 },
{ 44, 140 },
{ 48, 135 },
{ 50, 130 },
{ 43, 142 },
{ 53, 125 },
{ 56, 120 },
{ 256, 115 },
};
/* QAM64 SNR lookup table */
static struct mse2snr_tab qam64_mse2snr_tab[] = {
{ 15, 0 },
{ 16,