/*
tda18271-fe.c - driver for the Philips / NXP TDA18271 silicon tuner
Copyright (C) 2007, 2008 Michael Krufky <mkrufky@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/delay.h>
#include <linux/videodev2.h>
#include "tda18271-priv.h"
int tda18271_debug;
module_param_named(debug, tda18271_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debug level "
"(info=1, map=2, reg=4, adv=8, cal=16 (or-able))");
static LIST_HEAD(tda18271_list);
static DEFINE_MUTEX(tda18271_list_mutex);
/*---------------------------------------------------------------------*/
static int tda18271_ir_cal_init(struct dvb_frontend *fe)
{
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
tda18271_read_regs(fe);
/* test IR_CAL_OK to see if we need init */
if ((regs[R_EP1] & 0x08) == 0)
tda18271_init_regs(fe);
return 0;
}
/* ------------------------------------------------------------------ */
static int tda18271_channel_configuration(struct dvb_frontend *fe,
u32 ifc, u32 freq, u32 bw, u8 std,
int radio)
{
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
u32 N;
/* update TV broadcast parameters */
/* set standard */
regs[R_EP3] &= ~0x1f; /* clear std bits */
regs[R_EP3] |= std;
/* set cal mode to normal */
regs[R_EP4] &= ~0x03;
/* update IF output level & IF notch frequency */
regs[R_EP4] &= ~0x1c; /* clear if level bits */
switch (priv->mode) {
case TDA18271_ANALOG:
regs[R_MPD] &= ~0x80; /* IF notch = 0 */
break;
case TDA18271_DIGITAL:
regs[R_EP4] |= 0x04; /* IF level = 1 */
regs[R_MPD] |= 0x80; /* IF notch = 1 */
break;
}
if (radio)
regs[R_EP4] |= 0x80;
else
regs[R_EP4] &= ~0x80;
/* update RF_TOP / IF_TOP */
switch (priv->mode) {
case TDA18271_ANALOG:
regs[R_EB22] = 0x2c;
break;
case TDA18271_DIGITAL:
regs[R_EB22] = 0x37;
break;
}
tda18271_write_regs(fe, R_EB22, 1);
/* --------------------------------------------------------------- */
/* disable Power Level Indicator */
regs[R_EP1] |= 0x40;
/* frequency dependent parameters */
tda18271_calc_ir_measure(fe, &freq);
tda18271_calc_bp_filter(fe, &freq);
tda18271_calc_rf_band(fe, &freq);
tda18271_calc_gain_taper(fe, &freq);
/* --------------------------------------------------------------- */
/* dual tuner and agc1 extra configuration */
/* main vco when Master, cal vco when slave */
regs[R_EB1] |= 0x04; /* FIXME: assumes master */
/* agc1 always active */
regs[R_EB1