diff options
Diffstat (limited to 'drivers/media/video/cx88/cx88-dvb.c')
-rw-r--r-- | drivers/media/video/cx88/cx88-dvb.c | 90 |
1 files changed, 70 insertions, 20 deletions
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index da4dd4913d9f..aef5297534af 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -138,6 +138,28 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire) return ret; } +static void cx88_dvb_gate_ctrl(struct cx88_core *core, int open) +{ + struct videobuf_dvb_frontends *f; + struct videobuf_dvb_frontend *fe; + + if (!core->dvbdev) + return; + + f = &core->dvbdev->frontends; + + if (!f) + return; + + if (f->gate <= 1) /* undefined or fe0 */ + fe = videobuf_dvb_get_frontend(f, 1); + else + fe = videobuf_dvb_get_frontend(f, f->gate); + + if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl) + fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open); +} + /* ------------------------------------------------------------------ */ static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) @@ -592,6 +614,31 @@ static struct stv0288_config tevii_tuner_earda_config = { .set_ts_params = cx24116_set_ts_param, }; +static int cx8802_alloc_frontends(struct cx8802_dev *dev) +{ + struct cx88_core *core = dev->core; + struct videobuf_dvb_frontend *fe = NULL; + int i; + + mutex_init(&dev->frontends.lock); + INIT_LIST_HEAD(&dev->frontends.felist); + + if (!core->board.num_frontends) + return -ENODEV; + + printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, + core->board.num_frontends); + for (i = 1; i <= core->board.num_frontends; i++) { + fe = videobuf_dvb_alloc_frontend(&dev->frontends, i); + if (!fe) { + printk(KERN_ERR "%s() failed to alloc\n", __func__); + videobuf_dvb_dealloc_frontends(&dev->frontends); + return -ENOMEM; + } + } + return 0; +} + static int dvb_register(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; @@ -611,6 +658,9 @@ static int dvb_register(struct cx8802_dev *dev) /* multi-frontend gate control is undefined or defaults to fe0 */ dev->frontends.gate = 0; + /* Sets the gate control callback to be used by i2c command calls */ + core->gate_ctrl = cx88_dvb_gate_ctrl; + /* init frontend(s) */ switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_DVB_T1: @@ -1109,6 +1159,7 @@ static int dvb_register(struct cx8802_dev *dev) &dev->pci->dev, adapter_nr, mfe_shared); frontend_detach: + core->gate_ctrl = NULL; videobuf_dvb_dealloc_frontends(&dev->frontends); return -EINVAL; } @@ -1199,6 +1250,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; + struct videobuf_dvb_frontend *fe; + int i; dprintk( 1, "%s\n", __func__); dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", @@ -1214,39 +1267,34 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) /* If vp3054 isn't enabled, a stub will just return 0 */ err = vp3054_i2c_probe(dev); if (0 != err) - goto fail_probe; + goto fail_core; /* dvb stuff */ printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); dev->ts_gen_cntrl = 0x0c; + err = cx8802_alloc_frontends(dev); + if (err) + goto fail_core; + err = -ENODEV; - if (core->board.num_frontends) { - struct videobuf_dvb_frontend *fe; - int i; - - for (i = 1; i <= core->board.num_frontends; i++) { - fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i); - if (fe == NULL) { - printk(KERN_ERR "%s() failed to get frontend(%d)\n", + for (i = 1; i <= core->board.num_frontends; i++) { + fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i); + if (fe == NULL) { + printk(KERN_ERR "%s() failed to get frontend(%d)\n", __func__, i); - goto fail_probe; - } - videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops, + goto fail_probe; + } + 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; - } - } else { - /* no frontends allocated */ - printk(KERN_ERR "%s/2 .num_frontends should be non-zero\n", - core->name); - goto fail_core; + /* init struct videobuf_dvb */ + fe->dvb.name = dev->core->name; } + err = dvb_register(dev); if (err) /* frontends/adapter de-allocated in dvb_register */ @@ -1270,6 +1318,8 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv) vp3054_i2c_remove(dev); + core->gate_ctrl = NULL; + return 0; } |