Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / drivers / media / video / em28xx / em28xx-dvb.c
index fd8f44c..0b2333e 100644 (file)
@@ -97,7 +97,8 @@ static inline void print_err_status(struct em28xx *dev,
        if (packet < 0) {
                dprintk(1, "URB status %d [%s].\n", status, errmsg);
        } else {
-               dprintk(1, "URB packet %d, status %d [%s].\n", packet, status, errmsg);
+               dprintk(1, "URB packet %d, status %d [%s].\n",
+                       packet, status, errmsg);
        }
 }
 
@@ -134,21 +135,29 @@ static inline int dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
        return 0;
 }
 
-static int start_streaming(struct em28xx_dvb* dvb) {
+static int start_streaming(struct em28xx_dvb *dvb)
+{
+       int rc;
        struct em28xx *dev = dvb->adapter.priv;
 
        usb_set_interface(dev->udev, 0, 1);
-       dev->em28xx_write_regs_req(dev,0x00,0x48,"\x00",1);
+       rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
+       if (rc < 0)
+               return rc;
 
        return em28xx_init_isoc(dev, EM28XX_DVB_MAX_PACKETS,
                                EM28XX_DVB_NUM_BUFS, EM28XX_DVB_MAX_PACKETSIZE,
-                               dvb_isoc_copy, EM28XX_DIGITAL_CAPTURE);
+                               dvb_isoc_copy);
 }
 
-static int stop_streaming(struct em28xx_dvb* dvb) {
+static int stop_streaming(struct em28xx_dvb *dvb)
+{
        struct em28xx *dev = dvb->adapter.priv;
 
        em28xx_uninit_isoc(dev);
+
+       em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+
        return 0;
 }
 
@@ -167,7 +176,8 @@ static int start_feed(struct dvb_demux_feed *feed)
 
        if (dvb->nfeeds == 1) {
                ret = start_streaming(dvb);
-               if(ret < 0) rc = ret;
+               if (ret < 0)
+                       rc = ret;
        }
 
        mutex_unlock(&dvb->lock);
@@ -182,14 +192,27 @@ static int stop_feed(struct dvb_demux_feed *feed)
 
        mutex_lock(&dvb->lock);
        dvb->nfeeds--;
-       if (0 == dvb->nfeeds) {
+
+       if (0 == dvb->nfeeds)
                err = stop_streaming(dvb);
-       }
+
        mutex_unlock(&dvb->lock);
        return err;
 }
 
 
+
+/* ------------------------------------------------------------------ */
+static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+       struct em28xx *dev = fe->dvb->priv;
+
+       if (acquire)
+               return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
+       else
+               return em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+}
+
 /* ------------------------------------------------------------------ */
 
 static struct lgdt330x_config em2880_lgdt3303_dev = {
@@ -209,17 +232,13 @@ static struct zl10353_config em28xx_zl10353_with_xc3028 = {
 static int attach_xc3028(u8 addr, struct em28xx *dev)
 {
        struct dvb_frontend *fe;
-       struct xc2028_ctrl ctl;
        struct xc2028_config cfg;
 
-       memset (&cfg, 0, sizeof(cfg));
+       memset(&cfg, 0, sizeof(cfg));
        cfg.i2c_adap  = &dev->i2c_adap;
        cfg.i2c_addr  = addr;
-       cfg.ctrl      = &ctl;
        cfg.callback  = em28xx_tuner_callback;
 
-       em28xx_setup_xc3028(dev, &ctl);
-
        if (!dev->dvb->frontend) {
                printk(KERN_ERR "%s/2: dvb frontend not attached. "
                                "Can't attach xc3028\n",
@@ -232,7 +251,6 @@ static int attach_xc3028(u8 addr, struct em28xx *dev)
                printk(KERN_ERR "%s/2: xc3028 attach failed\n",
                       dev->name);
                dvb_frontend_detach(dev->dvb->frontend);
-               dvb_unregister_frontend(dev->dvb->frontend);
                dev->dvb->frontend = NULL;
                return -EINVAL;
        }
@@ -261,6 +279,10 @@ int register_dvb(struct em28xx_dvb *dvb,
                       dev->name, result);
                goto fail_adapter;
        }
+
+       /* Ensure all frontends negotiate bus access */
+       dvb->frontend->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl;
+
        dvb->adapter.priv = dev;
 
        /* register frontend */
@@ -280,6 +302,7 @@ int register_dvb(struct em28xx_dvb *dvb,
        dvb->demux.feednum    = 256;
        dvb->demux.start_feed = start_feed;
        dvb->demux.stop_feed  = stop_feed;
+
        result = dvb_dmx_init(&dvb->demux);
        if (result < 0) {
                printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
@@ -359,20 +382,23 @@ static int dvb_init(struct em28xx *dev)
        int result = 0;
        struct em28xx_dvb *dvb;
 
+       if (!dev->has_dvb) {
+               /* This device does not support the extension */
+               return 0;
+       }
+
        dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL);
-       if(dvb == NULL) {
-               printk("em28xx_dvb: memory allocation failed\n");
+
+       if (dvb == NULL) {
+               printk(KERN_INFO "em28xx_dvb: memory allocation failed\n");
                return -ENOMEM;
        }
        dev->dvb = dvb;
 
+       em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
        /* init frontend */
        switch (dev->model) {
        case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
-               /* Enable lgdt330x */
-               dev->mode = EM28XX_DIGITAL_MODE;
-               em28xx_tuner_callback(dev, XC2028_TUNER_RESET, 0);
-
                dvb->frontend = dvb_attach(lgdt330x_attach,
                                           &em2880_lgdt3303_dev,
                                           &dev->i2c_adap);
@@ -382,9 +408,6 @@ static int dvb_init(struct em28xx *dev)
                }
                break;
        case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
-               /* Enable zl10353 */
-               dev->mode = EM28XX_DIGITAL_MODE;
-               em28xx_tuner_callback(dev, XC2028_TUNER_RESET, 0);
                dvb->frontend = dvb_attach(zl10353_attach,
                                           &em28xx_zl10353_with_xc3028,
                                           &dev->i2c_adap);
@@ -410,13 +433,15 @@ static int dvb_init(struct em28xx *dev)
        /* register everything */
        result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
 
-       if (result < 0) {
+       if (result < 0)
                goto out_free;
-       }
 
+       em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+       printk(KERN_INFO "Successfully loaded em28xx-dvb\n");
        return 0;
 
 out_free:
+       em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
        kfree(dvb);
        dev->dvb = NULL;
        return result;
@@ -424,6 +449,11 @@ out_free:
 
 static int dvb_fini(struct em28xx *dev)
 {
+       if (!dev->has_dvb) {
+               /* This device does not support the extension */
+               return 0;
+       }
+
        if (dev->dvb) {
                unregister_dvb(dev->dvb);
                dev->dvb = NULL;