summaryrefslogtreecommitdiff
path: root/drivers/media/dvb
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-06-25 10:09:31 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-25 10:09:31 -0700
commit25581ad107be24b89d805da51a03d616f8f3d1be (patch)
tree36e2bd32667b5dd5a39e1939c1c5162f18967715 /drivers/media/dvb
parent72cf2709bf8e0410800f118c4298bfbf8715b303 (diff)
parent7477ddaa4d2d69bbcd49e12990af158dbb03f2f2 (diff)
downloadlinux-stable-25581ad107be24b89d805da51a03d616f8f3d1be.tar.gz
linux-stable-25581ad107be24b89d805da51a03d616f8f3d1be.tar.bz2
linux-stable-25581ad107be24b89d805da51a03d616f8f3d1be.zip
Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb
* master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (244 commits) V4L/DVB (4210b): git-dvb: tea575x-tuner build fix V4L/DVB (4210a): git-dvb versus matroxfb V4L/DVB (4209): Added some BTTV PCI IDs for newer boards Fixes some sync issues between V4L/DVB development and GIT V4L/DVB (4206): Cx88-blackbird: always set encoder height based on tvnorm->id V4L/DVB (4205): Merge tda9887 module into tuner. V4L/DVB (4203): Explicitly set the enum values. V4L/DVB (4202): allow selecting CX2341x port mode V4L/DVB (4200): Disable bitrate_mode when encoding mpeg-1. V4L/DVB (4199): Add cx2341x-specific control array to cx2341x.c V4L/DVB (4198): Avoid newer usages of obsoleted experimental MPEGCOMP API V4L/DVB (4197): Port new MPEG API to saa7134-empress with saa6752hs V4L/DVB (4196): Port cx88-blackbird to the new MPEG API. V4L/DVB (4193): Update cx2341x fw encoding API doc. V4L/DVB (4192): Use control helpers for saa7115, cx25840, msp3400. V4L/DVB (4191): Add CX2341X MPEG encoder module. V4L/DVB (4190): Add helper functions for control processing to v4l2-common. V4L/DVB (4189): Add videodev support for VIDIOC_S/G/TRY_EXT_CTRLS. V4L/DVB (4188): Add new MPEG control/ioctl definitions to videodev2.h V4L/DVB (4186): Add support for the DNTV Live! mini DVB-T card. ...
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c122
-rw-r--r--drivers/media/dvb/b2c2/flexcop-pci.c19
-rw-r--r--drivers/media/dvb/b2c2/flexcop-usb.c10
-rw-r--r--drivers/media/dvb/b2c2/flexcop.c12
-rw-r--r--drivers/media/dvb/bt8xx/bt878.c11
-rw-r--r--drivers/media/dvb/bt8xx/dst.c606
-rw-r--r--drivers/media/dvb/bt8xx/dst_ca.c116
-rw-r--r--drivers/media/dvb/bt8xx/dst_common.h33
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c118
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.h2
-rw-r--r--drivers/media/dvb/cinergyT2/Kconfig2
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c8
-rw-r--r--drivers/media/dvb/dvb-core/Makefile6
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c3
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c25
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.c4
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c151
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.h45
-rw-r--r--drivers/media/dvb/dvb-core/dvb_math.c145
-rw-r--r--drivers/media/dvb/dvb-core/dvb_math.h58
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c230
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c5
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.h4
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig10
-rw-r--r--drivers/media/dvb/dvb-usb/Makefile3
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c48
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-common.c9
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mb.c7
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c15
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u-fe.c8
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-dvb.c17
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-i2c.c24
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h4
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h6
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk-fe.c272
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk.c256
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk.h79
-rw-r--r--drivers/media/dvb/dvb-usb/umt-010.c2
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x-fe.c7
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045-fe.c9
-rw-r--r--drivers/media/dvb/frontends/Kconfig18
-rw-r--r--drivers/media/dvb/frontends/Makefile2
-rw-r--r--drivers/media/dvb/frontends/bcm3510.c4
-rw-r--r--drivers/media/dvb/frontends/bsbe1.h6
-rw-r--r--drivers/media/dvb/frontends/bsru6.h6
-rw-r--r--drivers/media/dvb/frontends/cx22700.c31
-rw-r--r--drivers/media/dvb/frontends/cx22700.h4
-rw-r--r--drivers/media/dvb/frontends/cx22702.c29
-rw-r--r--drivers/media/dvb/frontends/cx22702.h7
-rw-r--r--drivers/media/dvb/frontends/cx24110.c26
-rw-r--r--drivers/media/dvb/frontends/cx24110.h5
-rw-r--r--drivers/media/dvb/frontends/cx24123.c195
-rw-r--r--drivers/media/dvb/frontends/cx24123.h13
-rw-r--r--drivers/media/dvb/frontends/dib3000-common.h2
-rw-r--r--drivers/media/dvb/frontends/dib3000.h4
-rw-r--r--drivers/media/dvb/frontends/dib3000mb.c11
-rw-r--r--drivers/media/dvb/frontends/dib3000mc.c14
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c181
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h18
-rw-r--r--drivers/media/dvb/frontends/dvb_dummy_fe.c21
-rw-r--r--drivers/media/dvb/frontends/isl6421.c149
-rw-r--r--drivers/media/dvb/frontends/isl6421.h46
-rw-r--r--drivers/media/dvb/frontends/l64781.c11
-rw-r--r--drivers/media/dvb/frontends/l64781.h4
-rw-r--r--drivers/media/dvb/frontends/lg_h06xf.h64
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.c19
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.h1
-rw-r--r--drivers/media/dvb/frontends/lnbp21.c145
-rw-r--r--drivers/media/dvb/frontends/lnbp21.h102
-rw-r--r--drivers/media/dvb/frontends/mt312.c46
-rw-r--r--drivers/media/dvb/frontends/mt312.h4
-rw-r--r--drivers/media/dvb/frontends/mt352.c23
-rw-r--r--drivers/media/dvb/frontends/mt352.h6
-rw-r--r--drivers/media/dvb/frontends/nxt200x.c20
-rw-r--r--drivers/media/dvb/frontends/nxt200x.h4
-rw-r--r--drivers/media/dvb/frontends/nxt6000.c29
-rw-r--r--drivers/media/dvb/frontends/nxt6000.h4
-rw-r--r--drivers/media/dvb/frontends/or51132.c157
-rw-r--r--drivers/media/dvb/frontends/or51132.h2
-rw-r--r--drivers/media/dvb/frontends/or51211.c4
-rw-r--r--drivers/media/dvb/frontends/s5h1420.c43
-rw-r--r--drivers/media/dvb/frontends/s5h1420.h4
-rw-r--r--drivers/media/dvb/frontends/sp8870.c31
-rw-r--r--drivers/media/dvb/frontends/sp8870.h4
-rw-r--r--drivers/media/dvb/frontends/sp887x.c38
-rw-r--r--drivers/media/dvb/frontends/sp887x.h6
-rw-r--r--drivers/media/dvb/frontends/stv0297.c73
-rw-r--r--drivers/media/dvb/frontends/stv0297.h6
-rw-r--r--drivers/media/dvb/frontends/stv0299.c41
-rw-r--r--drivers/media/dvb/frontends/stv0299.h5
-rw-r--r--drivers/media/dvb/frontends/tda10021.c39
-rw-r--r--drivers/media/dvb/frontends/tda10021.h6
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c55
-rw-r--r--drivers/media/dvb/frontends/tda1004x.h5
-rw-r--r--drivers/media/dvb/frontends/tda8083.c12
-rw-r--r--drivers/media/dvb/frontends/tda8083.h4
-rw-r--r--drivers/media/dvb/frontends/ves1820.c19
-rw-r--r--drivers/media/dvb/frontends/ves1820.h4
-rw-r--r--drivers/media/dvb/frontends/ves1x93.c29
-rw-r--r--drivers/media/dvb/frontends/ves1x93.h4
-rw-r--r--drivers/media/dvb/frontends/zl10353.c30
-rw-r--r--drivers/media/dvb/frontends/zl10353.h6
-rw-r--r--drivers/media/dvb/pluto2/pluto2.c15
-rw-r--r--drivers/media/dvb/ttpci/Kconfig3
-rw-r--r--drivers/media/dvb/ttpci/Makefile6
-rw-r--r--drivers/media/dvb/ttpci/av7110.c135
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c283
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c59
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c4
-rw-r--r--drivers/media/dvb/ttpci/budget-patch.c43
-rw-r--r--drivers/media/dvb/ttpci/budget.c69
-rw-r--r--drivers/media/dvb/ttusb-budget/Kconfig2
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c264
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c6
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusbdecfe.c8
115 files changed, 3766 insertions, 1543 deletions
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 9c7f122826e0..3be87c72e37b 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -14,6 +14,7 @@
#include "stv0297.h"
#include "mt312.h"
#include "lgdt330x.h"
+#include "lg_h06xf.h"
#include "dvb-pll.h"
/* lnb control */
@@ -166,11 +167,12 @@ static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate,
return 0;
}
-static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
+static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
{
u8 buf[4];
u32 div;
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
+ struct flexcop_device *fc = fe->dvb->priv;
div = params->frequency / 125;
@@ -181,8 +183,11 @@ static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct i2c_adapter
if (params->frequency < 1500000) buf[3] |= 0x10;
- if (i2c_transfer(i2c, &msg, 1) != 1)
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) {
return -EIO;
+ }
return 0;
}
@@ -241,7 +246,6 @@ static struct stv0299_config samsung_tbmu24112_config = {
.volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 100,
.set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
- .pll_set = samsung_tbmu24112_pll_set,
};
/* dvb-t mt352 */
@@ -264,11 +268,14 @@ static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
return 0;
}
-static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
{
u32 div;
unsigned char bs = 0;
+ if (buf_len < 5)
+ return -EINVAL;
+
#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
@@ -276,19 +283,18 @@ static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_front
if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a;
if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08;
- pllbuf[0] = 0xc2; /* Note: non-linux standard PLL i2c address */
+ pllbuf[0] = 0x61;
pllbuf[1] = div >> 8;
pllbuf[2] = div & 0xff;
pllbuf[3] = 0xcc;
pllbuf[4] = bs;
- return 0;
+ return 5;
}
static struct mt352_config samsung_tdtc9251dh0_config = {
.demod_address = 0x0f,
.demod_init = samsung_tdtc9251dh0_demod_init,
- .pll_set = samsung_tdtc9251dh0_pll_set,
};
static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
@@ -297,56 +303,21 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir
return request_firmware(fw, name, fc->dev);
}
-static int lgdt3303_pll_set(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params)
+static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
{
struct flexcop_device *fc = fe->dvb->priv;
- u8 buf[4];
- struct i2c_msg msg =
- { .addr = 0x61, .flags = 0, .buf = buf, .len = 4 };
- int err;
-
- dvb_pll_configure(&dvb_pll_tdvs_tua6034,buf, params->frequency, 0);
- dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
- __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
- if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) {
- printk(KERN_WARNING "lgdt3303: %s error "
- "(addr %02x <- %02x, err = %i)\n",
- __FUNCTION__, buf[0], buf[1], err);
- if (err < 0)
- return err;
- else
- return -EREMOTEIO;
- }
-
- buf[0] = 0x86 | 0x18;
- buf[1] = 0x50;
- msg.len = 2;
- if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) {
- printk(KERN_WARNING "lgdt3303: %s error "
- "(addr %02x <- %02x, err = %i)\n",
- __FUNCTION__, buf[0], buf[1], err);
- if (err < 0)
- return err;
- else
- return -EREMOTEIO;
- }
-
- return 0;
+ return lg_h06xf_pll_set(fe, &fc->i2c_adap, params);
}
static struct lgdt330x_config air2pc_atsc_hd5000_config = {
.demod_address = 0x59,
.demod_chip = LGDT3303,
.serial_mpeg = 0x04,
- .pll_set = lgdt3303_pll_set,
.clock_polarity_flip = 1,
};
static struct nxt200x_config samsung_tbmv_config = {
.demod_address = 0x0a,
- .pll_address = 0xc2,
- .pll_desc = &dvb_pll_samsung_tbmv,
};
static struct bcm3510_config air2pc_atsc_first_gen_config = {
@@ -354,7 +325,7 @@ static struct bcm3510_config air2pc_atsc_first_gen_config = {
.request_firmware = flexcop_fe_request_firmware,
};
-static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
{
u8 buf[4];
u32 div;
@@ -371,6 +342,8 @@ static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct d
if (params->frequency < 1550000)
buf[3] |= 0x02;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
@@ -379,9 +352,52 @@ static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct d
static struct mt312_config skystar23_samsung_tbdu18132_config = {
.demod_address = 0x0e,
- .pll_set = skystar23_samsung_tbdu18132_pll_set,
};
+static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct flexcop_device *fc = fe->dvb->priv;
+ u8 buf[4];
+ u16 div;
+ int ret;
+
+/* 62.5 kHz * 10 */
+#define REF_FREQ 625
+#define FREQ_OFFSET 36125
+
+ div = ((fep->frequency/1000 + FREQ_OFFSET ) * 10) / REF_FREQ; // 4 MHz = 4000 KHz
+
+ buf[0] = (u8)( div >> 8) & 0x7f;
+ buf[1] = (u8) div & 0xff;
+
+/* F(osc) = N * Reference Freq. (62.5 kHz)
+ * byte 2 : 0 N14 N13 N12 N11 N10 N9 N8
+ * byte 3 : N7 N6 N5 N4 N3 N2 N1 N0
+ * byte 4 : 1 * * AGD R3 R2 R1 R0
+ * byte 5 : C1 * RE RTS BS4 BS3 BS2 BS1
+ * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */
+ buf[2] = 0x95;
+
+// Range(MHz) C1 * RE RTS BS4 BS3 BS2 BS1 Byte 5
+// 47 - 153 0 * 0 0 0 0 0 1 0x01
+// 153 - 430 0 * 0 0 0 0 1 0 0x02
+// 430 - 822 0 * 0 0 1 0 0 0 0x08
+// 822 - 862 1 * 0 0 1 0 0 0 0x88
+
+ if (fep->frequency <= 153000000) buf[3] = 0x01;
+ else if (fep->frequency <= 430000000) buf[3] = 0x02;
+ else if (fep->frequency <= 822000000) buf[3] = 0x08;
+ else buf[3] = 0x88;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
+ ret = fc->i2c_request(fc,FC_WRITE,FC_I2C_PORT_TUNER,0x61,buf[0],&buf[1],3);
+ deb_tuner("tuner write returned: %d\n",ret);
+
+ return 0;
+}
static u8 alps_tdee4_stv0297_inittab[] = {
0x80, 0x01,
@@ -490,7 +506,9 @@ int flexcop_frontend_init(struct flexcop_device *fc)
/* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
- ops = fc->fe->ops;
+ ops = &fc->fe->ops;
+
+ ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
ops->set_voltage = flexcop_set_voltage;
@@ -503,16 +521,19 @@ int flexcop_frontend_init(struct flexcop_device *fc)
/* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
fc->dev_type = FC_AIR_DVB;
+ fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
} else
/* try the air atsc 2nd generation (nxt2002) */
if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
fc->dev_type = FC_AIR_ATSC2;
+ dvb_pll_attach(fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_samsung_tbmv);
info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
} else
/* try the air atsc 3nd generation (lgdt3303) */
if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
fc->dev_type = FC_AIR_ATSC3;
+ fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
} else
/* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
@@ -523,11 +544,14 @@ int flexcop_frontend_init(struct flexcop_device *fc)
/* try the cable dvb (stv0297) */
if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
fc->dev_type = FC_CABLE;
+ fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
} else
/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
if ((fc->fe = vp310_mt312_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
- ops = fc->fe->ops;
+ ops = &fc->fe->ops;
+
+ ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
ops->diseqc_send_burst = flexcop_diseqc_send_burst;
@@ -547,7 +571,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
} else {
if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
err("frontend registration failed!");
- ops = fc->fe->ops;
+ ops = &fc->fe->ops;
if (ops->release != NULL)
ops->release(fc->fe);
fc->fe = NULL;
diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c
index 9bc40bdcc282..f04041702191 100644
--- a/drivers/media/dvb/b2c2/flexcop-pci.c
+++ b/drivers/media/dvb/b2c2/flexcop-pci.c
@@ -242,19 +242,16 @@ static int flexcop_pci_dma_init(struct flexcop_pci *fc_pci)
if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[0],FC_DEFAULT_DMA1_BUFSIZE)) != 0)
return ret;
- if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0)
- goto dma1_free;
+ if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0) {
+ flexcop_dma_free(&fc_pci->dma[0]);
+ return ret;
+ }
flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1);
flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2);
fc_pci->init_state |= FC_PCI_DMA_INIT;
- goto success;
-dma1_free:
- flexcop_dma_free(&fc_pci->dma[0]);
-
-success:
return ret;
}
@@ -303,7 +300,7 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci)
spin_lock_init(&fc_pci->irq_lock);
fc_pci->init_state |= FC_PCI_INIT;
- goto success;
+ return ret;
err_pci_iounmap:
pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
@@ -312,8 +309,6 @@ err_pci_release_regions:
pci_release_regions(fc_pci->pdev);
err_pci_disable_device:
pci_disable_device(fc_pci->pdev);
-
-success:
return ret;
}
@@ -378,14 +373,14 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
INIT_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work, fc_pci);
- goto success;
+ return ret;
+
err_fc_exit:
flexcop_device_exit(fc);
err_pci_exit:
flexcop_pci_exit(fc_pci);
err_kfree:
flexcop_device_kfree(fc);
-success:
return ret;
}
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c
index 06ec9fff0ec1..515954f96c9a 100644
--- a/drivers/media/dvb/b2c2/flexcop-usb.c
+++ b/drivers/media/dvb/b2c2/flexcop-usb.c
@@ -433,11 +433,10 @@ static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb)
flexcop_wan_set_speed(fc_usb->fc_dev,FC_WAN_SPEED_8MBITS);
flexcop_sram_ctrl(fc_usb->fc_dev,1,1,1);
- ret = 0;
- goto success;
+ return 0;
+
urb_error:
flexcop_usb_transfer_exit(fc_usb);
-success:
return ret;
}
@@ -515,15 +514,14 @@ static int flexcop_usb_probe(struct usb_interface *intf,
goto err_fc_exit;
info("%s successfully initialized and connected.",DRIVER_NAME);
- ret = 0;
- goto success;
+ return 0;
+
err_fc_exit:
flexcop_device_exit(fc);
err_usb_exit:
flexcop_usb_exit(fc_usb);
err_kfree:
flexcop_device_kfree(fc);
-success:
return ret;
}
diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c
index 56ba52470676..29ec4183118e 100644
--- a/drivers/media/dvb/b2c2/flexcop.c
+++ b/drivers/media/dvb/b2c2/flexcop.c
@@ -67,7 +67,7 @@ static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
static int flexcop_dvb_init(struct flexcop_device *fc)
{
int ret;
- if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner)) < 0) {
+ if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner,fc->dev)) < 0) {
err("error registering DVB adapter");
return ret;
}
@@ -116,7 +116,7 @@ static int flexcop_dvb_init(struct flexcop_device *fc)
dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx);
fc->init_state |= FC_STATE_DVB_INIT;
- goto success;
+ return 0;
err_connect_frontend:
fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend);
@@ -129,9 +129,6 @@ err_dmx_dev:
err_dmx:
dvb_unregister_adapter(&fc->dvb_adapter);
return ret;
-
-success:
- return 0;
}
static void flexcop_dvb_exit(struct flexcop_device *fc)
@@ -279,11 +276,10 @@ int flexcop_device_initialize(struct flexcop_device *fc)
flexcop_device_name(fc,"initialization of","complete");
- ret = 0;
- goto success;
+ return 0;
+
error:
flexcop_device_exit(fc);
-success:
return ret;
}
EXPORT_SYMBOL(flexcop_device_initialize);
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index 5500f8a0ffe2..761fa6e7d762 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -63,8 +63,6 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging, default is 0 (off).");
int bt878_num;
struct bt878 bt878[BT878_MAX];
-EXPORT_SYMBOL(bt878_debug);
-EXPORT_SYMBOL(bt878_verbose);
EXPORT_SYMBOL(bt878_num);
EXPORT_SYMBOL(bt878);
@@ -393,7 +391,9 @@ static struct cards card_list[] __devinitdata = {
{ 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" },
{ 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" },
{ 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" },
- { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"},
+ { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV" },
+ { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini" },
+
{ 0, -1, NULL }
};
@@ -417,6 +417,11 @@ static int __devinit bt878_probe(struct pci_dev *dev,
printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
bt878_num);
+ if (bt878_num >= BT878_MAX) {
+ printk(KERN_ERR "bt878: Too many devices inserted\n");
+ result = -ENOMEM;
+ goto fail0;
+ }
if (pci_enable_device(dev))
return -EIO;
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 1cfa5e5035d8..d687a14ec0a7 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -38,6 +38,10 @@ static unsigned int dst_addons;
module_param(dst_addons, int, 0644);
MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
+static unsigned int dst_algo;
+module_param(dst_algo, int, 0644);
+MODULE_PARM_DESC(dst_algo, "tuning algo: default is 0=(SW), 1=(HW)");
+
#define HAS_LOCK 1
#define ATTEMPT_TUNE 2
#define HAS_POWER 4
@@ -47,20 +51,24 @@ MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
#define DST_INFO 2
#define DST_DEBUG 3
-#define dprintk(x, y, z, format, arg...) do { \
- if (z) { \
- if ((x > DST_ERROR) && (x > y)) \
- printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg); \
- else if ((x > DST_NOTICE) && (x > y)) \
- printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg); \
- else if ((x > DST_INFO) && (x > y)) \
- printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg); \
- else if ((x > DST_DEBUG) && (x > y)) \
- printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg); \
- } else { \
- if (x > y) \
- printk(format, ##arg); \
- } \
+#define dprintk(x, y, z, format, arg...) do { \
+ if (z) { \
+ if ((x > DST_ERROR) && (x > y)) \
+ printk(KERN_ERR "dst(%d) %s: " format "\n", \
+ state->bt->nr, __func__ , ##arg); \
+ else if ((x > DST_NOTICE) && (x > y)) \
+ printk(KERN_NOTICE "dst(%d) %s: " format "\n", \
+ state->bt->nr, __func__ , ##arg); \
+ else if ((x > DST_INFO) && (x > y)) \
+ printk(KERN_INFO "dst(%d) %s: " format "\n", \
+ state->bt->nr, __func__ , ##arg); \
+ else if ((x > DST_DEBUG) && (x > y)) \
+ printk(KERN_DEBUG "dst(%d) %s: " format "\n", \
+ state->bt->nr, __func__ , ##arg); \
+ } else { \
+ if (x > y) \
+ printk(format, ##arg); \
+ } \
} while(0)
@@ -110,7 +118,7 @@ int dst_gpio_inb(struct dst_state *state, u8 *result)
*result = 0;
if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) {
- dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)\n", err);
+ dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)", err);
return -EREMOTEIO;
}
*result = (u8) rd_packet.rd.value;
@@ -363,6 +371,17 @@ static int dst_set_freq(struct dst_state *state, u32 freq)
state->tx_tuna[2] = (freq >> 16) & 0xff;
state->tx_tuna[3] = (freq >> 8) & 0xff;
state->tx_tuna[4] = (u8) freq;
+ } else if (state->dst_type == DST_TYPE_IS_ATSC) {
+ freq = freq / 1000;
+ if (freq < 51000 || freq > 858000)
+ return -EINVAL;
+ state->tx_tuna[2] = (freq >> 16) & 0xff;
+ state->tx_tuna[3] = (freq >> 8) & 0xff;
+ state->tx_tuna[4] = (u8) freq;
+ state->tx_tuna[5] = 0x00; /* ATSC */
+ state->tx_tuna[6] = 0x00;
+ if (state->dst_hw_cap & DST_TYPE_HAS_ANALOG)
+ state->tx_tuna[7] = 0x00; /* Digital */
} else
return -EINVAL;
@@ -447,29 +466,41 @@ static int dst_set_symbolrate(struct dst_state *state, u32 srate)
}
dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
srate /= 1000;
- if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
- sval = srate;
- sval <<= 20;
- do_div(sval, 88000);
- symcalc = (u32) sval;
- dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
- state->tx_tuna[5] = (u8) (symcalc >> 12);
- state->tx_tuna[6] = (u8) (symcalc >> 4);
- state->tx_tuna[7] = (u8) (symcalc << 4);
- } else {
- state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
- state->tx_tuna[6] = (u8) (srate >> 8);
- state->tx_tuna[7] = (u8) srate;
- }
- state->tx_tuna[8] &= ~0x20;
- if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
- if (srate > 8000)
- state->tx_tuna[8] |= 0x20;
+ if (state->dst_type == DST_TYPE_IS_SAT) {
+ if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
+ sval = srate;
+ sval <<= 20;
+ do_div(sval, 88000);
+ symcalc = (u32) sval;
+ dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
+ state->tx_tuna[5] = (u8) (symcalc >> 12);
+ state->tx_tuna[6] = (u8) (symcalc >> 4);
+ state->tx_tuna[7] = (u8) (symcalc << 4);
+ } else {
+ state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
+ state->tx_tuna[6] = (u8) (srate >> 8);
+ state->tx_tuna[7] = (u8) srate;
+ }
+ state->tx_tuna[8] &= ~0x20;
+ if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
+ if (srate > 8000)
+ state->tx_tuna[8] |= 0x20;
+ }
+ } else if (state->dst_type == DST_TYPE_IS_CABLE) {
+ dprintk(verbose, DST_DEBUG, 1, "%s", state->fw_name);
+ if (!strncmp(state->fw_name, "DCTNEW", 6)) {
+ state->tx_tuna[5] = (u8) (srate >> 8);
+ state->tx_tuna[6] = (u8) srate;
+ state->tx_tuna[7] = 0x00;
+ } else if (!strncmp(state->fw_name, "DCT-CI", 6)) {
+ state->tx_tuna[5] = 0x00;
+ state->tx_tuna[6] = (u8) (srate >> 8);
+ state->tx_tuna[7] = (u8) srate;
+ }
}
return 0;
}
-
static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation)
{
if (state->dst_type != DST_TYPE_IS_CABLE)
@@ -490,7 +521,10 @@ static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulatio
state->tx_tuna[8] = 0x80;
break;
case QAM_256:
- state->tx_tuna[8] = 0x00;
+ if (!strncmp(state->fw_name, "DCTNEW", 6))
+ state->tx_tuna[8] = 0xff;
+ else if (!strncmp(state->fw_name, "DCT-CI", 6))
+ state->tx_tuna[8] = 0x00;
break;
case QPSK:
case QAM_AUTO:
@@ -523,13 +557,19 @@ u8 dst_check_sum(u8 *buf, u32 len)
}
EXPORT_SYMBOL(dst_check_sum);
-static void dst_type_flags_print(u32 type_flags)
+static void dst_type_flags_print(struct dst_state *state)
{
+ u32 type_flags = state->type_flags;
+
dprintk(verbose, DST_ERROR, 0, "DST type flags :");
- if (type_flags & DST_TYPE_HAS_NEWTUNE)
- dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_NEWTUNE);
+ if (type_flags & DST_TYPE_HAS_TS188)
+ dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_TS188);
+ if (type_flags & DST_TYPE_HAS_NEWTUNE_2)
+ dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner 2", DST_TYPE_HAS_NEWTUNE_2);
if (type_flags & DST_TYPE_HAS_TS204)
dprintk(verbose, DST_ERROR, 0, " 0x%x ts204", DST_TYPE_HAS_TS204);
+ if (type_flags & DST_TYPE_HAS_VLF)
+ dprintk(verbose, DST_ERROR, 0, " 0x%x VLF", DST_TYPE_HAS_VLF);
if (type_flags & DST_TYPE_HAS_SYMDIV)
dprintk(verbose, DST_ERROR, 0, " 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
if (type_flags & DST_TYPE_HAS_FW_1)
@@ -542,7 +582,7 @@ static void dst_type_flags_print(u32 type_flags)
}
-static int dst_type_print(u8 type)
+static int dst_type_print(struct dst_state *state, u8 type)
{
char *otype;
switch (type) {
@@ -558,6 +598,10 @@ static int dst_type_print(u8 type)
otype = "cable";
break;
+ case DST_TYPE_IS_ATSC:
+ otype = "atsc";
+ break;
+
default:
dprintk(verbose, DST_INFO, 1, "invalid dst type %d", type);
return -EINVAL;
@@ -567,6 +611,127 @@ static int dst_type_print(u8 type)
return 0;
}
+struct tuner_types tuner_list[] = {
+ {
+ .tuner_type = TUNER_TYPE_L64724,
+ .tuner_name = "L 64724",
+ .board_name = "UNKNOWN",
+ .fw_name = "UNKNOWN"
+ },
+
+ {
+ .tuner_type = TUNER_TYPE_STV0299,
+ .tuner_name = "STV 0299",
+ .board_name = "VP1020",
+ .fw_name = "DST-MOT"
+ },
+
+ {
+ .tuner_type = TUNER_TYPE_STV0299,
+ .tuner_name = "STV 0299",
+ .board_name = "VP1020",
+ .fw_name = "DST-03T"
+ },
+
+ {
+ .tuner_type = TUNER_TYPE_MB86A15,
+ .tuner_name = "MB 86A15",
+ .board_name = "VP1022",
+ .fw_name = "DST-03T"
+ },
+
+ {
+ .tuner_type = TUNER_TYPE_MB86A15,
+ .tuner_name = "MB 86A15",
+ .board_name = "VP1025",
+ .fw_name = "DST-03T"
+ },
+
+ {
+ .tuner_type = TUNER_TYPE_STV0299,
+ .tuner_name = "STV 0299",
+ .board_name = "VP1030",
+ .fw_name = "DST-CI"
+ },
+
+ {
+ .tuner_type = TUNER_TYPE_STV0299,
+ .tuner_name = "STV 0299",
+ .board_name = "VP1030",
+ .fw_name = "DSTMCI"
+ },
+
+ {
+ .tuner_type = TUNER_TYPE_UNKNOWN,
+ .tuner_name = "UNKNOWN",
+ .board_name = "VP2021",
+ .fw_name = "DCTNEW"
+ },
+
+ {
+ .tuner_type = TUNER_TYPE_UNKNOWN,
+ .tuner_name = "UNKNOWN",
+ .board_name = "VP2030",
+ .fw_name = "DCT-CI"
+ },
+
+ {
+ .tuner_type = TUNER_TYPE_UNKNOWN,
+ .tuner_name = "UNKNOWN",
+ .board_name = "VP2031",
+ .fw_name = "DCT-CI"
+ },
+
+ {
+ .tuner_type = TUNER_TYPE_UNKNOWN,
+ .tuner_name = "UNKNOWN",
+ .board_name = "VP2040",
+ .fw_name = "DCT-CI"
+ },
+
+ {
+ .tuner_type = TUNER_TYPE_UNKNOWN,
+ .tuner_name = "UNKNOWN",
+ .board_name = "VP3020",
+ .fw_name = "DTTFTA"
+ },
+
+ {
+ .tuner_type = TUNER_TYPE_UNKNOWN,
+ .tuner_name = "UNKNOWN",
+ .board_name = "VP3021",
+ .fw_name = "DTTFTA"
+ },
+
+ {
+ .tuner_type = TUNER_TYPE_TDA10046,
+ .tuner_name = "TDA10046",
+ .board_name = "VP3040",
+ .fw_name = "DTT-CI"
+ },
+
+ {
+ .tuner_type = TUNER_TYPE_UNKNOWN,
+ .tuner_name = "UNKNOWN",
+ .board_name = "VP3051",
+ .fw_name = "DTTNXT"
+ },
+
+ {
+ .tuner_type = TUNER_TYPE_NXT200x,
+ .tuner_name = "NXT200x",
+ .board_name = "VP3220",
+ .fw_name = "ATSCDI"
+ },
+
+ {
+ .tuner_type = TUNER_TYPE_NXT200x,
+ .tuner_name = "NXT200x",
+ .board_name = "VP3250",
+ .fw_name = "ATSCAD"
+ },
+};
+
/*
Known cards list
Satellite
@@ -608,7 +773,8 @@ static struct dst_types dst_tlist[] = {
.offset = 0,
.dst_type = DST_TYPE_IS_SAT,
.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS,
- .dst_feature = 0
+ .dst_feature = 0,
+ .tuner_type = 0
}, /* obsolete */
{
@@ -616,15 +782,17 @@ static struct dst_types dst_tlist[] = {
.offset = 0,
.dst_type = DST_TYPE_IS_SAT,
.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
- .dst_feature = 0
+ .dst_feature = 0,
+ .tuner_type = 0
}, /* obsolete */
{
.device_id = "DST-030",
.offset = 0,
.dst_type = DST_TYPE_IS_SAT,
- .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
- .dst_feature = 0
+ .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
+ .dst_feature = 0,
+ .tuner_type = 0
}, /* obsolete */
{
@@ -633,7 +801,8 @@ static struct dst_types dst_tlist[] = {
.dst_type = DST_TYPE_IS_SAT,
.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
.dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5
- | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO
+ | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO,
+ .tuner_type = TUNER_TYPE_MULTI
},
{
@@ -641,57 +810,63 @@ static struct dst_types dst_tlist[] = {
.offset = 0,
.dst_type = DST_TYPE_IS_SAT,
.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
- .dst_feature = 0
+ .dst_feature = 0,
+ .tuner_type = 0
}, /* obsolete */
{
.device_id = "DST-CI",
.offset = 1,
.dst_type = DST_TYPE_IS_SAT,
- .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
- .dst_feature = DST_TYPE_HAS_CA
+ .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_1,
+ .dst_feature = DST_TYPE_HAS_CA,
+ .tuner_type = 0
}, /* An OEM board */
{
.device_id = "DSTMCI",
.offset = 1,
.dst_type = DST_TYPE_IS_SAT,
- .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT,
+ .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT | DST_TYPE_HAS_VLF,
.dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4
- | DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC
+ | DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC,
+ .tuner_type = TUNER_TYPE_MULTI
},
{
.device_id = "DSTFCI",
.offset = 1,
.dst_type = DST_TYPE_IS_SAT,
- .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
- .dst_feature = 0
+ .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
+ .dst_feature = 0,
+ .tuner_type = 0
}, /* unknown to vendor */
{
.device_id = "DCT-CI",
.offset = 1,
.dst_type = DST_TYPE_IS_CABLE,
- .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1
- | DST_TYPE_HAS_FW_2,
- .dst_feature = DST_TYPE_HAS_CA
+ .type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_VLF,
+ .dst_feature = DST_TYPE_HAS_CA,
+ .tuner_type = 0
},
{
.device_id = "DCTNEW",
.offset = 1,
.dst_type = DST_TYPE_IS_CABLE,
- .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD,
- .dst_feature = 0
+ .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_MULTI_FE,
+ .dst_feature = 0,
+ .tuner_type = 0
},
{
.device_id = "DTT-CI",
.offset = 1,
.dst_type = DST_TYPE_IS_TERR,
- .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE,
- .dst_feature = DST_TYPE_HAS_CA
+ .type_flags = DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_VLF,
+ .dst_feature = DST_TYPE_HAS_CA,
+ .tuner_type = 0
},
{
@@ -699,7 +874,8 @@ static struct dst_types dst_tlist[] = {
.offset = 1,
.dst_type = DST_TYPE_IS_TERR,
.type_flags = DST_TYPE_HAS_FW_2,
- .dst_feature = 0
+ .dst_feature = 0,
+ .tuner_type = 0
},
{
@@ -707,7 +883,8 @@ static struct dst_types dst_tlist[] = {
.offset = 1,
.dst_type = DST_TYPE_IS_TERR,
.type_flags = DST_TYPE_HAS_FW_2,
- .dst_feature = DST_TYPE_HAS_ANALOG
+ .dst_feature = DST_TYPE_HAS_ANALOG,
+ .tuner_type = 0
},
{
@@ -715,15 +892,17 @@ static struct dst_types dst_tlist[] = {
.offset = 1,
.dst_type = DST_TYPE_IS_ATSC,
.type_flags = DST_TYPE_HAS_FW_2,
- .dst_feature = 0
+ .dst_feature = 0,
+ .tuner_type = 0
},
{
.device_id = "ATSCAD",
.offset = 1,
.dst_type = DST_TYPE_IS_ATSC,
- .type_flags = DST_TYPE_HAS_FW_2,
- .dst_feature = 0
+ .type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
+ .dst_feature = DST_TYPE_HAS_MAC | DST_TYPE_HAS_ANALOG,
+ .tuner_type = 0
},
{ }
@@ -768,6 +947,9 @@ static int dst_fw_ver(struct dst_state *state)
static int dst_card_type(struct dst_state *state)
{
+ int j;
+ struct tuner_types *p_tuner_list = NULL;
+
u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
get_type[7] = dst_check_sum(get_type, 7);
if (dst_command(state, get_type, 8) < 0) {
@@ -775,9 +957,17 @@ static int dst_card_type(struct dst_state *state)
return -1;
}
memset(&state->card_info, '\0', 8);
- memcpy(&state->card_info, &state->rxbuffer, 8);
+ memcpy(&state->card_info, &state->rxbuffer, 7);
dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]);
+ for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
+ if (!strcmp(&state->card_info[0], p_tuner_list->board_name)) {
+ state->tuner_type = p_tuner_list->tuner_type;
+ dprintk(verbose, DST_ERROR, 1, "DST has [%s] tuner, tuner type=[%d]",
+ p_tuner_list->tuner_name, p_tuner_list->tuner_type);
+ }
+ }
+
return 0;
}
@@ -790,12 +980,64 @@ static int dst_get_vendor(struct dst_state *state)
return -1;
}
memset(&state->vendor, '\0', 8);
- memcpy(&state->vendor, &state->rxbuffer, 8);
+ memcpy(&state->vendor, &state->rxbuffer, 7);
dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]);
return 0;
}
+static void debug_dst_buffer(struct dst_state *state)
+{
+ int i;
+
+ if (verbose > 2) {
+ printk("%s: [", __func__);
+ for (i = 0; i < 8; i++)
+ printk(" %02x", state->rxbuffer[i]);
+ printk("]\n");
+ }
+}
+
+static int dst_check_stv0299(struct dst_state *state)
+{
+ u8 check_stv0299[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ check_stv0299[7] = dst_check_sum(check_stv0299, 7);
+ if (dst_command(state, check_stv0299, 8) < 0) {
+ dprintk(verbose, DST_ERROR, 1, "Cmd=[0x04] failed");
+ return -1;
+ }
+ debug_dst_buffer(state);
+
+ if (memcmp(&check_stv0299, &state->rxbuffer, 8)) {
+ dprintk(verbose, DST_ERROR, 1, "Found a STV0299 NIM");
+ state->tuner_type = TUNER_TYPE_STV0299;
+ return 0;
+ }
+
+ return -1;
+}
+
+static int dst_check_mb86a15(struct dst_state *state)
+{
+ u8 check_mb86a15[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ check_mb86a15[7] = dst_check_sum(check_mb86a15, 7);
+ if (dst_command(state, check_mb86a15, 8) < 0) {
+ dprintk(verbose, DST_ERROR, 1, "Cmd=[0x10], failed");
+ return -1;
+ }
+ debug_dst_buffer(state);
+
+ if (memcmp(&check_mb86a15, &state->rxbuffer, 8) < 0) {
+ dprintk(verbose, DST_ERROR, 1, "Found a MB86A15 NIM");
+ state->tuner_type = TUNER_TYPE_MB86A15;
+ return 0;
+ }
+
+ return -1;
+}
+
static int dst_get_tuner_info(struct dst_state *state)
{
u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -803,60 +1045,59 @@ static int dst_get_tuner_info(struct dst_state *state)
get_tuner_1[7] = dst_check_sum(get_tuner_1, 7);
get_tuner_2[7] = dst_check_sum(get_tuner_2, 7);
+ dprintk(verbose, DST_ERROR, 1, "DST TYpe = MULTI FE");
if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
- if (dst_command(state, get_tuner_2, 8) < 0) {
- dprintk(verbose, DST_INFO, 1, "Unsupported Command");
- return -1;
+ if (dst_command(state, get_tuner_1, 8) < 0) {
+ dprintk(verbose, DST_INFO, 1, "Cmd=[0x13], Unsupported");
+ goto force;
}
} else {
- if (dst_command(state, get_tuner_1, 8) < 0) {
- dprintk(verbose, DST_INFO, 1, "Unsupported Command");
- return -1;
+ if (dst_command(state, get_tuner_2, 8) < 0) {
+ dprintk(verbose, DST_INFO, 1, "Cmd=[0xb], Unsupported");
+ goto force;
}
}
memset(&state->board_info, '\0', 8);
memcpy(&state->board_info, &state->rxbuffer, 8);
if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
- if (state->board_info[1] == 0x0b) {
- if (state->type_flags & DST_TYPE_HAS_TS204)
- state->type_flags &= ~DST_TYPE_HAS_TS204;
- state->type_flags |= DST_TYPE_HAS_NEWTUNE;
- dprintk(verbose, DST_INFO, 1, "DST type has TS=188");
- } else {
- if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
- state->type_flags &= ~DST_TYPE_HAS_NEWTUNE;
- state->type_flags |= DST_TYPE_HAS_TS204;
- dprintk(verbose, DST_INFO, 1, "DST type has TS=204");
- }
- } else {
- if (state->board_info[0] == 0xbc) {
- if (state->type_flags & DST_TYPE_HAS_TS204)
- state->type_flags &= ~DST_TYPE_HAS_TS204;
- state->type_flags |= DST_TYPE_HAS_NEWTUNE;
- dprintk(verbose, DST_INFO, 1, "DST type has TS=188, Daughterboard=[%d]", state->board_info[1]);
-
- } else if (state->board_info[0] == 0xcc) {
- if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
- state->type_flags &= ~DST_TYPE_HAS_NEWTUNE;
- state->type_flags |= DST_TYPE_HAS_TS204;
- dprintk(verbose, DST_INFO, 1, "DST type has TS=204 Daughterboard=[%d]", state->board_info[1]);
+ dprintk(verbose, DST_ERROR, 1, "DST type has TS=188");
+ }
+ if (state->board_info[0] == 0xbc) {
+ if (state->type_flags != DST_TYPE_IS_ATSC)
+ state->type_flags |= DST_TYPE_HAS_TS188;
+ else
+ state->type_flags |= DST_TYPE_HAS_NEWTUNE_2;
+
+ if (state->board_info[1] == 0x01) {
+ state->dst_hw_cap |= DST_TYPE_HAS_DBOARD;
+ dprintk(verbose, DST_ERROR, 1, "DST has Daughterboard");
}
}
return 0;
+force:
+ if (!strncmp(state->fw_name, "DCT-CI", 6)) {
+ state->type_flags |= DST_TYPE_HAS_TS204;
+ dprintk(verbose, DST_ERROR, 1, "Forcing [%s] to TS188", state->fw_name);
+ }
+
+ return -1;
}
static int dst_get_device_id(struct dst_state *state)
{
u8 reply;
- int i;
- struct dst_types *p_dst_type;
+ int i, j;
+ struct dst_types *p_dst_type = NULL;
+ struct tuner_types *p_tuner_list = NULL;
+
u8 use_dst_type = 0;
u32 use_type_flags = 0;
static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
+ state->tuner_type = 0;
device_type[7] = dst_check_sum(device_type, 7);
if (write_dst(state, device_type, FIXED_COMM))
@@ -888,8 +1129,34 @@ static int dst_get_device_id(struct dst_state *state)
/* Card capabilities */
state->dst_hw_cap = p_dst_type->dst_feature;
- dprintk(verbose, DST_ERROR, 1, "Recognise [%s]\n", p_dst_type->device_id);
-
+ dprintk(verbose, DST_ERROR, 1, "Recognise [%s]", p_dst_type->device_id);
+ strncpy(&state->fw_name[0], p_dst_type->device_id, 6);
+ /* Multiple tuners */
+ if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) {
+ switch (use_dst_type) {
+ case DST_TYPE_IS_SAT:
+ /* STV0299 check */
+ if (dst_check_stv0299(state) < 0) {
+ dprintk(verbose, DST_ERROR, 1, "Unsupported");
+ state->tuner_type = TUNER_TYPE_MB86A15;
+ }
+ break;
+ default:
+ break;
+ }
+ if (dst_check_mb86a15(state) < 0)
+ dprintk(verbose, DST_ERROR, 1, "Unsupported");
+ /* Single tuner */
+ } else {
+ state->tuner_type = p_dst_type->tuner_type;
+ }
+ for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
+ if (!(strncmp(p_dst_type->device_id, p_tuner_list->fw_name, 7)) &&
+ p_tuner_list->tuner_type == state->tuner_type) {
+ dprintk(verbose, DST_ERROR, 1, "[%s] has a [%s]",
+ p_dst_type->device_id, p_tuner_list->tuner_name);
+ }
+ }
break;
}
}
@@ -900,10 +1167,10 @@ static int dst_get_device_id(struct dst_state *state)
use_dst_type = DST_TYPE_IS_SAT;
use_type_flags = DST_TYPE_HAS_SYMDIV;
}
- dst_type_print(use_dst_type);
+ dst_type_print(state, use_dst_type);
state->type_flags = use_type_flags;
state->dst_type = use_dst_type;
- dst_type_flags_print(state->type_flags);
+ dst_type_flags_print(state);
return 0;
}
@@ -911,15 +1178,15 @@ static int dst_get_device_id(struct dst_state *state)
static int dst_probe(struct dst_state *state)
{
mutex_init(&state->dst_mutex);
- if ((rdc_8820_reset(state)) < 0) {
- dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
- return -1;
- }
- if (dst_addons & DST_TYPE_HAS_CA)
+ if (dst_addons & DST_TYPE_HAS_CA) {
+ if ((rdc_8820_reset(state)) < 0) {
+ dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
+ return -1;
+ }
msleep(4000);
- else
+ } else {
msleep(100);
-
+ }
if ((dst_comm_init(state)) < 0) {
dprintk(verbose, DST_ERROR, 1, "DST Initialization Failed.");
return -1;
@@ -931,7 +1198,6 @@ static int dst_probe(struct dst_state *state)
}
if (dst_get_mac(state) < 0) {
dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command");
- return 0;
}
if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) {
if (dst_get_tuner_info(state) < 0)
@@ -1048,6 +1314,10 @@ static int dst_get_signal(struct dst_state *state)
state->decode_lock = (state->rxbuffer[1]) ? 1 : 0;
state->decode_strength = state->rxbuffer[4] << 8;
state->decode_snr = state->rxbuffer[3] << 8;
+ } else if (state->dst_type == DST_TYPE_IS_ATSC) {
+ state->decode_lock = (state->rxbuffer[6] == 0x00) ? 1 : 0;
+ state->decode_strength = state->rxbuffer[4] << 8;
+ state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3];
}
state->cur_jiff = jiffies;
}
@@ -1078,8 +1348,9 @@ static int dst_get_tuna(struct dst_state *state)
state->diseq_flags &= ~(HAS_LOCK);
if (!dst_wait_dst_ready(state, NO_DELAY))
return -EIO;
- if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
- /* how to get variable length reply ???? */
+ if ((state->type_flags & DST_TYPE_HAS_VLF) &&
+ !(state->dst_type == DST_TYPE_IS_ATSC))
+
retval = read_dst(state, state->rx_tuna, 10);
else
retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
@@ -1087,7 +1358,10 @@ static int dst_get_tuna(struct dst_state *state)
dprintk(verbose, DST_DEBUG, 1, "read not successful");
return retval;
}
- if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
+ if ((state->type_flags & DST_TYPE_HAS_VLF) &&
+ !(state->dst_type == DST_TYPE_IS_CABLE) &&
+ !(state->dst_type == DST_TYPE_IS_ATSC)) {
+
if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
return -EIO;
@@ -1133,7 +1407,10 @@ static int dst_write_tuna(struct dvb_frontend *fe)
dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed.");
goto error;
}
- if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
+// if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
+ if ((state->type_flags & DST_TYPE_HAS_VLF) &&
+ (!(state->dst_type == DST_TYPE_IS_ATSC))) {
+
state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
retval = write_dst(state, &state->tx_tuna[0], 10);
} else {
@@ -1189,9 +1466,12 @@ static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd
if (state->dst_type != DST_TYPE_IS_SAT)
return 0;
- if (cmd->msg_len == 0 || cmd->msg_len > 4)
+ if (cmd->msg_len > 0 && cmd->msg_len < 5)
+ memcpy(&paket[3], cmd->msg, cmd->msg_len);
+ else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5)
+ memcpy(&paket[2], cmd->msg, cmd->msg_len);
+ else
return -EINVAL;
- memcpy(&paket[3], cmd->msg, cmd->msg_len);
paket[7] = dst_check_sum(&paket[0], 7);
dst_command(state, paket, 8);
return 0;
@@ -1287,8 +1567,9 @@ static int dst_init(struct dvb_frontend *fe)
static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 };
static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
- static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+ static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+ static u8 atsc_tuner[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
state->inversion = INVERSION_OFF;
state->voltage = SEC_VOLTAGE_13;
@@ -1298,11 +1579,13 @@ static int dst_init(struct dvb_frontend *fe)
state->bandwidth = BANDWIDTH_7_MHZ;
state->cur_jiff = jiffies;
if (state->dst_type == DST_TYPE_IS_SAT)
- memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
+ memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
else if (state->dst_type == DST_TYPE_IS_TERR)
- memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
+ memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
else if (state->dst_type == DST_TYPE_IS_CABLE)
- memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
+ memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
+ else if (state->dst_type == DST_TYPE_IS_ATSC)
+ memcpy(state->tx_tuna, atsc_tuner, sizeof (atsc_tuner));
return 0;
}
@@ -1341,7 +1624,36 @@ static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
return 0;
}
-static int dst_set_frontend(struct dvb_frontend* fe,
+static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+ struct dst_state *state = fe->demodulator_priv;
+
+ if (p != NULL) {
+ dst_set_freq(state, p->frequency);
+ dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
+
+ if (state->dst_type == DST_TYPE_IS_SAT) {
+ if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
+ dst_set_inversion(state, p->inversion);
+ dst_set_fec(state, p->u.qpsk.fec_inner);
+ dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
+ dst_set_polarization(state);
+ dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
+
+ } else if (state->dst_type == DST_TYPE_IS_TERR)
+ dst_set_bandwidth(state, p->u.ofdm.bandwidth);
+ else if (state->dst_type == DST_TYPE_IS_CABLE) {
+ dst_set_fec(state, p->u.qam.fec_inner);
+ dst_set_symbolrate(state, p->u.qam.symbol_rate);
+ dst_set_modulation(state, p->u.qam.modulation);
+ }
+ dst_write_tuna(fe);
+ }
+
+ return 0;
+}
+
+static int dst_tune_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters* p,
unsigned int mode_flags,
int *delay,
@@ -1378,6 +1690,11 @@ static int dst_set_frontend(struct dvb_frontend* fe,
return 0;
}
+static int dst_get_tuning_algo(struct dvb_frontend *fe)
+{
+ return dst_algo;
+}
+
static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
{
struct dst_state *state = fe->demodulator_priv;
@@ -1408,6 +1725,7 @@ static void dst_release(struct dvb_frontend *fe)
static struct dvb_frontend_ops dst_dvbt_ops;
static struct dvb_frontend_ops dst_dvbs_ops;
static struct dvb_frontend_ops dst_dvbc_ops;
+static struct dvb_frontend_ops dst_atsc_ops;
struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
{
@@ -1417,24 +1735,25 @@ struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad
return NULL;
}
/* determine settings based on type */
+ /* create dvb_frontend */
switch (state->dst_type) {
case DST_TYPE_IS_TERR:
- memcpy(&state->ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
+ memcpy(&state->frontend.ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
break;
case DST_TYPE_IS_CABLE:
- memcpy(&state->ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
+ memcpy(&state->frontend.ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
break;
case DST_TYPE_IS_SAT:
- memcpy(&state->ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
+ memcpy(&state->frontend.ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
+ break;
+ case DST_TYPE_IS_ATSC:
+ memcpy(&state->frontend.ops, &dst_atsc_ops, sizeof(struct dvb_frontend_ops));
break;
default:
dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist.");
kfree(state);
return NULL;
}
-
- /* create dvb_frontend */
- state->frontend.ops = &state->ops;
state->frontend.demodulator_priv = state;
return state; /* Manu (DST is a card not a frontend) */
@@ -1455,8 +1774,10 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
.release = dst_release,
.init = dst_init,
- .tune = dst_set_frontend,
+ .tune = dst_tune_frontend,
+ .set_frontend = dst_set_frontend,
.get_frontend = dst_get_frontend,
+ .get_frontend_algo = dst_get_tuning_algo,
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
.read_snr = dst_read_snr,
@@ -1479,8 +1800,10 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
.release = dst_release,
.init = dst_init,
- .tune = dst_set_frontend,
+ .tune = dst_tune_frontend,
+ .set_frontend = dst_set_frontend,
.get_frontend = dst_get_frontend,
+ .get_frontend_algo = dst_get_tuning_algo,
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
.read_snr = dst_read_snr,
@@ -1506,13 +1829,38 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
.release = dst_release,
.init = dst_init,
- .tune = dst_set_frontend,
+ .tune = dst_tune_frontend,
+ .set_frontend = dst_set_frontend,
+ .get_frontend = dst_get_frontend,
+ .get_frontend_algo = dst_get_tuning_algo,
+ .read_status = dst_read_status,
+ .read_signal_strength = dst_read_signal_strength,
+ .read_snr = dst_read_snr,
+};
+
+static struct dvb_frontend_ops dst_atsc_ops = {
+ .info = {
+ .name = "DST ATSC",
+ .type = FE_ATSC,
+ .frequency_stepsize = 62500,
+ .frequency_min = 510000000,
+ .frequency_max = 858000000,
+ .symbol_rate_min = 1000000,
+ .symbol_rate_max = 45000000,
+ .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+ },
+
+ .release = dst_release,
+ .init = dst_init,
+ .tune = dst_tune_frontend,
+ .set_frontend = dst_set_frontend,
.get_frontend = dst_get_frontend,
+ .get_frontend_algo = dst_get_tuning_algo,
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
.read_snr = dst_read_snr,
};
-MODULE_DESCRIPTION("DST DVB-S/T/C Combo Frontend driver");
+MODULE_DESCRIPTION("DST DVB-S/T/C/ATSC Combo Frontend driver");
MODULE_AUTHOR("Jamie Honan, Manu Abraham");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
index f6b49a801eba..fa923b9b346e 100644
--- a/drivers/media/dvb/bt8xx/dst_ca.c
+++ b/drivers/media/dvb/bt8xx/dst_ca.c
@@ -68,6 +68,13 @@ static int ca_set_pid(void)
return -EOPNOTSUPP;
}
+static void put_command_and_length(u8 *data, int command, int length)
+{
+ data[0] = (command >> 16) & 0xff;
+ data[1] = (command >> 8) & 0xff;
+ data[2] = command & 0xff;
+ data[3] = length;
+}
static void put_checksum(u8 *check_string, int length)
{
@@ -124,15 +131,18 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string,
u8 dst_ca_comm_err = 0;
while (dst_ca_comm_err < RETRIES) {
- dst_comm_init(state);
dprintk(verbose, DST_CA_NOTICE, 1, " Put Command");
if (dst_ci_command(state, data, ca_string, len, read)) { // If error
dst_error_recovery(state);
dst_ca_comm_err++; // work required here.
+ } else {
+ break;
}
- break;
}
+ if(dst_ca_comm_err == RETRIES)
+ return -1;
+
return 0;
}
@@ -140,6 +150,7 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string,
static int ca_get_app_info(struct dst_state *state)
{
+ int length, str_length;
static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff};
put_checksum(&command[0], command[0]);
@@ -154,6 +165,68 @@ static int ca_get_app_info(struct dst_state *state)
(state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
+ // Transform dst message to correct application_info message
+ length = state->messages[5];
+ str_length = length - 6;
+ if (str_length < 0) {
+ str_length = 0;
+ dprintk(verbose, DST_CA_ERROR, 1, "Invalid string length returned in ca_get_app_info(). Recovering.");
+ }
+
+ // First, the command and length fields
+ put_command_and_length(&state->messages[0], CA_APP_INFO, length);
+
+ // Copy application_type, application_manufacturer and manufacturer_code
+ memcpy(&state->messages[4], &state->messages[7], 5);
+
+ // Set string length and copy string
+ state->messages[9] = str_length;
+ memcpy(&state->messages[10], &state->messages[12], str_length);
+
+ return 0;
+}
+
+static int ca_get_ca_info(struct dst_state *state)
+{
+ int srcPtr, dstPtr, i, num_ids;
+ static u8 slot_command[8] = {0x07, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0xff};
+ const int in_system_id_pos = 8, out_system_id_pos = 4, in_num_ids_pos = 7;
+
+ put_checksum(&slot_command[0], slot_command[0]);
+ if ((dst_put_ci(state, slot_command, sizeof (slot_command), state->messages, GET_REPLY)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
+ return -1;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
+
+ // Print raw data
+ dprintk(verbose, DST_CA_INFO, 0, " DST data = [");
+ for (i = 0; i < state->messages[0] + 1; i++) {
+ dprintk(verbose, DST_CA_INFO, 0, " 0x%02x", state->messages[i]);
+ }
+ dprintk(verbose, DST_CA_INFO, 0, "]\n");
+
+ // Set the command and length of the output
+ num_ids = state->messages[in_num_ids_pos];
+ if (num_ids >= 100) {
+ num_ids = 100;
+ dprintk(verbose, DST_CA_ERROR, 1, "Invalid number of ids (>100). Recovering.");
+ }
+ put_command_and_length(&state->messages[0], CA_INFO, num_ids * 2);
+
+ dprintk(verbose, DST_CA_INFO, 0, " CA_INFO = [");
+ srcPtr = in_system_id_pos;
+ dstPtr = out_system_id_pos;
+ for(i = 0; i < num_ids; i++) {
+ dprintk(verbose, DST_CA_INFO, 0, " 0x%02x%02x", state->messages[srcPtr + 0], state->messages[srcPtr + 1]);
+ // Append to output
+ state->messages[dstPtr + 0] = state->messages[srcPtr + 0];
+ state->messages[dstPtr + 1] = state->messages[srcPtr + 1];
+ srcPtr += 2;
+ dstPtr += 2;
+ }
+ dprintk(verbose, DST_CA_INFO, 0, "]\n");
+
return 0;
}
@@ -174,7 +247,7 @@ static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps,
dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]);
dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
- for (i = 0; i < 8; i++)
+ for (i = 0; i < slot_cap[0] + 1; i++)
dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]);
dprintk(verbose, DST_CA_INFO, 0, "\n");
@@ -260,6 +333,11 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message,
if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
return -EFAULT;
break;
+ case CA_INFO:
+ memcpy(p_ca_message->msg, state->messages, 128);
+ if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
+ return -EFAULT;
+ break;
}
}
@@ -302,7 +380,7 @@ static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 l
rdc_reset_state(state);
return -1;
}
- dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command succes.");
+ dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command success.");
return 0;
}
@@ -340,6 +418,7 @@ static int debug_string(u8 *msg, u32 length, u32 offset)
return 0;
}
+
static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
{
u32 length = 0;
@@ -455,6 +534,16 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
}
dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !");
break;
+ case CA_INFO_ENQUIRY:
+ dprintk(verbose, DST_CA_INFO, 1, " Getting CA Information");
+
+ if ((ca_get_ca_info(state)) < 0) {
+ dprintk(verbose, DST_CA_ERROR, 1, " -->CA_INFO_ENQUIRY Failed !");
+ result = -1;
+ goto free_mem_and_exit;
+ }
+ dprintk(verbose, DST_CA_INFO, 1, " -->CA_INFO_ENQUIRY Success !");
+ break;
}
}
free_mem_and_exit:
@@ -473,18 +562,15 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd
void __user *arg = (void __user *)ioctl_arg;
int result = 0;
- if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
- dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
- return -ENOMEM;
- }
- if ((p_ca_slot_info = (struct ca_slot_info *) kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL)) == NULL) {
+ p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL);
+ p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL);
+ p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL);
+ if (!p_ca_message || !p_ca_slot_info || !p_ca_caps) {
dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
- return -ENOMEM;
- }
- if ((p_ca_caps = (struct ca_caps *) kmalloc(sizeof (struct ca_caps), GFP_KERNEL)) == NULL) {
- dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
- return -ENOMEM;
+ result = -ENOMEM;
+ goto free_mem_and_exit;
}
+
/* We have now only the standard ioctl's, the driver is upposed to handle internals. */
switch (cmd) {
case CA_SEND_MSG:
@@ -582,7 +668,7 @@ static int dst_ca_release(struct inode *inode, struct file *file)
static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
{
- int bytes_read = 0;
+ ssize_t bytes_read = 0;
dprintk(verbose, DST_CA_DEBUG, 1, " Device read.");
diff --git a/drivers/media/dvb/bt8xx/dst_common.h b/drivers/media/dvb/bt8xx/dst_common.h
index 51d4e043716c..0677b047b3a7 100644
--- a/drivers/media/dvb/bt8xx/dst_common.h
+++ b/drivers/media/dvb/bt8xx/dst_common.h
@@ -42,7 +42,7 @@
#define DST_TYPE_IS_CABLE 2
#define DST_TYPE_IS_ATSC 3
-#define DST_TYPE_HAS_NEWTUNE 1
+#define DST_TYPE_HAS_TS188 1
#define DST_TYPE_HAS_TS204 2
#define DST_TYPE_HAS_SYMDIV 4
#define DST_TYPE_HAS_FW_1 8
@@ -52,6 +52,9 @@
#define DST_TYPE_HAS_OBS_REGS 128
#define DST_TYPE_HAS_INC_COUNT 256
#define DST_TYPE_HAS_MULTI_FE 512
+#define DST_TYPE_HAS_NEWTUNE_2 1024
+#define DST_TYPE_HAS_DBOARD 2048
+#define DST_TYPE_HAS_VLF 4096
/* Card capability list */
@@ -64,6 +67,20 @@
#define DST_TYPE_HAS_ANALOG 64 /* Analog inputs */
#define DST_TYPE_HAS_SESSION 128
+#define TUNER_TYPE_MULTI 1
+#define TUNER_TYPE_UNKNOWN 2
+/* DVB-S */
+#define TUNER_TYPE_L64724 4
+#define TUNER_TYPE_STV0299 8
+#define TUNER_TYPE_MB86A15 16
+
+/* DVB-T */
+#define TUNER_TYPE_TDA10046 32
+
+/* ATSC */
+#define TUNER_TYPE_NXT200x 64
+
+
#define RDC_8820_PIO_0_DISABLE 0
#define RDC_8820_PIO_0_ENABLE 1
#define RDC_8820_INT 2
@@ -84,8 +101,6 @@ struct dst_state {
struct bt878* bt;
- struct dvb_frontend_ops ops;
-
/* configuration settings */
const struct dst_config* config;
@@ -121,8 +136,17 @@ struct dst_state {
u8 card_info[8];
u8 vendor[8];
u8 board_info[8];
-
+ u32 tuner_type;
+ char *tuner_name;
struct mutex dst_mutex;
+ u8 fw_name[8];
+};
+
+struct tuner_types {
+ u32 tuner_type;
+ char *tuner_name;
+ char *board_name;
+ char *fw_name;
};
struct dst_types {
@@ -131,6 +155,7 @@ struct dst_types {
u8 dst_type;
u32 type_flags;
u32 dst_feature;
+ u32 tuner_type;
};
struct dst_config
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index ccc7b2eb4a2d..b715b972d2fc 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -147,12 +147,15 @@ static int thomson_dtt7579_demod_init(struct dvb_frontend* fe)
return 0;
}
-static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
{
u32 div;
unsigned char bs = 0;
unsigned char cp = 0;
+ if (buf_len < 5)
+ return -EINVAL;
+
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
if (params->frequency < 542000000)
@@ -169,22 +172,25 @@ static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
else
bs = 0x08;
- pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address
+ pllbuf[0] = 0x60;
pllbuf[1] = div >> 8;
pllbuf[2] = div & 0xff;
pllbuf[3] = cp;
pllbuf[4] = bs;
- return 0;
+ return 5;
}
static struct mt352_config thomson_dtt7579_config = {
.demod_address = 0x0f,
.demod_init = thomson_dtt7579_demod_init,
- .pll_set = thomson_dtt7579_pll_set,
};
-static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static struct zl10353_config thomson_dtt7579_zl10353_config = {
+ .demod_address = 0x0f,
+};
+
+static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
u32 freq = params->frequency;
@@ -237,7 +243,7 @@ static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete
return 0;
}
-static int pinnsat_pll_init(struct dvb_frontend* fe)
+static int pinnsat_tuner_init(struct dvb_frontend* fe)
{
struct dvb_bt8xx_card *card = fe->dvb->priv;
@@ -247,7 +253,7 @@ static int pinnsat_pll_init(struct dvb_frontend* fe)
return 0;
}
-static int pinnsat_pll_sleep(struct dvb_frontend* fe)
+static int pinnsat_tuner_sleep(struct dvb_frontend* fe)
{
struct dvb_bt8xx_card *card = fe->dvb->priv;
@@ -258,12 +264,9 @@ static int pinnsat_pll_sleep(struct dvb_frontend* fe)
static struct cx24110_config pctvsat_config = {
.demod_address = 0x55,
- .pll_init = pinnsat_pll_init,
- .pll_set = cx24108_pll_set,
- .pll_sleep = pinnsat_pll_sleep,
};
-static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int microtune_mt7202dtf_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
u8 cfg, cpump, band_select;
@@ -297,6 +300,8 @@ static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_front
data[2] = ((div >> 10) & 0x60) | cfg;
data[3] = (cpump << 6) | band_select;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
i2c_transfer(card->i2c_adapter, &msg, 1);
return (div * 166666 - 36000000);
}
@@ -310,7 +315,6 @@ static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const s
static struct sp887x_config microtune_mt7202dtf_config = {
.demod_address = 0x70,
- .pll_set = microtune_mt7202dtf_pll_set,
.request_firmware = microtune_mt7202dtf_request_firmware,
};
@@ -337,12 +341,14 @@ static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
return 0;
}
-static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int advbt771_samsung_tdtc9251dh0_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
{
u32 div;
unsigned char bs = 0;
unsigned char cp = 0;
+ if (buf_len < 5) return -EINVAL;
+
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
if (params->frequency < 150000000)
@@ -383,19 +389,18 @@ static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct
else
bs = 0x08;
- pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address
+ pllbuf[0] = 0x61;
pllbuf[1] = div >> 8;
pllbuf[2] = div & 0xff;
pllbuf[3] = cp;
pllbuf[4] = bs;
- return 0;
+ return 5;
}
static struct mt352_config advbt771_samsung_tdtc9251dh0_config = {
.demod_address = 0x0f,
.demod_init = advbt771_samsung_tdtc9251dh0_demod_init,
- .pll_set = advbt771_samsung_tdtc9251dh0_pll_set,
};
static struct dst_config dst_config = {
@@ -455,7 +460,7 @@ static struct or51211_config or51211_config = {
.sleep = or51211_sleep,
};
-static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int vp3021_alps_tded4_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
u8 buf[4];
@@ -478,6 +483,8 @@ static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
else
return -EINVAL;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
i2c_transfer(card->i2c_adapter, &msg, 1);
return 0;
}
@@ -485,7 +492,6 @@ static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
static struct nxt6000_config vp3021_alps_tded4_config = {
.demod_address = 0x0a,
.clock_inversion = 1,
- .pll_set = vp3021_alps_tded4_pll_set,
};
static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
@@ -506,14 +512,17 @@ static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
return 0;
}
-static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int digitv_alps_tded4_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
{
u32 div;
struct dvb_ofdm_parameters *op = &params->u.ofdm;
+ if (buf_len < 5)
+ return -EINVAL;
+
div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
- pllbuf[0] = 0xc2;
+ pllbuf[0] = 0x61;
pllbuf[1] = (div >> 8) & 0x7F;
pllbuf[2] = div & 0xFF;
pllbuf[3] = 0x85;
@@ -530,7 +539,7 @@ static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
if (op->bandwidth == 8)
pllbuf[4] |= 0x04;
- return 0;
+ return 5;
}
static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
@@ -557,43 +566,18 @@ static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
static struct mt352_config digitv_alps_tded4_config = {
.demod_address = 0x0a,
.demod_init = digitv_alps_tded4_demod_init,
- .pll_set = digitv_alps_tded4_pll_set,
};
-static int tdvs_tua6034_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int tdvs_tua6034_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
- u8 buf[4];
- struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
- int err;
-
- dvb_pll_configure(&dvb_pll_tdvs_tua6034, buf, params->frequency, 0);
- dprintk("%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
- __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
- if ((err = i2c_transfer(card->i2c_adapter, &msg, 1)) != 1) {
- printk(KERN_WARNING "dvb-bt8xx: %s error "
- "(addr %02x <- %02x, err = %i)\n",
- __FUNCTION__, buf[0], buf[1], err);
- if (err < 0)
- return err;
- else
- return -EREMOTEIO;
- }
-
- /* Set the Auxiliary Byte. */
- buf[2] &= ~0x20;
- buf[2] |= 0x18;
- buf[3] = 0x50;
- i2c_transfer(card->i2c_adapter, &msg, 1);
-
- return 0;
+ return lg_h06xf_pll_set(fe, card->i2c_adapter, params);
}
static struct lgdt330x_config tdvs_tua6034_config = {
.demod_address = 0x0e,
.demod_chip = LGDT3303,
.serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
- .pll_set = tdvs_tua6034_pll_set,
};
static void lgdt330x_reset(struct dvb_bt8xx_card *bt)
@@ -617,17 +601,25 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
switch(type) {
case BTTV_BOARD_DVICO_DVBT_LITE:
card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
+
+ if (card->fe == NULL)
+ card->fe = zl10353_attach(&thomson_dtt7579_zl10353_config,
+ card->i2c_adapter);
+
if (card->fe != NULL) {
- card->fe->ops->info.frequency_min = 174000000;
- card->fe->ops->info.frequency_max = 862000000;
+ card->fe->ops.tuner_ops.calc_regs = thomson_dtt7579_tuner_calc_regs;
+ card->fe->ops.info.frequency_min = 174000000;
+ card->fe->ops.info.frequency_max = 862000000;
}
break;
case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
lgdt330x_reset(card);
card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter);
- if (card->fe != NULL)
+ if (card->fe != NULL) {
+ card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params;
dprintk ("dvb_bt8xx: lgdt330x detected\n");
+ }
break;
case BTTV_BOARD_NEBULA_DIGITV:
@@ -640,6 +632,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
digitv_alps_tded4_reset(card);
card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter);
if (card->fe != NULL) {
+ card->fe->ops.tuner_ops.set_params = vp3021_alps_tded4_tuner_set_params;
dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
break;
}
@@ -648,19 +641,25 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
digitv_alps_tded4_reset(card);
card->fe = mt352_attach(&digitv_alps_tded4_config, card->i2c_adapter);
- if (card->fe != NULL)
+ if (card->fe != NULL) {
+ card->fe->ops.tuner_ops.calc_regs = digitv_alps_tded4_tuner_calc_regs;
dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n");
+ }
break;
case BTTV_BOARD_AVDVBT_761:
card->fe = sp887x_attach(&microtune_mt7202dtf_config, card->i2c_adapter);
+ if (card->fe) {
+ card->fe->ops.tuner_ops.set_params = microtune_mt7202dtf_tuner_set_params;
+ }
break;
case BTTV_BOARD_AVDVBT_771:
card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
if (card->fe != NULL) {
- card->fe->ops->info.frequency_min = 174000000;
- card->fe->ops->info.frequency_max = 862000000;
+ card->fe->ops.tuner_ops.calc_regs = advbt771_samsung_tdtc9251dh0_tuner_calc_regs;
+ card->fe->ops.info.frequency_min = 174000000;
+ card->fe->ops.info.frequency_max = 862000000;
}
break;
@@ -687,6 +686,11 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
case BTTV_BOARD_PINNACLESAT:
card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter);
+ if (card->fe) {
+ card->fe->ops.tuner_ops.init = pinnsat_tuner_init;
+ card->fe->ops.tuner_ops.sleep = pinnsat_tuner_sleep;
+ card->fe->ops.tuner_ops.set_params = cx24108_tuner_set_params;
+ }
break;
case BTTV_BOARD_PC_HDTV:
@@ -703,8 +707,8 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
else
if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
printk("dvb-bt8xx: Frontend registration failed!\n");
- if (card->fe->ops->release)
- card->fe->ops->release(card->fe);
+ if (card->fe->ops.release)
+ card->fe->ops.release(card->fe);
card->fe = NULL;
}
}
@@ -713,7 +717,7 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
{
int result;
- if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE)) < 0) {
+ if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE, &card->bt->dev->dev)) < 0) {
printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
return result;
}
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
index 00dd9fa54c82..4745a9017a19 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
@@ -37,6 +37,8 @@
#include "cx24110.h"
#include "or51211.h"
#include "lgdt330x.h"
+#include "lg_h06xf.h"
+#include "zl10353.h"
struct dvb_bt8xx_card {
struct mutex lock;
diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig
index 6018fcdba1e6..b5cdd57ec6f5 100644
--- a/drivers/media/dvb/cinergyT2/Kconfig
+++ b/drivers/media/dvb/cinergyT2/Kconfig
@@ -64,7 +64,7 @@ config DVB_CINERGYT2_QUERY_INTERVAL
config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
bool "Register the onboard IR Remote Control Receiver as Input Device"
depends on DVB_CINERGYT2_TUNING
- default "yes"
+ default y
help
Enable this option if you want to use the onboard Infrared Remote
Control Receiver as Linux-Input device.
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 9325d039ea65..1b8953600425 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -544,15 +544,19 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct
{
struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv;
+ unsigned int mask = 0;
if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
poll_wait(file, &cinergyt2->poll_wq, wait);
+ if (cinergyt2->pending_fe_events != 0)
+ mask |= (POLLIN | POLLRDNORM | POLLPRI);
+
mutex_unlock(&cinergyt2->sem);
- return (POLLIN | POLLRDNORM | POLLPRI);
+ return mask;
}
@@ -902,7 +906,7 @@ static int cinergyt2_probe (struct usb_interface *intf,
return -ENOMEM;
}
- if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE)) < 0) {
+ if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE, &cinergyt2->udev->dev)) < 0) {
kfree(cinergyt2);
return err;
}
diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile
index 7adb50c1e8eb..11054657fdb5 100644
--- a/drivers/media/dvb/dvb-core/Makefile
+++ b/drivers/media/dvb/dvb-core/Makefile
@@ -2,8 +2,8 @@
# Makefile for the kernel DVB device drivers.
#
-dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
- dvb_ca_en50221.o dvb_frontend.o \
- dvb_net.o dvb_ringbuffer.o
+dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
+ dvb_ca_en50221.o dvb_frontend.o \
+ dvb_net.o dvb_ringbuffer.o dvb_math.o
obj-$(CONFIG_DVB_CORE) += dvb-core.o
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 04578df3f249..988499dfddf8 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -872,9 +872,6 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file,
mutex_unlock(&dmxdevfilter->mutex);
break;
- case DMX_GET_EVENT:
- break;
-
case DMX_GET_PES_PIDS:
if (!dmxdev->demux->get_pes_pids) {
ret = -EINVAL;
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 00347a750681..2a03bf53cb29 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -1060,8 +1060,18 @@ static int dvb_ca_en50221_thread(void *data)
break;
case DVB_CA_SLOTSTATE_VALIDATE:
- if (dvb_ca_en50221_parse_attributes(ca, slot)
- != 0) {
+ if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) {
+ /* we need this extra check for annoying interfaces like the budget-av */
+ if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
+ (ca->pub->poll_slot_status)) {
+ int status = ca->pub->poll_slot_status(ca->pub, slot, 0);
+ if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
+ dvb_ca_en50221_thread_update_delay(ca);
+ break;
+ }
+ }
+
printk("dvb_ca adapter %d: Invalid PC card inserted :(\n",
ca->dvbdev->adapter->num);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
@@ -1108,6 +1118,17 @@ static int dvb_ca_en50221_thread(void *data)
case DVB_CA_SLOTSTATE_LINKINIT:
if (dvb_ca_en50221_link_init(ca, slot) != 0) {
+ /* we need this extra check for annoying interfaces like the budget-av */
+ if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
+ (ca->pub->poll_slot_status)) {
+ int status = ca->pub->poll_slot_status(ca->pub, slot, 0);
+ if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
+ dvb_ca_en50221_thread_update_delay(ca);
+ break;
+ }
+ }
+
printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
dvb_ca_en50221_thread_update_delay(ca);
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 83ec5e06c482..fcff5eab21a3 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -473,7 +473,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
goto bailout;
}
memcpy(&demux->tsbuf[i], buf, j);
- if ((demux->tsbuf[0] == 0x47) | (demux->tsbuf[0] == 0xB8)) {
+ if ((demux->tsbuf[0] == 0x47) || (demux->tsbuf[0] == 0xB8)) {
memcpy(tmppack, demux->tsbuf, 188);
if (tmppack[0] == 0xB8)
tmppack[0] = 0x47;
@@ -484,7 +484,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
}
while (p < count) {
- if ((buf[p] == 0x47) | (buf[p] == 0xB8)) {
+ if ((buf[p] == 0x47) || (buf[p] == 0xB8)) {
if (count - p >= 204) {
memcpy(tmppack, &buf[p], 188);
if (tmppack[0] == 0xB8)
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index a051790161b0..3152a54a2539 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -56,7 +56,7 @@ MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AU
module_param(dvb_override_tune_delay, int, 0644);
MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
module_param(dvb_powerdown_on_sleep, int, 0644);
-MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volatage off on sleep (default)");
+MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)");
#define dprintk if (dvb_frontend_debug) printk
@@ -72,6 +72,8 @@ MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB vola
#define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST)
#define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW)
#define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW)
+
+#define FE_ALGO_HW 1
/*
* FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling.
* FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune.
@@ -151,8 +153,8 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
sizeof (struct dvb_frontend_parameters));
if (status & FE_HAS_LOCK)
- if (fe->ops->get_frontend)
- fe->ops->get_frontend(fe, &e->parameters);
+ if (fe->ops.get_frontend)
+ fe->ops.get_frontend(fe, &e->parameters);
events->eventw = wp;
@@ -211,10 +213,15 @@ static void dvb_frontend_init(struct dvb_frontend *fe)
{
dprintk ("DVB: initialising frontend %i (%s)...\n",
fe->dvb->num,
- fe->ops->info.name);
-
- if (fe->ops->init)
- fe->ops->init(fe);
+ fe->ops.info.name);
+
+ if (fe->ops.init)
+ fe->ops.init(fe);
+ if (fe->ops.tuner_ops.init) {
+ fe->ops.tuner_ops.init(fe);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
}
void dvb_frontend_reinitialise(struct dvb_frontend *fe)
@@ -259,7 +266,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
u32 original_frequency = fepriv->parameters.frequency;
/* are we using autoinversion? */
- autoinversion = ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
+ autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
(fepriv->parameters.inversion == INVERSION_AUTO));
/* setup parameters correctly */
@@ -329,8 +336,8 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
fepriv->parameters.frequency += fepriv->lnb_drift;
if (autoinversion)
fepriv->parameters.inversion = fepriv->inversion;
- if (fe->ops->set_frontend)
- fe->ops->set_frontend(fe, &fepriv->parameters);
+ if (fe->ops.set_frontend)
+ fe->ops.set_frontend(fe, &fepriv->parameters);
fepriv->parameters.frequency = original_frequency;
fepriv->parameters.inversion = original_inversion;
@@ -354,8 +361,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
/* in SCAN mode, we just set the frontend when asked and leave it alone */
if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
if (fepriv->state & FESTATE_RETUNE) {
- if (fe->ops->set_frontend)
- fe->ops->set_frontend(fe, &fepriv->parameters);
+ if (fe->ops.set_frontend)
+ fe->ops.set_frontend(fe, &fepriv->parameters);
fepriv->state = FESTATE_TUNED;
}
fepriv->delay = 3*HZ;
@@ -367,8 +374,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
if (fepriv->state & FESTATE_RETUNE) {
s = 0;
} else {
- if (fe->ops->read_status)
- fe->ops->read_status(fe, &s);
+ if (fe->ops.read_status)
+ fe->ops.read_status(fe, &s);
if (s != fepriv->status) {
dvb_frontend_add_event(fe, s);
fepriv->status = s;
@@ -381,7 +388,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
fepriv->state = FESTATE_TUNED;
/* if we're tuned, then we have determined the correct inversion */
- if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
+ if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
(fepriv->parameters.inversion == INVERSION_AUTO)) {
fepriv->parameters.inversion = fepriv->inversion;
}
@@ -405,7 +412,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
/* don't actually do anything if we're in the LOSTLOCK state,
* the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
if ((fepriv->state & FESTATE_LOSTLOCK) &&
- (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
+ (fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
return;
}
@@ -540,16 +547,16 @@ static int dvb_frontend_thread(void *data)
if (fepriv->reinitialise) {
dvb_frontend_init(fe);
if (fepriv->tone != -1) {
- fe->ops->set_tone(fe, fepriv->tone);
+ fe->ops.set_tone(fe, fepriv->tone);
}
if (fepriv->voltage != -1) {
- fe->ops->set_voltage(fe, fepriv->voltage);
+ fe->ops.set_voltage(fe, fepriv->voltage);
}
fepriv->reinitialise = 0;
}
/* do an iteration of the tuning loop */
- if (fe->ops->tune) {
+ if (fe->ops.get_frontend_algo(fe) == FE_ALGO_HW) {
/* have we been asked to retune? */
params = NULL;
if (fepriv->state & FESTATE_RETUNE) {
@@ -557,7 +564,7 @@ static int dvb_frontend_thread(void *data)
fepriv->state = FESTATE_TUNED;
}
- fe->ops->tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
+ fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
if (s != fepriv->status) {
dvb_frontend_add_event(fe, s);
fepriv->status = s;
@@ -569,10 +576,15 @@ static int dvb_frontend_thread(void *data)
if (dvb_shutdown_timeout) {
if (dvb_powerdown_on_sleep)
- if (fe->ops->set_voltage)
- fe->ops->set_voltage(fe, SEC_VOLTAGE_OFF);
- if (fe->ops->sleep)
- fe->ops->sleep(fe);
+ if (fe->ops.set_voltage)
+ fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
+ if (fe->ops.tuner_ops.sleep) {
+ fe->ops.tuner_ops.sleep(fe);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+ if (fe->ops.sleep)
+ fe->ops.sleep(fe);
}
fepriv->thread_pid = 0;
@@ -724,7 +736,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case FE_GET_INFO: {
struct dvb_frontend_info* info = parg;
- memcpy(info, &fe->ops->info, sizeof(struct dvb_frontend_info));
+ memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
* do it, it is done for it. */
@@ -744,58 +756,58 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
break;
}
- if (fe->ops->read_status)
- err = fe->ops->read_status(fe, status);
+ if (fe->ops.read_status)
+ err = fe->ops.read_status(fe, status);
break;
}
case FE_READ_BER:
- if (fe->ops->read_ber)
- err = fe->ops->read_ber(fe, (__u32*) parg);
+ if (fe->ops.read_ber)
+ err = fe->ops.read_ber(fe, (__u32*) parg);
break;
case FE_READ_SIGNAL_STRENGTH:
- if (fe->ops->read_signal_strength)
- err = fe->ops->read_signal_strength(fe, (__u16*) parg);
+ if (fe->ops.read_signal_strength)
+ err = fe->ops.read_signal_strength(fe, (__u16*) parg);
break;
case FE_READ_SNR:
- if (fe->ops->read_snr)
- err = fe->ops->read_snr(fe, (__u16*) parg);
+ if (fe->ops.read_snr)
+ err = fe->ops.read_snr(fe, (__u16*) parg);
break;
case FE_READ_UNCORRECTED_BLOCKS:
- if (fe->ops->read_ucblocks)
- err = fe->ops->read_ucblocks(fe, (__u32*) parg);
+ if (fe->ops.read_ucblocks)
+ err = fe->ops.read_ucblocks(fe, (__u32*) parg);
break;
case FE_DISEQC_RESET_OVERLOAD:
- if (fe->ops->diseqc_reset_overload) {
- err = fe->ops->diseqc_reset_overload(fe);
+ if (fe->ops.diseqc_reset_overload) {
+ err = fe->ops.diseqc_reset_overload(fe);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
}
break;
case FE_DISEQC_SEND_MASTER_CMD:
- if (fe->ops->diseqc_send_master_cmd) {
- err = fe->ops->diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg);
+ if (fe->ops.diseqc_send_master_cmd) {
+ err = fe->ops.diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
}
break;
case FE_DISEQC_SEND_BURST:
- if (fe->ops->diseqc_send_burst) {
- err = fe->ops->diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg);
+ if (fe->ops.diseqc_send_burst) {
+ err = fe->ops.diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
}
break;
case FE_SET_TONE:
- if (fe->ops->set_tone) {
- err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg);
+ if (fe->ops.set_tone) {
+ err = fe->ops.set_tone(fe, (fe_sec_tone_mode_t) parg);
fepriv->tone = (fe_sec_tone_mode_t) parg;
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
@@ -803,8 +815,8 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
break;
case FE_SET_VOLTAGE:
- if (fe->ops->set_voltage) {
- err = fe->ops->set_voltage(fe, (fe_sec_voltage_t) parg);
+ if (fe->ops.set_voltage) {
+ err = fe->ops.set_voltage(fe, (fe_sec_voltage_t) parg);
fepriv->voltage = (fe_sec_voltage_t) parg;
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
@@ -812,11 +824,11 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
break;
case FE_DISHNETWORK_SEND_LEGACY_CMD:
- if (fe->ops->dishnetwork_send_legacy_command) {
- err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned long) parg);
+ if (fe->ops.dishnetwork_send_legacy_command) {
+ err = fe->ops.dishnetwork_send_legacy_command(fe, (unsigned long) parg);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
- } else if (fe->ops->set_voltage) {
+ } else if (fe->ops.set_voltage) {
/*
* NOTE: This is a fallback condition. Some frontends
* (stv0299 for instance) take longer than 8msec to
@@ -846,7 +858,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
/* before sending a command, initialize by sending
* a 32ms 18V to the switch
*/
- fe->ops->set_voltage(fe, SEC_VOLTAGE_18);
+ fe->ops.set_voltage(fe, SEC_VOLTAGE_18);
dvb_frontend_sleep_until(&nexttime, 32000);
for (i = 0; i < 9; i++) {
@@ -854,7 +866,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
do_gettimeofday(&tv[i + 1]);
if ((cmd & 0x01) != last) {
/* set voltage to (last ? 13V : 18V) */
- fe->ops->set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
+ fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
last = (last) ? 0 : 1;
}
cmd = cmd >> 1;
@@ -874,13 +886,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
break;
case FE_DISEQC_RECV_SLAVE_REPLY:
- if (fe->ops->diseqc_recv_slave_reply)
- err = fe->ops->diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg);
+ if (fe->ops.diseqc_recv_slave_reply)
+ err = fe->ops.diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg);
break;
case FE_ENABLE_HIGH_LNB_VOLTAGE:
- if (fe->ops->enable_high_lnb_voltage)
- err = fe->ops->enable_high_lnb_voltage(fe, (long) parg);
+ if (fe->ops.enable_high_lnb_voltage)
+ err = fe->ops.enable_high_lnb_voltage(fe, (long) parg);
break;
case FE_SET_FRONTEND: {
@@ -898,7 +910,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
fepriv->parameters.inversion = INVERSION_AUTO;
fetunesettings.parameters.inversion = INVERSION_AUTO;
}
- if (fe->ops->info.type == FE_OFDM) {
+ if (fe->ops.info.type == FE_OFDM) {
/* without hierachical coding code_rate_LP is irrelevant,
* so we tolerate the otherwise invalid FEC_NONE setting */
if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
@@ -907,13 +919,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
}
/* get frontend-specific tuning settings */
- if (fe->ops->get_tune_settings && (fe->ops->get_tune_settings(fe, &fetunesettings) == 0)) {
+ if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
fepriv->max_drift = fetunesettings.max_drift;
fepriv->step_size = fetunesettings.step_size;
} else {
/* default values */
- switch(fe->ops->info.type) {
+ switch(fe->ops.info.type) {
case FE_QPSK:
fepriv->min_delay = HZ/20;
fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000;
@@ -928,11 +940,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
case FE_OFDM:
fepriv->min_delay = HZ/20;
- fepriv->step_size = fe->ops->info.frequency_stepsize * 2;
- fepriv->max_drift = (fe->ops->info.frequency_stepsize * 2) + 1;
+ fepriv->step_size = fe->ops.info.frequency_stepsize * 2;
+ fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
break;
case FE_ATSC:
- printk("dvb-core: FE_ATSC not handled yet.\n");
+ fepriv->min_delay = HZ/20;
+ fepriv->step_size = 0;
+ fepriv->max_drift = 0;
break;
}
}
@@ -952,9 +966,9 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
break;
case FE_GET_FRONTEND:
- if (fe->ops->get_frontend) {
+ if (fe->ops.get_frontend) {
memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters));
- err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg);
+ err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg);
}
break;
@@ -1067,7 +1081,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
printk ("DVB: registering frontend %i (%s)...\n",
fe->dvb->num,
- fe->ops->info.name);
+ fe->ops.info.name);
dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
fe, DVB_DEVICE_FRONTEND);
@@ -1085,10 +1099,15 @@ int dvb_unregister_frontend(struct dvb_frontend* fe)
mutex_lock(&frontend_mutex);
dvb_unregister_device (fepriv->dvbdev);
dvb_frontend_stop (fe);
- if (fe->ops->release)
- fe->ops->release(fe);
+ if (fe->ops.tuner_ops.release) {
+ fe->ops.tuner_ops.release(fe);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+ if (fe->ops.release)
+ fe->ops.release(fe);
else
- printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops->info.name);
+ printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops.info.name);
/* fe is invalid now */
kfree(fepriv);
mutex_unlock(&frontend_mutex);
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index 5926a3b745c9..2887e2b862a4 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -49,6 +49,44 @@ struct dvb_frontend_tune_settings {
struct dvb_frontend;
+struct dvb_tuner_info {
+ char name[128];
+
+ u32 frequency_min;
+ u32 frequency_max;
+ u32 frequency_step;
+
+ u32 bandwidth_min;
+ u32 bandwidth_max;
+ u32 bandwidth_step;
+};
+
+struct dvb_tuner_ops {
+
+ struct dvb_tuner_info info;
+
+ int (*release)(struct dvb_frontend *fe);
+ int (*init)(struct dvb_frontend *fe);
+ int (*sleep)(struct dvb_frontend *fe);
+
+ /** This is for simple PLLs - set all parameters in one go. */
+ int (*set_params)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+
+ /** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
+ int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len);
+
+ int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
+ int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
+
+#define TUNER_STATUS_LOCKED 1
+ int (*get_status)(struct dvb_frontend *fe, u32 *status);
+
+ /** These are provided seperately from set_params in order to facilitate silicon
+ * tuners which require sophisticated tuning loops, controlling each parameter seperately. */
+ int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
+ int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
+};
+
struct dvb_frontend_ops {
struct dvb_frontend_info info;
@@ -64,6 +102,8 @@ struct dvb_frontend_ops {
unsigned int mode_flags,
int *delay,
fe_status_t *status);
+ /* get frontend tuning algorithm from the module */
+ int (*get_frontend_algo)(struct dvb_frontend *fe);
/* these two are only used for the swzigzag code */
int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
@@ -86,6 +126,8 @@ struct dvb_frontend_ops {
int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
+
+ struct dvb_tuner_ops tuner_ops;
};
#define MAX_EVENT 8
@@ -100,9 +142,10 @@ struct dvb_fe_events {
};
struct dvb_frontend {
- struct dvb_frontend_ops* ops;
+ struct dvb_frontend_ops ops;
struct dvb_adapter *dvb;
void* demodulator_priv;
+ void* tuner_priv;
void* frontend_priv;
void* misc_priv;
};
diff --git a/drivers/media/dvb/dvb-core/dvb_math.c b/drivers/media/dvb/dvb-core/dvb_math.c
new file mode 100644
index 000000000000..beb7c93aa6cb
--- /dev/null
+++ b/drivers/media/dvb/dvb-core/dvb_math.c
@@ -0,0 +1,145 @@
+/*
+ * dvb-math provides some complex fixed-point math
+ * operations shared between the dvb related stuff
+ *
+ * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/bug.h>
+#include "dvb_math.h"
+
+static const unsigned short logtable[256] = {
+ 0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7,
+ 0x0b5d, 0x0cc3, 0x0e27, 0x0f8a, 0x10eb, 0x124b, 0x13aa, 0x1508,
+ 0x1664, 0x17bf, 0x1919, 0x1a71, 0x1bc8, 0x1d1e, 0x1e73, 0x1fc6,
+ 0x2119, 0x226a, 0x23ba, 0x2508, 0x2656, 0x27a2, 0x28ed, 0x2a37,
+ 0x2b80, 0x2cc8, 0x2e0f, 0x2f54, 0x3098, 0x31dc, 0x331e, 0x345f,
+ 0x359f, 0x36de, 0x381b, 0x3958, 0x3a94, 0x3bce, 0x3d08, 0x3e41,
+ 0x3f78, 0x40af, 0x41e4, 0x4319, 0x444c, 0x457f, 0x46b0, 0x47e1,
+ 0x4910, 0x4a3f, 0x4b6c, 0x4c99, 0x4dc5, 0x4eef, 0x5019, 0x5142,
+ 0x526a, 0x5391, 0x54b7, 0x55dc, 0x5700, 0x5824, 0x5946, 0x5a68,
+ 0x5b89, 0x5ca8, 0x5dc7, 0x5ee5, 0x6003, 0x611f, 0x623a, 0x6355,
+ 0x646f, 0x6588, 0x66a0, 0x67b7, 0x68ce, 0x69e4, 0x6af8, 0x6c0c,
+ 0x6d20, 0x6e32, 0x6f44, 0x7055, 0x7165, 0x7274, 0x7383, 0x7490,
+ 0x759d, 0x76aa, 0x77b5, 0x78c0, 0x79ca, 0x7ad3, 0x7bdb, 0x7ce3,
+ 0x7dea, 0x7ef0, 0x7ff6, 0x80fb, 0x81ff, 0x8302, 0x8405, 0x8507,
+ 0x8608, 0x8709, 0x8809, 0x8908, 0x8a06, 0x8b04, 0x8c01, 0x8cfe,
+ 0x8dfa, 0x8ef5, 0x8fef, 0x90e9, 0x91e2, 0x92db, 0x93d2, 0x94ca,
+ 0x95c0, 0x96b6, 0x97ab, 0x98a0, 0x9994, 0x9a87, 0x9b7a, 0x9c6c,
+ 0x9d5e, 0x9e4f, 0x9f3f, 0xa02e, 0xa11e, 0xa20c, 0xa2fa, 0xa3e7,
+ 0xa4d4, 0xa5c0, 0xa6ab, 0xa796, 0xa881, 0xa96a, 0xaa53, 0xab3c,
+ 0xac24, 0xad0c, 0xadf2, 0xaed9, 0xafbe, 0xb0a4, 0xb188, 0xb26c,
+ 0xb350, 0xb433, 0xb515, 0xb5f7, 0xb6d9, 0xb7ba, 0xb89a, 0xb97a,
+ 0xba59, 0xbb38, 0xbc16, 0xbcf4, 0xbdd1, 0xbead, 0xbf8a, 0xc065,
+ 0xc140, 0xc21b, 0xc2f5, 0xc3cf, 0xc4a8, 0xc580, 0xc658, 0xc730,
+ 0xc807, 0xc8de, 0xc9b4, 0xca8a, 0xcb5f, 0xcc34, 0xcd08, 0xcddc,
+ 0xceaf, 0xcf82, 0xd054, 0xd126, 0xd1f7, 0xd2c8, 0xd399, 0xd469,
+ 0xd538, 0xd607, 0xd6d6, 0xd7a4, 0xd872, 0xd93f, 0xda0c, 0xdad9,
+ 0xdba5, 0xdc70, 0xdd3b, 0xde06, 0xded0, 0xdf9a, 0xe063, 0xe12c,
+ 0xe1f5, 0xe2bd, 0xe385, 0xe44c, 0xe513, 0xe5d9, 0xe69f, 0xe765,
+ 0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83,
+ 0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387,
+ 0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973,
+ 0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47
+};
+
+unsigned int intlog2(u32 value)
+{
+ /**
+ * returns: log2(value) * 2^24
+ * wrong result if value = 0 (log2(0) is undefined)
+ */
+ unsigned int msb;
+ unsigned int logentry;
+ unsigned int significand;
+ unsigned int interpolation;
+
+ if (unlikely(value == 0)) {
+ WARN_ON(1);
+ return 0;
+ }
+
+ /* first detect the msb (count begins at 0) */
+ msb = fls(value) - 1;
+
+ /**
+ * now we use a logtable after the following method:
+ *
+ * log2(2^x * y) * 2^24 = x * 2^24 + log2(y) * 2^24
+ * where x = msb and therefore 1 <= y < 2
+ * first y is determined by shifting the value left
+ * so that msb is bit 31
+ * 0x00231f56 -> 0x8C7D5800
+ * the result is y * 2^31 -> "significand"
+ * then the highest 9 bits are used for a table lookup
+ * the highest bit is discarded because it's always set
+ * the highest nine bits in our example are 100011000
+ * so we would use the entry 0x18
+ */
+ significand = value << (31 - msb);
+ logentry = (significand >> 23) & 0xff;
+
+ /**
+ * last step we do is interpolation because of the
+ * limitations of the log table the error is that part of
+ * the significand which isn't used for lookup then we
+ * compute the ratio between the error and the next table entry
+ * and interpolate it between the log table entry used and the
+ * next one the biggest error possible is 0x7fffff
+ * (in our example it's 0x7D5800)
+ * needed value for next table entry is 0x800000
+ * so the interpolation is
+ * (error / 0x800000) * (logtable_next - logtable_current)
+ * in the implementation the division is moved to the end for
+ * better accuracy there is also an overflow correction if
+ * logtable_next is 256
+ */
+ interpolation = ((significand & 0x7fffff) *
+ ((logtable[(logentry + 1) & 0xff] -
+ logtable[logentry]) & 0xffff)) >> 15;
+
+ /* now we return the result */
+ return ((msb << 24) + (logtable[logentry] << 8) + interpolation);
+}
+EXPORT_SYMBOL(intlog2);
+
+unsigned int intlog10(u32 value)
+{
+ /**
+ * returns: log10(value) * 2^24
+ * wrong result if value = 0 (log10(0) is undefined)
+ */
+ u64 log;
+
+ if (unlikely(value == 0)) {
+ WARN_ON(1);
+ return 0;
+ }
+
+ log = intlog2(value);
+
+ /**
+ * we use the following method:
+ * log10(x) = log2(x) * log10(2)
+ */
+
+ return (log * 646456993) >> 31;
+}
+EXPORT_SYMBOL(intlog10);
diff --git a/drivers/media/dvb/dvb-core/dvb_math.h b/drivers/media/dvb/dvb-core/dvb_math.h
new file mode 100644
index 000000000000..aecc867e9404
--- /dev/null
+++ b/drivers/media/dvb/dvb-core/dvb_math.h
@@ -0,0 +1,58 @@
+/*
+ * dvb-math provides some complex fixed-point math
+ * operations shared between the dvb related stuff
+ *
+ * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __DVB_MATH_H
+#define __DVB_MATH_H
+
+#include <linux/types.h>
+
+/**
+ * computes log2 of a value; the result is shifted left by 24 bits
+ *
+ * to use rational values you can use the following method:
+ * intlog2(value) = intlog2(value * 2^x) - x * 2^24
+ *
+ * example: intlog2(8) will give 3 << 24 = 3 * 2^24
+ * example: intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24
+ * example: intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24
+ *
+ * @param value The value (must be != 0)
+ * @return log2(value) * 2^24
+ */
+extern unsigned int intlog2(u32 value);
+
+/**
+ * computes log10 of a value; the result is shifted left by 24 bits
+ *
+ * to use rational values you can use the following method:
+ * intlog10(value) = intlog10(value * 10^x) - x * 2^24
+ *
+ * example: intlog10(1000) will give 3 << 24 = 3 * 2^24
+ * due to the implementation intlog10(1000) might be not exactly 3 * 2^24
+ *
+ * look at intlog2 for similar examples
+ *
+ * @param value The value (must be != 0)
+ * @return log10(value) * 2^24
+ */
+extern unsigned int intlog10(u32 value);
+
+#endif
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 9fd87521a163..8859ab74f0fe 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -12,7 +12,7 @@
* Hilmar Linder <hlinder@cosy.sbg.ac.at>
* and Wolfram Stering <wstering@cosy.sbg.ac.at>
*
- * ULE Decaps according to draft-ietf-ipdvb-ule-03.txt.
+ * ULE Decaps according to RFC 4326.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -42,6 +42,9 @@
* Bugfixes and robustness improvements.
* Filtering on dest MAC addresses, if present (D-Bit = 0)
* ULE_DEBUG compile-time option.
+ * Apr 2006: cp v3: Bugfixes and compliency with RFC 4326 (ULE) by
+ * Christian Praehauser <cpraehaus@cosy.sbg.ac.at>,
+ * Paris Lodron University of Salzburg.
*/
/*
@@ -49,9 +52,6 @@
*
* Unloading does not work for 2.6.9 kernels: a refcount doesn't go to zero.
*
- * TS_FEED callback is called once for every single TS cell although it is
- * registered (in dvb_net_feed_start()) for 100 TS cells (used for dvb_net_ule()).
- *
*/
#include <linux/module.h>
@@ -89,6 +89,9 @@ static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
#ifdef ULE_DEBUG
+#define MAC_ADDR_PRINTFMT "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"
+#define MAX_ADDR_PRINTFMT_ARGS(macap) (macap)[0],(macap)[1],(macap)[2],(macap)[3],(macap)[4],(macap)[5]
+
#define isprint(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))
static void hexdump( const unsigned char *buf, unsigned short len )
@@ -214,6 +217,8 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
#define ULE_TEST 0
#define ULE_BRIDGED 1
+#define ULE_OPTEXTHDR_PADDING 0
+
static int ule_test_sndu( struct dvb_net_priv *p )
{
return -1;
@@ -221,14 +226,28 @@ static int ule_test_sndu( struct dvb_net_priv *p )
static int ule_bridged_sndu( struct dvb_net_priv *p )
{
- /* BRIDGE SNDU handling sucks in draft-ietf-ipdvb-ule-03.txt.
- * This has to be the last extension header, otherwise it won't work.
- * Blame the authors!
+ struct ethhdr *hdr = (struct ethhdr*) p->ule_next_hdr;
+ if(ntohs(hdr->h_proto) < 1536) {
+ int framelen = p->ule_sndu_len - ((p->ule_next_hdr+sizeof(struct ethhdr)) - p->ule_skb->data);
+ /* A frame Type < 1536 for a bridged frame, introduces a LLC Length field. */
+ if(framelen != ntohs(hdr->h_proto)) {
+ return -1;
+ }
+ }
+ /* Note:
+ * From RFC4326:
+ * "A bridged SNDU is a Mandatory Extension Header of Type 1.
+ * It must be the final (or only) extension header specified in the header chain of a SNDU."
+ * The 'ule_bridged' flag will cause the extension header processing loop to terminate.
*/
p->ule_bridged = 1;
return 0;
}
+static int ule_exthdr_padding(struct dvb_net_priv *p)
+{
+ return 0;
+}
/** Handle ULE extension headers.
* Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding.
@@ -242,7 +261,8 @@ static int handle_one_ule_extension( struct dvb_net_priv *p )
{ [0] = ule_test_sndu, [1] = ule_bridged_sndu, [2] = NULL, };
/* Table of optional extension header handlers. The header type is the index. */
- static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) = { NULL, };
+ static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) =
+ { [0] = ule_exthdr_padding, [1] = NULL, };
int ext_len = 0;
unsigned char hlen = (p->ule_sndu_type & 0x0700) >> 8;
@@ -253,25 +273,31 @@ static int handle_one_ule_extension( struct dvb_net_priv *p )
/* Mandatory extension header */
if (ule_mandatory_ext_handlers[htype]) {
ext_len = ule_mandatory_ext_handlers[htype]( p );
- p->ule_next_hdr += ext_len;
- if (! p->ule_bridged) {
- p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr );
- p->ule_next_hdr += 2;
- } else {
- p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)) );
- /* This assures the extension handling loop will terminate. */
+ if(ext_len >= 0) {
+ p->ule_next_hdr += ext_len;
+ if (!p->ule_bridged) {
+ p->ule_sndu_type = ntohs(*(unsigned short *)p->ule_next_hdr);
+ p->ule_next_hdr += 2;
+ } else {
+ p->ule_sndu_type = ntohs(*(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)));
+ /* This assures the extension handling loop will terminate. */
+ }
}
+ // else: extension handler failed or SNDU should be discarded
} else
ext_len = -1; /* SNDU has to be discarded. */
} else {
/* Optional extension header. Calculate the length. */
- ext_len = hlen << 2;
+ ext_len = hlen << 1;
/* Process the optional extension header according to its type. */
if (ule_optional_ext_handlers[htype])
(void)ule_optional_ext_handlers[htype]( p );
p->ule_next_hdr += ext_len;
- p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr );
- p->ule_next_hdr += 2;
+ p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr-2) );
+ /*
+ * note: the length of the next header type is included in the
+ * length of THIS optional extension header
+ */
}
return ext_len;
@@ -284,8 +310,14 @@ static int handle_ule_extensions( struct dvb_net_priv *p )
p->ule_next_hdr = p->ule_skb->data;
do {
l = handle_one_ule_extension( p );
- if (l == -1) return -1; /* Stop extension header processing and discard SNDU. */
+ if (l < 0)
+ return l; /* Stop extension header processing and discard SNDU. */
total_ext_len += l;
+#ifdef ULE_DEBUG
+ dprintk("handle_ule_extensions: ule_next_hdr=%p, ule_sndu_type=%i, "
+ "l=%i, total_ext_len=%i\n", p->ule_next_hdr,
+ (int) p->ule_sndu_type, l, total_ext_len);
+#endif
} while (p->ule_sndu_type < 1536);
@@ -355,8 +387,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
if (priv->ule_skb) {
dev_kfree_skb( priv->ule_skb );
/* Prepare for next SNDU. */
- ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
- ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++;
+ priv->stats.rx_errors++;
+ priv->stats.rx_frame_errors++;
}
reset_ule(priv);
priv->need_pusi = 1;
@@ -396,27 +428,25 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
}
}
- /* Check continuity counter. */
if (new_ts) {
+ /* Check continuity counter. */
if ((ts[3] & 0x0F) == priv->tscc)
priv->tscc = (priv->tscc + 1) & 0x0F;
else {
/* TS discontinuity handling: */
printk(KERN_WARNING "%lu: TS discontinuity: got %#x, "
- "exptected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc);
+ "expected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc);
/* Drop partly decoded SNDU, reset state, resync on PUSI. */
if (priv->ule_skb) {
dev_kfree_skb( priv->ule_skb );
/* Prepare for next SNDU. */
// reset_ule(priv); moved to below.
- ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
- ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++;
+ priv->stats.rx_errors++;
+ priv->stats.rx_frame_errors++;
}
reset_ule(priv);
/* skip to next PUSI. */
priv->need_pusi = 1;
- ts += TS_SZ;
- priv->ts_count++;
continue;
}
/* If we still have an incomplete payload, but PUSI is
@@ -425,7 +455,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
* cells (continuity counter wrap). */
if (ts[1] & TS_PUSI) {
if (! priv->need_pusi) {
- if (*from_where > 181) {
+ if (!(*from_where < (ts_remain-1)) || *from_where != priv->ule_sndu_remain) {
/* Pointer field is invalid. Drop this TS cell and any started ULE SNDU. */
printk(KERN_WARNING "%lu: Invalid pointer "
"field: %u.\n", priv->ts_count, *from_where);
@@ -438,8 +468,6 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
}
reset_ule(priv);
priv->need_pusi = 1;
- ts += TS_SZ;
- priv->ts_count++;
continue;
}
/* Skip pointer field (we're processing a
@@ -452,8 +480,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
if (priv->ule_sndu_remain > 183) {
/* Current SNDU lacks more data than there could be available in the
* current TS cell. */
- ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
- ((struct dvb_net_priv *) dev->priv)->stats.rx_length_errors++;
+ priv->stats.rx_errors++;
+ priv->stats.rx_length_errors++;
printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but "
"got PUSI (pf %d, ts_remain %d). Flushing incomplete payload.\n",
priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain);
@@ -492,9 +520,11 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
} else
priv->ule_dbit = 0;
- if (priv->ule_sndu_len > 32763) {
+ if (priv->ule_sndu_len < 5) {
printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. "
"Resyncing.\n", priv->ts_count, priv->ule_sndu_len);
+ priv->stats.rx_errors++;
+ priv->stats.rx_length_errors++;
priv->ule_sndu_len = 0;
priv->need_pusi = 1;
new_ts = 1;
@@ -608,58 +638,103 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
ule_dump = 1;
#endif
- ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
- ((struct dvb_net_priv *) dev->priv)->stats.rx_crc_errors++;
+ priv->stats.rx_errors++;
+ priv->stats.rx_crc_errors++;
dev_kfree_skb(priv->ule_skb);
} else {
/* CRC32 verified OK. */
+ u8 dest_addr[ETH_ALEN];
+ static const u8 bc_addr[ETH_ALEN] =
+ { [ 0 ... ETH_ALEN-1] = 0xff };
+
+ /* CRC32 was OK. Remove it from skb. */
+ priv->ule_skb->tail -= 4;
+ priv->ule_skb->len -= 4;
+
+ if (!priv->ule_dbit) {
+ /*
+ * The destination MAC address is the
+ * next data in the skb. It comes
+ * before any extension headers.
+ *
+ * Check if the payload of this SNDU
+ * should be passed up the stack.
+ */
+ register int drop = 0;
+ if (priv->rx_mode != RX_MODE_PROMISC) {
+ if (priv->ule_skb->data[0] & 0x01) {
+ /* multicast or broadcast */
+ if (memcmp(priv->ule_skb->data, bc_addr, ETH_ALEN)) {
+ /* multicast */
+ if (priv->rx_mode == RX_MODE_MULTI) {
+ int i;
+ for(i = 0; i < priv->multi_num && memcmp(priv->ule_skb->data, priv->multi_macs[i], ETH_ALEN); i++)
+ ;
+ if (i == priv->multi_num)
+ drop = 1;
+ } else if (priv->rx_mode != RX_MODE_ALL_MULTI)
+ drop = 1; /* no broadcast; */
+ /* else: all multicast mode: accept all multicast packets */
+ }
+ /* else: broadcast */
+ }
+ else if (memcmp(priv->ule_skb->data, dev->dev_addr, ETH_ALEN))
+ drop = 1;
+ /* else: destination address matches the MAC address of our receiver device */
+ }
+ /* else: promiscious mode; pass everything up the stack */
+
+ if (drop) {
+#ifdef ULE_DEBUG
+ dprintk("Dropping SNDU: MAC destination address does not match: dest addr: "MAC_ADDR_PRINTFMT", dev addr: "MAC_ADDR_PRINTFMT"\n",
+ MAX_ADDR_PRINTFMT_ARGS(priv->ule_skb->data), MAX_ADDR_PRINTFMT_ARGS(dev->dev_addr));
+#endif
+ dev_kfree_skb(priv->ule_skb);
+ goto sndu_done;
+ }
+ else
+ {
+ memcpy(dest_addr, priv->ule_skb->data, ETH_ALEN);
+ skb_pull(priv->ule_skb, ETH_ALEN);
+ }
+ }
+
/* Handle ULE Extension Headers. */
if (priv->ule_sndu_type < 1536) {
/* There is an extension header. Handle it accordingly. */
- int l = handle_ule_extensions( priv );
+ int l = handle_ule_extensions(priv);
if (l < 0) {
/* Mandatory extension header unknown or TEST SNDU. Drop it. */
// printk( KERN_WARNING "Dropping SNDU, extension headers.\n" );
- dev_kfree_skb( priv->ule_skb );
+ dev_kfree_skb(priv->ule_skb);
goto sndu_done;
}
- skb_pull( priv->ule_skb, l );
+ skb_pull(priv->ule_skb, l);
}
- /* CRC32 was OK. Remove it from skb. */
- priv->ule_skb->tail -= 4;
- priv->ule_skb->len -= 4;
-
- /* Filter on receiver's destination MAC address, if present. */
- if (!priv->ule_dbit) {
- /* The destination MAC address is the next data in the skb. */
- if (memcmp( priv->ule_skb->data, dev->dev_addr, ETH_ALEN )) {
- /* MAC addresses don't match. Drop SNDU. */
- // printk( KERN_WARNING "Dropping SNDU, MAC address.\n" );
- dev_kfree_skb( priv->ule_skb );
- goto sndu_done;
- }
- if (! priv->ule_bridged) {
- skb_push( priv->ule_skb, ETH_ALEN + 2 );
- ethh = (struct ethhdr *)priv->ule_skb->data;
- memcpy( ethh->h_dest, ethh->h_source, ETH_ALEN );
- memset( ethh->h_source, 0, ETH_ALEN );
- ethh->h_proto = htons( priv->ule_sndu_type );
- } else {
- /* Skip the Receiver destination MAC address. */
- skb_pull( priv->ule_skb, ETH_ALEN );
- }
- } else {
- if (! priv->ule_bridged) {
- skb_push( priv->ule_skb, ETH_HLEN );
- ethh = (struct ethhdr *)priv->ule_skb->data;
- memcpy( ethh->h_dest, dev->dev_addr, ETH_ALEN );
- memset( ethh->h_source, 0, ETH_ALEN );
- ethh->h_proto = htons( priv->ule_sndu_type );
- } else {
- /* skb is in correct state; nothing to do. */
+ /*
+ * Construct/assure correct ethernet header.
+ * Note: in bridged mode (priv->ule_bridged !=
+ * 0) we already have the (original) ethernet
+ * header at the start of the payload (after
+ * optional dest. address and any extension
+ * headers).
+ */
+
+ if (!priv->ule_bridged) {
+ skb_push(priv->ule_skb, ETH_HLEN);
+ ethh = (struct ethhdr *)priv->ule_skb->data;
+ if (!priv->ule_dbit) {
+ /* dest_addr buffer is only valid if priv->ule_dbit == 0 */
+ memcpy(ethh->h_dest, dest_addr, ETH_ALEN);
+ memset(ethh->h_source, 0, ETH_ALEN);
}
+ else /* zeroize source and dest */
+ memset( ethh, 0, ETH_ALEN*2 );
+
+ ethh->h_proto = htons(priv->ule_sndu_type);
}
+ /* else: skb is in correct state; nothing to do. */
priv->ule_bridged = 0;
/* Stuff into kernel's protocol stack. */
@@ -668,8 +743,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
* receive the packet anyhow. */
/* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST)
priv->ule_skb->pkt_type = PACKET_HOST; */
- ((struct dvb_net_priv *) dev->priv)->stats.rx_packets++;
- ((struct dvb_net_priv *) dev->priv)->stats.rx_bytes += priv->ule_skb->len;
+ priv->stats.rx_packets++;
+ priv->stats.rx_bytes += priv->ule_skb->len;
netif_rx(priv->ule_skb);
}
sndu_done:
@@ -944,7 +1019,7 @@ static int dvb_net_feed_start(struct net_device *dev)
dprintk("%s: start filtering\n", __FUNCTION__);
priv->secfeed->start_filtering(priv->secfeed);
} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
- struct timespec timeout = { 0, 30000000 }; // 30 msec
+ struct timespec timeout = { 0, 10000000 }; // 10 msec
/* we have payloads encapsulated in TS */
dprintk("%s: alloc tsfeed\n", __FUNCTION__);
@@ -956,10 +1031,13 @@ static int dvb_net_feed_start(struct net_device *dev)
/* Set netdevice pointer for ts decaps callback. */
priv->tsfeed->priv = (void *)dev;
- ret = priv->tsfeed->set(priv->tsfeed, priv->pid,
- TS_PACKET, DMX_TS_PES_OTHER,
+ ret = priv->tsfeed->set(priv->tsfeed,
+ priv->pid, /* pid */
+ TS_PACKET, /* type */
+ DMX_TS_PES_OTHER, /* pes type */
32768, /* circular buffer size */
- timeout);
+ timeout /* timeout */
+ );
if (ret < 0) {
printk("%s: could not set ts feed\n", dev->name);
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 3852430d0260..134c2bbbeeb5 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -236,7 +236,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
"dvb/adapter%d/%s%d", adap->num, dnames[type], id);
class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
- NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
+ adap->device, "dvb%d.%s%d", adap->num, dnames[type], id);
dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
adap->num, dnames[type], id, nums2minor(adap->num, type, id),
@@ -285,7 +285,7 @@ skip:
}
-int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module)
+int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module, struct device *device)
{
int num;
@@ -306,6 +306,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu
adap->num = num;
adap->name = name;
adap->module = module;
+ adap->device = device;
list_add_tail (&adap->list_head, &dvb_adapter_list);
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
index 74ed5853f0fb..d7a976d040d7 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.h
+++ b/drivers/media/dvb/dvb-core/dvbdev.h
@@ -51,6 +51,8 @@ struct dvb_adapter {
u8 proposed_mac [6];
void* priv;
+ struct device *device;
+
struct module *module;
};
@@ -76,7 +78,7 @@ struct dvb_device {
};
-extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module);
+extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module, struct device *device);
extern int dvb_unregister_adapter (struct dvb_adapter *adap);
extern int dvb_register_device (struct dvb_adapter *adap,
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index e388fb1567d6..3bc6722a6443 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -88,6 +88,7 @@ config DVB_USB_CXUSB
select DVB_CX22702
select DVB_LGDT330X
select DVB_MT352
+ select DVB_ZL10353
help
Say Y here to support the Conexant USB2.0 hybrid reference design.
Currently, only DVB and ATSC modes are supported, analog mode
@@ -130,6 +131,15 @@ config DVB_USB_VP702X
DVB-S USB2.0 receivers.
+config DVB_USB_GP8PSK
+ tristate "GENPIX 8PSK->USB module support"
+ depends on DVB_USB
+ help
+ Say Y here to support the
+ GENPIX 8psk module
+
+ DVB-S USB2.0 receivers.
+
config DVB_USB_NOVA_T_USB2
tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
depends on DVB_USB
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index 2dc9aad9681e..9643f56c7fe9 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -7,6 +7,9 @@ obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o
obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o
+dvb-usb-gp8psk-objs = gp8psk.o gp8psk-fe.o
+obj-$(CONFIG_DVB_USB_GP8PSK) += dvb-usb-gp8psk.o
+
dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 1f0d3e995c8d..ae23bdde42a8 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -27,8 +27,10 @@
#include "cx22702.h"
#include "lgdt330x.h"
+#include "lg_h06xf.h"
#include "mt352.h"
#include "mt352_priv.h"
+#include "zl10353.h"
/* debug */
int dvb_usb_cxusb_debug;
@@ -322,32 +324,37 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
return 0;
}
+static int cxusb_lgh064f_tuner_set_params(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct dvb_usb_device *d = fe->dvb->priv;
+ return lg_h06xf_pll_set(fe, &d->i2c_adap, fep);
+}
+
static struct cx22702_config cxusb_cx22702_config = {
.demod_address = 0x63,
.output_mode = CX22702_PARALLEL_OUTPUT,
-
- .pll_init = dvb_usb_pll_init_i2c,
- .pll_set = dvb_usb_pll_set_i2c,
};
static struct lgdt330x_config cxusb_lgdt3303_config = {
.demod_address = 0x0e,
.demod_chip = LGDT3303,
- .pll_set = dvb_usb_pll_set_i2c,
};
static struct mt352_config cxusb_dee1601_config = {
.demod_address = 0x0f,
.demod_init = cxusb_dee1601_demod_init,
- .pll_set = dvb_usb_pll_set,
};
-struct mt352_config cxusb_mt352_config = {
+static struct zl10353_config cxusb_zl10353_dee1601_config = {
+ .demod_address = 0x0f,
+};
+
+static struct mt352_config cxusb_mt352_config = {
/* used in both lgz201 and th7579 */
.demod_address = 0x0f,
.demod_init = cxusb_mt352_demod_init,
- .pll_set = dvb_usb_pll_set,
};
/* Callbacks for DVB USB */
@@ -357,17 +364,10 @@ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_device *d)
d->pll_addr = 0x61;
memcpy(d->pll_init, bpll, 4);
d->pll_desc = &dvb_pll_fmd1216me;
- return 0;
-}
-static int cxusb_lgh064f_tuner_attach(struct dvb_usb_device *d)
-{
- u8 bpll[4] = { 0x00, 0x00, 0x18, 0x50 };
- /* bpll[2] : unset bit 3, set bits 4&5
- bpll[3] : 0x50 - digital, 0x20 - analog */
- d->pll_addr = 0x61;
- memcpy(d->pll_init, bpll, 4);
- d->pll_desc = &dvb_pll_tdvs_tua6034;
+ d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+ d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
+
return 0;
}
@@ -375,6 +375,7 @@ static int cxusb_dee1601_tuner_attach(struct dvb_usb_device *d)
{
d->pll_addr = 0x61;
d->pll_desc = &dvb_pll_thomson_dtt7579;
+ d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
return 0;
}
@@ -382,6 +383,7 @@ static int cxusb_lgz201_tuner_attach(struct dvb_usb_device *d)
{
d->pll_addr = 0x61;
d->pll_desc = &dvb_pll_lg_z201;
+ d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
return 0;
}
@@ -389,6 +391,13 @@ static int cxusb_dtt7579_tuner_attach(struct dvb_usb_device *d)
{
d->pll_addr = 0x60;
d->pll_desc = &dvb_pll_thomson_dtt7579;
+ d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+ return 0;
+}
+
+static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_device *d)
+{
+ d->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params;
return 0;
}
@@ -439,7 +448,8 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_device *d)
cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
- if ((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL)
+ if (((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL) ||
+ ((d->fe = zl10353_attach(&cxusb_zl10353_dee1601_config, &d->i2c_adap)) != NULL))
return 0;
return -EIO;
@@ -555,7 +565,7 @@ static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = {
.streaming_ctrl = cxusb_streaming_ctrl,
.power_ctrl = cxusb_bluebird_power_ctrl,
.frontend_attach = cxusb_lgdt3303_frontend_attach,
- .tuner_attach = cxusb_lgh064f_tuner_attach,
+ .tuner_attach = cxusb_lgdt3303_tuner_attach,
.i2c_algo = &cxusb_i2c_algo,
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
index 2d52b76671d3..abd75b4a350d 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-common.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -173,11 +173,10 @@ int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d)
struct dib3000_config demod_cfg;
struct dibusb_state *st = d->priv;
- demod_cfg.pll_set = dvb_usb_pll_set_i2c;
- demod_cfg.pll_init = dvb_usb_pll_init_i2c;
-
for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++)
if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) {
+ d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+ d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
return 0;
}
@@ -190,6 +189,10 @@ int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d)
{
d->pll_addr = 0x60;
d->pll_desc = &dvb_pll_env57h1xd5;
+
+ d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+ d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
+
return 0;
}
EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
index dd5a13195886..f4c45f386ebc 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -20,11 +20,12 @@ static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
struct dibusb_state *st = d->priv;
demod_cfg.demod_address = 0x8;
- demod_cfg.pll_set = dvb_usb_pll_set_i2c;
- demod_cfg.pll_init = dvb_usb_pll_init_i2c;
- if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL)
+ if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) {
+ d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+ d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
return -ENODEV;
+ }
d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index 91136c00ce9d..c14d9efb48fd 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -112,27 +112,30 @@ static int digitv_mt352_demod_init(struct dvb_frontend *fe)
static struct mt352_config digitv_mt352_config = {
.demod_init = digitv_mt352_demod_init,
- .pll_set = dvb_usb_pll_set,
};
-static int digitv_nxt6000_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
{
struct dvb_usb_device *d = fe->dvb->priv;
u8 b[5];
- dvb_usb_pll_set(fe,fep,b);
+ dvb_usb_tuner_calc_regs(fe,fep,b, 5);
return digitv_ctrl_msg(d,USB_WRITE_TUNER,0,&b[1],4,NULL,0);
}
static struct nxt6000_config digitv_nxt6000_config = {
.clock_inversion = 1,
- .pll_set = digitv_nxt6000_pll_set,
};
static int digitv_frontend_attach(struct dvb_usb_device *d)
{
- if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL ||
- (d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL)
+ if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL) {
+ d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
return 0;
+ }
+ if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL) {
+ d->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
+ return 0;
+ }
return -EIO;
}
diff --git a/drivers/media/dvb/dvb-usb/dtt200u-fe.c b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
index cd21ddbfd054..17413adec7a1 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u-fe.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
@@ -18,7 +18,6 @@ struct dtt200u_fe_state {
struct dvb_frontend_parameters fep;
struct dvb_frontend frontend;
- struct dvb_frontend_ops ops;
};
static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
@@ -163,16 +162,13 @@ struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
deb_info("attaching frontend dtt200u\n");
state->d = d;
- memcpy(&state->ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
- goto success;
+ return &state->frontend;
error:
return NULL;
-success:
- return &state->frontend;
}
static struct dvb_frontend_ops dtt200u_fe_ops = {
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
index 6fa92100248b..ec631708c394 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
@@ -82,7 +82,7 @@ int dvb_usb_dvb_init(struct dvb_usb_device *d)
int ret;
if ((ret = dvb_register_adapter(&d->dvb_adap, d->desc->name,
- d->owner)) < 0) {
+ d->owner, &d->udev->dev)) < 0) {
deb_info("dvb_register_adapter failed: error %d", ret);
goto err;
}
@@ -121,16 +121,15 @@ int dvb_usb_dvb_init(struct dvb_usb_device *d)
dvb_net_init(&d->dvb_adap, &d->dvb_net, &d->demux.dmx);
- goto success;
+ d->state |= DVB_USB_STATE_DVB;
+ return 0;
+
err_dmx_dev:
dvb_dmx_release(&d->demux);
err_dmx:
dvb_unregister_adapter(&d->dvb_adap);
err:
return ret;
-success:
- d->state |= DVB_USB_STATE_DVB;
- return 0;
}
int dvb_usb_dvb_exit(struct dvb_usb_device *d)
@@ -184,13 +183,13 @@ int dvb_usb_fe_init(struct dvb_usb_device* d)
/* re-assign sleep and wakeup functions */
if (d->fe != NULL) {
- d->fe_init = d->fe->ops->init; d->fe->ops->init = dvb_usb_fe_wakeup;
- d->fe_sleep = d->fe->ops->sleep; d->fe->ops->sleep = dvb_usb_fe_sleep;
+ d->fe_init = d->fe->ops.init; d->fe->ops.init = dvb_usb_fe_wakeup;
+ d->fe_sleep = d->fe->ops.sleep; d->fe->ops.sleep = dvb_usb_fe_sleep;
if (dvb_register_frontend(&d->dvb_adap, d->fe)) {
err("Frontend registration failed.");
- if (d->fe->ops->release)
- d->fe->ops->release(d->fe);
+ if (d->fe->ops.release)
+ d->fe->ops.release(d->fe);
d->fe = NULL;
return -ENODEV;
}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
index 9b254532af4d..6b611a725093 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -46,7 +46,7 @@ int dvb_usb_i2c_exit(struct dvb_usb_device *d)
return 0;
}
-int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
+int dvb_usb_tuner_init_i2c(struct dvb_frontend *fe)
{
struct dvb_usb_device *d = fe->dvb->priv;
struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 };
@@ -63,6 +63,8 @@ int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
deb_pll("pll-buf: %x %x %x %x\n",d->pll_init[0],d->pll_init[1],
d->pll_init[2],d->pll_init[3]);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
err("tuner i2c write failed for pll_init.");
ret = -EREMOTEIO;
@@ -73,38 +75,42 @@ int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
d->tuner_pass_ctrl(fe,0,d->pll_addr);
return ret;
}
-EXPORT_SYMBOL(dvb_usb_pll_init_i2c);
+EXPORT_SYMBOL(dvb_usb_tuner_init_i2c);
-int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 b[5])
+int dvb_usb_tuner_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 *b, int buf_len)
{
struct dvb_usb_device *d = fe->dvb->priv;
+ if (buf_len != 5)
+ return -EINVAL;
if (d->pll_desc == NULL)
return 0;
deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc);
- b[0] = d->pll_addr << 1;
+ b[0] = d->pll_addr;
dvb_pll_configure(d->pll_desc,&b[1],fep->frequency,fep->u.ofdm.bandwidth);
deb_pll("pll-buf: %x %x %x %x %x\n",b[0],b[1],b[2],b[3],b[4]);
- return 0;
+ return 5;
}
-EXPORT_SYMBOL(dvb_usb_pll_set);
+EXPORT_SYMBOL(dvb_usb_tuner_calc_regs);
-int dvb_usb_pll_set_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+int dvb_usb_tuner_set_params_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
{
struct dvb_usb_device *d = fe->dvb->priv;
int ret = 0;
u8 b[5];
struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = &b[1], .len = 4 };
- dvb_usb_pll_set(fe,fep,b);
+ dvb_usb_tuner_calc_regs(fe,fep,b,5);
if (d->tuner_pass_ctrl)
d->tuner_pass_ctrl(fe,1,d->pll_addr);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
err("tuner i2c write failed for pll_set.");
ret = -EREMOTEIO;
@@ -116,4 +122,4 @@ int dvb_usb_pll_set_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters
return ret;
}
-EXPORT_SYMBOL(dvb_usb_pll_set_i2c);
+EXPORT_SYMBOL(dvb_usb_tuner_set_params_i2c);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index cb239049b098..95698918bc11 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -31,6 +31,7 @@
#define USB_VID_VISIONPLUS 0x13d3
#define USB_VID_TWINHAN 0x1822
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
+#define USB_VID_GENPIX 0x09c0
/* Product IDs */
#define USB_PID_ADSTECH_USB2_COLD 0xa333
@@ -104,5 +105,6 @@
#define USB_PID_KYE_DVB_T_WARM 0x701f
#define USB_PID_PCTV_200E 0x020e
#define USB_PID_PCTV_400E 0x020f
-
+#define USB_PID_GENPIX_8PSK_COLD 0x0200
+#define USB_PID_GENPIX_8PSK_WARM 0x0201
#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index fead958a57e3..4cf9f89c51bf 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -330,9 +330,9 @@ extern int dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);
extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *);
/* commonly used pll init and set functions */
-extern int dvb_usb_pll_init_i2c(struct dvb_frontend *);
-extern int dvb_usb_pll_set(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]);
-extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
+extern int dvb_usb_tuner_init_i2c(struct dvb_frontend *);
+extern int dvb_usb_tuner_calc_regs(struct dvb_frontend *, struct dvb_frontend_parameters *, u8 *buf, int buf_len);
+extern int dvb_usb_tuner_set_params_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
/* commonly used firmware download types and function */
struct hexline {
diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
new file mode 100644
index 000000000000..6ccbdc9cd772
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
@@ -0,0 +1,272 @@
+/* DVB USB compliant Linux driver for the
+ * - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ *
+ * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ *
+ * Thanks to GENPIX for the sample code used to implement this module.
+ *
+ * This module is based off the vp7045 and vp702x modules
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "gp8psk.h"
+
+struct gp8psk_fe_state {
+ struct dvb_frontend fe;
+
+ struct dvb_usb_device *d;
+
+ u16 snr;
+
+ unsigned long next_snr_check;
+};
+
+static int gp8psk_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
+{
+ struct gp8psk_fe_state *st = fe->demodulator_priv;
+ u8 lock;
+
+ if (gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0, 0, &lock,1))
+ return -EINVAL;
+
+ if (lock)
+ *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
+ else
+ *status = 0;
+
+ return 0;
+}
+
+/* not supported by this Frontend */
+static int gp8psk_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
+{
+ (void) fe;
+ *ber = 0;
+ return 0;
+}
+
+/* not supported by this Frontend */
+static int gp8psk_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
+{
+ (void) fe;
+ *unc = 0;
+ return 0;
+}
+
+static int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+ struct gp8psk_fe_state *st = fe->demodulator_priv;
+ u8 buf[2];
+
+ if (time_after(jiffies,st->next_snr_check)) {
+ gp8psk_usb_in_op(st->d,GET_SIGNAL_STRENGTH,0,0,buf,2);
+ *snr = (int)(buf[1]) << 8 | buf[0];
+ /* snr is reported in dBu*256 */
+ /* snr / 38.4 ~= 100% strength */
+ /* snr * 17 returns 100% strength as 65535 */
+ if (*snr <= 3855)
+ *snr = (*snr<<4) + *snr; // snr * 17
+ else
+ *snr = 65535;
+ st->next_snr_check = jiffies + (10*HZ)/1000;
+ } else {
+ *snr = st->snr;
+ }
+ return 0;
+}
+
+static int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
+{
+ return gp8psk_fe_read_snr(fe, strength);
+}
+
+static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+ tune->min_delay_ms = 800;
+ return 0;
+}
+
+static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct gp8psk_fe_state *state = fe->demodulator_priv;
+ u8 cmd[10];
+ u32 freq = fep->frequency * 1000;
+
+ cmd[4] = freq & 0xff;
+ cmd[5] = (freq >> 8) & 0xff;
+ cmd[6] = (freq >> 16) & 0xff;
+ cmd[7] = (freq >> 24) & 0xff;
+
+ switch(fe->ops.info.type) {
+ case FE_QPSK:
+ cmd[0] = fep->u.qpsk.symbol_rate & 0xff;
+ cmd[1] = (fep->u.qpsk.symbol_rate >> 8) & 0xff;
+ cmd[2] = (fep->u.qpsk.symbol_rate >> 16) & 0xff;
+ cmd[3] = (fep->u.qpsk.symbol_rate >> 24) & 0xff;
+ cmd[8] = ADV_MOD_DVB_QPSK;
+ cmd[9] = 0x03; /*ADV_MOD_FEC_XXX*/
+ break;
+ default:
+ // other modes are unsuported right now
+ cmd[0] = 0;
+ cmd[1] = 0;
+ cmd[2] = 0;
+ cmd[3] = 0;
+ cmd[8] = 0;
+ cmd[9] = 0;
+ break;
+ }
+
+ gp8psk_usb_out_op(state->d,TUNE_8PSK,0,0,cmd,10);
+
+ state->next_snr_check = jiffies;
+
+ return 0;
+}
+
+static int gp8psk_fe_get_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+{
+ return 0;
+}
+
+
+static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe,
+ struct dvb_diseqc_master_cmd *m)
+{
+ struct gp8psk_fe_state *st = fe->demodulator_priv;
+
+ deb_fe("%s\n",__FUNCTION__);
+
+ if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0,
+ m->msg, m->msg_len)) {
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe,
+ fe_sec_mini_cmd_t burst)
+{
+ struct gp8psk_fe_state *st = fe->demodulator_priv;
+ u8 cmd;
+
+ deb_fe("%s\n",__FUNCTION__);
+
+ /* These commands are certainly wrong */
+ cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01;
+
+ if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, cmd, 0,
+ &cmd, 0)) {
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int gp8psk_fe_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+ struct gp8psk_fe_state* state = fe->demodulator_priv;
+
+ if (gp8psk_usb_out_op(state->d,SET_22KHZ_TONE,
+ (tone == SEC_TONE_ON), 0, NULL, 0)) {
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int gp8psk_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+ struct gp8psk_fe_state* state = fe->demodulator_priv;
+
+ if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE,
+ voltage == SEC_VOLTAGE_18, 0, NULL, 0)) {
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd)
+{
+ struct gp8psk_fe_state* state = fe->demodulator_priv;
+ u8 cmd = sw_cmd & 0x7f;
+
+ if (gp8psk_usb_out_op(state->d,SET_DN_SWITCH, cmd, 0,
+ NULL, 0)) {
+ return -EINVAL;
+ }
+ if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, !!(sw_cmd & 0x80),
+ 0, NULL, 0)) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void gp8psk_fe_release(struct dvb_frontend* fe)
+{
+ struct gp8psk_fe_state *state = fe->demodulator_priv;
+ kfree(state);
+}
+
+static struct dvb_frontend_ops gp8psk_fe_ops;
+
+struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d)
+{
+ struct gp8psk_fe_state *s = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL);
+ if (s == NULL)
+ goto error;
+
+ s->d = d;
+ memcpy(&s->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops));
+ s->fe.demodulator_priv = s;
+
+ goto success;
+error:
+ return NULL;
+success:
+ return &s->fe;
+}
+
+
+static struct dvb_frontend_ops gp8psk_fe_ops = {
+ .info = {
+ .name = "Genpix 8psk-USB DVB-S",
+ .type = FE_QPSK,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_stepsize = 100,
+ .symbol_rate_min = 1000000,
+ .symbol_rate_max = 45000000,
+ .symbol_rate_tolerance = 500, /* ppm */
+ .caps = FE_CAN_INVERSION_AUTO |
+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK
+ },
+
+ .release = gp8psk_fe_release,
+
+ .init = NULL,
+ .sleep = NULL,
+
+ .set_frontend = gp8psk_fe_set_frontend,
+ .get_frontend = gp8psk_fe_get_frontend,
+ .get_tune_settings = gp8psk_fe_get_tune_settings,
+
+ .read_status = gp8psk_fe_read_status,
+ .read_ber = gp8psk_fe_read_ber,
+ .read_signal_strength = gp8psk_fe_read_signal_strength,
+ .read_snr = gp8psk_fe_read_snr,
+ .read_ucblocks = gp8psk_fe_read_unc_blocks,
+
+ .diseqc_send_master_cmd = gp8psk_fe_send_diseqc_msg,
+ .diseqc_send_burst = gp8psk_fe_send_diseqc_burst,
+ .set_tone = gp8psk_fe_set_tone,
+ .set_voltage = gp8psk_fe_set_voltage,
+ .dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd,
+};
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
new file mode 100644
index 000000000000..9a98f3fdae31
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/gp8psk.c
@@ -0,0 +1,256 @@
+/* DVB USB compliant Linux driver for the
+ * - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ *
+ * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ *
+ * Thanks to GENPIX for the sample code used to implement this module.
+ *
+ * This module is based off the vp7045 and vp702x modules
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "gp8psk.h"
+
+/* debug */
+static char bcm4500_firmware[] = "dvb-usb-gp8psk-02.fw";
+int dvb_usb_gp8psk_debug;
+module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+
+int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+{
+ int ret = 0,try = 0;
+
+ if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
+ return ret;
+
+ while (ret >= 0 && ret != blen && try < 3) {
+ ret = usb_control_msg(d->udev,
+ usb_rcvctrlpipe(d->udev,0),
+ req,
+ USB_TYPE_VENDOR | USB_DIR_IN,
+ value,index,b,blen,
+ 2000);
+ deb_info("reading number %d (ret: %d)\n",try,ret);
+ try++;
+ }
+
+ if (ret < 0 || ret != blen) {
+ warn("usb in operation failed.");
+ ret = -EIO;
+ } else
+ ret = 0;
+
+ deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+ debug_dump(b,blen,deb_xfer);
+
+ mutex_unlock(&d->usb_mutex);
+
+ return ret;
+}
+
+int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+ u16 index, u8 *b, int blen)
+{
+ int ret;
+
+ deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+ debug_dump(b,blen,deb_xfer);
+
+ if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
+ return ret;
+
+ if (usb_control_msg(d->udev,
+ usb_sndctrlpipe(d->udev,0),
+ req,
+ USB_TYPE_VENDOR | USB_DIR_OUT,
+ value,index,b,blen,
+ 2000) != blen) {
+ warn("usb out operation failed.");
+ ret = -EIO;
+ } else
+ ret = 0;
+ mutex_unlock(&d->usb_mutex);
+
+ return ret;
+}
+
+static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
+{
+ int ret;
+ const struct firmware *fw = NULL;
+ u8 *ptr, *buf;
+ if ((ret = request_firmware(&fw, bcm4500_firmware,
+ &d->udev->dev)) != 0) {
+ err("did not find the bcm4500 firmware file. (%s) "
+ "Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
+ bcm4500_firmware,ret);
+ return ret;
+ }
+
+ ret = -EINVAL;
+
+ if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0))
+ goto out_rel_fw;
+
+ info("downloaidng bcm4500 firmware from file '%s'",bcm4500_firmware);
+
+ ptr = fw->data;
+ buf = kmalloc(512, GFP_KERNEL | GFP_DMA);
+
+ while (ptr[0] != 0xff) {
+ u16 buflen = ptr[0] + 4;
+ if (ptr + buflen >= fw->data + fw->size) {
+ err("failed to load bcm4500 firmware.");
+ goto out_free;
+ }
+ memcpy(buf, ptr, buflen);
+ if (dvb_usb_generic_write(d, buf, buflen)) {
+ err("failed to load bcm4500 firmware.");
+ goto out_free;
+ }
+ ptr += buflen;
+ }
+
+ ret = 0;
+
+out_free:
+ kfree(buf);
+out_rel_fw:
+ release_firmware(fw);
+
+ return ret;
+}
+
+static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ u8 status, buf;
+ if (onoff) {
+ gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
+ if (! (status & 0x01)) /* started */
+ if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
+ return -EINVAL;
+
+ if (! (status & 0x02)) /* BCM4500 firmware loaded */
+ if(gp8psk_load_bcm4500fw(d))
+ return EINVAL;
+
+ if (! (status & 0x04)) /* LNB Power */
+ if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
+ &buf, 1))
+ return EINVAL;
+
+ /* Set DVB mode */
+ if(gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
+ return -EINVAL;
+ gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
+ } else {
+ /* Turn off LNB power */
+ if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
+ return EINVAL;
+ /* Turn off 8psk power */
+ if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
+ return -EINVAL;
+
+ }
+ return 0;
+}
+
+
+static int gp8psk_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ return gp8psk_usb_out_op(d, ARM_TRANSFER, onoff, 0 , NULL, 0);
+}
+
+static int gp8psk_frontend_attach(struct dvb_usb_device *d)
+{
+ d->fe = gp8psk_fe_attach(d);
+
+ return 0;
+}
+
+static struct dvb_usb_properties gp8psk_properties;
+
+static int gp8psk_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL);
+}
+
+static struct usb_device_id gp8psk_usb_table [] = {
+ { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_COLD) },
+ { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_WARM) },
+ { 0 },
+};
+MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
+
+static struct dvb_usb_properties gp8psk_properties = {
+ .caps = 0,
+
+ .usb_ctrl = CYPRESS_FX2,
+ .firmware = "dvb-usb-gp8psk-01.fw",
+
+ .streaming_ctrl = gp8psk_streaming_ctrl,
+ .power_ctrl = gp8psk_power_ctrl,
+ .frontend_attach = gp8psk_frontend_attach,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 7,
+ .endpoint = 0x82,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { .name = "Genpix 8PSK-USB DVB-S USB2.0 receiver",
+ .cold_ids = { &gp8psk_usb_table[0], NULL },
+ .warm_ids = { &gp8psk_usb_table[1], NULL },
+ },
+ { 0 },
+ }
+};
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver gp8psk_usb_driver = {
+ .name = "dvb_usb_gp8psk",
+ .probe = gp8psk_usb_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = gp8psk_usb_table,
+};
+
+/* module stuff */
+static int __init gp8psk_usb_module_init(void)
+{
+ int result;
+ if ((result = usb_register(&gp8psk_usb_driver))) {
+ err("usb_register failed. (%d)",result);
+ return result;
+ }
+
+ return 0;
+}
+
+static void __exit gp8psk_usb_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&gp8psk_usb_driver);
+}
+
+module_init(gp8psk_usb_module_init);
+module_exit(gp8psk_usb_module_exit);
+
+MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>");
+MODULE_DESCRIPTION("Driver for Genpix 8psk-USB DVB-S USB2.0");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.h b/drivers/media/dvb/dvb-usb/gp8psk.h
new file mode 100644
index 000000000000..3eba7061011c
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/gp8psk.h
@@ -0,0 +1,79 @@
+/* DVB USB compliant Linux driver for the
+ * - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ *
+ * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ *
+ * Thanks to GENPIX for the sample code used to implement this module.
+ *
+ * This module is based off the vp7045 and vp702x modules
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#ifndef _DVB_USB_GP8PSK_H_
+#define _DVB_USB_GP8PSK_H_
+
+#define DVB_USB_LOG_PREFIX "gp8psk"
+#include "dvb-usb.h"
+
+extern int dvb_usb_gp8psk_debug;
+#define deb_info(args...) dprintk(dvb_usb_gp8psk_debug,0x01,args)
+#define deb_xfer(args...) dprintk(dvb_usb_gp8psk_debug,0x02,args)
+#define deb_rc(args...) dprintk(dvb_usb_gp8psk_debug,0x04,args)
+#define deb_fe(args...) dprintk(dvb_usb_gp8psk_debug,0x08,args)
+/* gp8psk commands */
+
+/* Twinhan Vendor requests */
+#define TH_COMMAND_IN 0xC0
+#define TH_COMMAND_OUT 0xC1
+
+/* command bytes */
+#define GET_8PSK_CONFIG 0x80
+#define SET_8PSK_CONFIG 0x81
+#define ARM_TRANSFER 0x85
+#define TUNE_8PSK 0x86
+#define GET_SIGNAL_STRENGTH 0x87
+#define LOAD_BCM4500 0x88
+#define BOOT_8PSK 0x89
+#define START_INTERSIL 0x8A
+#define SET_LNB_VOLTAGE 0x8B
+#define SET_22KHZ_TONE 0x8C
+#define SEND_DISEQC_COMMAND 0x8D
+#define SET_DVB_MODE 0x8E
+#define SET_DN_SWITCH 0x8F
+#define GET_SIGNAL_LOCK 0x90
+
+/* Satellite modulation modes */
+#define ADV_MOD_DVB_QPSK 0 /* DVB-S QPSK */
+#define ADV_MOD_TURBO_QPSK 1 /* Turbo QPSK */
+#define ADV_MOD_TURBO_8PSK 2 /* Turbo 8PSK (also used for Trellis 8PSK) */
+#define ADV_MOD_TURBO_16QAM 3 /* Turbo 16QAM (also used for Trellis 8PSK) */
+
+#define ADV_MOD_DCII_C_QPSK 4 /* Digicipher II Combo */
+#define ADV_MOD_DCII_I_QPSK 5 /* Digicipher II I-stream */
+#define ADV_MOD_DCII_Q_QPSK 6 /* Digicipher II Q-stream */
+#define ADV_MOD_DCII_C_OQPSK 7 /* Digicipher II offset QPSK */
+#define ADV_MOD_DSS_QPSK 8 /* DSS (DIRECTV) QPSK */
+#define ADV_MOD_DVB_BPSK 9 /* DVB-S BPSK */
+
+#define GET_USB_SPEED 0x07
+ #define USB_SPEED_LOW 0
+ #define USB_SPEED_FULL 1
+ #define USB_SPEED_HIGH 2
+
+#define RESET_FX2 0x13
+
+#define FW_VERSION_READ 0x0B
+#define VENDOR_STRING_READ 0x0C
+#define PRODUCT_STRING_READ 0x0D
+#define FW_BCD_VERSION_READ 0x14
+
+extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d);
+extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
+extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+ u16 index, u8 *b, int blen);
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
index 14f1911c79bb..97d74da0dad8 100644
--- a/drivers/media/dvb/dvb-usb/umt-010.c
+++ b/drivers/media/dvb/dvb-usb/umt-010.c
@@ -57,7 +57,6 @@ static int umt_mt352_frontend_attach(struct dvb_usb_device *d)
memset(&umt_config,0,sizeof(struct mt352_config));
umt_config.demod_init = umt_mt352_demod_init;
umt_config.demod_address = 0xf;
- umt_config.pll_set = dvb_usb_pll_set;
d->fe = mt352_attach(&umt_config, &d->i2c_adap);
@@ -68,6 +67,7 @@ static int umt_tuner_attach (struct dvb_usb_device *d)
{
d->pll_addr = 0x61;
d->pll_desc = &dvb_pll_tua6034;
+ d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
return 0;
}
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
index 2a89f8c5da99..d4da494132ec 100644
--- a/drivers/media/dvb/dvb-usb/vp702x-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c
@@ -287,17 +287,16 @@ struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d)
goto error;
s->d = d;
- s->fe.ops = &vp702x_fe_ops;
+
+ memcpy(&s->fe.ops,&vp702x_fe_ops,sizeof(struct dvb_frontend_ops));
s->fe.demodulator_priv = s;
s->lnb_buf[1] = SET_LNB_POWER;
s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */
- goto success;
+ return &s->fe;
error:
return NULL;
-success:
- return &s->fe;
}
diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c
index 9999336aeeb6..8452eef90322 100644
--- a/drivers/media/dvb/dvb-usb/vp7045-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c
@@ -23,8 +23,6 @@
struct vp7045_fe_state {
struct dvb_frontend fe;
- struct dvb_frontend_ops ops;
-
struct dvb_usb_device *d;
};
@@ -151,15 +149,12 @@ struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
goto error;
s->d = d;
- memcpy(&s->ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
- s->fe.ops = &s->ops;
+ memcpy(&s->fe.ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
s->fe.demodulator_priv = s;
- goto success;
+ return &s->fe;
error:
return NULL;
-success:
- return &s->fe;
}
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 37d5e0af1683..0ef361f0309b 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -157,7 +157,7 @@ config DVB_STV0297
help
A DVB-C tuner module. Say Y when you want to support this frontend.
-comment "ATSC (North American/Korean Terresterial DTV) frontends"
+comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends"
depends on DVB_CORE
config DVB_NXT200X
@@ -216,4 +216,20 @@ config DVB_LGDT330X
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend.
+
+comment "Miscellaneous devices"
+ depends on DVB_CORE
+
+config DVB_LNBP21
+ tristate "LNBP21 SEC controller"
+ depends on DVB_CORE
+ help
+ An SEC control chip.
+
+config DVB_ISL6421
+ tristate "ISL6421 SEC controller"
+ depends on DVB_CORE
+ help
+ An SEC control chip.
+
endmenu
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index d09b6071fbaf..5222245c7f59 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -31,3 +31,5 @@ obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
obj-$(CONFIG_DVB_CX24123) += cx24123.o
+obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
+obj-$(CONFIG_DVB_ISL6421) += isl6421.o
diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
index 1708a1d4893e..baeb311de893 100644
--- a/drivers/media/dvb/frontends/bcm3510.c
+++ b/drivers/media/dvb/frontends/bcm3510.c
@@ -48,7 +48,6 @@
struct bcm3510_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
const struct bcm3510_config* config;
struct dvb_frontend frontend;
@@ -791,10 +790,9 @@ struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config,
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
mutex_init(&state->hab_mutex);
diff --git a/drivers/media/dvb/frontends/bsbe1.h b/drivers/media/dvb/frontends/bsbe1.h
index 78573b22ada9..d8f65738e5d2 100644
--- a/drivers/media/dvb/frontends/bsbe1.h
+++ b/drivers/media/dvb/frontends/bsbe1.h
@@ -89,12 +89,13 @@ static int alps_bsbe1_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
return 0;
}
-static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
+static int alps_bsbe1_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
{
int ret;
u8 data[4];
u32 div;
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+ struct i2c_adapter *i2c = fe->tuner_priv;
if ((params->frequency < 950000) || (params->frequency > 2150000))
return -EINVAL;
@@ -105,6 +106,8 @@ static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c,
data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
ret = i2c_transfer(i2c, &msg, 1);
return (ret != 1) ? -EIO : 0;
}
@@ -117,7 +120,6 @@ static struct stv0299_config alps_bsbe1_config = {
.skip_reinit = 0,
.min_delay_ms = 100,
.set_symbol_rate = alps_bsbe1_set_symbol_rate,
- .pll_set = alps_bsbe1_pll_set,
};
#endif
diff --git a/drivers/media/dvb/frontends/bsru6.h b/drivers/media/dvb/frontends/bsru6.h
index 2a5366ce79cc..e231cd84b3a1 100644
--- a/drivers/media/dvb/frontends/bsru6.h
+++ b/drivers/media/dvb/frontends/bsru6.h
@@ -101,11 +101,12 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ra
return 0;
}
-static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params)
+static int alps_bsru6_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
u8 buf[4];
u32 div;
struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
+ struct i2c_adapter *i2c = fe->tuner_priv;
if ((params->frequency < 950000) || (params->frequency > 2150000))
return -EINVAL;
@@ -119,6 +120,8 @@ static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c,
if (params->frequency > 1530000)
buf[3] = 0xc0;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(i2c, &msg, 1) != 1)
return -EIO;
return 0;
@@ -134,7 +137,6 @@ static struct stv0299_config alps_bsru6_config = {
.volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 100,
.set_symbol_rate = alps_bsru6_set_symbol_rate,
- .pll_set = alps_bsru6_pll_set,
};
#endif
diff --git a/drivers/media/dvb/frontends/cx22700.c b/drivers/media/dvb/frontends/cx22700.c
index 755f774f6b7d..3c7c09a362b2 100644
--- a/drivers/media/dvb/frontends/cx22700.c
+++ b/drivers/media/dvb/frontends/cx22700.c
@@ -34,8 +34,6 @@ struct cx22700_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
-
const struct cx22700_config* config;
struct dvb_frontend frontend;
@@ -247,12 +245,6 @@ static int cx22700_init (struct dvb_frontend* fe)
cx22700_writereg (state, 0x00, 0x01);
- if (state->config->pll_init) {
- cx22700_writereg (state, 0x0a, 0x00); /* open i2c bus switch */
- state->config->pll_init(fe);
- cx22700_writereg (state, 0x0a, 0x01); /* close i2c bus switch */
- }
-
return 0;
}
@@ -333,9 +325,11 @@ static int cx22700_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
cx22700_writereg (state, 0x00, 0x02); /* XXX CHECKME: soft reset*/
cx22700_writereg (state, 0x00, 0x00);
- cx22700_writereg (state, 0x0a, 0x00); /* open i2c bus switch */
- state->config->pll_set(fe, p);
- cx22700_writereg (state, 0x0a, 0x01); /* close i2c bus switch */
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
cx22700_set_inversion (state, p->inversion);
cx22700_set_tps (state, &p->u.ofdm);
cx22700_writereg (state, 0x37, 0x01); /* PAL loop filter off */
@@ -353,6 +347,17 @@ static int cx22700_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
return cx22700_get_tps (state, &p->u.ofdm);
}
+static int cx22700_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+ struct cx22700_state* state = fe->demodulator_priv;
+
+ if (enable) {
+ return cx22700_writereg(state, 0x0a, 0x00);
+ } else {
+ return cx22700_writereg(state, 0x0a, 0x01);
+ }
+}
+
static int cx22700_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
{
fesettings->min_delay_ms = 150;
@@ -381,13 +386,12 @@ struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &cx22700_ops, sizeof(struct dvb_frontend_ops));
/* check if the demod is there */
if (cx22700_readreg(state, 0x07) < 0) goto error;
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &cx22700_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -413,6 +417,7 @@ static struct dvb_frontend_ops cx22700_ops = {
.release = cx22700_release,
.init = cx22700_init,
+ .i2c_gate_ctrl = cx22700_i2c_gate_ctrl,
.set_frontend = cx22700_set_frontend,
.get_frontend = cx22700_get_frontend,
diff --git a/drivers/media/dvb/frontends/cx22700.h b/drivers/media/dvb/frontends/cx22700.h
index c9145b45874b..dcd8979c1a15 100644
--- a/drivers/media/dvb/frontends/cx22700.h
+++ b/drivers/media/dvb/frontends/cx22700.h
@@ -29,10 +29,6 @@ struct cx22700_config
{
/* the demodulator's i2c address */
u8 demod_address;
-
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};
extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c
index 0fc899f81c5e..4106d46c957f 100644
--- a/drivers/media/dvb/frontends/cx22702.c
+++ b/drivers/media/dvb/frontends/cx22702.c
@@ -40,8 +40,6 @@ struct cx22702_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
-
/* configuration settings */
const struct cx22702_config* config;
@@ -211,22 +209,10 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
u8 val;
struct cx22702_state* state = fe->demodulator_priv;
- /* set PLL */
- cx22702_i2c_gate_ctrl(fe, 1);
- if (state->config->pll_set) {
- state->config->pll_set(fe, p);
- } else if (state->config->pll_desc) {
- u8 pllbuf[4];
- struct i2c_msg msg = { .addr = state->config->pll_address,
- .buf = pllbuf, .len = 4 };
- dvb_pll_configure(state->config->pll_desc, pllbuf,
- p->frequency,
- p->u.ofdm.bandwidth);
- i2c_transfer(state->i2c, &msg, 1);
- } else {
- BUG();
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
- cx22702_i2c_gate_ctrl(fe, 0);
/* set inversion */
cx22702_set_inversion (state, p->inversion);
@@ -358,10 +344,6 @@ static int cx22702_init (struct dvb_frontend* fe)
cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02);
- /* init PLL */
- if (state->config->pll_init)
- state->config->pll_init(fe);
-
cx22702_i2c_gate_ctrl(fe, 0);
return 0;
@@ -495,7 +477,6 @@ struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &cx22702_ops, sizeof(struct dvb_frontend_ops));
state->prevUCBlocks = 0;
/* check if the demod is there */
@@ -503,7 +484,7 @@ struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
goto error;
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &cx22702_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -530,6 +511,7 @@ static struct dvb_frontend_ops cx22702_ops = {
.release = cx22702_release,
.init = cx22702_init,
+ .i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
.set_frontend = cx22702_set_tps,
.get_frontend = cx22702_get_frontend,
@@ -540,7 +522,6 @@ static struct dvb_frontend_ops cx22702_ops = {
.read_signal_strength = cx22702_read_signal_strength,
.read_snr = cx22702_read_snr,
.read_ucblocks = cx22702_read_ucblocks,
- .i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
};
module_param(debug, int, 0644);
diff --git a/drivers/media/dvb/frontends/cx22702.h b/drivers/media/dvb/frontends/cx22702.h
index 5633976a58f1..7f2f241e5d44 100644
--- a/drivers/media/dvb/frontends/cx22702.h
+++ b/drivers/media/dvb/frontends/cx22702.h
@@ -39,13 +39,6 @@ struct cx22702_config
#define CX22702_PARALLEL_OUTPUT 0
#define CX22702_SERIAL_OUTPUT 1
u8 output_mode;
-
- /* PLL maintenance */
- u8 pll_address;
- struct dvb_pll_desc *pll_desc;
-
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};
extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index f3edf8b517dd..ce3c7398bac9 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -36,8 +36,6 @@ struct cx24110_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
-
const struct cx24110_config* config;
struct dvb_frontend frontend;
@@ -250,7 +248,7 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
static const u32 bands[]={5000000UL,15000000UL,90999000UL/2};
int i;
-dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
+ dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
if (srate>90999000UL/2)
srate=90999000UL/2;
if (srate<500000)
@@ -366,17 +364,6 @@ static int cx24110_initfe(struct dvb_frontend* fe)
cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
};
- if (state->config->pll_init) state->config->pll_init(fe);
-
- return 0;
-}
-
-static int cx24110_sleep(struct dvb_frontend *fe)
-{
- struct cx24110_state *state = fe->demodulator_priv;
-
- if (state->config->pll_sleep)
- return state->config->pll_sleep(fe);
return 0;
}
@@ -548,7 +535,12 @@ static int cx24110_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
{
struct cx24110_state *state = fe->demodulator_priv;
- state->config->pll_set(fe, p);
+
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
cx24110_set_inversion (state, p->inversion);
cx24110_set_fec (state, p->u.qpsk.fec_inner);
cx24110_set_symbolrate (state, p->u.qpsk.symbol_rate);
@@ -612,7 +604,6 @@ struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &cx24110_ops, sizeof(struct dvb_frontend_ops));
state->lastber = 0;
state->lastbler = 0;
state->lastesn0 = 0;
@@ -622,7 +613,7 @@ struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
if ((ret != 0x5a) && (ret != 0x69)) goto error;
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &cx24110_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -651,7 +642,6 @@ static struct dvb_frontend_ops cx24110_ops = {
.release = cx24110_release,
.init = cx24110_initfe,
- .sleep = cx24110_sleep,
.set_frontend = cx24110_set_frontend,
.get_frontend = cx24110_get_frontend,
.read_status = cx24110_read_status,
diff --git a/drivers/media/dvb/frontends/cx24110.h b/drivers/media/dvb/frontends/cx24110.h
index 609ac642b406..b354a64e0e74 100644
--- a/drivers/media/dvb/frontends/cx24110.h
+++ b/drivers/media/dvb/frontends/cx24110.h
@@ -31,11 +31,6 @@ struct cx24110_config
{
/* the demodulator's i2c address */
u8 demod_address;
-
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
- int (*pll_sleep)(struct dvb_frontend* fe);
};
extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
index 691dc840dcc0..f2f795cba56a 100644
--- a/drivers/media/dvb/frontends/cx24123.c
+++ b/drivers/media/dvb/frontends/cx24123.c
@@ -41,14 +41,12 @@ static int debug;
struct cx24123_state
{
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
const struct cx24123_config* config;
struct dvb_frontend frontend;
u32 lastber;
u16 snr;
- u8 lnbreg;
/* Some PLL specifics for tuning */
u32 VCAarg;
@@ -249,29 +247,6 @@ static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
return 0;
}
-static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data)
-{
- u8 buf[] = { reg, data };
- /* fixme: put the intersil addr int the config */
- struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 };
- int err;
-
- if (debug>1)
- printk("cx24123: %s: writeln addr=0x08, reg 0x%02x, value 0x%02x\n",
- __FUNCTION__,reg, data);
-
- if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
- printk("%s: writelnbreg error (err == %i, reg == 0x%02x,"
- " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
- return -EREMOTEIO;
- }
-
- /* cache the write, no way to read back */
- state->lnbreg = data;
-
- return 0;
-}
-
static int cx24123_readreg(struct cx24123_state* state, u8 reg)
{
int ret;
@@ -295,11 +270,6 @@ static int cx24123_readreg(struct cx24123_state* state, u8 reg)
return b1[0];
}
-static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg)
-{
- return state->lnbreg;
-}
-
static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
{
u8 nom_reg = cx24123_readreg(state, 0x0e);
@@ -458,8 +428,8 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
u8 pll_mult;
/* check if symbol rate is within limits */
- if ((srate > state->ops.info.symbol_rate_max) ||
- (srate < state->ops.info.symbol_rate_min))
+ if ((srate > state->frontend.ops.info.symbol_rate_max) ||
+ (srate < state->frontend.ops.info.symbol_rate_min))
return -EOPNOTSUPP;;
/* choose the sampling rate high enough for the required operation,
@@ -687,13 +657,6 @@ static int cx24123_initfe(struct dvb_frontend* fe)
for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
- if (state->config->pll_init)
- state->config->pll_init(fe);
-
- /* Configure the LNB for 14V */
- if (state->config->use_isl6421)
- cx24123_writelnbreg(state, 0x0, 0x2a);
-
return 0;
}
@@ -702,50 +665,18 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
struct cx24123_state *state = fe->demodulator_priv;
u8 val;
- switch (state->config->use_isl6421) {
-
- case 1:
+ val = cx24123_readreg(state, 0x29) & ~0x40;
- val = cx24123_readlnbreg(state, 0x0);
-
- switch (voltage) {
- case SEC_VOLTAGE_13:
- dprintk("%s: isl6421 voltage = 13V\n",__FUNCTION__);
- return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */
- case SEC_VOLTAGE_18:
- dprintk("%s: isl6421 voltage = 18V\n",__FUNCTION__);
- return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */
- case SEC_VOLTAGE_OFF:
- dprintk("%s: isl5421 voltage off\n",__FUNCTION__);
- return cx24123_writelnbreg(state, 0x0, val & 0x30);
- default:
- return -EINVAL;
- };
-
- case 0:
-
- val = cx24123_readreg(state, 0x29);
-
- switch (voltage) {
- case SEC_VOLTAGE_13:
- dprintk("%s: setting voltage 13V\n", __FUNCTION__);
- if (state->config->enable_lnb_voltage)
- state->config->enable_lnb_voltage(fe, 1);
- return cx24123_writereg(state, 0x29, val | 0x80);
- case SEC_VOLTAGE_18:
- dprintk("%s: setting voltage 18V\n", __FUNCTION__);
- if (state->config->enable_lnb_voltage)
- state->config->enable_lnb_voltage(fe, 1);
- return cx24123_writereg(state, 0x29, val & 0x7f);
- case SEC_VOLTAGE_OFF:
- dprintk("%s: setting voltage off\n", __FUNCTION__);
- if (state->config->enable_lnb_voltage)
- state->config->enable_lnb_voltage(fe, 0);
- return 0;
- default:
- return -EINVAL;
- };
- }
+ switch (voltage) {
+ case SEC_VOLTAGE_13:
+ dprintk("%s: setting voltage 13V\n", __FUNCTION__);
+ return cx24123_writereg(state, 0x29, val | 0x80);
+ case SEC_VOLTAGE_18:
+ dprintk("%s: setting voltage 18V\n", __FUNCTION__);
+ return cx24123_writereg(state, 0x29, val & 0x7f);
+ default:
+ return -EINVAL;
+ };
return 0;
}
@@ -766,27 +697,20 @@ static void cx24123_wait_for_diseqc(struct cx24123_state *state)
static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
{
struct cx24123_state *state = fe->demodulator_priv;
- int i, val;
+ int i, val, tone;
dprintk("%s:\n",__FUNCTION__);
- /* check if continuous tone has been stopped */
- if (state->config->use_isl6421)
- val = cx24123_readlnbreg(state, 0x00) & 0x10;
- else
- val = cx24123_readreg(state, 0x29) & 0x10;
-
-
- if (val) {
- printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
- return -ENOTSUPP;
- }
+ /* stop continuous tone if enabled */
+ tone = cx24123_readreg(state, 0x29);
+ if (tone & 0x10)
+ cx24123_writereg(state, 0x29, tone & ~0x50);
/* wait for diseqc queue ready */
cx24123_wait_for_diseqc(state);
/* select tone mode */
- cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8);
+ cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
for (i = 0; i < cmd->msg_len; i++)
cx24123_writereg(state, 0x2C + i, cmd->msg[i]);
@@ -797,36 +721,33 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
/* wait for diseqc message to finish sending */
cx24123_wait_for_diseqc(state);
+ /* restart continuous tone if enabled */
+ if (tone & 0x10) {
+ cx24123_writereg(state, 0x29, tone & ~0x40);
+ }
+
return 0;
}
static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
{
struct cx24123_state *state = fe->demodulator_priv;
- int val;
+ int val, tone;
dprintk("%s:\n", __FUNCTION__);
- /* check if continuous tone has been stoped */
- if (state->config->use_isl6421)
- val = cx24123_readlnbreg(state, 0x00) & 0x10;
- else
- val = cx24123_readreg(state, 0x29) & 0x10;
-
-
- if (val) {
- printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
- return -ENOTSUPP;
- }
+ /* stop continuous tone if enabled */
+ tone = cx24123_readreg(state, 0x29);
+ if (tone & 0x10)
+ cx24123_writereg(state, 0x29, tone & ~0x50);
+ /* wait for diseqc queue ready */
cx24123_wait_for_diseqc(state);
/* select tone mode */
- val = cx24123_readreg(state, 0x2a) & 0xf8;
- cx24123_writereg(state, 0x2a, val | 0x04);
-
+ cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) | 0x4);
+ msleep(30);
val = cx24123_readreg(state, 0x29);
-
if (burst == SEC_MINI_A)
cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00));
else if (burst == SEC_MINI_B)
@@ -835,7 +756,12 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
return -EINVAL;
cx24123_wait_for_diseqc(state);
+ cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
+ /* restart continuous tone if enabled */
+ if (tone & 0x10) {
+ cx24123_writereg(state, 0x29, tone & ~0x40);
+ }
return 0;
}
@@ -976,38 +902,21 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
struct cx24123_state *state = fe->demodulator_priv;
u8 val;
- switch (state->config->use_isl6421) {
- case 1:
-
- val = cx24123_readlnbreg(state, 0x0);
-
- switch (tone) {
- case SEC_TONE_ON:
- dprintk("%s: isl6421 sec tone on\n",__FUNCTION__);
- return cx24123_writelnbreg(state, 0x0, val | 0x10);
- case SEC_TONE_OFF:
- dprintk("%s: isl6421 sec tone off\n",__FUNCTION__);
- return cx24123_writelnbreg(state, 0x0, val & 0x2f);
- default:
- printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
- return -EINVAL;
- }
-
- case 0:
+ /* wait for diseqc queue ready */
+ cx24123_wait_for_diseqc(state);
- val = cx24123_readreg(state, 0x29);
+ val = cx24123_readreg(state, 0x29) & ~0x40;
- switch (tone) {
- case SEC_TONE_ON:
- dprintk("%s: setting tone on\n", __FUNCTION__);
- return cx24123_writereg(state, 0x29, val | 0x10);
- case SEC_TONE_OFF:
- dprintk("%s: setting tone off\n",__FUNCTION__);
- return cx24123_writereg(state, 0x29, val & 0xef);
- default:
- printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
- return -EINVAL;
- }
+ switch (tone) {
+ case SEC_TONE_ON:
+ dprintk("%s: setting tone on\n", __FUNCTION__);
+ return cx24123_writereg(state, 0x29, val | 0x10);
+ case SEC_TONE_OFF:
+ dprintk("%s: setting tone off\n",__FUNCTION__);
+ return cx24123_writereg(state, 0x29, val & 0xef);
+ default:
+ printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
+ return -EINVAL;
}
return 0;
@@ -1040,10 +949,8 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
state->lastber = 0;
state->snr = 0;
- state->lnbreg = 0;
state->VCAarg = 0;
state->VGAarg = 0;
state->bandselectarg = 0;
@@ -1059,7 +966,7 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
}
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
diff --git a/drivers/media/dvb/frontends/cx24123.h b/drivers/media/dvb/frontends/cx24123.h
index 0c922b5e9263..9606f825935c 100644
--- a/drivers/media/dvb/frontends/cx24123.h
+++ b/drivers/media/dvb/frontends/cx24123.h
@@ -28,21 +28,8 @@ struct cx24123_config
/* the demodulator's i2c address */
u8 demod_address;
- /*
- cards like Hauppauge Nova-S Plus/Nova-SE2 use an Intersil ISL6421 chip
- for LNB control, while KWorld DVB-S 100 use the LNBDC and LNBTone bits
- from register 0x29 of the CX24123 demodulator
- */
- int use_isl6421;
-
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-
/* Need to set device param for start_dma */
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
-
- void (*enable_lnb_voltage)(struct dvb_frontend* fe, int on);
};
extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
diff --git a/drivers/media/dvb/frontends/dib3000-common.h b/drivers/media/dvb/frontends/dib3000-common.h
index c31d6df15472..be1c0d3e1389 100644
--- a/drivers/media/dvb/frontends/dib3000-common.h
+++ b/drivers/media/dvb/frontends/dib3000-common.h
@@ -38,8 +38,6 @@
struct dib3000_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
-
/* configuration settings */
struct dib3000_config config;
diff --git a/drivers/media/dvb/frontends/dib3000.h b/drivers/media/dvb/frontends/dib3000.h
index 2d5475b5c063..ec927628d273 100644
--- a/drivers/media/dvb/frontends/dib3000.h
+++ b/drivers/media/dvb/frontends/dib3000.h
@@ -30,10 +30,6 @@ struct dib3000_config
{
/* the demodulator's i2c address */
u8 demod_address;
-
- /* PLL maintenance and the i2c address of the PLL */
- int (*pll_init)(struct dvb_frontend *fe);
- int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params);
};
struct dib_fe_xfer_ops
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
index ae589adb1c0a..7c6dc7e30900 100644
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ b/drivers/media/dvb/frontends/dib3000mb.c
@@ -60,8 +60,9 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
fe_code_rate_t fe_cr = FEC_NONE;
int search_state, seq;
- if (tuner && state->config.pll_set) {
- state->config.pll_set(fe, fep);
+ if (tuner && fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, fep);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
deb_setf("bandwidth: ");
switch (ofdm->bandwidth) {
@@ -386,9 +387,6 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);
- if (state->config.pll_init)
- state->config.pll_init(fe);
-
return 0;
}
@@ -707,7 +705,6 @@ struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
/* setup the state */
state->i2c = i2c;
memcpy(&state->config,config,sizeof(struct dib3000_config));
- memcpy(&state->ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops));
/* check for the correct demod */
if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
@@ -717,7 +714,7 @@ struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
goto error;
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
/* set the xfer operations */
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index 3b303dbb6156..6c3be2529980 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -462,8 +462,9 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
int search_state,auto_val;
u16 val;
- if (tuner && state->config.pll_set) { /* initial call from dvb */
- state->config.pll_set(fe,fep);
+ if (tuner && fe->ops.tuner_ops.set_params) { /* initial call from dvb */
+ fe->ops.tuner_ops.set_params(fe, fep);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
state->last_tuned_freq = fep->frequency;
// if (!scanboost) {
@@ -642,9 +643,6 @@ static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF);
- if (state->config.pll_init)
- state->config.pll_init(fe);
-
deb_info("init end\n");
return 0;
}
@@ -839,7 +837,6 @@ struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
/* setup the state */
state->i2c = i2c;
memcpy(&state->config,config,sizeof(struct dib3000_config));
- memcpy(&state->ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
/* check for the correct demod */
if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
@@ -859,7 +856,7 @@ struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
}
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
/* set the xfer operations */
@@ -876,6 +873,7 @@ error:
kfree(state);
return NULL;
}
+EXPORT_SYMBOL(dib3000mc_attach);
static struct dvb_frontend_ops dib3000mc_ops = {
@@ -914,5 +912,3 @@ static struct dvb_frontend_ops dib3000mc_ops = {
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(dib3000mc_attach);
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index 791706ec1da3..a189683454b7 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -227,10 +227,10 @@ struct dvb_pll_desc dvb_pll_tua6034 = {
EXPORT_SYMBOL(dvb_pll_tua6034);
/* Infineon TUA6034
- * used in LG TDVS H061F and LG TDVS H062F
+ * used in LG TDVS-H061F, LG TDVS-H062F and LG TDVS-H064F
*/
-struct dvb_pll_desc dvb_pll_tdvs_tua6034 = {
- .name = "LG/Infineon TUA6034",
+struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = {
+ .name = "LG TDVS-H06xF",
.min = 54000000,
.max = 863000000,
.count = 3,
@@ -240,7 +240,7 @@ struct dvb_pll_desc dvb_pll_tdvs_tua6034 = {
{ 999999999, 44000000, 62500, 0xce, 0x04 },
},
};
-EXPORT_SYMBOL(dvb_pll_tdvs_tua6034);
+EXPORT_SYMBOL(dvb_pll_lg_tdvs_h06xf);
/* Philips FMD1216ME
* used in Medion Hybrid PCMCIA card and USB Box
@@ -419,6 +419,19 @@ struct dvb_pll_desc dvb_pll_thomson_fe6600 = {
};
EXPORT_SYMBOL(dvb_pll_thomson_fe6600);
+struct dvb_pll_priv {
+ /* i2c details */
+ int pll_i2c_address;
+ struct i2c_adapter *i2c;
+
+ /* the PLL descriptor */
+ struct dvb_pll_desc *pll_desc;
+
+ /* cached frequency/bandwidth */
+ u32 frequency;
+ u32 bandwidth;
+};
+
/* ----------------------------------------------------------- */
/* code */
@@ -443,7 +456,8 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
if (debug)
printk("pll: %s: freq=%d bw=%d | i=%d/%d\n",
desc->name, freq, bandwidth, i, desc->count);
- BUG_ON(i == desc->count);
+ if (i == desc->count)
+ return -EINVAL;
div = (freq + desc->entries[i].offset) / desc->entries[i].stepsize;
buf[0] = div >> 8;
@@ -462,6 +476,163 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
}
EXPORT_SYMBOL(dvb_pll_configure);
+static int dvb_pll_release(struct dvb_frontend *fe)
+{
+ if (fe->tuner_priv)
+ kfree(fe->tuner_priv);
+ fe->tuner_priv = NULL;
+ return 0;
+}
+
+static int dvb_pll_sleep(struct dvb_frontend *fe)
+{
+ struct dvb_pll_priv *priv = fe->tuner_priv;
+ u8 buf[4];
+ struct i2c_msg msg =
+ { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) };
+ int i;
+ int result;
+
+ for (i = 0; i < priv->pll_desc->count; i++) {
+ if (priv->pll_desc->entries[i].limit == 0)
+ break;
+ }
+ if (i == priv->pll_desc->count)
+ return 0;
+
+ buf[0] = 0;
+ buf[1] = 0;
+ buf[2] = priv->pll_desc->entries[i].config;
+ buf[3] = priv->pll_desc->entries[i].cb;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
+ return result;
+ }
+
+ return 0;
+}
+
+static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+ struct dvb_pll_priv *priv = fe->tuner_priv;
+ u8 buf[4];
+ struct i2c_msg msg =
+ { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) };
+ int result;
+ u32 div;
+ int i;
+ u32 bandwidth = 0;
+
+ if (priv->i2c == NULL)
+ return -EINVAL;
+
+ // DVBT bandwidth only just now
+ if (fe->ops.info.type == FE_OFDM) {
+ bandwidth = params->u.ofdm.bandwidth;
+ }
+
+ if ((result = dvb_pll_configure(priv->pll_desc, buf, params->frequency, bandwidth)) != 0)
+ return result;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
+ return result;
+ }
+
+ // calculate the frequency we set it to
+ for (i = 0; i < priv->pll_desc->count; i++) {
+ if (params->frequency > priv->pll_desc->entries[i].limit)
+ continue;
+ break;
+ }
+ div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize;
+ priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset;
+ priv->bandwidth = bandwidth;
+
+ return 0;
+}
+
+static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len)
+{
+ struct dvb_pll_priv *priv = fe->tuner_priv;
+ int result;
+ u32 div;
+ int i;
+ u32 bandwidth = 0;
+
+ if (buf_len < 5)
+ return -EINVAL;
+
+ // DVBT bandwidth only just now
+ if (fe->ops.info.type == FE_OFDM) {
+ bandwidth = params->u.ofdm.bandwidth;
+ }
+
+ if ((result = dvb_pll_configure(priv->pll_desc, buf+1, params->frequency, bandwidth)) != 0)
+ return result;
+ buf[0] = priv->pll_i2c_address;
+
+ // calculate the frequency we set it to
+ for (i = 0; i < priv->pll_desc->count; i++) {
+ if (params->frequency > priv->pll_desc->entries[i].limit)
+ continue;
+ break;
+ }
+ div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize;
+ priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset;
+ priv->bandwidth = bandwidth;
+
+ return 5;
+}
+
+static int dvb_pll_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ struct dvb_pll_priv *priv = fe->tuner_priv;
+ *frequency = priv->frequency;
+ return 0;
+}
+
+static int dvb_pll_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+ struct dvb_pll_priv *priv = fe->tuner_priv;
+ *bandwidth = priv->bandwidth;
+ return 0;
+}
+
+static struct dvb_tuner_ops dvb_pll_tuner_ops = {
+ .release = dvb_pll_release,
+ .sleep = dvb_pll_sleep,
+ .set_params = dvb_pll_set_params,
+ .calc_regs = dvb_pll_calc_regs,
+ .get_frequency = dvb_pll_get_frequency,
+ .get_bandwidth = dvb_pll_get_bandwidth,
+};
+
+int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
+{
+ struct dvb_pll_priv *priv = NULL;
+
+ priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
+ if (priv == NULL)
+ return -ENOMEM;
+
+ priv->pll_i2c_address = pll_addr;
+ priv->i2c = i2c;
+ priv->pll_desc = desc;
+
+ memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, sizeof(struct dvb_tuner_ops));
+ strncpy(fe->ops.tuner_ops.info.name, desc->name, 128);
+ fe->ops.tuner_ops.info.frequency_min = desc->min;
+ fe->ops.tuner_ops.info.frequency_min = desc->max;
+
+ fe->tuner_priv = priv;
+ return 0;
+}
+EXPORT_SYMBOL(dvb_pll_attach);
+
MODULE_DESCRIPTION("dvb pll library");
MODULE_AUTHOR("Gerd Knorr");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index 2b8461784989..66361cd18807 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -5,6 +5,9 @@
#ifndef __DVB_PLL_H__
#define __DVB_PLL_H__
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
struct dvb_pll_desc {
char *name;
u32 min;
@@ -31,7 +34,7 @@ extern struct dvb_pll_desc dvb_pll_unknown_1;
extern struct dvb_pll_desc dvb_pll_tua6010xs;
extern struct dvb_pll_desc dvb_pll_env57h1xd5;
extern struct dvb_pll_desc dvb_pll_tua6034;
-extern struct dvb_pll_desc dvb_pll_tdvs_tua6034;
+extern struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf;
extern struct dvb_pll_desc dvb_pll_tda665x;
extern struct dvb_pll_desc dvb_pll_fmd1216me;
extern struct dvb_pll_desc dvb_pll_tded4;
@@ -44,7 +47,18 @@ extern struct dvb_pll_desc dvb_pll_philips_td1316;
extern struct dvb_pll_desc dvb_pll_thomson_fe6600;
-int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
+extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
u32 freq, int bandwidth);
+/**
+ * Attach a dvb-pll to the supplied frontend structure.
+ *
+ * @param fe Frontend to attach to.
+ * @param pll_addr i2c address of the PLL (if used).
+ * @param i2c i2c adapter to use (set to NULL if not used).
+ * @param desc dvb_pll_desc to use.
+ * @return 0 on success, nonzero on failure.
+ */
+extern int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc);
+
#endif
diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c
index 645946a992d9..6271b1e7f6ab 100644
--- a/drivers/media/dvb/frontends/dvb_dummy_fe.c
+++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c
@@ -30,7 +30,6 @@
struct dvb_dummy_fe_state {
- struct dvb_frontend_ops ops;
struct dvb_frontend frontend;
};
@@ -77,6 +76,11 @@ static int dvb_dummy_fe_get_frontend(struct dvb_frontend* fe, struct dvb_fronten
static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
+ if (fe->ops->tuner_ops->set_params) {
+ fe->ops->tuner_ops->set_params(fe, p);
+ if (fe->ops->i2c_gate_ctrl) fe->ops->i2c_gate_ctrl(fe, 0);
+ }
+
return 0;
}
@@ -116,11 +120,8 @@ struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void)
state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
if (state == NULL) goto error;
- /* setup the state */
- memcpy(&state->ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops));
-
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -139,11 +140,8 @@ struct dvb_frontend* dvb_dummy_fe_qpsk_attach()
state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
if (state == NULL) goto error;
- /* setup the state */
- memcpy(&state->ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops));
-
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -162,11 +160,8 @@ struct dvb_frontend* dvb_dummy_fe_qam_attach()
state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
if (state == NULL) goto error;
- /* setup the state */
- memcpy(&state->ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops));
-
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
diff --git a/drivers/media/dvb/frontends/isl6421.c b/drivers/media/dvb/frontends/isl6421.c
new file mode 100644
index 000000000000..58c34db31071
--- /dev/null
+++ b/drivers/media/dvb/frontends/isl6421.c
@@ -0,0 +1,149 @@
+/*
+ * isl6421.h - driver for lnb supply and control ic ISL6421
+ *
+ * Copyright (C) 2006 Andrew de Quincey
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "isl6421.h"
+
+struct isl6421 {
+ u8 config;
+ u8 override_or;
+ u8 override_and;
+ struct i2c_adapter *i2c;
+ u8 i2c_addr;
+ void (*release_chain)(struct dvb_frontend* fe);
+};
+
+static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+ struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+ struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0,
+ .buf = &isl6421->config,
+ .len = sizeof(isl6421->config) };
+
+ isl6421->config &= ~(ISL6421_VSEL1 | ISL6421_EN1);
+
+ switch(voltage) {
+ case SEC_VOLTAGE_OFF:
+ break;
+ case SEC_VOLTAGE_13:
+ isl6421->config |= ISL6421_EN1;
+ break;
+ case SEC_VOLTAGE_18:
+ isl6421->config |= (ISL6421_EN1 | ISL6421_VSEL1);
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ isl6421->config |= isl6421->override_or;
+ isl6421->config &= isl6421->override_and;
+
+ return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+ struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+ struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0,
+ .buf = &isl6421->config,
+ .len = sizeof(isl6421->config) };
+
+ if (arg)
+ isl6421->config |= ISL6421_LLC1;
+ else
+ isl6421->config &= ~ISL6421_LLC1;
+
+ isl6421->config |= isl6421->override_or;
+ isl6421->config &= isl6421->override_and;
+
+ return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void isl6421_release(struct dvb_frontend *fe)
+{
+ struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+
+ /* power off */
+ isl6421_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+ /* free data & call next release routine */
+ fe->ops.release = isl6421->release_chain;
+ kfree(fe->misc_priv);
+ fe->misc_priv = NULL;
+ if (fe->ops.release)
+ fe->ops.release(fe);
+}
+
+int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+ u8 override_set, u8 override_clear)
+{
+ struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL);
+ if (!isl6421)
+ return -ENOMEM;
+
+ /* default configuration */
+ isl6421->config = ISL6421_ISEL1;
+ isl6421->i2c = i2c;
+ isl6421->i2c_addr = i2c_addr;
+ fe->misc_priv = isl6421;
+
+ /* bits which should be forced to '1' */
+ isl6421->override_or = override_set;
+
+ /* bits which should be forced to '0' */
+ isl6421->override_and = ~override_clear;
+
+ /* detect if it is present or not */
+ if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+ kfree(isl6421);
+ fe->misc_priv = NULL;
+ return -EIO;
+ }
+
+ /* install release callback */
+ isl6421->release_chain = fe->ops.release;
+ fe->ops.release = isl6421_release;
+
+ /* override frontend ops */
+ fe->ops.set_voltage = isl6421_set_voltage;
+ fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage;
+
+ return 0;
+}
+EXPORT_SYMBOL(isl6421_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6421");
+MODULE_AUTHOR("Andrew de Quincey & Oliver Endriss");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/isl6421.h b/drivers/media/dvb/frontends/isl6421.h
new file mode 100644
index 000000000000..675f80a19b99
--- /dev/null
+++ b/drivers/media/dvb/frontends/isl6421.h
@@ -0,0 +1,46 @@
+/*
+ * isl6421.h - driver for lnb supply and control ic ISL6421
+ *
+ * Copyright (C) 2006 Andrew de Quincey
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef _ISL6421_H
+#define _ISL6421_H
+
+#include <linux/dvb/frontend.h>
+
+/* system register bits */
+#define ISL6421_OLF1 0x01
+#define ISL6421_EN1 0x02
+#define ISL6421_VSEL1 0x04
+#define ISL6421_LLC1 0x08
+#define ISL6421_ENT1 0x10
+#define ISL6421_ISEL1 0x20
+#define ISL6421_DCL 0x40
+
+/* override_set and override_clear control which system register bits (above) to always set & clear */
+extern int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+ u8 override_set, u8 override_clear);
+
+#endif
diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb/frontends/l64781.c
index 1c7c91224472..f3bc82e44a28 100644
--- a/drivers/media/dvb/frontends/l64781.c
+++ b/drivers/media/dvb/frontends/l64781.c
@@ -32,7 +32,6 @@
struct l64781_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
const struct l64781_config* config;
struct dvb_frontend frontend;
@@ -141,7 +140,10 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
u8 val0x06;
int bw = p->bandwidth - BANDWIDTH_8_MHZ;
- state->config->pll_set(fe, param);
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, param);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
if (param->inversion != INVERSION_ON &&
param->inversion != INVERSION_OFF)
@@ -463,8 +465,6 @@ static int l64781_init(struct dvb_frontend* fe)
/* Everything is two's complement, soft bit and CSI_OUT too */
l64781_writereg (state, 0x1e, 0x09);
- if (state->config->pll_init) state->config->pll_init(fe);
-
/* delay a bit after first init attempt */
if (state->first) {
state->first = 0;
@@ -508,7 +508,6 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &l64781_ops, sizeof(struct dvb_frontend_ops));
state->first = 1;
/**
@@ -554,7 +553,7 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
}
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &l64781_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
diff --git a/drivers/media/dvb/frontends/l64781.h b/drivers/media/dvb/frontends/l64781.h
index 947f65f87465..83b8bc210274 100644
--- a/drivers/media/dvb/frontends/l64781.h
+++ b/drivers/media/dvb/frontends/l64781.h
@@ -29,10 +29,6 @@ struct l64781_config
{
/* the demodulator's i2c address */
u8 demod_address;
-
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};
diff --git a/drivers/media/dvb/frontends/lg_h06xf.h b/drivers/media/dvb/frontends/lg_h06xf.h
new file mode 100644
index 000000000000..754d51d11120
--- /dev/null
+++ b/drivers/media/dvb/frontends/lg_h06xf.h
@@ -0,0 +1,64 @@
+/*
+ * lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF
+ *
+ * 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.
+ */
+
+#ifndef _LG_H06XF_H_
+#define _LG_H06XF_H_
+#include "dvb-pll.h"
+
+static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap,
+ struct dvb_frontend_parameters* params)
+{
+ u8 buf[4];
+ struct i2c_msg msg = { .addr = 0x61, .flags = 0,
+ .buf = buf, .len = sizeof(buf) };
+ int err;
+
+ dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
+ printk(KERN_WARNING "lg_h06xf: %s error "
+ "(addr %02x <- %02x, err = %i)\n",
+ __FUNCTION__, buf[0], buf[1], err);
+ if (err < 0)
+ return err;
+ else
+ return -EREMOTEIO;
+ }
+
+ /* Set the Auxiliary Byte. */
+ buf[0] = buf[2];
+ buf[0] &= ~0x20;
+ buf[0] |= 0x18;
+ buf[1] = 0x50;
+ msg.len = 2;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
+ printk(KERN_WARNING "lg_h06xf: %s error "
+ "(addr %02x <- %02x, err = %i)\n",
+ __FUNCTION__, buf[0], buf[1], err);
+ if (err < 0)
+ return err;
+ else
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+#endif
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index 4691ac54bc1d..6e8ad176e1a1 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -29,6 +29,7 @@
* DViCO FusionHDTV 5 Lite
* DViCO FusionHDTV 5 USB Gold
* Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
+ * pcHDTV HD5500
*
* TODO:
* signal strength always returns 0.
@@ -59,7 +60,6 @@ if (debug) printk(KERN_DEBUG "lgdt330x: " args); \
struct lgdt330x_state
{
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
/* Configuration settings */
const struct lgdt330x_config* config;
@@ -399,8 +399,10 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
}
/* Tune to the specified frequency */
- if (state->config->pll_set)
- state->config->pll_set(fe, param);
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, param);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
/* Keep track of the new frequency */
/* FIXME this is the wrong way to do this... */
@@ -672,6 +674,7 @@ static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
if (state->current_modulation == VSB_8) {
+ i2c_read_demod_bytes(state, 0x6e, buf, 5);
/* Phase Tracker Mean-Square Error Register for VSB */
noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
} else {
@@ -721,16 +724,19 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
/* Setup the state */
state->config = config;
state->i2c = i2c;
+
+ /* Create dvb_frontend */
switch (config->demod_chip) {
case LGDT3302:
- memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
+ memcpy(&state->frontend.ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
break;
case LGDT3303:
- memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
+ memcpy(&state->frontend.ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
break;
default:
goto error;
}
+ state->frontend.demodulator_priv = state;
/* Verify communication with demod chip */
if (i2c_read_demod_bytes(state, 2, buf, 1))
@@ -739,9 +745,6 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
state->current_frequency = -1;
state->current_modulation = -1;
- /* Create dvb_frontend */
- state->frontend.ops = &state->ops;
- state->frontend.demodulator_priv = state;
return &state->frontend;
error:
diff --git a/drivers/media/dvb/frontends/lgdt330x.h b/drivers/media/dvb/frontends/lgdt330x.h
index 2a6529cccf1a..bad903c6f0f8 100644
--- a/drivers/media/dvb/frontends/lgdt330x.h
+++ b/drivers/media/dvb/frontends/lgdt330x.h
@@ -43,7 +43,6 @@ struct lgdt330x_config
/* PLL interface */
int (*pll_rf_set) (struct dvb_frontend* fe, int index);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
/* Need to set device param for start_dma */
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c
new file mode 100644
index 000000000000..e933edc8dd29
--- /dev/null
+++ b/drivers/media/dvb/frontends/lnbp21.c
@@ -0,0 +1,145 @@
+/*
+ * lnbp21.h - driver for lnb supply and control ic lnbp21
+ *
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "lnbp21.h"
+
+struct lnbp21 {
+ u8 config;
+ u8 override_or;
+ u8 override_and;
+ struct i2c_adapter *i2c;
+ void (*release_chain)(struct dvb_frontend* fe);
+};
+
+static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+ struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+ struct i2c_msg msg = { .addr = 0x08, .flags = 0,
+ .buf = &lnbp21->config,
+ .len = sizeof(lnbp21->config) };
+
+ lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN);
+
+ switch(voltage) {
+ case SEC_VOLTAGE_OFF:
+ break;
+ case SEC_VOLTAGE_13:
+ lnbp21->config |= LNBP21_EN;
+ break;
+ case SEC_VOLTAGE_18:
+ lnbp21->config |= (LNBP21_EN | LNBP21_VSEL);
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ lnbp21->config |= lnbp21->override_or;
+ lnbp21->config &= lnbp21->override_and;
+
+ return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+ struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+ struct i2c_msg msg = { .addr = 0x08, .flags = 0,
+ .buf = &lnbp21->config,
+ .len = sizeof(lnbp21->config) };
+
+ if (arg)
+ lnbp21->config |= LNBP21_LLC;
+ else
+ lnbp21->config &= ~LNBP21_LLC;
+
+ lnbp21->config |= lnbp21->override_or;
+ lnbp21->config &= lnbp21->override_and;
+
+ return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void lnbp21_release(struct dvb_frontend *fe)
+{
+ struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+
+ /* LNBP power off */
+ lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+ /* free data & call next release routine */
+ fe->ops.release = lnbp21->release_chain;
+ kfree(fe->misc_priv);
+ fe->misc_priv = NULL;
+ if (fe->ops.release)
+ fe->ops.release(fe);
+}
+
+int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
+{
+ struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
+ if (!lnbp21)
+ return -ENOMEM;
+
+ /* default configuration */
+ lnbp21->config = LNBP21_ISEL;
+ lnbp21->i2c = i2c;
+ fe->misc_priv = lnbp21;
+
+ /* bits which should be forced to '1' */
+ lnbp21->override_or = override_set;
+
+ /* bits which should be forced to '0' */
+ lnbp21->override_and = ~override_clear;
+
+ /* detect if it is present or not */
+ if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+ kfree(lnbp21);
+ fe->misc_priv = NULL;
+ return -EIO;
+ }
+
+ /* install release callback */
+ lnbp21->release_chain = fe->ops.release;
+ fe->ops.release = lnbp21_release;
+
+ /* override frontend ops */
+ fe->ops.set_voltage = lnbp21_set_voltage;
+ fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
+
+ return 0;
+}
+EXPORT_SYMBOL(lnbp21_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21");
+MODULE_AUTHOR("Oliver Endriss");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/lnbp21.h b/drivers/media/dvb/frontends/lnbp21.h
index 0dcbe61b61b1..047a4ab68c01 100644
--- a/drivers/media/dvb/frontends/lnbp21.h
+++ b/drivers/media/dvb/frontends/lnbp21.h
@@ -27,7 +27,7 @@
#ifndef _LNBP21_H
#define _LNBP21_H
-/* system register */
+/* system register bits */
#define LNBP21_OLF 0x01
#define LNBP21_OTF 0x02
#define LNBP21_EN 0x04
@@ -37,103 +37,9 @@
#define LNBP21_ISEL 0x40
#define LNBP21_PCL 0x80
-struct lnbp21 {
- u8 config;
- u8 override_or;
- u8 override_and;
- struct i2c_adapter *i2c;
- void (*release_chain)(struct dvb_frontend* fe);
-};
+#include <linux/dvb/frontend.h>
-static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
- struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
- struct i2c_msg msg = { .addr = 0x08, .flags = 0,
- .buf = &lnbp21->config,
- .len = sizeof(lnbp21->config) };
-
- lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN);
-
- switch(voltage) {
- case SEC_VOLTAGE_OFF:
- break;
- case SEC_VOLTAGE_13:
- lnbp21->config |= LNBP21_EN;
- break;
- case SEC_VOLTAGE_18:
- lnbp21->config |= (LNBP21_EN | LNBP21_VSEL);
- break;
- default:
- return -EINVAL;
- };
-
- lnbp21->config |= lnbp21->override_or;
- lnbp21->config &= lnbp21->override_and;
-
- return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
-{
- struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
- struct i2c_msg msg = { .addr = 0x08, .flags = 0,
- .buf = &lnbp21->config,
- .len = sizeof(lnbp21->config) };
-
- if (arg)
- lnbp21->config |= LNBP21_LLC;
- else
- lnbp21->config &= ~LNBP21_LLC;
-
- lnbp21->config |= lnbp21->override_or;
- lnbp21->config &= lnbp21->override_and;
-
- return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static void lnbp21_exit(struct dvb_frontend *fe)
-{
- struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
-
- /* LNBP power off */
- lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
-
- /* free data & call next release routine */
- fe->ops->release = lnbp21->release_chain;
- kfree(fe->misc_priv);
- fe->misc_priv = NULL;
- if (fe->ops->release)
- fe->ops->release(fe);
-}
-
-static int lnbp21_init(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
-{
- struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
-
- if (!lnbp21)
- return -ENOMEM;
-
- /* default configuration */
- lnbp21->config = LNBP21_ISEL;
-
- /* bits which should be forced to '1' */
- lnbp21->override_or = override_set;
-
- /* bits which should be forced to '0' */
- lnbp21->override_and = ~override_clear;
-
- /* install release callback */
- lnbp21->release_chain = fe->ops->release;
- fe->ops->release = lnbp21_exit;
-
- /* override frontend ops */
- fe->ops->set_voltage = lnbp21_set_voltage;
- fe->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
-
- lnbp21->i2c = i2c;
- fe->misc_priv = lnbp21;
-
- return lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
-}
+/* override_set and override_clear control which system register bits (above) to always set & clear */
+extern int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear);
#endif
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
index d3aea83cf218..1ef821825641 100644
--- a/drivers/media/dvb/frontends/mt312.c
+++ b/drivers/media/dvb/frontends/mt312.c
@@ -39,7 +39,6 @@
struct mt312_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
/* configuration settings */
const struct mt312_config* config;
struct dvb_frontend frontend;
@@ -277,12 +276,6 @@ static int mt312_initfe(struct dvb_frontend* fe)
if ((ret = mt312_writereg(state, CS_SW_LIM, 0x69)) < 0)
return ret;
- if (state->config->pll_init) {
- mt312_writereg(state, GPP_CTRL, 0x40);
- state->config->pll_init(fe);
- mt312_writereg(state, GPP_CTRL, 0x00);
- }
-
return 0;
}
@@ -477,16 +470,16 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency);
- if ((p->frequency < fe->ops->info.frequency_min)
- || (p->frequency > fe->ops->info.frequency_max))
+ if ((p->frequency < fe->ops.info.frequency_min)
+ || (p->frequency > fe->ops.info.frequency_max))
return -EINVAL;
if ((p->inversion < INVERSION_OFF)
|| (p->inversion > INVERSION_ON))
return -EINVAL;
- if ((p->u.qpsk.symbol_rate < fe->ops->info.symbol_rate_min)
- || (p->u.qpsk.symbol_rate > fe->ops->info.symbol_rate_max))
+ if ((p->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min)
+ || (p->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max))
return -EINVAL;
if ((p->u.qpsk.fec_inner < FEC_NONE)
@@ -529,9 +522,10 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
return -EINVAL;
}
- mt312_writereg(state, GPP_CTRL, 0x40);
- state->config->pll_set(fe, p);
- mt312_writereg(state, GPP_CTRL, 0x00);
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
/* sr = (u16)(sr * 256.0 / 1000000.0) */
sr = mt312_div(p->u.qpsk.symbol_rate * 4, 15625);
@@ -578,6 +572,17 @@ static int mt312_get_frontend(struct dvb_frontend* fe,
return 0;
}
+static int mt312_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+ struct mt312_state* state = fe->demodulator_priv;
+
+ if (enable) {
+ return mt312_writereg(state, GPP_CTRL, 0x40);
+ } else {
+ return mt312_writereg(state, GPP_CTRL, 0x00);
+ }
+}
+
static int mt312_sleep(struct dvb_frontend* fe)
{
struct mt312_state *state = fe->demodulator_priv;
@@ -633,6 +638,7 @@ static struct dvb_frontend_ops vp310_mt312_ops = {
.init = mt312_initfe,
.sleep = mt312_sleep,
+ .i2c_gate_ctrl = mt312_i2c_gate_ctrl,
.set_frontend = mt312_set_frontend,
.get_frontend = mt312_get_frontend,
@@ -663,19 +669,22 @@ struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
/* check if the demod is there */
if (mt312_readreg(state, ID, &state->id) < 0)
goto error;
+ /* create dvb_frontend */
+ memcpy(&state->frontend.ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
+ state->frontend.demodulator_priv = state;
+
switch (state->id) {
case ID_VP310:
- strcpy(state->ops.info.name, "Zarlink VP310 DVB-S");
+ strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S");
state->frequency = 90;
break;
case ID_MT312:
- strcpy(state->ops.info.name, "Zarlink MT312 DVB-S");
+ strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S");
state->frequency = 60;
break;
default:
@@ -683,9 +692,6 @@ struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
goto error;
}
- /* create dvb_frontend */
- state->frontend.ops = &state->ops;
- state->frontend.demodulator_priv = state;
return &state->frontend;
error:
diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h
index 074d844f0139..666a1bd1c244 100644
--- a/drivers/media/dvb/frontends/mt312.h
+++ b/drivers/media/dvb/frontends/mt312.h
@@ -32,10 +32,6 @@ struct mt312_config
{
/* the demodulator's i2c address */
u8 demod_address;
-
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};
struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c
index aaaec909ddf8..5de7376c94ce 100644
--- a/drivers/media/dvb/frontends/mt352.c
+++ b/drivers/media/dvb/frontends/mt352.c
@@ -45,7 +45,6 @@
struct mt352_state {
struct i2c_adapter* i2c;
struct dvb_frontend frontend;
- struct dvb_frontend_ops ops;
/* configuration settings */
struct mt352_config config;
@@ -286,16 +285,25 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
mt352_calc_nominal_rate(state, op->bandwidth, buf+4);
mt352_calc_input_freq(state, buf+6);
- state->config.pll_set(fe, param, buf+8);
- mt352_write(fe, buf, sizeof(buf));
if (state->config.no_tuner) {
- /* start decoding */
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, param);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
+ mt352_write(fe, buf, 8);
mt352_write(fe, fsm_go, 2);
} else {
- /* start tuning */
- mt352_write(fe, tuner_go, 2);
+ if (fe->ops.tuner_ops.calc_regs) {
+ fe->ops.tuner_ops.calc_regs(fe, param, buf+8, 5);
+ buf[8] <<= 1;
+ mt352_write(fe, buf, sizeof(buf));
+ mt352_write(fe, tuner_go, 2);
+ }
}
+
return 0;
}
@@ -541,13 +549,12 @@ struct dvb_frontend* mt352_attach(const struct mt352_config* config,
/* setup the state */
state->i2c = i2c;
memcpy(&state->config,config,sizeof(struct mt352_config));
- memcpy(&state->ops, &mt352_ops, sizeof(struct dvb_frontend_ops));
/* check if the demod is there */
if (mt352_read_register(state, CHIP_ID) != ID_MT352) goto error;
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &mt352_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
diff --git a/drivers/media/dvb/frontends/mt352.h b/drivers/media/dvb/frontends/mt352.h
index 03040cd595bb..9e7ff4b8fe5f 100644
--- a/drivers/media/dvb/frontends/mt352.h
+++ b/drivers/media/dvb/frontends/mt352.h
@@ -49,12 +49,6 @@ struct mt352_config
/* Initialise the demodulator and PLL. Cannot be NULL */
int (*demod_init)(struct dvb_frontend* fe);
-
- /* PLL setup - fill out the supplied 5 byte buffer with your PLL settings.
- * byte0: Set to pll i2c address (nonlinux; left shifted by 1)
- * byte1-4: PLL configuration.
- */
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf);
};
extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
index 9e3535394509..55671cb5255e 100644
--- a/drivers/media/dvb/frontends/nxt200x.c
+++ b/drivers/media/dvb/frontends/nxt200x.c
@@ -55,7 +55,6 @@
struct nxt200x_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
const struct nxt200x_config* config;
struct dvb_frontend frontend;
@@ -333,17 +332,17 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
dprintk("%s\n", __FUNCTION__);
- dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[0], data[1], data[2], data[3]);
+ dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[1], data[2], data[3], data[4]);
/* if NXT2004, write directly to tuner. if NXT2002, write through NXT chip.
* direct write is required for Philips TUV1236D and ALPS TDHU2 */
switch (state->demod_chip) {
case NXT2004:
- if (i2c_writebytes(state, state->config->pll_address, data, 4))
+ if (i2c_writebytes(state, data[0], data+1, 4))
printk(KERN_WARNING "nxt200x: error writing to tuner\n");
/* wait until we have a lock */
while (count < 20) {
- i2c_readbytes(state, state->config->pll_address, &buf, 1);
+ i2c_readbytes(state, data[0], &buf, 1);
if (buf & 0x40)
return 0;
msleep(100);
@@ -361,10 +360,10 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
nxt200x_writebytes(state, 0x34, &buf, 1);
/* write actual tuner bytes */
- nxt200x_writebytes(state, 0x36, data, 4);
+ nxt200x_writebytes(state, 0x36, data+1, 4);
/* set tuner i2c address */
- buf = state->config->pll_address;
+ buf = data[0] << 1;
nxt200x_writebytes(state, 0x35, &buf, 1);
/* write UC Opmode to begin transfer */
@@ -534,7 +533,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
struct dvb_frontend_parameters *p)
{
struct nxt200x_state* state = fe->demodulator_priv;
- u8 buf[4];
+ u8 buf[5];
/* stop the micro first */
nxt200x_microcontroller_stop(state);
@@ -548,7 +547,9 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
}
/* get tuning information */
- dvb_pll_configure(state->config->pll_desc, buf, p->frequency, 0);
+ if (fe->ops.tuner_ops.calc_regs) {
+ fe->ops.tuner_ops.calc_regs(fe, p, buf, 5);
+ }
/* set additional params */
switch (p->u.vsb.modulation) {
@@ -1159,7 +1160,6 @@ struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &nxt200x_ops, sizeof(struct dvb_frontend_ops));
state->initialised = 0;
/* read card id */
@@ -1198,7 +1198,7 @@ struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
}
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &nxt200x_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
diff --git a/drivers/media/dvb/frontends/nxt200x.h b/drivers/media/dvb/frontends/nxt200x.h
index 1d9d70bc37ef..34d61735845b 100644
--- a/drivers/media/dvb/frontends/nxt200x.h
+++ b/drivers/media/dvb/frontends/nxt200x.h
@@ -38,10 +38,6 @@ struct nxt200x_config
/* the demodulator's i2c address */
u8 demod_address;
- /* tuner information */
- u8 pll_address;
- struct dvb_pll_desc *pll_desc;
-
/* used to set pll input */
int (*set_pll_input)(u8* buf, int input);
diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c
index a16eeba0020d..d313d7dcf386 100644
--- a/drivers/media/dvb/frontends/nxt6000.c
+++ b/drivers/media/dvb/frontends/nxt6000.c
@@ -33,7 +33,6 @@
struct nxt6000_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
/* configuration settings */
const struct nxt6000_config* config;
struct dvb_frontend frontend;
@@ -207,12 +206,6 @@ static void nxt6000_setup(struct dvb_frontend* fe)
nxt6000_writereg(state, SUB_DIAG_MODE_SEL, 0);
nxt6000_writereg(state, TS_FORMAT, 0);
-
- if (state->config->pll_init) {
- nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */
- state->config->pll_init(fe);
- nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00); /* close i2c bus switch */
- }
}
static void nxt6000_dump_status(struct nxt6000_state *state)
@@ -469,9 +462,10 @@ static int nxt6000_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
struct nxt6000_state* state = fe->demodulator_priv;
int result;
- nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */
- state->config->pll_set(fe, param);
- nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00); /* close i2c bus switch */
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, param);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
if ((result = nxt6000_set_bandwidth(state, param->u.ofdm.bandwidth)) < 0)
return result;
@@ -532,6 +526,17 @@ static int nxt6000_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_fron
return 0;
}
+static int nxt6000_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+ struct nxt6000_state* state = fe->demodulator_priv;
+
+ if (enable) {
+ return nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01);
+ } else {
+ return nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00);
+ }
+}
+
static struct dvb_frontend_ops nxt6000_ops;
struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
@@ -546,13 +551,12 @@ struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &nxt6000_ops, sizeof(struct dvb_frontend_ops));
/* check if the demod is there */
if (nxt6000_readreg(state, OFDM_MSC_REV) != NXT6000ASICDEVICE) goto error;
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &nxt6000_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -584,6 +588,7 @@ static struct dvb_frontend_ops nxt6000_ops = {
.release = nxt6000_release,
.init = nxt6000_init,
+ .i2c_gate_ctrl = nxt6000_i2c_gate_ctrl,
.get_tune_settings = nxt6000_fe_get_tune_settings,
diff --git a/drivers/media/dvb/frontends/nxt6000.h b/drivers/media/dvb/frontends/nxt6000.h
index b7d9bead3002..117031d11708 100644
--- a/drivers/media/dvb/frontends/nxt6000.h
+++ b/drivers/media/dvb/frontends/nxt6000.h
@@ -31,10 +31,6 @@ struct nxt6000_config
/* should clock inversion be used? */
u8 clock_inversion:1;
-
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};
extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
index 80e0f28127b7..d20ab30c1e83 100644
--- a/drivers/media/dvb/frontends/or51132.c
+++ b/drivers/media/dvb/frontends/or51132.c
@@ -54,7 +54,6 @@ static int debug;
struct or51132_state
{
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
/* Configuration settings */
const struct or51132_config* config;
@@ -106,9 +105,8 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
{
struct or51132_state* state = fe->demodulator_priv;
static u8 run_buf[] = {0x7F,0x01};
- static u8 get_ver_buf[] = {0x04,0x00,0x30,0x00,0x00};
- u8 rec_buf[14];
- u8 cmd_buf[14];
+ u8 rec_buf[8];
+ u8 cmd_buf[3];
u32 firmwareAsize, firmwareBsize;
int i,ret;
@@ -157,7 +155,6 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
cmd_buf[0] = 0x10;
cmd_buf[1] = 0x10;
cmd_buf[2] = 0x00;
- cmd_buf[3] = 0x00;
msleep(20); /* 20ms */
if ((ret = i2c_writebytes(state,state->config->demod_address,
cmd_buf,3))) {
@@ -167,8 +164,6 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
cmd_buf[0] = 0x04;
cmd_buf[1] = 0x17;
- cmd_buf[2] = 0x00;
- cmd_buf[3] = 0x00;
msleep(20); /* 20ms */
if ((ret = i2c_writebytes(state,state->config->demod_address,
cmd_buf,2))) {
@@ -178,8 +173,6 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
cmd_buf[0] = 0x00;
cmd_buf[1] = 0x00;
- cmd_buf[2] = 0x00;
- cmd_buf[3] = 0x00;
msleep(20); /* 20ms */
if ((ret = i2c_writebytes(state,state->config->demod_address,
cmd_buf,2))) {
@@ -189,7 +182,11 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
for(i=0;i<4;i++) {
msleep(20); /* 20ms */
- get_ver_buf[4] = i+1;
+ /* Once upon a time, this command might have had something
+ to do with getting the firmware version, but it's
+ not used anymore:
+ {0x04,0x00,0x30,0x00,i+1} */
+ /* Read 8 bytes, two bytes at a time */
if ((ret = i2c_readbytes(state,state->config->demod_address,
&rec_buf[i*2],2))) {
printk(KERN_WARNING
@@ -208,7 +205,6 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
cmd_buf[0] = 0x10;
cmd_buf[1] = 0x00;
cmd_buf[2] = 0x00;
- cmd_buf[3] = 0x00;
msleep(20); /* 20ms */
if ((ret = i2c_writebytes(state,state->config->demod_address,
cmd_buf,3))) {
@@ -243,7 +239,7 @@ static int or51132_sleep(struct dvb_frontend* fe)
static int or51132_setmode(struct dvb_frontend* fe)
{
struct or51132_state* state = fe->demodulator_priv;
- unsigned char cmd_buf[4];
+ unsigned char cmd_buf[3];
dprintk("setmode %d\n",(int)state->current_modulation);
/* set operation mode in Receiver 1 register; */
@@ -263,7 +259,6 @@ static int or51132_setmode(struct dvb_frontend* fe)
default:
printk("setmode:Modulation set to unsupported value\n");
};
- cmd_buf[3] = 0x00;
if (i2c_writebytes(state,state->config->demod_address,
cmd_buf,3)) {
printk(KERN_WARNING "or51132: set_mode error 1\n");
@@ -301,7 +296,6 @@ static int or51132_setmode(struct dvb_frontend* fe)
default:
printk("setmode: Modulation set to unsupported value\n");
};
- cmd_buf[3] = 0x00;
msleep(20); /* 20ms */
if (i2c_writebytes(state,state->config->demod_address,
cmd_buf,3)) {
@@ -313,52 +307,65 @@ static int or51132_setmode(struct dvb_frontend* fe)
return 0;
}
+/* Some modulations use the same firmware. This classifies modulations
+ by the firmware they use. */
+#define MOD_FWCLASS_UNKNOWN 0
+#define MOD_FWCLASS_VSB 1
+#define MOD_FWCLASS_QAM 2
+static int modulation_fw_class(fe_modulation_t modulation)
+{
+ switch(modulation) {
+ case VSB_8:
+ return MOD_FWCLASS_VSB;
+ case QAM_AUTO:
+ case QAM_64:
+ case QAM_256:
+ return MOD_FWCLASS_QAM;
+ default:
+ return MOD_FWCLASS_UNKNOWN;
+ }
+}
+
static int or51132_set_parameters(struct dvb_frontend* fe,
struct dvb_frontend_parameters *param)
{
int ret;
- u8 buf[4];
struct or51132_state* state = fe->demodulator_priv;
const struct firmware *fw;
-
- /* Change only if we are actually changing the modulation */
- if (state->current_modulation != param->u.vsb.modulation) {
- switch(param->u.vsb.modulation) {
- case VSB_8:
+ const char *fwname;
+ int clock_mode;
+
+ /* Upload new firmware only if we need a different one */
+ if (modulation_fw_class(state->current_modulation) !=
+ modulation_fw_class(param->u.vsb.modulation)) {
+ switch(modulation_fw_class(param->u.vsb.modulation)) {
+ case MOD_FWCLASS_VSB:
dprintk("set_parameters VSB MODE\n");
- printk("or51132: Waiting for firmware upload(%s)...\n",
- OR51132_VSB_FIRMWARE);
- ret = request_firmware(&fw, OR51132_VSB_FIRMWARE,
- &state->i2c->dev);
- if (ret){
- printk(KERN_WARNING "or51132: No firmware up"
- "loaded(timeout or file not found?)\n");
- return ret;
- }
+ fwname = OR51132_VSB_FIRMWARE;
+
/* Set non-punctured clock for VSB */
- state->config->set_ts_params(fe, 0);
+ clock_mode = 0;
break;
- case QAM_AUTO:
- case QAM_64:
- case QAM_256:
+ case MOD_FWCLASS_QAM:
dprintk("set_parameters QAM MODE\n");
- printk("or51132: Waiting for firmware upload(%s)...\n",
- OR51132_QAM_FIRMWARE);
- ret = request_firmware(&fw, OR51132_QAM_FIRMWARE,
- &state->i2c->dev);
- if (ret){
- printk(KERN_WARNING "or51132: No firmware up"
- "loaded(timeout or file not found?)\n");
- return ret;
- }
+ fwname = OR51132_QAM_FIRMWARE;
+
/* Set punctured clock for QAM */
- state->config->set_ts_params(fe, 1);
+ clock_mode = 1;
break;
default:
- printk("or51132:Modulation type(%d) UNSUPPORTED\n",
+ printk("or51132: Modulation type(%d) UNSUPPORTED\n",
param->u.vsb.modulation);
return -1;
- };
+ }
+ printk("or51132: Waiting for firmware upload(%s)...\n",
+ fwname);
+ ret = request_firmware(&fw, fwname, &state->i2c->dev);
+ if (ret) {
+ printk(KERN_WARNING "or51132: No firmware up"
+ "loaded(timeout or file not found?)\n");
+ return ret;
+ }
ret = or51132_load_firmware(fe, fw);
release_firmware(fw);
if (ret) {
@@ -367,18 +374,18 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
return ret;
}
printk("or51132: Firmware upload complete.\n");
-
+ state->config->set_ts_params(fe, clock_mode);
+ }
+ /* Change only if we are actually changing the modulation */
+ if (state->current_modulation != param->u.vsb.modulation) {
state->current_modulation = param->u.vsb.modulation;
or51132_setmode(fe);
}
- dvb_pll_configure(state->config->pll_desc, buf,
- param->frequency, 0);
- dprintk("set_parameters tuner bytes: 0x%02x 0x%02x "
- "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]);
- if (i2c_writebytes(state, state->config->pll_address ,buf, 4))
- printk(KERN_WARNING "or51132: set_parameters error "
- "writing to tuner\n");
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, param);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
/* Set to current mode */
or51132_setmode(fe);
@@ -388,6 +395,44 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
return 0;
}
+static int or51132_get_parameters(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *param)
+{
+ struct or51132_state* state = fe->demodulator_priv;
+ u8 buf[2];
+
+ /* Receiver Status */
+ buf[0]=0x04;
+ buf[1]=0x00;
+ msleep(30); /* 30ms */
+ if (i2c_writebytes(state,state->config->demod_address,buf,2)) {
+ printk(KERN_WARNING "or51132: get_parameters write error\n");
+ return -EREMOTEIO;
+ }
+ msleep(30); /* 30ms */
+ if (i2c_readbytes(state,state->config->demod_address,buf,2)) {
+ printk(KERN_WARNING "or51132: get_parameters read error\n");
+ return -EREMOTEIO;
+ }
+ switch(buf[0]) {
+ case 0x06: param->u.vsb.modulation = VSB_8; break;
+ case 0x43: param->u.vsb.modulation = QAM_64; break;
+ case 0x45: param->u.vsb.modulation = QAM_256; break;
+ default:
+ printk(KERN_WARNING "or51132: unknown status 0x%02x\n",
+ buf[0]);
+ return -EREMOTEIO;
+ }
+
+ /* FIXME: Read frequency from frontend, take AFC into account */
+ param->frequency = state->current_frequency;
+
+ /* FIXME: How to read inversion setting? Receiver 6 register? */
+ param->inversion = INVERSION_AUTO;
+
+ return 0;
+}
+
static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
struct or51132_state* state = fe->demodulator_priv;
@@ -572,12 +617,11 @@ struct dvb_frontend* or51132_attach(const struct or51132_config* config,
/* Setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &or51132_ops, sizeof(struct dvb_frontend_ops));
state->current_frequency = -1;
state->current_modulation = -1;
/* Create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &or51132_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -590,7 +634,7 @@ static struct dvb_frontend_ops or51132_ops = {
.info = {
.name = "Oren OR51132 VSB/QAM Frontend",
- .type = FE_ATSC,
+ .type = FE_ATSC,
.frequency_min = 44000000,
.frequency_max = 958000000,
.frequency_stepsize = 166666,
@@ -606,6 +650,7 @@ static struct dvb_frontend_ops or51132_ops = {
.sleep = or51132_sleep,
.set_frontend = or51132_set_parameters,
+ .get_frontend = or51132_get_parameters,
.get_tune_settings = or51132_get_tune_settings,
.read_status = or51132_read_status,
diff --git a/drivers/media/dvb/frontends/or51132.h b/drivers/media/dvb/frontends/or51132.h
index 622cdd18381b..89658883abf5 100644
--- a/drivers/media/dvb/frontends/or51132.h
+++ b/drivers/media/dvb/frontends/or51132.h
@@ -29,8 +29,6 @@ struct or51132_config
{
/* The demodulator's i2c address */
u8 demod_address;
- u8 pll_address;
- struct dvb_pll_desc *pll_desc;
/* Need to set device param for start_dma */
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
index 7c3aed1f546b..26bed616fabe 100644
--- a/drivers/media/dvb/frontends/or51211.c
+++ b/drivers/media/dvb/frontends/or51211.c
@@ -54,7 +54,6 @@ static u8 cmd_buf[] = {0x04,0x01,0x50,0x80,0x06}; // ATSC
struct or51211_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
/* Configuration settings */
const struct or51211_config* config;
@@ -585,12 +584,11 @@ struct dvb_frontend* or51211_attach(const struct or51211_config* config,
/* Setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &or51211_ops, sizeof(struct dvb_frontend_ops));
state->initialized = 0;
state->current_frequency = 0;
/* Create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &or51211_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
index d69477596921..2c2c344c4c64 100644
--- a/drivers/media/dvb/frontends/s5h1420.c
+++ b/drivers/media/dvb/frontends/s5h1420.c
@@ -38,7 +38,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
struct s5h1420_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
const struct s5h1420_config* config;
struct dvb_frontend frontend;
@@ -584,7 +583,6 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
struct s5h1420_state* state = fe->demodulator_priv;
int frequency_delta;
struct dvb_frontend_tune_settings fesettings;
- u32 tmp;
/* check if we should do a fast-tune */
memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters));
@@ -596,10 +594,17 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
(state->fec_inner == p->u.qpsk.fec_inner) &&
(state->symbol_rate == p->u.qpsk.symbol_rate)) {
- if (state->config->pll_set) {
- s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
- state->config->pll_set(fe, p, &tmp);
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+ if (fe->ops.tuner_ops.get_frequency) {
+ u32 tmp;
+ fe->ops.tuner_ops.get_frequency(fe, &tmp);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
s5h1420_setfreqoffset(state, p->frequency - tmp);
+ } else {
+ s5h1420_setfreqoffset(state, 0);
}
return 0;
}
@@ -646,9 +651,9 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1);
/* set tuner PLL */
- if (state->config->pll_set) {
- s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
- state->config->pll_set(fe, p, &tmp);
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
s5h1420_setfreqoffset(state, 0);
}
@@ -708,6 +713,17 @@ static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
return 0;
}
+static int s5h1420_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+ struct s5h1420_state* state = fe->demodulator_priv;
+
+ if (enable) {
+ return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
+ } else {
+ return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe);
+ }
+}
+
static int s5h1420_init (struct dvb_frontend* fe)
{
struct s5h1420_state* state = fe->demodulator_priv;
@@ -717,13 +733,6 @@ static int s5h1420_init (struct dvb_frontend* fe)
msleep(10);
s5h1420_reset(state);
- /* init PLL */
- if (state->config->pll_init) {
- s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
- state->config->pll_init(fe);
- s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe);
- }
-
return 0;
}
@@ -756,7 +765,6 @@ struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
state->postlocked = 0;
state->fclk = 88000000;
state->tunedfreq = 0;
@@ -769,7 +777,7 @@ struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
goto error;
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -800,6 +808,7 @@ static struct dvb_frontend_ops s5h1420_ops = {
.init = s5h1420_init,
.sleep = s5h1420_sleep,
+ .i2c_gate_ctrl = s5h1420_i2c_gate_ctrl,
.set_frontend = s5h1420_set_frontend,
.get_frontend = s5h1420_get_frontend,
diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h
index 73296f13c324..4e39015fa67e 100644
--- a/drivers/media/dvb/frontends/s5h1420.h
+++ b/drivers/media/dvb/frontends/s5h1420.h
@@ -32,10 +32,6 @@ struct s5h1420_config
/* does the inversion require inversion? */
u8 invert:1;
-
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout);
};
extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c
index 73829e647e50..44ec5b9a4695 100644
--- a/drivers/media/dvb/frontends/sp8870.c
+++ b/drivers/media/dvb/frontends/sp8870.c
@@ -44,8 +44,6 @@ struct sp8870_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
-
const struct sp8870_config* config;
struct dvb_frontend frontend;
@@ -262,9 +260,10 @@ static int sp8870_set_frontend_parameters (struct dvb_frontend* fe,
sp8870_microcontroller_stop(state);
// set tuner parameters
- sp8870_writereg(state, 0x206, 0x001);
- state->config->pll_set(fe, p);
- sp8870_writereg(state, 0x206, 0x000);
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
// sample rate correction bit [23..17]
sp8870_writereg(state, 0x0319, 0x000A);
@@ -349,13 +348,6 @@ static int sp8870_init (struct dvb_frontend* fe)
sp8870_writereg(state, 0x0D00, 0x010);
sp8870_writereg(state, 0x0D01, 0x000);
- /* setup PLL */
- if (state->config->pll_init) {
- sp8870_writereg(state, 0x206, 0x001);
- state->config->pll_init(fe);
- sp8870_writereg(state, 0x206, 0x000);
- }
-
return 0;
}
@@ -541,6 +533,17 @@ static int sp8870_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend
return 0;
}
+static int sp8870_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+ struct sp8870_state* state = fe->demodulator_priv;
+
+ if (enable) {
+ return sp8870_writereg(state, 0x206, 0x001);
+ } else {
+ return sp8870_writereg(state, 0x206, 0x000);
+ }
+}
+
static void sp8870_release(struct dvb_frontend* fe)
{
struct sp8870_state* state = fe->demodulator_priv;
@@ -561,14 +564,13 @@ struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &sp8870_ops, sizeof(struct dvb_frontend_ops));
state->initialised = 0;
/* check if the demod is there */
if (sp8870_readreg(state, 0x0200) < 0) goto error;
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &sp8870_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -597,6 +599,7 @@ static struct dvb_frontend_ops sp8870_ops = {
.init = sp8870_init,
.sleep = sp8870_sleep,
+ .i2c_gate_ctrl = sp8870_i2c_gate_ctrl,
.set_frontend = sp8870_set_frontend,
.get_tune_settings = sp8870_get_tune_settings,
diff --git a/drivers/media/dvb/frontends/sp8870.h b/drivers/media/dvb/frontends/sp8870.h
index f3b555dbc960..93afbb969d6b 100644
--- a/drivers/media/dvb/frontends/sp8870.h
+++ b/drivers/media/dvb/frontends/sp8870.h
@@ -31,10 +31,6 @@ struct sp8870_config
/* the demodulator's i2c address */
u8 demod_address;
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-
/* request firmware for device */
int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
};
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
index eb8a602198ca..b0a2b02f6608 100644
--- a/drivers/media/dvb/frontends/sp887x.c
+++ b/drivers/media/dvb/frontends/sp887x.c
@@ -24,7 +24,6 @@
struct sp887x_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
const struct sp887x_config* config;
struct dvb_frontend frontend;
@@ -208,15 +207,6 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
/* bit 0x010: enable data valid signal */
sp887x_writereg(state, 0xd00, 0x010);
sp887x_writereg(state, 0x0d1, 0x000);
-
- /* setup the PLL */
- if (state->config->pll_init) {
- sp887x_writereg(state, 0x206, 0x001);
- state->config->pll_init(fe);
- sp887x_writereg(state, 0x206, 0x000);
- }
-
- printk ("done.\n");
return 0;
};
@@ -362,9 +352,16 @@ static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
sp887x_microcontroller_stop(state);
/* setup the PLL */
- sp887x_writereg(state, 0x206, 0x001);
- actual_freq = state->config->pll_set(fe, p);
- sp887x_writereg(state, 0x206, 0x000);
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+ if (fe->ops.tuner_ops.get_frequency) {
+ fe->ops.tuner_ops.get_frequency(fe, &actual_freq);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ } else {
+ actual_freq = p->frequency;
+ }
/* read status reg in order to clear <pending irqs */
sp887x_readreg(state, 0x200);
@@ -486,6 +483,17 @@ static int sp887x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
return 0;
}
+static int sp887x_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+ struct sp887x_state* state = fe->demodulator_priv;
+
+ if (enable) {
+ return sp887x_writereg(state, 0x206, 0x001);
+ } else {
+ return sp887x_writereg(state, 0x206, 0x000);
+ }
+}
+
static int sp887x_sleep(struct dvb_frontend* fe)
{
struct sp887x_state* state = fe->demodulator_priv;
@@ -555,14 +563,13 @@ struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &sp887x_ops, sizeof(struct dvb_frontend_ops));
state->initialised = 0;
/* check if the demod is there */
if (sp887x_readreg(state, 0x0200) < 0) goto error;
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &sp887x_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -589,6 +596,7 @@ static struct dvb_frontend_ops sp887x_ops = {
.init = sp887x_init,
.sleep = sp887x_sleep,
+ .i2c_gate_ctrl = sp887x_i2c_gate_ctrl,
.set_frontend = sp887x_setup_frontend_parameters,
.get_tune_settings = sp887x_get_tune_settings,
diff --git a/drivers/media/dvb/frontends/sp887x.h b/drivers/media/dvb/frontends/sp887x.h
index 6a05d8f8e8cc..c44b0ebdf1e2 100644
--- a/drivers/media/dvb/frontends/sp887x.h
+++ b/drivers/media/dvb/frontends/sp887x.h
@@ -13,12 +13,6 @@ struct sp887x_config
/* the demodulator's i2c address */
u8 demod_address;
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
-
- /* this should return the actual frequency tuned to */
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-
/* request firmware for device */
int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
};
diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c
index eb15676d374f..1ca64249010c 100644
--- a/drivers/media/dvb/frontends/stv0297.c
+++ b/drivers/media/dvb/frontends/stv0297.c
@@ -32,7 +32,6 @@
struct stv0297_state {
struct i2c_adapter *i2c;
- struct dvb_frontend_ops ops;
const struct stv0297_config *config;
struct dvb_frontend frontend;
@@ -68,19 +67,25 @@ static int stv0297_readreg(struct stv0297_state *state, u8 reg)
int ret;
u8 b0[] = { reg };
u8 b1[] = { 0 };
- struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len =
- 1},
- {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
- };
+ struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 1},
+ {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
+ };
// this device needs a STOP between the register and data
- if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
- return -1;
- }
- if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
- return -1;
+ if (state->config->stop_during_read) {
+ if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+ return -1;
+ }
+ if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+ return -1;
+ }
+ } else {
+ if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+ return -1;
+ }
}
return b1[0];
@@ -107,13 +112,20 @@ static int stv0297_readregs(struct stv0297_state *state, u8 reg1, u8 * b, u8 len
};
// this device needs a STOP between the register and data
- if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
- return -1;
- }
- if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
- dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
- return -1;
+ if (state->config->stop_during_read) {
+ if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+ return -1;
+ }
+ if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+ return -1;
+ }
+ } else {
+ if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+ dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+ return -1;
+ }
}
return 0;
@@ -276,12 +288,14 @@ static int stv0297_set_inversion(struct stv0297_state *state, fe_spectral_invers
return 0;
}
-int stv0297_enable_plli2c(struct dvb_frontend *fe)
+static int stv0297_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
{
struct stv0297_state *state = fe->demodulator_priv;
- stv0297_writereg(state, 0x87, 0x78);
- stv0297_writereg(state, 0x86, 0xc8);
+ if (enable) {
+ stv0297_writereg(state, 0x87, 0x78);
+ stv0297_writereg(state, 0x86, 0xc8);
+ }
return 0;
}
@@ -296,9 +310,6 @@ static int stv0297_init(struct dvb_frontend *fe)
stv0297_writereg(state, state->config->inittab[i], state->config->inittab[i+1]);
msleep(200);
- if (state->config->pll_init)
- state->config->pll_init(fe);
-
return 0;
}
@@ -389,7 +400,7 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
case QAM_32:
case QAM_64:
delay = 100;
- sweeprate = 1500;
+ sweeprate = 1000;
break;
case QAM_128:
@@ -421,7 +432,10 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
}
stv0297_init(fe);
- state->config->pll_set(fe, p);
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
/* clear software interrupts */
stv0297_writereg(state, 0x82, 0x0);
@@ -634,7 +648,6 @@ struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &stv0297_ops, sizeof(struct dvb_frontend_ops));
state->base_freq = 0;
/* check if the demod is there */
@@ -642,7 +655,7 @@ struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
goto error;
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &stv0297_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -668,6 +681,7 @@ static struct dvb_frontend_ops stv0297_ops = {
.init = stv0297_init,
.sleep = stv0297_sleep,
+ .i2c_gate_ctrl = stv0297_i2c_gate_ctrl,
.set_frontend = stv0297_set_frontend,
.get_frontend = stv0297_get_frontend,
@@ -684,4 +698,3 @@ MODULE_AUTHOR("Dennis Noermann and Andrew de Quincey");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(stv0297_attach);
-EXPORT_SYMBOL(stv0297_enable_plli2c);
diff --git a/drivers/media/dvb/frontends/stv0297.h b/drivers/media/dvb/frontends/stv0297.h
index 9e53f019db71..1da5384fb985 100644
--- a/drivers/media/dvb/frontends/stv0297.h
+++ b/drivers/media/dvb/frontends/stv0297.h
@@ -38,13 +38,11 @@ struct stv0297_config
/* does the "inversion" need inverted? */
u8 invert:1;
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+ /* set to 1 if the device requires an i2c STOP during reading */
+ u8 stop_during_read:1;
};
extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
struct i2c_adapter* i2c);
-extern int stv0297_enable_plli2c(struct dvb_frontend* fe);
#endif // STV0297_H
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index 5bcd00f792e6..96648a75440d 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -56,7 +56,6 @@
struct stv0299_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
const struct stv0299_config* config;
struct dvb_frontend frontend;
@@ -131,13 +130,6 @@ static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len
return ret == 2 ? 0 : ret;
}
-int stv0299_enable_plli2c (struct dvb_frontend* fe)
-{
- struct stv0299_state* state = fe->demodulator_priv;
-
- return stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
-}
-
static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
{
dprintk ("%s\n", __FUNCTION__);
@@ -457,12 +449,6 @@ static int stv0299_init (struct dvb_frontend* fe)
for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2)
stv0299_writeregI(state, state->config->inittab[i], state->config->inittab[i+1]);
- if (state->config->pll_init) {
- stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
- state->config->pll_init(fe, state->i2c);
- stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */
- }
-
return 0;
}
@@ -560,9 +546,10 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
if (state->config->invert) invval = (~invval) & 1;
stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval);
- stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
- state->config->pll_set(fe, state->i2c, p);
- stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
stv0299_set_FEC (state, p->u.qpsk.fec_inner);
stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate);
@@ -611,6 +598,19 @@ static int stv0299_sleep(struct dvb_frontend* fe)
return 0;
}
+static int stv0299_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+ struct stv0299_state* state = fe->demodulator_priv;
+
+ if (enable) {
+ stv0299_writeregI(state, 0x05, 0xb5);
+ } else {
+ stv0299_writeregI(state, 0x05, 0x35);
+ }
+ udelay(1);
+ return 0;
+}
+
static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
{
struct stv0299_state* state = fe->demodulator_priv;
@@ -647,7 +647,6 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &stv0299_ops, sizeof(struct dvb_frontend_ops));
state->initialised = 0;
state->tuner_frequency = 0;
state->symbol_rate = 0;
@@ -664,7 +663,7 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
if (id != 0xa1 && id != 0x80) goto error;
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &stv0299_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -695,6 +694,7 @@ static struct dvb_frontend_ops stv0299_ops = {
.init = stv0299_init,
.sleep = stv0299_sleep,
+ .i2c_gate_ctrl = stv0299_i2c_gate_ctrl,
.set_frontend = stv0299_set_frontend,
.get_frontend = stv0299_get_frontend,
@@ -721,9 +721,8 @@ MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
MODULE_DESCRIPTION("ST STV0299 DVB Demodulator driver");
MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, "
- "Andreas Oberritter, Andrew de Quincey, Kenneth Aafløy");
+ "Andreas Oberritter, Andrew de Quincey, Kenneth Aafly");
MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(stv0299_enable_plli2c);
EXPORT_SYMBOL(stv0299_writereg);
EXPORT_SYMBOL(stv0299_attach);
diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h
index 32c87b4c2f13..1504828e4232 100644
--- a/drivers/media/dvb/frontends/stv0299.h
+++ b/drivers/media/dvb/frontends/stv0299.h
@@ -87,14 +87,9 @@ struct stv0299_config
/* Set the symbol rate */
int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio);
-
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend *fe, struct i2c_adapter *i2c);
- int (*pll_set)(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params);
};
extern int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data);
-extern int stv0299_enable_plli2c (struct dvb_frontend* fe);
extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
struct i2c_adapter* i2c);
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
index 21255cac9793..e83ff2104c9b 100644
--- a/drivers/media/dvb/frontends/tda10021.c
+++ b/drivers/media/dvb/frontends/tda10021.c
@@ -36,7 +36,6 @@
struct tda10021_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
/* configuration settings */
const struct tda10021_config* config;
struct dvb_frontend frontend;
@@ -90,6 +89,14 @@ static int tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
return (ret != 1) ? -EREMOTEIO : 0;
}
+int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data)
+{
+ struct tda10021_state* state = fe->demodulator_priv;
+
+ return tda10021_writereg(state, reg, data);
+}
+EXPORT_SYMBOL(tda10021_write_byte);
+
static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
{
u8 b0 [] = { reg };
@@ -225,13 +232,6 @@ static int tda10021_init (struct dvb_frontend *fe)
//Activate PLL
tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef);
-
- if (state->config->pll_init) {
- lock_tuner(state);
- state->config->pll_init(fe);
- unlock_tuner(state);
- }
-
return 0;
}
@@ -259,9 +259,10 @@ static int tda10021_set_parameters (struct dvb_frontend *fe,
//printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->u.qam.symbol_rate);
- lock_tuner(state);
- state->config->pll_set(fe, p);
- unlock_tuner(state);
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
tda10021_set_symbolrate (state, p->u.qam.symbol_rate);
tda10021_writereg (state, 0x34, state->pwm);
@@ -376,6 +377,18 @@ static int tda10021_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
return 0;
}
+static int tda10021_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+ struct tda10021_state* state = fe->demodulator_priv;
+
+ if (enable) {
+ lock_tuner(state);
+ } else {
+ unlock_tuner(state);
+ }
+ return 0;
+}
+
static int tda10021_sleep(struct dvb_frontend* fe)
{
struct tda10021_state* state = fe->demodulator_priv;
@@ -407,7 +420,6 @@ struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &tda10021_ops, sizeof(struct dvb_frontend_ops));
state->pwm = pwm;
state->reg0 = tda10021_inittab[0];
@@ -415,7 +427,7 @@ struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
if ((tda10021_readreg(state, 0x1a) & 0xf0) != 0x70) goto error;
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &tda10021_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -448,6 +460,7 @@ static struct dvb_frontend_ops tda10021_ops = {
.init = tda10021_init,
.sleep = tda10021_sleep,
+ .i2c_gate_ctrl = tda10021_i2c_gate_ctrl,
.set_frontend = tda10021_set_parameters,
.get_frontend = tda10021_get_frontend,
diff --git a/drivers/media/dvb/frontends/tda10021.h b/drivers/media/dvb/frontends/tda10021.h
index 53be939e8c55..b1df4259bee9 100644
--- a/drivers/media/dvb/frontends/tda10021.h
+++ b/drivers/media/dvb/frontends/tda10021.h
@@ -30,13 +30,11 @@ struct tda10021_config
{
/* the demodulator's i2c address */
u8 demod_address;
-
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};
extern struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
struct i2c_adapter* i2c, u8 pwm);
+extern int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data);
+
#endif // TDA10021_H
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index b83dafa4e12c..59a2ed614fca 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -47,7 +47,6 @@ enum tda1004x_demod {
struct tda1004x_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
const struct tda1004x_config* config;
struct dvb_frontend frontend;
@@ -600,13 +599,6 @@ static int tda10045_init(struct dvb_frontend* fe)
tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0); // wake up the ADC
- // Init the PLL
- if (state->config->pll_init) {
- tda1004x_enable_tuner_i2c(state);
- state->config->pll_init(fe);
- tda1004x_disable_tuner_i2c(state);
- }
-
// tda setup
tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
tda1004x_write_mask(state, TDA1004X_AUTO, 8, 0); // select HP stream
@@ -635,16 +627,6 @@ static int tda10046_init(struct dvb_frontend* fe)
return -EIO;
}
- // Init the tuner PLL
- if (state->config->pll_init) {
- tda1004x_enable_tuner_i2c(state);
- if (state->config->pll_init(fe)) {
- printk(KERN_ERR "tda1004x: pll init failed\n");
- return -EIO;
- }
- tda1004x_disable_tuner_i2c(state);
- }
-
// tda setup
tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87); // 100 ppm crystal, select HP stream
@@ -712,12 +694,10 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
}
// set frequency
- tda1004x_enable_tuner_i2c(state);
- if (state->config->pll_set(fe, fe_params)) {
- printk(KERN_ERR "tda1004x: pll set failed\n");
- return -EIO;
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, fe_params);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
}
- tda1004x_disable_tuner_i2c(state);
// Hardcoded to use auto as much as possible on the TDA10045 as it
// is very unreliable if AUTO mode is _not_ used.
@@ -1183,16 +1163,6 @@ static int tda1004x_sleep(struct dvb_frontend* fe)
break;
case TDA1004X_DEMOD_TDA10046:
- if (state->config->pll_sleep != NULL) {
- tda1004x_enable_tuner_i2c(state);
- state->config->pll_sleep(fe);
- if (state->config->if_freq != TDA10046_FREQ_052) {
- /* special hack for Philips EUROPA Based boards:
- * keep the I2c bridge open for tuner access in analog mode
- */
- tda1004x_disable_tuner_i2c(state);
- }
- }
/* set outputs to tristate */
tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0xff);
tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1);
@@ -1202,6 +1172,17 @@ static int tda1004x_sleep(struct dvb_frontend* fe)
return 0;
}
+static int tda1004x_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+ struct tda1004x_state* state = fe->demodulator_priv;
+
+ if (enable) {
+ return tda1004x_enable_tuner_i2c(state);
+ } else {
+ return tda1004x_disable_tuner_i2c(state);
+ }
+}
+
static int tda1004x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
{
fesettings->min_delay_ms = 800;
@@ -1235,6 +1216,7 @@ static struct dvb_frontend_ops tda10045_ops = {
.init = tda10045_init,
.sleep = tda1004x_sleep,
+ .i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
.set_frontend = tda1004x_set_fe,
.get_frontend = tda1004x_get_fe,
@@ -1260,7 +1242,6 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));
state->demod_type = TDA1004X_DEMOD_TDA10045;
/* check if the demod is there */
@@ -1270,7 +1251,7 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
}
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
}
@@ -1293,6 +1274,7 @@ static struct dvb_frontend_ops tda10046_ops = {
.init = tda10046_init,
.sleep = tda1004x_sleep,
+ .i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
.set_frontend = tda1004x_set_fe,
.get_frontend = tda1004x_get_fe,
@@ -1318,7 +1300,6 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));
state->demod_type = TDA1004X_DEMOD_TDA10046;
/* check if the demod is there */
@@ -1328,7 +1309,7 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
}
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
}
diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h
index cc0c4af64067..b877b23ed734 100644
--- a/drivers/media/dvb/frontends/tda1004x.h
+++ b/drivers/media/dvb/frontends/tda1004x.h
@@ -66,11 +66,6 @@ struct tda1004x_config
/* AGC configuration */
enum tda10046_agc agc_config;
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- void (*pll_sleep)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-
/* request firmware for device */
/* set this to NULL if the card has a firmware EEPROM */
int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c
index 91baa9cedd79..3aa45ebbac3d 100644
--- a/drivers/media/dvb/frontends/tda8083.c
+++ b/drivers/media/dvb/frontends/tda8083.c
@@ -37,7 +37,6 @@
struct tda8083_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
/* configuration settings */
const struct tda8083_config* config;
struct dvb_frontend frontend;
@@ -293,7 +292,11 @@ static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
{
struct tda8083_state* state = fe->demodulator_priv;
- state->config->pll_set(fe, p);
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
tda8083_set_inversion (state, p->inversion);
tda8083_set_fec (state, p->u.qpsk.fec_inner);
tda8083_set_symbolrate (state, p->u.qpsk.symbol_rate);
@@ -334,8 +337,6 @@ static int tda8083_init(struct dvb_frontend* fe)
for (i=0; i<44; i++)
tda8083_writereg (state, i, tda8083_init_tab[i]);
- if (state->config->pll_init) state->config->pll_init(fe);
-
tda8083_writereg (state, 0x00, 0x3c);
tda8083_writereg (state, 0x00, 0x04);
@@ -395,13 +396,12 @@ struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &tda8083_ops, sizeof(struct dvb_frontend_ops));
/* check if the demod is there */
if ((tda8083_readreg(state, 0x00)) != 0x05) goto error;
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &tda8083_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
diff --git a/drivers/media/dvb/frontends/tda8083.h b/drivers/media/dvb/frontends/tda8083.h
index 466663307bf1..e7a48f61ea2c 100644
--- a/drivers/media/dvb/frontends/tda8083.h
+++ b/drivers/media/dvb/frontends/tda8083.h
@@ -33,10 +33,6 @@ struct tda8083_config
{
/* the demodulator's i2c address */
u8 demod_address;
-
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};
extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c
index ad8647a3c85e..6bffe85c161c 100644
--- a/drivers/media/dvb/frontends/ves1820.c
+++ b/drivers/media/dvb/frontends/ves1820.c
@@ -35,7 +35,6 @@
struct ves1820_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
/* configuration settings */
const struct ves1820_config* config;
struct dvb_frontend frontend;
@@ -204,9 +203,6 @@ static int ves1820_init(struct dvb_frontend* fe)
ves1820_writereg(state, 0x34, state->pwm);
- if (state->config->pll_init)
- state->config->pll_init(fe);
-
return 0;
}
@@ -223,7 +219,11 @@ static int ves1820_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_p
if (real_qam < 0 || real_qam > 4)
return -EINVAL;
- state->config->pll_set(fe, p);
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
ves1820_set_symbolrate(state, p->u.qam.symbol_rate);
ves1820_writereg(state, 0x34, state->pwm);
@@ -380,7 +380,6 @@ struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
goto error;
/* setup the state */
- memcpy(&state->ops, &ves1820_ops, sizeof(struct dvb_frontend_ops));
state->reg0 = ves1820_inittab[0];
state->config = config;
state->i2c = i2c;
@@ -393,12 +392,12 @@ struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
if (verbose)
printk("ves1820: pwm=0x%02x\n", state->pwm);
- state->ops.info.symbol_rate_min = (state->config->xin / 2) / 64; /* SACLK/64 == (XIN/2)/64 */
- state->ops.info.symbol_rate_max = (state->config->xin / 2) / 4; /* SACLK/4 */
-
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &ves1820_ops, sizeof(struct dvb_frontend_ops));
+ state->frontend.ops.info.symbol_rate_min = (state->config->xin / 2) / 64; /* SACLK/64 == (XIN/2)/64 */
+ state->frontend.ops.info.symbol_rate_max = (state->config->xin / 2) / 4; /* SACLK/4 */
state->frontend.demodulator_priv = state;
+
return &state->frontend;
error:
diff --git a/drivers/media/dvb/frontends/ves1820.h b/drivers/media/dvb/frontends/ves1820.h
index 355f130b1be8..520f09522fbb 100644
--- a/drivers/media/dvb/frontends/ves1820.h
+++ b/drivers/media/dvb/frontends/ves1820.h
@@ -39,10 +39,6 @@ struct ves1820_config
/* SELAGC control */
u8 selagc:1;
-
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};
extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
diff --git a/drivers/media/dvb/frontends/ves1x93.c b/drivers/media/dvb/frontends/ves1x93.c
index 821df8e839d0..54d7b07571b8 100644
--- a/drivers/media/dvb/frontends/ves1x93.c
+++ b/drivers/media/dvb/frontends/ves1x93.c
@@ -36,7 +36,6 @@
struct ves1x93_state {
struct i2c_adapter* i2c;
- struct dvb_frontend_ops ops;
/* configuration settings */
const struct ves1x93_config* config;
struct dvb_frontend frontend;
@@ -278,12 +277,6 @@ static int ves1x93_init (struct dvb_frontend* fe)
}
}
- if (state->config->pll_init) {
- ves1x93_writereg(state, 0x00, 0x11);
- state->config->pll_init(fe);
- ves1x93_writereg(state, 0x00, 0x01);
- }
-
return 0;
}
@@ -395,9 +388,10 @@ static int ves1x93_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
{
struct ves1x93_state* state = fe->demodulator_priv;
- ves1x93_writereg(state, 0x00, 0x11);
- state->config->pll_set(fe, p);
- ves1x93_writereg(state, 0x00, 0x01);
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, p);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
ves1x93_set_inversion (state, p->inversion);
ves1x93_set_fec (state, p->u.qpsk.fec_inner);
ves1x93_set_symbolrate (state, p->u.qpsk.symbol_rate);
@@ -442,6 +436,17 @@ static void ves1x93_release(struct dvb_frontend* fe)
kfree(state);
}
+static int ves1x93_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+ struct ves1x93_state* state = fe->demodulator_priv;
+
+ if (enable) {
+ return ves1x93_writereg(state, 0x00, 0x11);
+ } else {
+ return ves1x93_writereg(state, 0x00, 0x01);
+ }
+}
+
static struct dvb_frontend_ops ves1x93_ops;
struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
@@ -457,7 +462,6 @@ struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
/* setup the state */
state->config = config;
state->i2c = i2c;
- memcpy(&state->ops, &ves1x93_ops, sizeof(struct dvb_frontend_ops));
state->inversion = INVERSION_OFF;
/* check if the demod is there + identify it */
@@ -492,7 +496,7 @@ struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
}
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &ves1x93_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
@@ -523,6 +527,7 @@ static struct dvb_frontend_ops ves1x93_ops = {
.init = ves1x93_init,
.sleep = ves1x93_sleep,
+ .i2c_gate_ctrl = ves1x93_i2c_gate_ctrl,
.set_frontend = ves1x93_set_frontend,
.get_frontend = ves1x93_get_frontend,
diff --git a/drivers/media/dvb/frontends/ves1x93.h b/drivers/media/dvb/frontends/ves1x93.h
index 1627e37c57a4..ba88ae0855c9 100644
--- a/drivers/media/dvb/frontends/ves1x93.h
+++ b/drivers/media/dvb/frontends/ves1x93.h
@@ -38,10 +38,6 @@ struct ves1x93_config
/* should PWM be inverted? */
u8 invert_pwm:1;
-
- /* PLL maintenance */
- int (*pll_init)(struct dvb_frontend* fe);
- int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};
extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
index d7d9f59d76d2..2b95e8b6cd39 100644
--- a/drivers/media/dvb/frontends/zl10353.c
+++ b/drivers/media/dvb/frontends/zl10353.c
@@ -34,7 +34,6 @@
struct zl10353_state {
struct i2c_adapter *i2c;
struct dvb_frontend frontend;
- struct dvb_frontend_ops ops;
struct zl10353_config config;
};
@@ -126,6 +125,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
struct dvb_frontend_parameters *param)
{
struct zl10353_state *state = fe->demodulator_priv;
+
u8 pllbuf[6] = { 0x67 };
/* These settings set "auto-everything" and start the FSM. */
@@ -142,7 +142,30 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
zl10353_single_write(fe, 0x66, 0xE9);
zl10353_single_write(fe, 0x62, 0x0A);
- state->config.pll_set(fe, param, pllbuf + 1);
+ // if there is no attached secondary tuner, we call set_params to program
+ // a potential tuner attached somewhere else
+ if (state->config.no_tuner) {
+ if (fe->ops.tuner_ops.set_params) {
+ fe->ops.tuner_ops.set_params(fe, param);
+ if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+ }
+
+ // if pllbuf is defined, retrieve the settings
+ if (fe->ops.tuner_ops.calc_regs) {
+ fe->ops.tuner_ops.calc_regs(fe, param, pllbuf+1, 5);
+ pllbuf[1] <<= 1;
+ } else {
+ // fake pllbuf settings
+ pllbuf[1] = 0x61 << 1;
+ pllbuf[2] = 0;
+ pllbuf[3] = 0;
+ pllbuf[3] = 0;
+ pllbuf[4] = 0;
+ }
+
+ // there is no call to _just_ start decoding, so we send the pllbuf anyway
+ // even if there isn't a PLL attached to the secondary bus
zl10353_write(fe, pllbuf, sizeof(pllbuf));
zl10353_single_write(fe, 0x70, 0x01);
@@ -254,14 +277,13 @@ struct dvb_frontend *zl10353_attach(const struct zl10353_config *config,
/* setup the state */
state->i2c = i2c;
memcpy(&state->config, config, sizeof(struct zl10353_config));
- memcpy(&state->ops, &zl10353_ops, sizeof(struct dvb_frontend_ops));
/* check if the demod is there */
if (zl10353_read_register(state, CHIP_ID) != ID_ZL10353)
goto error;
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &zl10353_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h
index 5cc4ae718d8c..9770cb840cfc 100644
--- a/drivers/media/dvb/frontends/zl10353.h
+++ b/drivers/media/dvb/frontends/zl10353.h
@@ -29,10 +29,8 @@ struct zl10353_config
/* demodulator's I2C address */
u8 demod_address;
- /* function which configures the PLL buffer (for secondary I2C
- * connected tuner) or tunes the PLL (for direct connected tuner) */
- int (*pll_set)(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *params, u8 *pllbuf);
+ /* set if no pll is connected to the secondary i2c bus */
+ int no_tuner;
};
extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index 1c5316e209ef..acabea0793b6 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -424,8 +424,8 @@ static inline u32 divide(u32 numerator, u32 denominator)
}
/* LG Innotek TDTE-E001P (Infineon TUA6034) */
-static int lg_tdtpe001p_pll_set(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *p)
+static int lg_tdtpe001p_tuner_set_params(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
{
struct pluto *pluto = frontend_to_pluto(fe);
struct i2c_msg msg;
@@ -473,6 +473,8 @@ static int lg_tdtpe001p_pll_set(struct dvb_frontend *fe,
msg.buf = buf;
msg.len = sizeof(buf);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
ret = i2c_transfer(&pluto->i2c_adap, &msg, 1);
if (ret < 0)
return ret;
@@ -497,8 +499,6 @@ static struct tda1004x_config pluto2_fe_config __devinitdata = {
.xtal_freq = TDA10046_XTAL_16M,
.agc_config = TDA10046_AGC_DEFAULT,
.if_freq = TDA10046_FREQ_3617,
- .pll_set = lg_tdtpe001p_pll_set,
- .pll_sleep = NULL,
.request_firmware = pluto2_request_firmware,
};
@@ -511,11 +511,12 @@ static int __devinit frontend_init(struct pluto *pluto)
dev_err(&pluto->pdev->dev, "could not attach frontend\n");
return -ENODEV;
}
+ pluto->fe->ops.tuner_ops.set_params = lg_tdtpe001p_tuner_set_params;
ret = dvb_register_frontend(&pluto->dvb_adapter, pluto->fe);
if (ret < 0) {
- if (pluto->fe->ops->release)
- pluto->fe->ops->release(pluto->fe);
+ if (pluto->fe->ops.release)
+ pluto->fe->ops.release(pluto->fe);
return ret;
}
@@ -647,7 +648,7 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
goto err_pluto_hw_exit;
/* dvb */
- ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE);
+ ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev);
if (ret < 0)
goto err_i2c_bit_del_bus;
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index b5ac7dfde52f..987881fa988c 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -10,6 +10,7 @@ config DVB_AV7110
select DVB_SP8870
select DVB_STV0297
select DVB_L64781
+ select DVB_LNBP21
help
Support for SAA7146 and AV7110 based DVB cards as produced
by Fujitsu-Siemens, Technotrend, Hauppauge and others.
@@ -67,6 +68,7 @@ config DVB_BUDGET
select DVB_TDA8083
select DVB_TDA10021
select DVB_S5H1420
+ select DVB_LNBP21
help
Support for simple SAA7146 based DVB cards
(so called Budget- or Nova-PCI cards) without onboard
@@ -84,6 +86,7 @@ config DVB_BUDGET_CI
select DVB_STV0297
select DVB_STV0299
select DVB_TDA1004X
+ select DVB_LNBP21
help
Support for simple SAA7146 based DVB cards
(so called Budget- or Nova-PCI cards) without onboard
diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile
index a690730ac39d..aa85ecdc6c80 100644
--- a/drivers/media/dvb/ttpci/Makefile
+++ b/drivers/media/dvb/ttpci/Makefile
@@ -15,9 +15,9 @@ EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
hostprogs-y := fdump
-ifdef CONFIG_DVB_AV7110_FIRMWARE
-$(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h
+ifeq ($(CONFIG_DVB_AV7110_FIRMWARE),y)
+$(obj)/av7110.o: $(obj)/av7110_firm.h
-$(obj)/av7110_firm.h:
+$(obj)/av7110_firm.h: $(obj)/fdump
$(obj)/fdump $(CONFIG_DVB_AV7110_FIRMWARE_FILE) dvb_ttpci_fw $@
endif
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index d028245c8eed..8832f80c05f7 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -1552,7 +1552,7 @@ static int get_firmware(struct av7110* av7110)
#endif
-static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
u8 pwr = 0;
@@ -1575,6 +1575,8 @@ static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
// NOTE: since we're using a prescaler of 2, we set the
// divisor frequency to 62.5kHz and divide by 125 above
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
@@ -1584,10 +1586,9 @@ static struct ves1x93_config alps_bsrv2_config = {
.demod_address = 0x08,
.xin = 90100000UL,
.invert_pwm = 0,
- .pll_set = alps_bsrv2_pll_set,
};
-static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
{
struct av7110* av7110 = fe->dvb->priv;
u32 div;
@@ -1601,6 +1602,8 @@ static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
data[2] = 0x85 | ((div >> 10) & 0x60);
data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
@@ -1611,14 +1614,12 @@ static struct ves1820_config alps_tdbe2_config = {
.xin = 57840000UL,
.invert = 1,
.selagc = VES1820_SELAGC_SIGNAMPERR,
- .pll_set = alps_tdbe2_pll_set,
};
-static int grundig_29504_451_pll_set(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params)
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
{
struct av7110* av7110 = fe->dvb->priv;
u32 div;
@@ -1631,6 +1632,8 @@ static int grundig_29504_451_pll_set(struct dvb_frontend* fe,
data[2] = 0x8e;
data[3] = 0x00;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
@@ -1638,13 +1641,11 @@ static int grundig_29504_451_pll_set(struct dvb_frontend* fe,
static struct tda8083_config grundig_29504_451_config = {
.demod_address = 0x68,
- .pll_set = grundig_29504_451_pll_set,
};
-static int philips_cd1516_pll_set(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params)
+static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
{
struct av7110* av7110 = fe->dvb->priv;
u32 div;
@@ -1659,6 +1660,8 @@ static int philips_cd1516_pll_set(struct dvb_frontend* fe,
data[2] = 0x8e;
data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
@@ -1669,12 +1672,11 @@ static struct ves1820_config philips_cd1516_config = {
.xin = 57840000UL,
.invert = 1,
.selagc = VES1820_SELAGC_SIGNAMPERR,
- .pll_set = philips_cd1516_pll_set,
};
-static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
{
struct av7110* av7110 = fe->dvb->priv;
u32 div, pwr;
@@ -1693,6 +1695,8 @@ static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
data[2] = 0x85;
data[3] = pwr << 6;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
@@ -1708,7 +1712,6 @@ static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct fir
static struct sp8870_config alps_tdlb7_config = {
.demod_address = 0x71,
- .pll_set = alps_tdlb7_pll_set,
.request_firmware = alps_tdlb7_request_firmware,
};
@@ -1806,7 +1809,7 @@ static u8 nexusca_stv0297_inittab[] = {
0xff, 0xff,
};
-static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
{
struct av7110* av7110 = fe->dvb->priv;
u32 div;
@@ -1832,7 +1835,8 @@ static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
else
return -EINVAL;
- stv0297_enable_plli2c(fe);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
printk("nexusca: pll transfer failed!\n");
return -EIO;
@@ -1840,8 +1844,8 @@ static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
// wait for PLL lock
for(i = 0; i < 20; i++) {
-
- stv0297_enable_plli2c(fe);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
if (data[0] & 0x40) break;
msleep(10);
@@ -1855,12 +1859,12 @@ static struct stv0297_config nexusca_stv0297_config = {
.demod_address = 0x1C,
.inittab = nexusca_stv0297_inittab,
.invert = 1,
- .pll_set = nexusca_stv0297_pll_set,
+ .stop_during_read = 1,
};
-static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
{
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
u32 div;
@@ -1887,13 +1891,14 @@ static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_fronten
data[2] = ((div >> 10) & 0x60) | cfg;
data[3] = (cpump << 6) | band_select;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
return 0;
}
static struct l64781_config grundig_29504_401_config = {
.demod_address = 0x55,
- .pll_set = grundig_29504_401_pll_set,
};
@@ -2079,6 +2084,9 @@ static int frontend_init(struct av7110 *av7110)
case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
av7110->fe = ves1820_attach(&philips_cd1516_config,
&av7110->i2c_adap, read_pwm(av7110));
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
+ }
break;
}
@@ -2091,9 +2099,10 @@ static int frontend_init(struct av7110 *av7110)
// try the ALPS BSRV2 first of all
av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
if (av7110->fe) {
- av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
- av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
- av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+ av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+ av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+ av7110->fe->ops.set_tone = av7110_set_tone;
av7110->recover = dvb_s_recover;
break;
}
@@ -2101,9 +2110,12 @@ static int frontend_init(struct av7110 *av7110)
// try the ALPS BSRU6 now
av7110->fe = stv0299_attach(&alps_bsru6_config, &av7110->i2c_adap);
if (av7110->fe) {
- av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
- av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
- av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+ av7110->fe->tuner_priv = &av7110->i2c_adap;
+
+ av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+ av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+ av7110->fe->ops.set_tone = av7110_set_tone;
av7110->recover = dvb_s_recover;
break;
}
@@ -2111,9 +2123,10 @@ static int frontend_init(struct av7110 *av7110)
// Try the grundig 29504-451
av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
if (av7110->fe) {
- av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
- av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
- av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+ av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+ av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+ av7110->fe->ops.set_tone = av7110_set_tone;
av7110->recover = dvb_s_recover;
break;
}
@@ -2124,11 +2137,17 @@ static int frontend_init(struct av7110 *av7110)
/* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap,
read_pwm(av7110));
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
+ }
break;
case 0x0003:
/* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap,
read_pwm(av7110));
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
+ }
break;
}
break;
@@ -2137,20 +2156,27 @@ static int frontend_init(struct av7110 *av7110)
// ALPS TDLB7
av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
+ }
break;
case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
+ }
break;
case 0x0004: // Galaxis DVB-S rev1.3
/* ALPS BSRV2 */
av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
if (av7110->fe) {
- av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
- av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
- av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+ av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+ av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+ av7110->fe->ops.set_tone = av7110_set_tone;
av7110->recover = dvb_s_recover;
}
break;
@@ -2159,9 +2185,10 @@ static int frontend_init(struct av7110 *av7110)
/* Grundig 29504-451 */
av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
if (av7110->fe) {
- av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
- av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
- av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+ av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+ av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+ av7110->fe->ops.set_tone = av7110_set_tone;
av7110->recover = dvb_s_recover;
}
break;
@@ -2169,12 +2196,17 @@ static int frontend_init(struct av7110 *av7110)
case 0x0008: // Hauppauge/TT DVB-T
av7110->fe = l64781_attach(&grundig_29504_401_config, &av7110->i2c_adap);
+ if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
+ }
break;
case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap);
if (av7110->fe) {
+ av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
+
/* set TDA9819 into DVB mode */
saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
@@ -2189,13 +2221,16 @@ static int frontend_init(struct av7110 *av7110)
/* ALPS BSBE1 */
av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap);
if (av7110->fe) {
- if (lnbp21_init(av7110->fe, &av7110->i2c_adap, 0, 0)) {
+ av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
+ av7110->fe->tuner_priv = &av7110->i2c_adap;
+
+ if (lnbp21_attach(av7110->fe, &av7110->i2c_adap, 0, 0)) {
printk("dvb-ttpci: LNBP21 not found!\n");
- if (av7110->fe->ops->release)
- av7110->fe->ops->release(av7110->fe);
+ if (av7110->fe->ops.release)
+ av7110->fe->ops.release(av7110->fe);
av7110->fe = NULL;
} else {
- av7110->fe->ops->dishnetwork_send_legacy_command = NULL;
+ av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
av7110->recover = dvb_s_recover;
}
}
@@ -2212,21 +2247,21 @@ static int frontend_init(struct av7110 *av7110)
av7110->dev->pci->subsystem_vendor,
av7110->dev->pci->subsystem_device);
} else {
- FE_FUNC_OVERRIDE(av7110->fe->ops->init, av7110->fe_init, av7110_fe_init);
- FE_FUNC_OVERRIDE(av7110->fe->ops->read_status, av7110->fe_read_status, av7110_fe_read_status);
- FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
- FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
- FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
- FE_FUNC_OVERRIDE(av7110->fe->ops->set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
- FE_FUNC_OVERRIDE(av7110->fe->ops->set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)
- FE_FUNC_OVERRIDE(av7110->fe->ops->dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
- FE_FUNC_OVERRIDE(av7110->fe->ops->set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
+ FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
+ FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
+ FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
+ FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
+ FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
+ FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
+ FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)
+ FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
+ FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
if (ret < 0) {
printk("av7110: Frontend registration failed!\n");
- if (av7110->fe->ops->release)
- av7110->fe->ops->release(av7110->fe);
+ if (av7110->fe->ops.release)
+ av7110->fe->ops.release(av7110->fe);
av7110->fe = NULL;
}
}
@@ -2413,7 +2448,7 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
goto err_kfree_0;
ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
- THIS_MODULE);
+ THIS_MODULE, &dev->pci->dev);
if (ret < 0)
goto err_put_firmware_1;
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 8a7cd7d505cf..6163cb03b8f4 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -50,6 +50,12 @@
#define DEBICICAM 0x02420000
+#define SLOTSTATUS_NONE 1
+#define SLOTSTATUS_PRESENT 2
+#define SLOTSTATUS_RESET 4
+#define SLOTSTATUS_READY 8
+#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
+
struct budget_av {
struct budget budget;
struct video_device *vd;
@@ -58,8 +64,15 @@ struct budget_av {
struct tasklet_struct ciintf_irq_tasklet;
int slot_status;
struct dvb_ca_en50221 ca;
+ u8 reinitialise_demod:1;
+ u8 tda10021_poclkp:1;
+ u8 tda10021_ts_enabled;
+ int (*tda10021_set_frontend)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
};
+static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot);
+
+
/* GPIO Connections:
* 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*!
* 1 - CI memory select 0=>IO memory, 1=>Attribute Memory
@@ -129,9 +142,10 @@ static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int ad
udelay(1);
result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
-
- if (result == -ETIMEDOUT)
- budget_av->slot_status = 0;
+ if (result == -ETIMEDOUT) {
+ ciintf_slot_shutdown(ca, slot);
+ printk(KERN_INFO "budget-av: cam ejected 1\n");
+ }
return result;
}
@@ -147,9 +161,10 @@ static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int a
udelay(1);
result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
-
- if (result == -ETIMEDOUT)
- budget_av->slot_status = 0;
+ if (result == -ETIMEDOUT) {
+ ciintf_slot_shutdown(ca, slot);
+ printk(KERN_INFO "budget-av: cam ejected 2\n");
+ }
return result;
}
@@ -165,9 +180,11 @@ static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addre
udelay(1);
result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
-
- if (result == -ETIMEDOUT)
- budget_av->slot_status = 0;
+ if ((result == -ETIMEDOUT) || ((result == 0xff) && ((address & 3) < 2))) {
+ ciintf_slot_shutdown(ca, slot);
+ printk(KERN_INFO "budget-av: cam ejected 3\n");
+ return -ETIMEDOUT;
+ }
return result;
}
@@ -183,9 +200,10 @@ static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addr
udelay(1);
result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
-
- if (result == -ETIMEDOUT)
- budget_av->slot_status = 0;
+ if (result == -ETIMEDOUT) {
+ ciintf_slot_shutdown(ca, slot);
+ printk(KERN_INFO "budget-av: cam ejected 5\n");
+ }
return result;
}
@@ -193,12 +211,12 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
struct saa7146_dev *saa = budget_av->budget.dev;
- int timeout = 50; // 5 seconds (4.4.6 Ready)
if (slot != 0)
return -EINVAL;
dprintk(1, "ciintf_slot_reset\n");
+ budget_av->slot_status = SLOTSTATUS_RESET;
saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
@@ -208,20 +226,17 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
msleep(20); /* 20 ms Vcc settling time */
saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
+ ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
+ msleep(20);
- /* This should have been based on pin 16 READY of the pcmcia port,
- * but AFAICS it is not routed to the saa7146 */
- while (--timeout > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d)
- msleep(100);
-
- /* reinitialise the frontend */
- dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
+ /* reinitialise the frontend if necessary */
+ if (budget_av->reinitialise_demod)
+ dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
- if (timeout <= 0)
- {
- printk(KERN_ERR "budget-av: cam reset failed (timeout).\n");
- saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
- return -ETIMEDOUT;
+ /* set tda10021 back to original clock configuration on reset */
+ if (budget_av->tda10021_poclkp) {
+ tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
+ budget_av->tda10021_ts_enabled = 0;
}
return 0;
@@ -238,7 +253,13 @@ static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
dprintk(1, "ciintf_slot_shutdown\n");
ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
- budget_av->slot_status = 0;
+ budget_av->slot_status = SLOTSTATUS_NONE;
+
+ /* set tda10021 back to original clock configuration when cam removed */
+ if (budget_av->tda10021_poclkp) {
+ tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
+ budget_av->tda10021_ts_enabled = 0;
+ }
return 0;
}
@@ -253,6 +274,13 @@ static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status);
ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
+
+ /* tda10021 seems to need a different TS clock config when data is routed to the CAM */
+ if (budget_av->tda10021_poclkp) {
+ tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
+ budget_av->tda10021_ts_enabled = 1;
+ }
+
return 0;
}
@@ -260,50 +288,61 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
struct saa7146_dev *saa = budget_av->budget.dev;
- int cam_present = 0;
+ int result;
if (slot != 0)
return -EINVAL;
- if (!budget_av->slot_status)
- {
- // first of all test the card detect line
+ /* test the card detect line - needs to be done carefully
+ * since it never goes high for some CAMs on this interface (e.g. topuptv) */
+ if (budget_av->slot_status == SLOTSTATUS_NONE) {
saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
udelay(1);
- if (saa7146_read(saa, PSR) & MASK_06)
- {
- cam_present = 1;
+ if (saa7146_read(saa, PSR) & MASK_06) {
+ if (budget_av->slot_status == SLOTSTATUS_NONE) {
+ budget_av->slot_status = SLOTSTATUS_PRESENT;
+ printk(KERN_INFO "budget-av: cam inserted A\n");
+ }
}
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
+ }
- // that is unreliable however, so try and read from IO memory
- if (!cam_present)
- {
- saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
- if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) != -ETIMEDOUT)
- {
- cam_present = 1;
+ /* We also try and read from IO memory to work round the above detection bug. If
+ * there is no CAM, we will get a timeout. Only done if there is no cam
+ * present, since this test actually breaks some cams :(
+ *
+ * if the CI interface is not open, we also do the above test since we
+ * don't care if the cam has problems - we'll be resetting it on open() anyway */
+ if ((budget_av->slot_status == SLOTSTATUS_NONE) || (!open)) {
+ saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
+ result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1);
+ if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) {
+ budget_av->slot_status = SLOTSTATUS_PRESENT;
+ printk(KERN_INFO "budget-av: cam inserted B\n");
+ } else if (result < 0) {
+ if (budget_av->slot_status != SLOTSTATUS_NONE) {
+ ciintf_slot_shutdown(ca, slot);
+ printk(KERN_INFO "budget-av: cam ejected 5\n");
+ return 0;
}
}
+ }
- // did we find something?
- if (cam_present) {
- printk(KERN_INFO "budget-av: cam inserted\n");
- budget_av->slot_status = 1;
- }
- } else if (!open) {
- saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
- if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT)
- {
- printk(KERN_INFO "budget-av: cam ejected\n");
- saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
- budget_av->slot_status = 0;
+ /* read from attribute memory in reset/ready state to know when the CAM is ready */
+ if (budget_av->slot_status == SLOTSTATUS_RESET) {
+ result = ciintf_read_attribute_mem(ca, slot, 0);
+ if (result == 0x1d) {
+ budget_av->slot_status = SLOTSTATUS_READY;
}
}
- if (budget_av->slot_status == 1)
- return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
-
+ /* work out correct return code */
+ if (budget_av->slot_status != SLOTSTATUS_NONE) {
+ if (budget_av->slot_status & SLOTSTATUS_READY) {
+ return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
+ }
+ return DVB_CA_EN50221_POLL_CAM_PRESENT;
+ }
return 0;
}
@@ -333,6 +372,8 @@ static int ciintf_init(struct budget_av *budget_av)
budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
budget_av->ca.data = budget_av;
+ budget_av->budget.ci_present = 1;
+ budget_av->slot_status = SLOTSTATUS_NONE;
if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
&budget_av->ca, 0, 1)) != 0) {
@@ -341,7 +382,6 @@ static int ciintf_init(struct budget_av *budget_av)
}
printk(KERN_INFO "budget-av: ci interface initialised.\n");
- budget_av->budget.ci_present = 1;
return 0;
error:
@@ -472,12 +512,12 @@ static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 sra
return 0;
}
-static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
- struct i2c_adapter *i2c,
- struct dvb_frontend_parameters *params)
+static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
{
u32 div;
u8 buf[4];
+ struct budget *budget = (struct budget *) fe->dvb->priv;
struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
if ((params->frequency < 950000) || (params->frequency > 2150000))
@@ -501,7 +541,9 @@ static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
else if (params->frequency < 2150000)
buf[3] |= 0xC0;
- if (i2c_transfer(i2c, &msg, 1) != 1)
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
@@ -509,9 +551,8 @@ static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
#define MIN2(a,b) ((a) < (b) ? (a) : (b))
#define MIN3(a,b,c) MIN2(MIN2(a,b),c)
-static int philips_su1278sh2_tua6100_pll_set(struct dvb_frontend *fe,
- struct i2c_adapter *i2c,
- struct dvb_frontend_parameters *params)
+static int philips_su1278sh2_tua6100_tuner_set_params(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
{
u8 reg0 [2] = { 0x00, 0x00 };
u8 reg1 [4] = { 0x01, 0x00, 0x00, 0x00 };
@@ -521,6 +562,7 @@ static int philips_su1278sh2_tua6100_pll_set(struct dvb_frontend *fe,
int R, A, N, P, M;
struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = NULL,.len = 0 };
int freq = params->frequency;
+ struct budget *budget = (struct budget *) fe->dvb->priv;
first_ZF = (freq) / 1000;
@@ -620,21 +662,25 @@ static int philips_su1278sh2_tua6100_pll_set(struct dvb_frontend *fe,
reg0[1] |= 0x03;
/* already enabled - do not reenable i2c repeater or TX fails */
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
msg.buf = reg0;
msg.len = sizeof(reg0);
- if (i2c_transfer(i2c, &msg, 1) != 1)
+ if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
return -EIO;
- stv0299_enable_plli2c(fe);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
msg.buf = reg1;
msg.len = sizeof(reg1);
- if (i2c_transfer(i2c, &msg, 1) != 1)
+ if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
return -EIO;
- stv0299_enable_plli2c(fe);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
msg.buf = reg2;
msg.len = sizeof(reg2);
- if (i2c_transfer(i2c, &msg, 1) != 1)
+ if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
@@ -692,7 +738,6 @@ static struct stv0299_config typhoon_config = {
.volt13_op0_op1 = STV0299_VOLT13_OP0,
.min_delay_ms = 100,
.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
- .pll_set = philips_su1278_ty_ci_pll_set,
};
@@ -706,7 +751,6 @@ static struct stv0299_config cinergy_1200s_config = {
.volt13_op0_op1 = STV0299_VOLT13_OP0,
.min_delay_ms = 100,
.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
- .pll_set = philips_su1278_ty_ci_pll_set,
};
static struct stv0299_config cinergy_1200s_1894_0010_config = {
@@ -719,10 +763,9 @@ static struct stv0299_config cinergy_1200s_1894_0010_config = {
.volt13_op0_op1 = STV0299_VOLT13_OP0,
.min_delay_ms = 100,
.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
- .pll_set = philips_su1278sh2_tua6100_pll_set,
};
-static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
struct budget *budget = (struct budget *) fe->dvb->priv;
u8 buf[4];
@@ -738,6 +781,8 @@ static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_p
buf[3] = (params->frequency < 150000000 ? 0x01 :
params->frequency < 445000000 ? 0x02 : 0x04);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
@@ -745,19 +790,20 @@ static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_p
static struct tda10021_config philips_cu1216_config = {
.demod_address = 0x0c,
- .pll_set = philips_cu1216_pll_set,
};
-static int philips_tu1216_pll_init(struct dvb_frontend *fe)
+static int philips_tu1216_tuner_init(struct dvb_frontend *fe)
{
struct budget *budget = (struct budget *) fe->dvb->priv;
static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
// setup PLL configuration
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
return -EIO;
msleep(1);
@@ -765,7 +811,7 @@ static int philips_tu1216_pll_init(struct dvb_frontend *fe)
return 0;
}
-static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
struct budget *budget = (struct budget *) fe->dvb->priv;
u8 tuner_buf[4];
@@ -839,6 +885,8 @@ static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_p
tuner_buf[2] = 0xca;
tuner_buf[3] = (cp << 5) | (filter << 3) | band;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
return -EIO;
@@ -862,9 +910,6 @@ static struct tda1004x_config philips_tu1216_config = {
.xtal_freq = TDA10046_XTAL_4M,
.agc_config = TDA10046_AGC_DEFAULT,
.if_freq = TDA10046_FREQ_3617,
- .pll_init = philips_tu1216_pll_init,
- .pll_set = philips_tu1216_pll_set,
- .pll_sleep = NULL,
.request_firmware = philips_tu1216_request_firmware,
};
@@ -911,13 +956,13 @@ static u8 philips_sd1878_inittab[] = {
0xff, 0xff
};
-static int philips_sd1878_tda8261_pll_set(struct dvb_frontend *fe,
- struct i2c_adapter *i2c,
- struct dvb_frontend_parameters *params)
+static int philips_sd1878_tda8261_tuner_set_params(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
{
u8 buf[4];
int rc;
struct i2c_msg tuner_msg = {.addr=0x60,.flags=0,.buf=buf,.len=sizeof(buf)};
+ struct budget *budget = (struct budget *) fe->dvb->priv;
if((params->frequency < 950000) || (params->frequency > 2150000))
return -EINVAL;
@@ -926,7 +971,9 @@ static int philips_sd1878_tda8261_pll_set(struct dvb_frontend *fe,
params->frequency, 0);
if(rc < 0) return rc;
- if(i2c_transfer(i2c, &tuner_msg, 1) != 1)
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if(i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
return -EIO;
return 0;
@@ -969,7 +1016,7 @@ static int philips_sd1878_ci_set_symbol_rate(struct dvb_frontend *fe,
static struct stv0299_config philips_sd1878_config = {
.demod_address = 0x68,
- .inittab = philips_sd1878_inittab,
+ .inittab = philips_sd1878_inittab,
.mclk = 88000000UL,
.invert = 0,
.skip_reinit = 0,
@@ -977,7 +1024,6 @@ static struct stv0299_config philips_sd1878_config = {
.volt13_op0_op1 = STV0299_VOLT13_OP0,
.min_delay_ms = 100,
.set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
- .pll_set = philips_sd1878_tda8261_pll_set,
};
static u8 read_pwm(struct budget_av *budget_av)
@@ -1003,6 +1049,7 @@ static u8 read_pwm(struct budget_av *budget_av)
#define SUBID_DVBS_TV_STAR 0x0014
#define SUBID_DVBS_TV_STAR_CI 0x0016
+#define SUBID_DVBS_EASYWATCH_1 0x001a
#define SUBID_DVBS_EASYWATCH 0x001e
#define SUBID_DVBC_KNC1 0x0020
#define SUBID_DVBC_KNC1_PLUS 0x0021
@@ -1012,17 +1059,36 @@ static u8 read_pwm(struct budget_av *budget_av)
#define SUBID_DVBT_KNC1 0x0030
#define SUBID_DVBT_CINERGY1200 0x1157
+
+static int tda10021_set_frontend(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct budget_av* budget_av = fe->dvb->priv;
+ int result;
+
+ result = budget_av->tda10021_set_frontend(fe, p);
+ if (budget_av->tda10021_ts_enabled) {
+ tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
+ } else {
+ tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
+ }
+
+ return result;
+}
+
static void frontend_init(struct budget_av *budget_av)
{
struct saa7146_dev * saa = budget_av->budget.dev;
struct dvb_frontend * fe = NULL;
+ /* Enable / PowerON Frontend */
+ saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
+
+ /* additional setup necessary for the PLUS cards */
switch (saa->pci->subsystem_device) {
case SUBID_DVBS_KNC1_PLUS:
case SUBID_DVBC_KNC1_PLUS:
case SUBID_DVBT_KNC1_PLUS:
- // Enable / PowerON Frontend
- saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
break;
}
@@ -1030,12 +1096,19 @@ static void frontend_init(struct budget_av *budget_av)
switch (saa->pci->subsystem_device) {
case SUBID_DVBS_KNC1:
+ case SUBID_DVBS_EASYWATCH_1:
if (saa->pci->subsystem_vendor == 0x1894) {
fe = stv0299_attach(&cinergy_1200s_1894_0010_config,
&budget_av->budget.i2c_adap);
+ if (fe) {
+ fe->ops.tuner_ops.set_params = philips_su1278sh2_tua6100_tuner_set_params;
+ }
} else {
fe = stv0299_attach(&typhoon_config,
&budget_av->budget.i2c_adap);
+ if (fe) {
+ fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
+ }
}
break;
@@ -1045,41 +1118,53 @@ static void frontend_init(struct budget_av *budget_av)
case SUBID_DVBS_EASYWATCH:
fe = stv0299_attach(&philips_sd1878_config,
&budget_av->budget.i2c_adap);
+ if (fe) {
+ fe->ops.tuner_ops.set_params = philips_sd1878_tda8261_tuner_set_params;
+ }
break;
case SUBID_DVBS_KNC1_PLUS:
case SUBID_DVBS_TYPHOON:
fe = stv0299_attach(&typhoon_config,
&budget_av->budget.i2c_adap);
+ if (fe) {
+ fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
+ }
break;
case SUBID_DVBS_CINERGY1200:
fe = stv0299_attach(&cinergy_1200s_config,
&budget_av->budget.i2c_adap);
+ if (fe) {
+ fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
+ }
break;
case SUBID_DVBC_KNC1:
case SUBID_DVBC_KNC1_PLUS:
+ case SUBID_DVBC_CINERGY1200:
+ budget_av->reinitialise_demod = 1;
fe = tda10021_attach(&philips_cu1216_config,
&budget_av->budget.i2c_adap,
read_pwm(budget_av));
+ if (fe) {
+ budget_av->tda10021_poclkp = 1;
+ budget_av->tda10021_set_frontend = fe->ops.set_frontend;
+ fe->ops.set_frontend = tda10021_set_frontend;
+ fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
+ }
break;
case SUBID_DVBT_KNC1:
case SUBID_DVBT_KNC1_PLUS:
- fe = tda10046_attach(&philips_tu1216_config,
- &budget_av->budget.i2c_adap);
- break;
-
- case SUBID_DVBC_CINERGY1200:
- fe = tda10021_attach(&philips_cu1216_config,
- &budget_av->budget.i2c_adap,
- read_pwm(budget_av));
- break;
-
case SUBID_DVBT_CINERGY1200:
+ budget_av->reinitialise_demod = 1;
fe = tda10046_attach(&philips_tu1216_config,
&budget_av->budget.i2c_adap);
+ if (fe) {
+ fe->ops.tuner_ops.init = philips_tu1216_tuner_init;
+ fe->ops.tuner_ops.set_params = philips_tu1216_tuner_set_params;
+ }
break;
}
@@ -1098,8 +1183,8 @@ static void frontend_init(struct budget_av *budget_av)
if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
budget_av->budget.dvb_frontend)) {
printk(KERN_ERR "budget-av: Frontend registration failed!\n");
- if (budget_av->budget.dvb_frontend->ops->release)
- budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend);
+ if (budget_av->budget.dvb_frontend->ops.release)
+ budget_av->budget.dvb_frontend->ops.release(budget_av->budget.dvb_frontend);
budget_av->budget.dvb_frontend = NULL;
}
}
@@ -1293,6 +1378,7 @@ MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR);
+MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S);
MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
@@ -1309,6 +1395,7 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
+ MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index e64a609cf4ff..4b966eea3834 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -620,10 +620,10 @@ static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate,
return 0;
}
-static int philips_su1278_tt_pll_set(struct dvb_frontend *fe,
- struct i2c_adapter *i2c,
- struct dvb_frontend_parameters *params)
+static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *params)
{
+ struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
u32 div;
u8 buf[4];
struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
@@ -649,7 +649,9 @@ static int philips_su1278_tt_pll_set(struct dvb_frontend *fe,
else if (params->frequency < 2150000)
buf[3] |= 0xC0;
- if (i2c_transfer(i2c, &msg, 1) != 1)
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
@@ -665,12 +667,11 @@ static struct stv0299_config philips_su1278_tt_config = {
.volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 50,
.set_symbol_rate = philips_su1278_tt_set_symbol_rate,
- .pll_set = philips_su1278_tt_pll_set,
};
-static int philips_tdm1316l_pll_init(struct dvb_frontend *fe)
+static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
{
struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
@@ -679,6 +680,8 @@ static int philips_tdm1316l_pll_init(struct dvb_frontend *fe)
sizeof(td1316_init) };
// setup PLL configuration
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
return -EIO;
msleep(1);
@@ -687,14 +690,18 @@ static int philips_tdm1316l_pll_init(struct dvb_frontend *fe)
tuner_msg.addr = 0x65;
tuner_msg.buf = disable_mc44BC374c;
tuner_msg.len = sizeof(disable_mc44BC374c);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
}
return 0;
}
-static int philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
u8 tuner_buf[4];
@@ -770,6 +777,8 @@ static int philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend
tuner_buf[2] = 0xca;
tuner_buf[3] = (cp << 5) | (filter << 3) | band;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
return -EIO;
@@ -793,13 +802,10 @@ static struct tda1004x_config philips_tdm1316l_config = {
.xtal_freq = TDA10046_XTAL_4M,
.agc_config = TDA10046_AGC_DEFAULT,
.if_freq = TDA10046_FREQ_3617,
- .pll_init = philips_tdm1316l_pll_init,
- .pll_set = philips_tdm1316l_pll_set,
- .pll_sleep = NULL,
.request_firmware = philips_tdm1316l_request_firmware,
};
-static int dvbc_philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
u8 tuner_buf[5];
@@ -857,13 +863,15 @@ static int dvbc_philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_fro
tuner_buf[3] = (cp << 5) | (filter << 3) | band;
tuner_buf[4] = 0x80;
- stv0297_enable_plli2c(fe);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
return -EIO;
msleep(50);
- stv0297_enable_plli2c(fe);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
return -EIO;
@@ -969,7 +977,7 @@ static struct stv0297_config dvbc_philips_tdm1316l_config = {
.demod_address = 0x1c,
.inittab = dvbc_philips_tdm1316l_inittab,
.invert = 0,
- .pll_set = dvbc_philips_tdm1316l_pll_set,
+ .stop_during_read = 1,
};
@@ -982,6 +990,8 @@ static void frontend_init(struct budget_ci *budget_ci)
budget_ci->budget.dvb_frontend =
stv0299_attach(&alps_bsru6_config, &budget_ci->budget.i2c_adap);
if (budget_ci->budget.dvb_frontend) {
+ budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+ budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
break;
}
break;
@@ -990,6 +1000,7 @@ static void frontend_init(struct budget_ci *budget_ci)
budget_ci->budget.dvb_frontend =
stv0299_attach(&philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
if (budget_ci->budget.dvb_frontend) {
+ budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
break;
}
break;
@@ -999,6 +1010,7 @@ static void frontend_init(struct budget_ci *budget_ci)
budget_ci->budget.dvb_frontend =
stv0297_attach(&dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
if (budget_ci->budget.dvb_frontend) {
+ budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
break;
}
break;
@@ -1008,6 +1020,8 @@ static void frontend_init(struct budget_ci *budget_ci)
budget_ci->budget.dvb_frontend =
tda10045_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
if (budget_ci->budget.dvb_frontend) {
+ budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
+ budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
break;
}
break;
@@ -1017,6 +1031,8 @@ static void frontend_init(struct budget_ci *budget_ci)
budget_ci->budget.dvb_frontend =
tda10046_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
if (budget_ci->budget.dvb_frontend) {
+ budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
+ budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
break;
}
break;
@@ -1024,11 +1040,14 @@ static void frontend_init(struct budget_ci *budget_ci)
case 0x1017: // TT S-1500 PCI
budget_ci->budget.dvb_frontend = stv0299_attach(&alps_bsbe1_config, &budget_ci->budget.i2c_adap);
if (budget_ci->budget.dvb_frontend) {
- budget_ci->budget.dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
- if (lnbp21_init(budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0)) {
+ budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
+ budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
+
+ budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
+ if (lnbp21_attach(budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0)) {
printk("%s: No LNBP21 found!\n", __FUNCTION__);
- if (budget_ci->budget.dvb_frontend->ops->release)
- budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend);
+ if (budget_ci->budget.dvb_frontend->ops.release)
+ budget_ci->budget.dvb_frontend->ops.release(budget_ci->budget.dvb_frontend);
budget_ci->budget.dvb_frontend = NULL;
}
}
@@ -1046,8 +1065,8 @@ static void frontend_init(struct budget_ci *budget_ci)
if (dvb_register_frontend
(&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
printk("budget-ci: Frontend registration failed!\n");
- if (budget_ci->budget.dvb_frontend->ops->release)
- budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend);
+ if (budget_ci->budget.dvb_frontend->ops.release)
+ budget_ci->budget.dvb_frontend->ops.release(budget_ci->budget.dvb_frontend);
budget_ci->budget.dvb_frontend = NULL;
}
}
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index ea2066d461fc..e4cf7775e07f 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -400,7 +400,9 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
budget->dev->name, budget->buffer_width, budget->buffer_height);
printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
- dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner);
+ if ((ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner, &budget->dev->pci->dev)) < 0) {
+ return ret;
+ }
/* set dd1 stream a & b */
saa7146_write(dev, DD1_STREAM_B, 0x00000000);
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index 1b3aaac5e763..ee60ce90a400 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -258,7 +258,7 @@ static int budget_patch_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_c
return 0;
}
-static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
u8 pwr = 0;
@@ -281,7 +281,10 @@ static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
// NOTE: since we're using a prescaler of 2, we set the
// divisor frequency to 62.5kHz and divide by 125 above
- if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1)
+ return -EIO;
return 0;
}
@@ -289,10 +292,9 @@ static struct ves1x93_config alps_bsrv2_config = {
.demod_address = 0x08,
.xin = 90100000UL,
.invert_pwm = 0,
- .pll_set = alps_bsrv2_pll_set,
};
-static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
u32 div;
@@ -305,13 +307,15 @@ static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_fronten
data[2] = 0x8e;
data[3] = 0x00;
- if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1)
+ return -EIO;
return 0;
}
static struct tda8083_config grundig_29504_451_config = {
.demod_address = 0x68,
- .pll_set = grundig_29504_451_pll_set,
};
static void frontend_init(struct budget_patch* budget)
@@ -323,27 +327,32 @@ static void frontend_init(struct budget_patch* budget)
// try the ALPS BSRV2 first of all
budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
- budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd;
- budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst;
- budget->dvb_frontend->ops->set_tone = budget_patch_set_tone;
+ budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+ budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd;
+ budget->dvb_frontend->ops.diseqc_send_burst = budget_patch_diseqc_send_burst;
+ budget->dvb_frontend->ops.set_tone = budget_patch_set_tone;
break;
}
// try the ALPS BSRU6 now
budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
- budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
- budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
- budget->dvb_frontend->ops->set_tone = budget_set_tone;
+ budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+ budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+
+ budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
+ budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
+ budget->dvb_frontend->ops.set_tone = budget_set_tone;
break;
}
// Try the grundig 29504-451
budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
- budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
- budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
- budget->dvb_frontend->ops->set_tone = budget_set_tone;
+ budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+ budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
+ budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
+ budget->dvb_frontend->ops.set_tone = budget_set_tone;
break;
}
break;
@@ -358,8 +367,8 @@ static void frontend_init(struct budget_patch* budget)
} else {
if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) {
printk("budget-av: Frontend registration failed!\n");
- if (budget->dvb_frontend->ops->release)
- budget->dvb_frontend->ops->release(budget->dvb_frontend);
+ if (budget->dvb_frontend->ops.release)
+ budget->dvb_frontend->ops.release(budget->dvb_frontend);
budget->dvb_frontend = NULL;
}
}
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index c23c02d95641..35761f13c12b 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -186,7 +186,7 @@ static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t m
return 0;
}
-static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
u8 pwr = 0;
@@ -209,6 +209,8 @@ static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
// NOTE: since we're using a prescaler of 2, we set the
// divisor frequency to 62.5kHz and divide by 125 above
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
return 0;
}
@@ -218,10 +220,9 @@ static struct ves1x93_config alps_bsrv2_config =
.demod_address = 0x08,
.xin = 90100000UL,
.invert_pwm = 0,
- .pll_set = alps_bsrv2_pll_set,
};
-static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
u32 div;
@@ -235,6 +236,8 @@ static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
data[2] = 0x85 | ((div >> 10) & 0x60);
data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
return 0;
}
@@ -244,10 +247,9 @@ static struct ves1820_config alps_tdbe2_config = {
.xin = 57840000UL,
.invert = 1,
.selagc = VES1820_SELAGC_SIGNAMPERR,
- .pll_set = alps_tdbe2_pll_set,
};
-static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
u32 div;
@@ -274,16 +276,17 @@ static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_fronten
data[2] = ((div >> 10) & 0x60) | cfg;
data[3] = (cpump << 6) | band_select;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
return 0;
}
static struct l64781_config grundig_29504_401_config = {
.demod_address = 0x55,
- .pll_set = grundig_29504_401_pll_set,
};
-static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
u32 div;
@@ -296,16 +299,17 @@ static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_fronten
data[2] = 0x8e;
data[3] = 0x00;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
return 0;
}
static struct tda8083_config grundig_29504_451_config = {
.demod_address = 0x68,
- .pll_set = grundig_29504_451_pll_set,
};
-static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout)
+static int s5h1420_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
u32 div;
@@ -326,16 +330,16 @@ static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete
else
data[3] = 0xc0;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
- *freqout = div * 1000;
return 0;
}
static struct s5h1420_config s5h1420_config = {
.demod_address = 0x53,
.invert = 1,
- .pll_set = s5h1420_pll_set,
};
static u8 read_pwm(struct budget* budget)
@@ -359,18 +363,21 @@ static void frontend_init(struct budget *budget)
// try the ALPS BSRV2 first of all
budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
- budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
- budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
- budget->dvb_frontend->ops->set_tone = budget_set_tone;
+ budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+ budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
+ budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
+ budget->dvb_frontend->ops.set_tone = budget_set_tone;
break;
}
// try the ALPS BSRU6 now
budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
- budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
- budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
- budget->dvb_frontend->ops->set_tone = budget_set_tone;
+ budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+ budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+ budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
+ budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
+ budget->dvb_frontend->ops.set_tone = budget_set_tone;
break;
}
break;
@@ -378,35 +385,45 @@ static void frontend_init(struct budget *budget)
case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
- if (budget->dvb_frontend) break;
+ if (budget->dvb_frontend) {
+ budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
+ break;
+ }
break;
case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap);
- if (budget->dvb_frontend) break;
+ if (budget->dvb_frontend) {
+ budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
+ break;
+ }
break;
case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059))
budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
- budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
- budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
+ budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+ budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+ budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
+ budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
}
break;
case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
- budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
- budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
+ budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+ budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
+ budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
}
break;
case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
budget->dvb_frontend = s5h1420_attach(&s5h1420_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
- if (lnbp21_init(budget->dvb_frontend, &budget->i2c_adap, 0, 0)) {
+ budget->dvb_frontend->ops.tuner_ops.set_params = s5h1420_tuner_set_params;
+ if (lnbp21_attach(budget->dvb_frontend, &budget->i2c_adap, 0, 0)) {
printk("%s: No LNBP21 found!\n", __FUNCTION__);
goto error_out;
}
@@ -428,8 +445,8 @@ static void frontend_init(struct budget *budget)
error_out:
printk("budget: Frontend registration failed!\n");
- if (budget->dvb_frontend->ops->release)
- budget->dvb_frontend->ops->release(budget->dvb_frontend);
+ if (budget->dvb_frontend->ops.release)
+ budget->dvb_frontend->ops.release(budget->dvb_frontend);
budget->dvb_frontend = NULL;
return;
}
diff --git a/drivers/media/dvb/ttusb-budget/Kconfig b/drivers/media/dvb/ttusb-budget/Kconfig
index 914587d52b57..92c7cdcf8981 100644
--- a/drivers/media/dvb/ttusb-budget/Kconfig
+++ b/drivers/media/dvb/ttusb-budget/Kconfig
@@ -6,6 +6,8 @@ config DVB_TTUSB_BUDGET
select DVB_VES1820
select DVB_TDA8083
select DVB_STV0299
+ select DVB_STV0297
+ select DVB_LNBP21
help
Support for external USB adapters designed by Technotrend and
produced by Hauppauge, shipped under the brand name 'Nova-USB'.
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 6ceae38125c7..14559ef6153c 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -30,6 +30,8 @@
#include "tda1004x.h"
#include "stv0299.h"
#include "tda8083.h"
+#include "stv0297.h"
+#include "lnbp21.h"
#include <linux/dvb/frontend.h>
#include <linux/dvb/dmx.h>
@@ -486,31 +488,6 @@ static int ttusb_send_diseqc(struct dvb_frontend* fe,
}
#endif
-static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
- struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
- int ret;
- u8 data[1];
- struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = data, .len = sizeof(data) };
-
- switch(voltage) {
- case SEC_VOLTAGE_OFF:
- data[0] = 0x00;
- break;
- case SEC_VOLTAGE_13:
- data[0] = 0x44;
- break;
- case SEC_VOLTAGE_18:
- data[0] = 0x4c;
- break;
- default:
- return -EINVAL;
- };
-
- ret = i2c_transfer(&ttusb->i2c_adap, &msg, 1);
- return (ret != 1) ? -EIO : 0;
-}
-
static int ttusb_update_lnb(struct ttusb *ttusb)
{
u8 b[] = { 0xaa, ++ttusb->c, 0x16, 5, /*power: */ 1,
@@ -1048,7 +1025,7 @@ static u32 functionality(struct i2c_adapter *adapter)
-static int alps_tdmb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdmb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
u8 data[4];
@@ -1062,20 +1039,21 @@ static int alps_tdmb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
data[2] = ((div >> 10) & 0x60) | 0x85;
data[3] = params->frequency < 592000000 ? 0x40 : 0x80;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) return -EIO;
return 0;
}
static struct cx22700_config alps_tdmb7_config = {
.demod_address = 0x43,
- .pll_set = alps_tdmb7_pll_set,
};
-static int philips_tdm1316l_pll_init(struct dvb_frontend* fe)
+static int philips_tdm1316l_tuner_init(struct dvb_frontend* fe)
{
struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
@@ -1083,6 +1061,8 @@ static int philips_tdm1316l_pll_init(struct dvb_frontend* fe)
struct i2c_msg tuner_msg = { .addr=0x60, .flags=0, .buf=td1316_init, .len=sizeof(td1316_init) };
// setup PLL configuration
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) return -EIO;
msleep(1);
@@ -1090,6 +1070,8 @@ static int philips_tdm1316l_pll_init(struct dvb_frontend* fe)
tuner_msg.addr = 0x65;
tuner_msg.buf = disable_mc44BC374c;
tuner_msg.len = sizeof(disable_mc44BC374c);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1);
}
@@ -1097,7 +1079,7 @@ static int philips_tdm1316l_pll_init(struct dvb_frontend* fe)
return 0;
}
-static int philips_tdm1316l_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int philips_tdm1316l_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
u8 tuner_buf[4];
@@ -1157,6 +1139,8 @@ static int philips_tdm1316l_pll_set(struct dvb_frontend* fe, struct dvb_frontend
tuner_buf[2] = 0xca;
tuner_buf[3] = (cp << 5) | (filter << 3) | band;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1)
return -EIO;
@@ -1176,8 +1160,6 @@ static struct tda1004x_config philips_tdm1316l_config = {
.demod_address = 0x8,
.invert = 1,
.invert_oclk = 0,
- .pll_init = philips_tdm1316l_pll_init,
- .pll_set = philips_tdm1316l_pll_set,
.request_firmware = philips_tdm1316l_request_firmware,
};
@@ -1299,7 +1281,7 @@ static int alps_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32
return 0;
}
-static int philips_tsa5059_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params)
+static int philips_tsa5059_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
u8 buf[4];
@@ -1322,7 +1304,9 @@ static int philips_tsa5059_pll_set(struct dvb_frontend *fe, struct i2c_adapter *
if (ttusb->revision == TTUSB_REV_2_2)
buf[3] |= 0x20;
- if (i2c_transfer(i2c, &msg, 1) != 1)
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
@@ -1338,10 +1322,9 @@ static struct stv0299_config alps_stv0299_config = {
.volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 100,
.set_symbol_rate = alps_stv0299_set_symbol_rate,
- .pll_set = philips_tsa5059_pll_set,
};
-static int ttusb_novas_grundig_29504_491_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int ttusb_novas_grundig_29504_491_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
u8 buf[4];
@@ -1355,6 +1338,8 @@ static int ttusb_novas_grundig_29504_491_pll_set(struct dvb_frontend *fe, struct
buf[2] = 0x8e;
buf[3] = 0x00;
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
return -EIO;
@@ -1364,10 +1349,9 @@ static int ttusb_novas_grundig_29504_491_pll_set(struct dvb_frontend *fe, struct
static struct tda8083_config ttusb_novas_grundig_29504_491_config = {
.demod_address = 0x68,
- .pll_set = ttusb_novas_grundig_29504_491_pll_set,
};
-static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct ttusb* ttusb = fe->dvb->priv;
u32 div;
@@ -1381,6 +1365,8 @@ static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
data[2] = 0x85 | ((div >> 10) & 0x60);
data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
if (i2c_transfer (&ttusb->i2c_adap, &msg, 1) != 1)
return -EIO;
@@ -1393,7 +1379,6 @@ static struct ves1820_config alps_tdbe2_config = {
.xin = 57840000UL,
.invert = 1,
.selagc = VES1820_SELAGC_SIGNAMPERR,
- .pll_set = alps_tdbe2_pll_set,
};
static u8 read_pwm(struct ttusb* ttusb)
@@ -1410,6 +1395,174 @@ static u8 read_pwm(struct ttusb* ttusb)
}
+static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+ struct ttusb *ttusb = (struct ttusb *) fe->dvb->priv;
+ u8 tuner_buf[5];
+ struct i2c_msg tuner_msg = {.addr = 0x60,
+ .flags = 0,
+ .buf = tuner_buf,
+ .len = sizeof(tuner_buf) };
+ int tuner_frequency = 0;
+ u8 band, cp, filter;
+
+ // determine charge pump
+ tuner_frequency = params->frequency;
+ if (tuner_frequency < 87000000) {return -EINVAL;}
+ else if (tuner_frequency < 130000000) {cp = 3; band = 1;}
+ else if (tuner_frequency < 160000000) {cp = 5; band = 1;}
+ else if (tuner_frequency < 200000000) {cp = 6; band = 1;}
+ else if (tuner_frequency < 290000000) {cp = 3; band = 2;}
+ else if (tuner_frequency < 420000000) {cp = 5; band = 2;}
+ else if (tuner_frequency < 480000000) {cp = 6; band = 2;}
+ else if (tuner_frequency < 620000000) {cp = 3; band = 4;}
+ else if (tuner_frequency < 830000000) {cp = 5; band = 4;}
+ else if (tuner_frequency < 895000000) {cp = 7; band = 4;}
+ else {return -EINVAL;}
+
+ // assume PLL filter should always be 8MHz for the moment.
+ filter = 1;
+
+ // calculate divisor
+ // (Finput + Fif)/Fref; Fif = 36125000 Hz, Fref = 62500 Hz
+ tuner_frequency = ((params->frequency + 36125000) / 62500);
+
+ // setup tuner buffer
+ tuner_buf[0] = tuner_frequency >> 8;
+ tuner_buf[1] = tuner_frequency & 0xff;
+ tuner_buf[2] = 0xc8;
+ tuner_buf[3] = (cp << 5) | (filter << 3) | band;
+ tuner_buf[4] = 0x80;
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
+ printk("dvb-ttusb-budget: dvbc_philips_tdm1316l_pll_set Error 1\n");
+ return -EIO;
+ }
+
+ msleep(50);
+
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
+ printk("dvb-ttusb-budget: dvbc_philips_tdm1316l_pll_set Error 2\n");
+ return -EIO;
+ }
+
+ msleep(1);
+
+ return 0;
+}
+
+static u8 dvbc_philips_tdm1316l_inittab[] = {
+ 0x80, 0x21,
+ 0x80, 0x20,
+ 0x81, 0x01,
+ 0x81, 0x00,
+ 0x00, 0x09,
+ 0x01, 0x69,
+ 0x03, 0x00,
+ 0x04, 0x00,
+ 0x07, 0x00,
+ 0x08, 0x00,
+ 0x20, 0x00,
+ 0x21, 0x40,
+ 0x22, 0x00,
+ 0x23, 0x00,
+ 0x24, 0x40,
+ 0x25, 0x88,
+ 0x30, 0xff,
+ 0x31, 0x00,
+ 0x32, 0xff,
+ 0x33, 0x00,
+ 0x34, 0x50,
+ 0x35, 0x7f,
+ 0x36, 0x00,
+ 0x37, 0x20,
+ 0x38, 0x00,
+ 0x40, 0x1c,
+ 0x41, 0xff,
+ 0x42, 0x29,
+ 0x43, 0x20,
+ 0x44, 0xff,
+ 0x45, 0x00,
+ 0x46, 0x00,
+ 0x49, 0x04,
+ 0x4a, 0xff,
+ 0x4b, 0x7f,
+ 0x52, 0x30,
+ 0x55, 0xae,
+ 0x56, 0x47,
+ 0x57, 0xe1,
+ 0x58, 0x3a,
+ 0x5a, 0x1e,
+ 0x5b, 0x34,
+ 0x60, 0x00,
+ 0x63, 0x00,
+ 0x64, 0x00,
+ 0x65, 0x00,
+ 0x66, 0x00,
+ 0x67, 0x00,
+ 0x68, 0x00,
+ 0x69, 0x00,
+ 0x6a, 0x02,
+ 0x6b, 0x00,
+ 0x70, 0xff,
+ 0x71, 0x00,
+ 0x72, 0x00,
+ 0x73, 0x00,
+ 0x74, 0x0c,
+ 0x80, 0x00,
+ 0x81, 0x00,
+ 0x82, 0x00,
+ 0x83, 0x00,
+ 0x84, 0x04,
+ 0x85, 0x80,
+ 0x86, 0x24,
+ 0x87, 0x78,
+ 0x88, 0x00,
+ 0x89, 0x00,
+ 0x90, 0x01,
+ 0x91, 0x01,
+ 0xa0, 0x00,
+ 0xa1, 0x00,
+ 0xa2, 0x00,
+ 0xb0, 0x91,
+ 0xb1, 0x0b,
+ 0xc0, 0x4b,
+ 0xc1, 0x00,
+ 0xc2, 0x00,
+ 0xd0, 0x00,
+ 0xd1, 0x00,
+ 0xd2, 0x00,
+ 0xd3, 0x00,
+ 0xd4, 0x00,
+ 0xd5, 0x00,
+ 0xde, 0x00,
+ 0xdf, 0x00,
+ 0x61, 0x38,
+ 0x62, 0x0a,
+ 0x53, 0x13,
+ 0x59, 0x08,
+ 0x55, 0x00,
+ 0x56, 0x40,
+ 0x57, 0x08,
+ 0x58, 0x3d,
+ 0x88, 0x10,
+ 0xa0, 0x00,
+ 0xa0, 0x00,
+ 0xa0, 0x00,
+ 0xa0, 0x04,
+ 0xff, 0xff,
+};
+
+static struct stv0297_config dvbc_philips_tdm1316l_config = {
+ .demod_address = 0x1c,
+ .inittab = dvbc_philips_tdm1316l_inittab,
+ .invert = 0,
+};
+
static void frontend_init(struct ttusb* ttusb)
{
switch(le16_to_cpu(ttusb->dev->descriptor.idProduct)) {
@@ -1417,11 +1570,13 @@ static void frontend_init(struct ttusb* ttusb)
// try the stv0299 based first
ttusb->fe = stv0299_attach(&alps_stv0299_config, &ttusb->i2c_adap);
if (ttusb->fe != NULL) {
+ ttusb->fe->ops.tuner_ops.set_params = philips_tsa5059_tuner_set_params;
+
if(ttusb->revision == TTUSB_REV_2_2) { // ALPS BSBE1
alps_stv0299_config.inittab = alps_bsbe1_inittab;
- ttusb->fe->ops->set_voltage = lnbp21_set_voltage;
+ lnbp21_attach(ttusb->fe, &ttusb->i2c_adap, 0, 0);
} else { // ALPS BSRU6
- ttusb->fe->ops->set_voltage = ttusb_set_voltage;
+ ttusb->fe->ops.set_voltage = ttusb_set_voltage;
}
break;
}
@@ -1429,28 +1584,41 @@ static void frontend_init(struct ttusb* ttusb)
// Grundig 29504-491
ttusb->fe = tda8083_attach(&ttusb_novas_grundig_29504_491_config, &ttusb->i2c_adap);
if (ttusb->fe != NULL) {
- ttusb->fe->ops->set_voltage = ttusb_set_voltage;
+ ttusb->fe->ops.tuner_ops.set_params = ttusb_novas_grundig_29504_491_tuner_set_params;
+ ttusb->fe->ops.set_voltage = ttusb_set_voltage;
break;
}
-
break;
case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
ttusb->fe = ves1820_attach(&alps_tdbe2_config, &ttusb->i2c_adap, read_pwm(ttusb));
- if (ttusb->fe != NULL)
+ if (ttusb->fe != NULL) {
+ ttusb->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
+ break;
+ }
+
+ ttusb->fe = stv0297_attach(&dvbc_philips_tdm1316l_config, &ttusb->i2c_adap);
+ if (ttusb->fe != NULL) {
+ ttusb->fe->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
break;
+ }
break;
case 0x1005: // Hauppauge/TT Nova-USB-t budget (tda10046/Philips td1316(tda6651tt) OR cx22700/ALPS TDMB7(??))
// try the ALPS TDMB7 first
ttusb->fe = cx22700_attach(&alps_tdmb7_config, &ttusb->i2c_adap);
- if (ttusb->fe != NULL)
+ if (ttusb->fe != NULL) {
+ ttusb->fe->ops.tuner_ops.set_params = alps_tdmb7_tuner_set_params;
break;
+ }
// Philips td1316
ttusb->fe = tda10046_attach(&philips_tdm1316l_config, &ttusb->i2c_adap);
- if (ttusb->fe != NULL)
+ if (ttusb->fe != NULL) {
+ ttusb->fe->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
+ ttusb->fe->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
break;
+ }
break;
}
@@ -1461,8 +1629,8 @@ static void frontend_init(struct ttusb* ttusb)
} else {
if (dvb_register_frontend(&ttusb->adapter, ttusb->fe)) {
printk("dvb-ttusb-budget: Frontend registration failed!\n");
- if (ttusb->fe->ops->release)
- ttusb->fe->ops->release(ttusb->fe);
+ if (ttusb->fe->ops.release)
+ ttusb->fe->ops.release(ttusb->fe);
ttusb->fe = NULL;
}
}
@@ -1507,7 +1675,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
mutex_unlock(&ttusb->semi2c);
- if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE)) < 0) {
+ if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE, &udev->dev)) < 0) {
ttusb_free_iso_urbs(ttusb);
kfree(ttusb);
return result;
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 44dea3211848..6c1cb770bcf5 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -1432,7 +1432,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
dprintk("%s\n", __FUNCTION__);
if ((result = dvb_register_adapter(&dec->adapter,
- dec->model_name, THIS_MODULE)) < 0) {
+ dec->model_name, THIS_MODULE, &dec->udev->dev)) < 0) {
printk("%s: dvb_register_adapter failed: error %d\n",
__FUNCTION__, result);
@@ -1657,8 +1657,8 @@ static int ttusb_dec_probe(struct usb_interface *intf,
} else {
if (dvb_register_frontend(&dec->adapter, dec->fe)) {
printk("budget-ci: Frontend registration failed!\n");
- if (dec->fe->ops->release)
- dec->fe->ops->release(dec->fe);
+ if (dec->fe->ops.release)
+ dec->fe->ops.release(dec->fe);
dec->fe = NULL;
}
}
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
index a5a46175fa09..42f39a89bc4d 100644
--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
@@ -28,8 +28,6 @@
struct ttusbdecfe_state {
- struct dvb_frontend_ops ops;
-
/* configuration settings */
const struct ttusbdecfe_config* config;
@@ -203,10 +201,9 @@ struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* conf
/* setup the state */
state->config = config;
- memcpy(&state->ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops));
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
}
@@ -226,10 +223,9 @@ struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* conf
state->config = config;
state->voltage = 0;
state->hi_band = 0;
- memcpy(&state->ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops));
/* create dvb_frontend */
- state->frontend.ops = &state->ops;
+ memcpy(&state->frontend.ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
}