diff options
author | Holger Waechtler <devnull@localhost> | 2002-12-23 21:25:34 +0000 |
---|---|---|
committer | Holger Waechtler <devnull@localhost> | 2002-12-23 21:25:34 +0000 |
commit | 96dc63cd3ca635f5e626e16a04b9f15887d026f6 (patch) | |
tree | f164f79eb608fa353f9e793b9ece139ff312e6ad | |
parent | 8f19e30c12a4d3b6d76a2b569cdde2e41bdd6a1c (diff) | |
download | mediapointer-dvb-s2-96dc63cd3ca635f5e626e16a04b9f15887d026f6.tar.gz mediapointer-dvb-s2-96dc63cd3ca635f5e626e16a04b9f15887d026f6.tar.bz2 |
generic stv0299 driver by Peter Schildmann <peter.schildmann@web.de>
replaces the old BSRU6 driver..
-rw-r--r-- | linux/drivers/media/dvb/frontends/Kconfig | 10 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/Makefile | 2 | ||||
-rw-r--r-- | linux/drivers/media/dvb/frontends/stv0299.c (renamed from linux/drivers/media/dvb/frontends/alps_bsru6.c) | 216 |
3 files changed, 169 insertions, 59 deletions
diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index 77be2e7a3..e9c68eb93 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -1,13 +1,17 @@ comment "Supported Frontend Modules" depends on DVB -config DVB_ALPS_BSRU6 - tristate "Alps BSRU6 (QPSK)" +config DVB_STV0299 + tristate "STV0299 based DVB-S frontend (QPSK)" depends on DVB_CORE help A DVB-S tuner module. - Say Y when you want to support this frontend. + Say Y when you want to support frontend based on this + demodulator. + + Some examples are the Alps BSRU6, the Philips SU1278 and + the LG TDQB-S00x. If you don't know what tuner module is soldered on your DVB adapter simply enable all supported frontends, the diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index 9e9a35a00..d14464a20 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -4,7 +4,7 @@ EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -obj-$(CONFIG_DVB_ALPS_BSRU6) += alps_bsru6.o +obj-$(CONFIG_DVB_STV0299) += stv0299.o obj-$(CONFIG_DVB_ALPS_BSRV2) += alps_bsrv2.o obj-$(CONFIG_DVB_ALPS_TDLB7) += alps_tdlb7.o obj-$(CONFIG_DVB_ALPS_TDMB7) += alps_tdmb7.o diff --git a/linux/drivers/media/dvb/frontends/alps_bsru6.c b/linux/drivers/media/dvb/frontends/stv0299.c index b5efa09ff..ef1ceeebf 100644 --- a/linux/drivers/media/dvb/frontends/alps_bsru6.c +++ b/linux/drivers/media/dvb/frontends/stv0299.c @@ -1,9 +1,18 @@ -/* - Alps BSRU6 and LG TDQB-S00x DVB QPSK frontend driver +/* + Universal driver for STV0299/TDA5059 based + DVB QPSK frontends + + Alps BSRU6, LG TDQB-S00x Copyright (C) 2001-2002 Convergence Integrated Media GmbH - <ralph@convergence.de>, <holger@convergence.de>, + <ralph@convergence.de>, + <holger@convergence.de>, <js@convergence.de> + + Philips SU1278/SH + + Copyright (C) 2002 by Peter Schildmann + <peter.schildmann@web.de> 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 @@ -27,18 +36,20 @@ #include "compat.h" #include "dvb_frontend.h" - static int debug = 0; #define dprintk if (debug) printk +/* frontend types */ +#define UNKNOWN_FRONTEND -1 +#define PHILIPS_SU1278SH 0 +#define ALPS_BSRU6 1 +/* Master Clock = 88 MHz */ #define M_CLK (88000000UL) -/* M=21, K=0, P=0, f_VCO = 4MHz*4*(M+1)/(K+1) = 352 MHz */ - static -struct dvb_frontend_info bsru6_info = { - name: "stv0299 based (e.g. Alps BSRU6 or LG TDQB-S00x)", +struct dvb_frontend_info uni0299_info = { + name: "STV0299/TSA5059 based", type: FE_QPSK, frequency_min: 950000, frequency_max: 2150000, @@ -58,30 +69,44 @@ struct dvb_frontend_info bsru6_info = { static u8 init_tab [] = { - 0x01, 0x15, // M: 0x15 DIRCLK: 0 K:0 - 0x02, 0x30, // P: 0 SERCLK: 0 VCO:ON STDBY:0 - - 0x03, 0x00, - 0x04, 0x7d, // F22FR, F22=22kHz - 0x05, 0x35, // SDAT:0 SCLT:0 I2CT:1 - 0x06, 0x00, // DAC mode and MSB - 0x07, 0x00, // DAC LSB - 0x08, 0x40, // DiSEqC off - 0x09, 0x00, - 0x0a, 0x42, - 0x0c, 0x51, // QPSK reverse:1 Nyquist:0 OP0 val:1 OP0 con:1 OP1 val:1 OP1 con:1 - 0x0d, 0x82, - 0x0e, 0x23, - 0x0f, 0x52, - - 0x10, 0x3d, // AGC2 + /* clock registers */ + 0x01, 0x15, /* K = 0, DIRCLK = 0, M = 0x15 */ + 0x02, 0x30, /* STDBY = 0, VCO = 0 (ON), SERCLK = 0, P = 0 */ + /* f_VCO = 4MHz * 4 * (M+1) / (K+1) = 352 MHz */ + 0x03, 0x00, /* auxiliary clock not used */ + 0x04, 0x7d, /* F22FR = 0x7d */ + /* F22 = f_VCO / 128 / 0x7d = 22 kHz */ + + /* I2C bus repeater */ + 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ + + /* general purpose DAC registers */ + 0x06, 0x40, /* DAC not used, set to high impendance mode */ + 0x07, 0x00, /* DAC LSB */ + + /* DiSEqC registers */ + 0x08, 0x40, /* DiSEqC off */ + 0x09, 0x00, /* FIFO */ + + /* Input/Output configuration register */ + 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ + /* OP0 ctl = Normal, OP0 val = 1 (18 V) */ + /* Nyquist filter = 00, QPSK reverse = 0 */ + + /* AGC1 control register */ + 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ + + /* Timing loop register */ + 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ + + 0x10, 0x3f, // AGC2 0x3d 0x11, 0x84, 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on 0x13, 0xb6, // alpha_car b:4 a:0 noise est:256ks derot:on 0x14, 0x93, // beat carc:0 d:0 e:0xf phase detect algo: 1 0x15, 0xc9, // lock detector threshold - 0x16, 0x1d, + 0x16, 0x1d, /* AGC1 integrator value */ 0x17, 0x00, 0x18, 0x14, 0x19, 0xf2, @@ -207,14 +232,15 @@ int stv0299_readregs (struct dvb_i2c_bus *i2c, u8 reg1, u8 *b, u8 len) } - static -int tsa5059_write (struct dvb_i2c_bus *i2c, u8 data [4]) +int tsa5059_write (struct dvb_i2c_bus *i2c, u8 data [4], int ftype) { int ret; u8 rpt1 [] = { 0x05, 0xb5 }; /* enable i2c repeater on stv0299 */ + /* TSA5059 i2c-bus address */ + u8 addr = (ftype == PHILIPS_SU1278SH) ? 0x60 : 0x61; struct i2c_msg msg [] = {{ addr: 0x68, flags: 0, buf: rpt1, len: 2 }, - { addr: 0x61, flags: 0, buf: data, len: 4 }}; + { addr: addr, flags: 0, buf: data, len: 4 }}; dprintk ("%s\n", __FUNCTION__); @@ -232,20 +258,50 @@ int tsa5059_write (struct dvb_i2c_bus *i2c, u8 data [4]) * reference clock comparision frequency of 125 kHz. */ static -int tsa5059_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, u8 pwr) +int tsa5059_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype) +{ + u32 div = freq / 125; + + u8 buf[4] = { (div >> 8) & 0x7f, div & 0xff, 0x84 }; + + if (ftype == PHILIPS_SU1278SH) + /* activate f_xtal/f_comp signal output */ + /* charge pump current C0/C1 = 00 */ + buf[3] = 0x20; + else + buf[3] = freq > 1530000 ? 0xc0 : 0xc4; + + dprintk ("%s\n", __FUNCTION__); + + return tsa5059_write (i2c, buf, ftype); +} + + +#if 0 +static +int tsa5059_read_status (struct dvb_i2c_bus *i2c) { - u32 div = freq / 125; - u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, 0x84, - freq > 1530000 ? 0xc0 : 0xc4 }; + int ret; + u8 rpt1 [] = { 0x05, 0xb5 }; + u8 stat [] = { 0 }; + + struct i2c_msg msg [] = {{ addr: 0x68, flags: 0, buf: rpt1, len: 2 }, + { addr: 0x60, flags: I2C_M_RD, buf: stat, len: 1 }}; dprintk ("%s\n", __FUNCTION__); - return tsa5059_write (i2c, buf); + ret = i2c->xfer (i2c, msg, 2); + + if (ret != 2) + dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + + return stat[0]; } +#endif static -int stv0299_init (struct dvb_i2c_bus *i2c) +int stv0299_init (struct dvb_i2c_bus *i2c, int ftype) { int i; @@ -254,6 +310,12 @@ int stv0299_init (struct dvb_i2c_bus *i2c) for (i=0; i<sizeof(init_tab); i+=2) stv0299_writereg (i2c, init_tab[i], init_tab[i+1]); + /* AGC1 reference register setup */ + if (ftype == PHILIPS_SU1278SH) + stv0299_writereg (i2c, 0x0f, 0xd2); /* Iagc = Inverse, m1 = 18 */ + else + stv0299_writereg (i2c, 0x0f, 0x52); /* Iagc = Normal, m1 = 18 */ + return 0; } @@ -447,7 +509,7 @@ int stv0299_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage) val = stv0299_readreg (i2c, 0x0c); val &= 0x0f; - val |= 0x40; + val |= 0x40; /* LNB power on */ switch (voltage) { case SEC_VOLTAGE_13: @@ -532,15 +594,16 @@ int stv0299_get_symbolrate (struct dvb_i2c_bus *i2c) static -int bsru6_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) { + int tuner_type = (int)fe->data; struct dvb_i2c_bus *i2c = fe->i2c; dprintk ("%s\n", __FUNCTION__); switch (cmd) { case FE_GET_INFO: - memcpy (arg, &bsru6_info, sizeof(struct dvb_frontend_info)); + memcpy (arg, &uni0299_info, sizeof(struct dvb_frontend_info)); break; case FE_READ_STATUS: @@ -549,6 +612,8 @@ int bsru6_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) u8 signal = 0xff - stv0299_readreg (i2c, 0x18); u8 sync = stv0299_readreg (i2c, 0x1b); + dprintk ("VSTATUS: 0x%02x\n", sync); + *status = 0; if (signal > 10) @@ -578,6 +643,11 @@ int bsru6_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) { s32 signal = 0xffff - ((stv0299_readreg (i2c, 0x18) << 8) | stv0299_readreg (i2c, 0x19)); + + dprintk ("AGC2I: 0x%02x%02x, signal=0x%04x\n", + stv0299_readreg (i2c, 0x18), + stv0299_readreg (i2c, 0x19), signal); + signal = signal * 5 / 4; *((u16*) arg) = (signal > 0xffff) ? 0xffff : (signal < 0) ? 0 : signal; @@ -600,15 +670,17 @@ int bsru6_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) { struct dvb_frontend_parameters *p = arg; - tsa5059_set_tv_freq (i2c, p->frequency, 3); + tsa5059_set_tv_freq (i2c, p->frequency, tuner_type); stv0299_set_FEC (i2c, p->u.qpsk.fec_inner); stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate); stv0299_check_inversion (i2c); - tsa5059_set_tv_freq (i2c, p->frequency, 0); + /* tsa5059_set_tv_freq (i2c, p->frequency); */ stv0299_writereg (i2c, 0x22, 0x00); stv0299_writereg (i2c, 0x23, 0x00); stv0299_readreg (i2c, 0x23); stv0299_writereg (i2c, 0x12, 0xb9); + + /* printk ("%s: tsa5059 status: %x\n", __FUNCTION__, tsa5059_read_status(i2c)); */ break; } @@ -638,7 +710,7 @@ int bsru6_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) break; case FE_INIT: - return stv0299_init (i2c); + return stv0299_init (i2c, tuner_type); case FE_RESET: stv0299_writereg (i2c, 0x22, 0x00); @@ -666,56 +738,90 @@ int bsru6_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) return 0; } - +static +int probe_tuner (struct dvb_i2c_bus *i2c) +{ + int type; + + /* read the status register of TSA5059 */ + u8 rpt[] = { 0x05, 0xb5 }; + u8 stat [] = { 0 }; + struct i2c_msg msg1 [] = {{ addr: 0x68, flags: 0, buf: rpt, len: 2 }, + { addr: 0x60, flags: I2C_M_RD, buf: stat, len: 1 }}; + struct i2c_msg msg2 [] = {{ addr: 0x68, flags: 0, buf: rpt, len: 2 }, + { addr: 0x61, flags: I2C_M_RD, buf: stat, len: 1 }}; + + if (i2c->xfer(i2c, msg1, 2) == 2) { + type = PHILIPS_SU1278SH; + printk ("%s: setup for tuner SU1278/SH\n", __FILE__); + } else if (i2c->xfer(i2c, msg2, 2) == 2) { + type = ALPS_BSRU6; + printk ("%s: setup for tuner BSRU6, TDQB-S00x\n", __FILE__); + } else { + type = UNKNOWN_FRONTEND; + printk ("%s: unknown PLL synthesizer, " + "please report to <linuxdvb@linuxtv.org>!!\n", + __FILE__); + } + return type; +} static -int bsru6_attach (struct dvb_i2c_bus *i2c) +int uni0299_attach (struct dvb_i2c_bus *i2c) { + int tuner_type; u8 id = stv0299_readreg (i2c, 0x00); dprintk ("%s\n", __FUNCTION__); - if (id != 0xa1 && id != 0x80) + /* register 0x00 contains 0xa1 for STV0299 and STV0299B */ + /* register 0x00 might contain 0x80 when returning from standby */ + if (id != 0xa1) + return -ENODEV; + + if ((tuner_type = probe_tuner(i2c)) < 0) return -ENODEV; - dvb_register_frontend (bsru6_ioctl, i2c, NULL, &bsru6_info); + dvb_register_frontend (uni0299_ioctl, i2c, (void*) tuner_type, + &uni0299_info); return 0; } static -void bsru6_detach (struct dvb_i2c_bus *i2c) +void uni0299_detach (struct dvb_i2c_bus *i2c) { dprintk ("%s\n", __FUNCTION__); - dvb_unregister_frontend (bsru6_ioctl, i2c); + dvb_unregister_frontend (uni0299_ioctl, i2c); } static -int __init init_bsru6 (void) +int __init init_uni0299 (void) { dprintk ("%s\n", __FUNCTION__); - return dvb_register_i2c_device (THIS_MODULE, bsru6_attach, bsru6_detach); + return dvb_register_i2c_device (THIS_MODULE, uni0299_attach, uni0299_detach); } static -void __exit exit_bsru6 (void) +void __exit exit_uni0299 (void) { dprintk ("%s\n", __FUNCTION__); - dvb_unregister_i2c_device (bsru6_attach); + dvb_unregister_i2c_device (uni0299_attach); } -module_init (init_bsru6); -module_exit (exit_bsru6); +module_init (init_uni0299); +module_exit (exit_uni0299); MODULE_PARM(debug,"i"); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -MODULE_DESCRIPTION("Alps BSRU6/LG TDQB-S00x DVB Frontend driver"); -MODULE_AUTHOR("Ralph Metzler, Holger Waechtler"); + +MODULE_DESCRIPTION("Universal STV0299/TSA5059 DVB Frontend driver"); +MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann"); MODULE_LICENSE("GPL"); |