summaryrefslogtreecommitdiff
path: root/drivers/media/video/cx88/cx88-dvb.c
diff options
context:
space:
mode:
authorSteven Toth <stoth@linuxtv.org>2008-10-11 11:05:50 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-17 17:23:10 -0300
commit363c35fc448943c3d6121332d28bcda2d2fbf87c (patch)
tree739864d237b7fa60bef51bc510fe55c888b606ca /drivers/media/video/cx88/cx88-dvb.c
parent548da7625c825eccc31b4b3865ae5389c3660486 (diff)
V4L/DVB (9222): S2API: Add Multiple-frontend on a single adapter support.
A detailed description from the original patches 2 years ago: "The WinTV-HVR3000 has a single transport bus which is shared between a DVB-T and DVB-S modulator. These patches build on the bus acquisition cx88 work from a few weeks ago to add support for this. So to applications the HVR3000 looks like this: /dev/dvb/adapter0/fe0 (cx24123 DVB-S demod) /dev/dvb/adapter0/fe1 (cx22702 DVB-T demod) Additional boards continue as before, eg: /dev/dvb/adapter1/fe0 (lgdt3302 ATSC demod) The basic change is removing the single instance of the videobuf_dvb in cx8802_dev and saa7134_dev(?) and replacing it with a list and some supporting functions. *NOTE* This branch was taken before v4l-dvb was closed for 2.6.19 so two or three current cx88 patches appear to be reversed by this tree, this will be cleaned up in the near future. The patches missing change the mutex handing to core->lock, fix an enumeration problem." It should be recognised that a number of people have been maintaining this patchset. Significant levels of Kudos to everyone one involved, including but not limited to: Darron Broad Fabio M. Di Nitto Carlo Scarfoglio Hans Werner Without the work of these people, and countless others, my two year old patches would of died on the Mercurial linuxtv.org vine a long time ago. TODO: Revise these patches a little further so that the need for demux1 and dvr0 is optional, not mandatory on the HVR3000. HISTORY (darron): This is the last update to MFE prepared by Hans which is based upon the `scratchpad' diff created by Carlo. All MFE work prior to that point must be attributed to Fabio who ported and maintained Steve's original patch up to that time. Signed-off-by: Steven Toth <stoth@linuxtv.org> Signed-off-by: Darron Broad <darron@kewl.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx88/cx88-dvb.c')
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c423
1 files changed, 296 insertions, 127 deletions
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 344ed2626e59..099de66c72c4 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -116,13 +116,24 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
struct cx8802_dev *dev= fe->dvb->priv;
struct cx8802_driver *drv = NULL;
int ret = 0;
+ int fe_id;
+
+ fe_id = videobuf_dvb_find_frontend(&dev->frontends, fe);
+ if (!fe_id) {
+ printk(KERN_ERR "%s() No frontend found\n", __FUNCTION__);
+ return -EINVAL;
+ }
+
drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
if (drv) {
- if (acquire)
+ if (acquire){
+ dev->frontends.active_fe_id = fe_id;
ret = drv->request_acquire(drv);
- else
+ } else {
ret = drv->request_release(drv);
+ dev->frontends.active_fe_id = 0;
+ }
}
return ret;
@@ -396,7 +407,7 @@ static int tevii_dvbs_set_voltage(struct dvb_frontend *fe,
cx_write(MO_GP0_IO, 0x00006060);
break;
case SEC_VOLTAGE_OFF:
- printk("LNB Voltage SEC_VOLTAGE_off\n");
+ printk("LNB Voltage SEC_VOLTAGE_off\n");
break;
}
@@ -483,6 +494,7 @@ static struct xc5000_config dvico_fusionhdtv7_tuner_config = {
static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
{
struct dvb_frontend *fe;
+ struct videobuf_dvb_frontend *fe0 = NULL;
struct xc2028_ctrl ctl;
struct xc2028_config cfg = {
.i2c_adap = &dev->core->i2c_adap,
@@ -490,7 +502,12 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
.ctrl = &ctl,
};
- if (!dev->dvb.frontend) {
+/* Get the first frontend */
+ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+ if (!fe0)
+ return -EINVAL;
+
+ if (!fe0->dvb.frontend) {
printk(KERN_ERR "%s/2: dvb frontend not attached. "
"Can't attach xc3028\n",
dev->core->name);
@@ -504,10 +521,13 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
*/
cx88_setup_xc3028(dev->core, &ctl);
- fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg);
+ fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg);
if (!fe) {
printk(KERN_ERR "%s/2: xc3028 attach failed\n",
dev->core->name);
+ dvb_frontend_detach(fe0->dvb.frontend);
+ dvb_unregister_frontend(fe0->dvb.frontend);
+ fe0->dvb.frontend = NULL;
return -EINVAL;
}
@@ -532,8 +552,10 @@ static int cx24116_reset_device(struct dvb_frontend *fe)
struct cx88_core *core = dev->core;
/* Reset the part */
+ /* Put the cx24116 into reset */
cx_write(MO_SRST_IO, 0);
msleep(10);
+ /* Take the cx24116 out of reset */
cx_write(MO_SRST_IO, 1);
msleep(10);
@@ -573,20 +595,28 @@ static struct stv0288_config tevii_tuner_earda_config = {
static int dvb_register(struct cx8802_dev *dev)
{
+ //struct cx88_core *core = dev->core;
+
+ ///* init struct videobuf_dvb */
+ //fe->dvb.name = core->name;
+ //dev->ts_gen_cntrl = 0x0c;
+
struct cx88_core *core = dev->core;
+ struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
- /* init struct videobuf_dvb */
- dev->dvb.name = core->name;
- dev->ts_gen_cntrl = 0x0c;
+ /* Get the first frontend */
+ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+ if (!fe0)
+ return -EINVAL;
/* init frontend */
switch (core->boardnr) {
case CX88_BOARD_HAUPPAUGE_DVB_T1:
- dev->dvb.frontend = dvb_attach(cx22702_attach,
+ fe0->dvb.frontend = dvb_attach(cx22702_attach,
&connexant_refboard_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
0x61, &core->i2c_adap,
DVB_PLL_THOMSON_DTT759X))
goto frontend_detach;
@@ -596,11 +626,11 @@ static int dvb_register(struct cx8802_dev *dev)
case CX88_BOARD_CONEXANT_DVB_T1:
case CX88_BOARD_KWORLD_DVB_T_CX22702:
case CX88_BOARD_WINFAST_DTV1000:
- dev->dvb.frontend = dvb_attach(cx22702_attach,
+ fe0->dvb.frontend = dvb_attach(cx22702_attach,
&connexant_refboard_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
0x60, &core->i2c_adap,
DVB_PLL_THOMSON_DTT7579))
goto frontend_detach;
@@ -610,33 +640,65 @@ static int dvb_register(struct cx8802_dev *dev)
case CX88_BOARD_HAUPPAUGE_HVR1100:
case CX88_BOARD_HAUPPAUGE_HVR1100LP:
case CX88_BOARD_HAUPPAUGE_HVR1300:
- case CX88_BOARD_HAUPPAUGE_HVR3000:
- dev->dvb.frontend = dvb_attach(cx22702_attach,
+ fe0->dvb.frontend = dvb_attach(cx22702_attach,
&hauppauge_hvr_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_PHILIPS_FMD1216ME_MK3))
goto frontend_detach;
}
break;
+ case CX88_BOARD_HAUPPAUGE_HVR3000:
+ /* DVB-S init */
+ fe0->dvb.frontend = dvb_attach(cx24123_attach,
+ &hauppauge_novas_config,
+ &dev->core->i2c_adap);
+ if (fe0->dvb.frontend) {
+ if (!dvb_attach(isl6421_attach, fe0->dvb.frontend,
+ &dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) {
+ dprintk( 1, "%s(): HVR3000 - DVB-S LNB Init: failed\n", __FUNCTION__);
+ }
+ } else {
+ dprintk( 1, "%s(): HVR3000 - DVB-S Init: failed\n", __FUNCTION__);
+ }
+ /* DVB-T init */
+ fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
+ if (fe1) {
+ fe1->dvb.frontend = dvb_attach(cx22702_attach,
+ &hauppauge_hvr_config,
+ &dev->core->i2c_adap);
+ if (fe1->dvb.frontend) {
+ fe1->dvb.frontend->id = 1;
+ if(!dvb_attach(simple_tuner_attach, fe1->dvb.frontend,
+ &dev->core->i2c_adap, 0x61,
+ TUNER_PHILIPS_FMD1216ME_MK3)) {
+ dprintk( 1, "%s(): HVR3000 - DVB-T misc Init: failed\n", __FUNCTION__);
+ }
+ } else {
+ dprintk( 1, "%s(): HVR3000 - DVB-T Init: failed\n", __FUNCTION__);
+ }
+ } else {
+ dprintk( 1, "%s(): HVR3000 - DVB-T Init: can't find frontend 2.\n", __FUNCTION__);
+ }
+ break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
- dev->dvb.frontend = dvb_attach(mt352_attach,
+ fe0->dvb.frontend = dvb_attach(mt352_attach,
&dvico_fusionhdtv,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
0x60, NULL, DVB_PLL_THOMSON_DTT7579))
goto frontend_detach;
break;
}
/* ZL10353 replaces MT352 on later cards */
- dev->dvb.frontend = dvb_attach(zl10353_attach,
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
&dvico_fusionhdtv_plus_v1_1,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
0x60, NULL, DVB_PLL_THOMSON_DTT7579))
goto frontend_detach;
}
@@ -644,31 +706,31 @@ static int dvb_register(struct cx8802_dev *dev)
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
/* The tin box says DEE1601, but it seems to be DTT7579
* compatible, with a slightly different MT352 AGC gain. */
- dev->dvb.frontend = dvb_attach(mt352_attach,
+ fe0->dvb.frontend = dvb_attach(mt352_attach,
&dvico_fusionhdtv_dual,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
0x61, NULL, DVB_PLL_THOMSON_DTT7579))
goto frontend_detach;
break;
}
/* ZL10353 replaces MT352 on later cards */
- dev->dvb.frontend = dvb_attach(zl10353_attach,
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
&dvico_fusionhdtv_plus_v1_1,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
0x61, NULL, DVB_PLL_THOMSON_DTT7579))
goto frontend_detach;
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
- dev->dvb.frontend = dvb_attach(mt352_attach,
+ fe0->dvb.frontend = dvb_attach(mt352_attach,
&dvico_fusionhdtv,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
0x61, NULL, DVB_PLL_LG_Z201))
goto frontend_detach;
}
@@ -676,11 +738,11 @@ static int dvb_register(struct cx8802_dev *dev)
case CX88_BOARD_KWORLD_DVB_T:
case CX88_BOARD_DNTV_LIVE_DVB_T:
case CX88_BOARD_ADSTECH_DVB_T_PCI:
- dev->dvb.frontend = dvb_attach(mt352_attach,
+ fe0->dvb.frontend = dvb_attach(mt352_attach,
&dntv_live_dvbt_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
0x61, NULL, DVB_PLL_UNKNOWN_1))
goto frontend_detach;
}
@@ -688,10 +750,10 @@ static int dvb_register(struct cx8802_dev *dev)
case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
/* MT352 is on a secondary I2C bus made from some GPIO lines */
- dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
+ fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
&dev->vp3054->adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_PHILIPS_FMD1216ME_MK3))
goto frontend_detach;
@@ -702,22 +764,22 @@ static int dvb_register(struct cx8802_dev *dev)
#endif
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
- dev->dvb.frontend = dvb_attach(zl10353_attach,
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
&dvico_fusionhdtv_hybrid,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_THOMSON_FE6600))
goto frontend_detach;
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
- dev->dvb.frontend = dvb_attach(zl10353_attach,
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
&dvico_fusionhdtv_xc3028,
&core->i2c_adap);
- if (dev->dvb.frontend == NULL)
- dev->dvb.frontend = dvb_attach(mt352_attach,
+ if (fe0->dvb.frontend == NULL)
+ fe0->dvb.frontend = dvb_attach(mt352_attach,
&dvico_fusionhdtv_mt352_xc3028,
&core->i2c_adap);
/*
@@ -725,16 +787,16 @@ static int dvb_register(struct cx8802_dev *dev)
* We must not permit gate_ctrl to be performed, or
* the xc3028 cannot communicate on the bus.
*/
- if (dev->dvb.frontend)
- dev->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+ if (fe0->dvb.frontend)
+ fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
if (attach_xc3028(0x61, dev) < 0)
return -EINVAL;
break;
case CX88_BOARD_PCHDTV_HD3000:
- dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
+ fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_THOMSON_DTT761X))
goto frontend_detach;
@@ -751,11 +813,11 @@ static int dvb_register(struct cx8802_dev *dev)
/* Select RF connector callback */
fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
- dev->dvb.frontend = dvb_attach(lgdt330x_attach,
+ fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
&fusionhdtv_3_gold,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_MICROTUNE_4042FI5))
goto frontend_detach;
@@ -769,11 +831,11 @@ static int dvb_register(struct cx8802_dev *dev)
mdelay(100);
cx_set(MO_GP0_IO, 9);
mdelay(200);
- dev->dvb.frontend = dvb_attach(lgdt330x_attach,
+ fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
&fusionhdtv_3_gold,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_THOMSON_DTT761X))
goto frontend_detach;
@@ -787,15 +849,15 @@ static int dvb_register(struct cx8802_dev *dev)
mdelay(100);
cx_set(MO_GP0_IO, 1);
mdelay(200);
- dev->dvb.frontend = dvb_attach(lgdt330x_attach,
+ fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
&fusionhdtv_5_gold,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_LG_TDVS_H06XF))
goto frontend_detach;
- if (!dvb_attach(tda9887_attach, dev->dvb.frontend,
+ if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x43))
goto frontend_detach;
}
@@ -808,25 +870,25 @@ static int dvb_register(struct cx8802_dev *dev)
mdelay(100);
cx_set(MO_GP0_IO, 1);
mdelay(200);
- dev->dvb.frontend = dvb_attach(lgdt330x_attach,
+ fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
&pchdtv_hd5500,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_LG_TDVS_H06XF))
goto frontend_detach;
- if (!dvb_attach(tda9887_attach, dev->dvb.frontend,
+ if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x43))
goto frontend_detach;
}
break;
case CX88_BOARD_ATI_HDTVWONDER:
- dev->dvb.frontend = dvb_attach(nxt200x_attach,
+ fe0->dvb.frontend = dvb_attach(nxt200x_attach,
&ati_hdtvwonder,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x61,
TUNER_PHILIPS_TUV1236D))
goto frontend_detach;
@@ -834,49 +896,49 @@ static int dvb_register(struct cx8802_dev *dev)
break;
case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
- dev->dvb.frontend = dvb_attach(cx24123_attach,
+ fe0->dvb.frontend = dvb_attach(cx24123_attach,
&hauppauge_novas_config,
&core->i2c_adap);
- if (dev->dvb.frontend) {
- if (!dvb_attach(isl6421_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend) {
+ if (!dvb_attach(isl6421_attach, fe0->dvb.frontend,
&core->i2c_adap, 0x08, ISL6421_DCL, 0x00))
goto frontend_detach;
}
break;
case CX88_BOARD_KWORLD_DVBS_100:
- dev->dvb.frontend = dvb_attach(cx24123_attach,
+ fe0->dvb.frontend = dvb_attach(cx24123_attach,
&kworld_dvbs_100_config,
&core->i2c_adap);
- if (dev->dvb.frontend) {
- core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
- dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
+ if (fe0->dvb.frontend) {
+ core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+ fe0->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
}
break;
case CX88_BOARD_GENIATECH_DVBS:
- dev->dvb.frontend = dvb_attach(cx24123_attach,
+ fe0->dvb.frontend = dvb_attach(cx24123_attach,
&geniatech_dvbs_config,
&core->i2c_adap);
- if (dev->dvb.frontend) {
- core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
- dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
+ if (fe0->dvb.frontend) {
+ core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+ fe0->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
}
break;
case CX88_BOARD_PINNACLE_PCTV_HD_800i:
- dev->dvb.frontend = dvb_attach(s5h1409_attach,
+ fe0->dvb.frontend = dvb_attach(s5h1409_attach,
&pinnacle_pctv_hd_800i_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(xc5000_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
&core->i2c_adap,
&pinnacle_pctv_hd_800i_tuner_config))
goto frontend_detach;
}
break;
case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
- dev->dvb.frontend = dvb_attach(s5h1409_attach,
+ fe0->dvb.frontend = dvb_attach(s5h1409_attach,
&dvico_hdtv5_pci_nano_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
+ if (fe0->dvb.frontend != NULL) {
struct dvb_frontend *fe;
struct xc2028_config cfg = {
.i2c_adap = &core->i2c_adap,
@@ -889,17 +951,17 @@ static int dvb_register(struct cx8802_dev *dev)
};
fe = dvb_attach(xc2028_attach,
- dev->dvb.frontend, &cfg);
+ fe0->dvb.frontend, &cfg);
if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
fe->ops.tuner_ops.set_config(fe, &ctl);
}
break;
case CX88_BOARD_PINNACLE_HYBRID_PCTV:
- dev->dvb.frontend = dvb_attach(zl10353_attach,
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
&cx88_pinnacle_hybrid_pctv,
&core->i2c_adap);
- if (dev->dvb.frontend) {
- dev->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+ if (fe0->dvb.frontend) {
+ fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
if (attach_xc3028(0x61, dev) < 0)
goto frontend_detach;
}
@@ -907,85 +969,116 @@ static int dvb_register(struct cx8802_dev *dev)
case CX88_BOARD_GENIATECH_X8000_MT:
dev->ts_gen_cntrl = 0x00;
- dev->dvb.frontend = dvb_attach(zl10353_attach,
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
&cx88_geniatech_x8000_mt,
&core->i2c_adap);
if (attach_xc3028(0x61, dev) < 0)
goto frontend_detach;
break;
case CX88_BOARD_KWORLD_ATSC_120:
- dev->dvb.frontend = dvb_attach(s5h1409_attach,
+ fe0->dvb.frontend = dvb_attach(s5h1409_attach,
&kworld_atsc_120_config,
&core->i2c_adap);
if (attach_xc3028(0x61, dev) < 0)
goto frontend_detach;
break;
case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
- dev->dvb.frontend = dvb_attach(s5h1411_attach,
+ fe0->dvb.frontend = dvb_attach(s5h1411_attach,
&dvico_fusionhdtv7_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(xc5000_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
&core->i2c_adap,
&dvico_fusionhdtv7_tuner_config))
goto frontend_detach;
}
break;
case CX88_BOARD_HAUPPAUGE_HVR4000:
+ /* DVB-S/S2 Init */
+ fe0->dvb.frontend = dvb_attach(cx24116_attach,
+ &hauppauge_hvr4000_config,
+ &dev->core->i2c_adap);
+ if (fe0->dvb.frontend) {
+ if(!dvb_attach(isl6421_attach, fe0->dvb.frontend,
+ &dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) {
+ dprintk( 1, "%s(): HVR4000 - DVB-S LNB Init: failed\n", __FUNCTION__);
+ }
+ } else {
+ dprintk( 1, "%s(): HVR4000 - DVB-S Init: failed\n", __FUNCTION__);
+ }
+ /* DVB-T Init */
+ fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
+ if (fe1) {
+ fe1->dvb.frontend = dvb_attach(cx22702_attach,
+ &hauppauge_hvr_config,
+ &dev->core->i2c_adap);
+ if (fe1->dvb.frontend) {
+ fe1->dvb.frontend->id = 1;
+ if(!dvb_attach(simple_tuner_attach, fe1->dvb.frontend,
+ &dev->core->i2c_adap, 0x61,
+ TUNER_PHILIPS_FMD1216ME_MK3)) {
+ dprintk( 1, "%s(): HVR4000 - DVB-T misc Init: failed\n", __FUNCTION__);
+ }
+ } else {
+ dprintk( 1, "%s(): HVR4000 - DVB-T Init: failed\n", __FUNCTION__);
+ }
+ } else {
+ dprintk( 1, "%s(): HVR4000 - DVB-T Init: can't find frontend 2.\n", __FUNCTION__);
+ }
+ break;
case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
- /* Support for DVB-S only, not DVB-T support */
- dev->dvb.frontend = dvb_attach(cx24116_attach,
+ fe0->dvb.frontend = dvb_attach(cx24116_attach,
&hauppauge_hvr4000_config,
&dev->core->i2c_adap);
- if (dev->dvb.frontend) {
- dvb_attach(isl6421_attach, dev->dvb.frontend,
+ if (fe0->dvb.frontend) {
+ dvb_attach(isl6421_attach, fe0->dvb.frontend,
&dev->core->i2c_adap,
0x08, ISL6421_DCL, 0x00);
}
break;
case CX88_BOARD_TEVII_S420:
- dev->dvb.frontend = dvb_attach(stv0299_attach,
+ fe0->dvb.frontend = dvb_attach(stv0299_attach,
&tevii_tuner_sharp_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
&core->i2c_adap, DVB_PLL_OPERA1))
goto frontend_detach;
- core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
- dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+ core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+ fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
} else {
- dev->dvb.frontend = dvb_attach(stv0288_attach,
+ fe0->dvb.frontend = dvb_attach(stv0288_attach,
&tevii_tuner_earda_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- if (!dvb_attach(stb6000_attach, dev->dvb.frontend, 0x61,
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61,
&core->i2c_adap))
goto frontend_detach;
- core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
- dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+ core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+ fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
}
}
break;
case CX88_BOARD_TEVII_S460:
- dev->dvb.frontend = dvb_attach(cx24116_attach,
+ fe0->dvb.frontend = dvb_attach(cx24116_attach,
&tevii_s460_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
- dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+ if (fe0->dvb.frontend != NULL) {
+ core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+ fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
}
break;
case CX88_BOARD_OMICOM_SS4_PCI:
case CX88_BOARD_TBS_8920:
case CX88_BOARD_PROF_7300:
- dev->dvb.frontend = dvb_attach(cx24116_attach,
+ fe0->dvb.frontend = dvb_attach(cx24116_attach,
&hauppauge_hvr4000_config,
&core->i2c_adap);
- if (dev->dvb.frontend != NULL) {
- core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
- dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+ if (fe0->dvb.frontend != NULL) {
+ core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+ fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
}
break;
default:
@@ -993,29 +1086,32 @@ static int dvb_register(struct cx8802_dev *dev)
core->name);
break;
}
- if (NULL == dev->dvb.frontend) {
+
+ if ( (NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend) ) {
printk(KERN_ERR
"%s/2: frontend initialization failed\n",
core->name);
return -EINVAL;
}
/* define general-purpose callback pointer */
- dev->dvb.frontend->callback = cx88_tuner_callback;
+ fe0->dvb.frontend->callback = cx88_tuner_callback;
/* Ensure all frontends negotiate bus access */
- dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
+ fe0->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
+ if (fe1)
+ fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
/* Put the analog decoder in standby to keep it quiet */
cx88_call_i2c_clients(core, TUNER_SET_STANDBY, NULL);
/* register everything */
- return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev,
- &dev->pci->dev, adapter_nr);
+ return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
+ &dev->pci->dev, adapter_nr);
frontend_detach:
- if (dev->dvb.frontend) {
- dvb_frontend_detach(dev->dvb.frontend);
- dev->dvb.frontend = NULL;
+ if (fe0->dvb.frontend) {
+ dvb_frontend_detach(fe0->dvb.frontend);
+ fe0->dvb.frontend = NULL;
}
return -EINVAL;
}
@@ -1039,6 +1135,66 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
cx_clear(MO_GP0_IO, 0x00000004);
udelay(1000);
break;
+
+ case CX88_BOARD_HAUPPAUGE_HVR3000: /* ? */
+ if(core->dvbdev->frontends.active_fe_id == 1) {
+ /* DVB-S/S2 Enabled */
+
+ /* Toggle reset on cx22702 leaving i2c active */
+ cx_write(MO_GP0_IO, core->board.input[0].gpio0);
+ udelay(1000);
+ cx_clear(MO_GP0_IO, 0x00000080);
+ udelay(50);
+ cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset */
+ cx_set(MO_GP0_IO, 0x00000004); /* tri-state the cx22702 pins */
+ udelay(1000);
+
+ cx_write(MO_SRST_IO, 1); /* Take the cx24116/cx24123 out of reset */
+ core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */
+ } else
+ if (core->dvbdev->frontends.active_fe_id == 2) {
+ /* DVB-T Enabled */
+
+ /* Put the cx24116/cx24123 into reset */
+ cx_write(MO_SRST_IO, 0);
+
+ /* cx22702 out of reset and enable it */
+ cx_set(MO_GP0_IO, 0x00000080);
+ cx_clear(MO_GP0_IO, 0x00000004);
+ core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */
+ udelay(1000);
+ }
+ break;
+ case CX88_BOARD_HAUPPAUGE_HVR4000:
+ if(core->dvbdev->frontends.active_fe_id == 1) {
+ /* DVB-S/S2 Enabled */
+
+ /* Toggle reset on cx22702 leaving i2c active */
+ cx_write(MO_GP0_IO, (core->board.input[0].gpio0 & 0x0000ff00) | 0x00000080);
+ udelay(1000);
+ cx_clear(MO_GP0_IO, 0x00000080);
+ udelay(50);
+ cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset */
+ cx_set(MO_GP0_IO, 0x00000004); /* tri-state the cx22702 pins */
+ udelay(1000);
+
+ cx_write(MO_SRST_IO, 1); /* Take the cx24116/cx24123 out of reset */
+ core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */
+ } else
+ if (core->dvbdev->frontends.active_fe_id == 2) {
+ /* DVB-T Enabled */
+
+ /* Put the cx24116/cx24123 into reset */
+ cx_write(MO_SRST_IO, 0);
+
+ /* cx22702 out of reset and enable it */
+ cx_set(MO_GP0_IO, 0x00000080);
+ cx_clear(MO_GP0_IO, 0x00000004);
+ core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */
+ udelay(1000);
+ }
+ break;
+
default:
err = -ENODEV;
}
@@ -1056,6 +1212,9 @@ static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
case CX88_BOARD_HAUPPAUGE_HVR1300:
/* Do Nothing, leave the cx22702 on the bus. */
break;
+ case CX88_BOARD_HAUPPAUGE_HVR3000:
+ case CX88_BOARD_HAUPPAUGE_HVR4000:
+ break;
default:
err = -ENODEV;
}
@@ -1066,7 +1225,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
{
struct cx88_core *core = drv->core;
struct cx8802_dev *dev = drv->core->dvbdev;
- int err;
+ int err,i;
+ struct videobuf_dvb_frontend *fe;
dprintk( 1, "%s\n", __func__);
dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
@@ -1086,12 +1246,23 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
/* dvb stuff */
printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
- videobuf_queue_sg_init(&dev->dvb.dvbq, &dvb_qops,
+ dev->ts_gen_cntrl = 0x0c;
+
+ for (i = 1; i <= core->board.num_frontends; i++) {
+ fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
+ if (!fe) {
+ printk(KERN_ERR "%s() failed to get frontend(%d)\n", __FUNCTION__, i);
+ continue;
+ }
+ videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
&dev->pci->dev, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_TOP,
sizeof(struct cx88_buffer),
dev);
+ /* init struct videobuf_dvb */
+ fe->dvb.name = dev->core->name;
+ }
err = dvb_register(dev);
if (err != 0)
printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n",
@@ -1105,9 +1276,7 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv)
{
struct cx8802_dev *dev = drv->core->dvbdev;
- /* dvb */
- if (dev->dvb.frontend)
- videobuf_dvb_unregister(&dev->dvb);
+ videobuf_dvb_unregister_bus(&dev->frontends);
vp3054_i2c_remove(dev);