summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHolger Waechtler <devnull@localhost>2002-12-23 21:25:34 +0000
committerHolger Waechtler <devnull@localhost>2002-12-23 21:25:34 +0000
commit96dc63cd3ca635f5e626e16a04b9f15887d026f6 (patch)
treef164f79eb608fa353f9e793b9ece139ff312e6ad
parent8f19e30c12a4d3b6d76a2b569cdde2e41bdd6a1c (diff)
downloadmediapointer-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/Kconfig10
-rw-r--r--linux/drivers/media/dvb/frontends/Makefile2
-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");