diff options
author | Antti Palosaari <crope@iki.fi> | 2011-04-07 15:51:52 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-05-20 09:30:07 -0300 |
commit | f71095be6645aee0828623701e35e7e7d52910d8 (patch) | |
tree | c8e0f073d203d0a4c8c8525a12d8e0a3b166a57d /drivers/media | |
parent | f9d0bc1c08d205008e9414a0853e4aca8b07168a (diff) |
[media] em28xx: Multi Frontend (MFE) support
Register multiple FEs for same adapter. After that it is
possible to register two FEs for same adapter. For example
one for DVB-T and one for DVB-C.
Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-dvb.c | 91 |
1 files changed, 56 insertions, 35 deletions
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 84120596d0e3..0766bc6be14b 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -59,7 +59,7 @@ if (debug >= level) \ #define EM28XX_DVB_MAX_PACKETS 64 struct em28xx_dvb { - struct dvb_frontend *frontend; + struct dvb_frontend *fe[2]; /* feed count management */ struct mutex lock; @@ -345,17 +345,17 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) cfg.i2c_adap = &dev->i2c_adap; cfg.i2c_addr = addr; - if (!dev->dvb->frontend) { + if (!dev->dvb->fe[0]) { em28xx_errdev("/2: dvb frontend not attached. " "Can't attach xc3028\n"); return -EINVAL; } - fe = dvb_attach(xc2028_attach, dev->dvb->frontend, &cfg); + fe = dvb_attach(xc2028_attach, dev->dvb->fe[0], &cfg); if (!fe) { em28xx_errdev("/2: xc3028 attach failed\n"); - dvb_frontend_detach(dev->dvb->frontend); - dev->dvb->frontend = NULL; + dvb_frontend_detach(dev->dvb->fe[0]); + dev->dvb->fe[0] = NULL; return -EINVAL; } @@ -385,16 +385,28 @@ static int register_dvb(struct em28xx_dvb *dvb, } /* Ensure all frontends negotiate bus access */ - dvb->frontend->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; + dvb->fe[0]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; + if (dvb->fe[1]) + dvb->fe[1]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; dvb->adapter.priv = dev; /* register frontend */ - result = dvb_register_frontend(&dvb->adapter, dvb->frontend); + result = dvb_register_frontend(&dvb->adapter, dvb->fe[0]); if (result < 0) { printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", dev->name, result); - goto fail_frontend; + goto fail_frontend0; + } + + /* register 2nd frontend */ + if (dvb->fe[1]) { + result = dvb_register_frontend(&dvb->adapter, dvb->fe[1]); + if (result < 0) { + printk(KERN_WARNING "%s: 2nd dvb_register_frontend failed (errno = %d)\n", + dev->name, result); + goto fail_frontend1; + } } /* register demux stuff */ @@ -460,9 +472,14 @@ fail_fe_hw: fail_dmxdev: dvb_dmx_release(&dvb->demux); fail_dmx: - dvb_unregister_frontend(dvb->frontend); -fail_frontend: - dvb_frontend_detach(dvb->frontend); + if (dvb->fe[1]) + dvb_unregister_frontend(dvb->fe[1]); + dvb_unregister_frontend(dvb->fe[0]); +fail_frontend1: + if (dvb->fe[1]) + dvb_frontend_detach(dvb->fe[1]); +fail_frontend0: + dvb_frontend_detach(dvb->fe[0]); dvb_unregister_adapter(&dvb->adapter); fail_adapter: return result; @@ -475,12 +492,15 @@ static void unregister_dvb(struct em28xx_dvb *dvb) dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); dvb_dmxdev_release(&dvb->dmxdev); dvb_dmx_release(&dvb->demux); - dvb_unregister_frontend(dvb->frontend); - dvb_frontend_detach(dvb->frontend); + if (dvb->fe[1]) + dvb_unregister_frontend(dvb->fe[1]); + dvb_unregister_frontend(dvb->fe[0]); + if (dvb->fe[1]) + dvb_frontend_detach(dvb->fe[1]); + dvb_frontend_detach(dvb->fe[0]); dvb_unregister_adapter(&dvb->adapter); } - static int dvb_init(struct em28xx *dev) { int result = 0; @@ -499,16 +519,17 @@ static int dvb_init(struct em28xx *dev) return -ENOMEM; } dev->dvb = dvb; + dvb->fe[0] = dvb->fe[1] = NULL; mutex_lock(&dev->lock); em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); /* init frontend */ switch (dev->model) { case EM2874_LEADERSHIP_ISDBT: - dvb->frontend = dvb_attach(s921_attach, + dvb->fe[0] = dvb_attach(s921_attach, &sharp_isdbt, &dev->i2c_adap); - if (!dvb->frontend) { + if (!dvb->fe[0]) { result = -EINVAL; goto out_free; } @@ -518,7 +539,7 @@ static int dvb_init(struct em28xx *dev) case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950: case EM2880_BOARD_PINNACLE_PCTV_HD_PRO: case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600: - dvb->frontend = dvb_attach(lgdt330x_attach, + dvb->fe[0] = dvb_attach(lgdt330x_attach, &em2880_lgdt3303_dev, &dev->i2c_adap); if (attach_xc3028(0x61, dev) < 0) { @@ -527,7 +548,7 @@ static int dvb_init(struct em28xx *dev) } break; case EM2880_BOARD_KWORLD_DVB_310U: - dvb->frontend = dvb_attach(zl10353_attach, + dvb->fe[0] = dvb_attach(zl10353_attach, &em28xx_zl10353_with_xc3028, &dev->i2c_adap); if (attach_xc3028(0x61, dev) < 0) { @@ -538,7 +559,7 @@ static int dvb_init(struct em28xx *dev) case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: case EM2882_BOARD_TERRATEC_HYBRID_XS: case EM2880_BOARD_EMPIRE_DUAL_TV: - dvb->frontend = dvb_attach(zl10353_attach, + dvb->fe[0] = dvb_attach(zl10353_attach, &em28xx_zl10353_xc3028_no_i2c_gate, &dev->i2c_adap); if (attach_xc3028(0x61, dev) < 0) { @@ -551,13 +572,13 @@ static int dvb_init(struct em28xx *dev) case EM2881_BOARD_PINNACLE_HYBRID_PRO: case EM2882_BOARD_DIKOM_DK300: case EM2882_BOARD_KWORLD_VS_DVBT: - dvb->frontend = dvb_attach(zl10353_attach, + dvb->fe[0] = dvb_attach(zl10353_attach, &em28xx_zl10353_xc3028_no_i2c_gate, &dev->i2c_adap); - if (dvb->frontend == NULL) { + if (dvb->fe[0] == NULL) { /* This board could have either a zl10353 or a mt352. If the chip id isn't for zl10353, try mt352 */ - dvb->frontend = dvb_attach(mt352_attach, + dvb->fe[0] = dvb_attach(mt352_attach, &terratec_xs_mt352_cfg, &dev->i2c_adap); } @@ -569,7 +590,7 @@ static int dvb_init(struct em28xx *dev) break; case EM2883_BOARD_KWORLD_HYBRID_330U: case EM2882_BOARD_EVGA_INDTUBE: - dvb->frontend = dvb_attach(s5h1409_attach, + dvb->fe[0] = dvb_attach(s5h1409_attach, &em28xx_s5h1409_with_xc3028, &dev->i2c_adap); if (attach_xc3028(0x61, dev) < 0) { @@ -578,11 +599,11 @@ static int dvb_init(struct em28xx *dev) } break; case EM2882_BOARD_KWORLD_ATSC_315U: - dvb->frontend = dvb_attach(lgdt330x_attach, + dvb->fe[0] = dvb_attach(lgdt330x_attach, &em2880_lgdt3303_dev, &dev->i2c_adap); - if (dvb->frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dvb->frontend, + if (dvb->fe[0] != NULL) { + if (!dvb_attach(simple_tuner_attach, dvb->fe[0], &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) { result = -EINVAL; goto out_free; @@ -591,7 +612,7 @@ static int dvb_init(struct em28xx *dev) break; case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2: case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E: - dvb->frontend = dvb_attach(drxd_attach, &em28xx_drxd, NULL, + dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL, &dev->i2c_adap, &dev->udev->dev); if (attach_xc3028(0x61, dev) < 0) { result = -EINVAL; @@ -600,11 +621,11 @@ static int dvb_init(struct em28xx *dev) break; case EM2870_BOARD_REDDO_DVB_C_USB_BOX: /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */ - dvb->frontend = dvb_attach(tda10023_attach, + dvb->fe[0] = dvb_attach(tda10023_attach, &em28xx_tda10023_config, &dev->i2c_adap, 0x48); - if (dvb->frontend) { - if (!dvb_attach(simple_tuner_attach, dvb->frontend, + if (dvb->fe[0]) { + if (!dvb_attach(simple_tuner_attach, dvb->fe[0], &dev->i2c_adap, 0x60, TUNER_PHILIPS_CU1216L)) { result = -EINVAL; goto out_free; @@ -612,11 +633,11 @@ static int dvb_init(struct em28xx *dev) } break; case EM2870_BOARD_KWORLD_A340: - dvb->frontend = dvb_attach(lgdt3305_attach, + dvb->fe[0] = dvb_attach(lgdt3305_attach, &em2870_lgdt3304_dev, &dev->i2c_adap); - if (dvb->frontend != NULL) - dvb_attach(tda18271_attach, dvb->frontend, 0x60, + if (dvb->fe[0] != NULL) + dvb_attach(tda18271_attach, dvb->fe[0], 0x60, &dev->i2c_adap, &kworld_a340_config); break; default: @@ -624,13 +645,13 @@ static int dvb_init(struct em28xx *dev) " isn't supported yet\n"); break; } - if (NULL == dvb->frontend) { + if (NULL == dvb->fe[0]) { em28xx_errdev("/2: frontend initialization failed\n"); result = -EINVAL; goto out_free; } /* define general-purpose callback pointer */ - dvb->frontend->callback = em28xx_tuner_callback; + dvb->fe[0]->callback = em28xx_tuner_callback; /* register everything */ result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); |