V4L/DVB (9764): em28xx: Add support for suspend the device when not used
authorMauro Carvalho Chehab <mchehab@redhat.com>
Thu, 27 Nov 2008 12:10:40 +0000 (09:10 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 29 Dec 2008 19:53:43 +0000 (17:53 -0200)
Several chips may be turned off when the device is not used, like audio,
video and dvb demods. This patch adds a gpio callback at the core
structs to allow turning off such devices.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/em28xx/em28xx-core.c
drivers/media/video/em28xx/em28xx-dvb.c
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/em28xx/em28xx.h

index be78485c1664051bda444f4141cbf666d2070533..a4b61e5a7635456f9dac3e20081e12b200e83163 100644 (file)
@@ -1456,7 +1456,7 @@ void em28xx_pre_card_setup(struct em28xx *dev)
        em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
 
        /* Unlock device */
-       em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+       em28xx_set_mode(dev, EM28XX_SUSPEND);
 }
 
 static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
index 71a1aaaa982ec695da0afc628767a1136fa92718..c3ff8ad416e6d4e8f44d344f5e54d4c0becb4d9f 100644 (file)
@@ -737,12 +737,14 @@ int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio)
        if (!gpio)
                return rc;
 
-       em28xx_write_reg(dev, 0x48, 0x00);
-       if (dev->mode == EM28XX_ANALOG_MODE)
-               em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67);
-       else
-               em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37);
-       msleep(6);
+       if (dev->mode != EM28XX_SUSPEND) {
+               em28xx_write_reg(dev, 0x48, 0x00);
+               if (dev->mode == EM28XX_ANALOG_MODE)
+                       em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67);
+               else
+                       em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37);
+               msleep(6);
+       }
 
        /* Send GPIO reset sequences specified at board entry */
        while (gpio->sleep >= 0) {
@@ -767,9 +769,12 @@ int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode)
        if (dev->mode == set_mode)
                return 0;
 
-       if (set_mode == EM28XX_MODE_UNDEFINED) {
+       if (set_mode == EM28XX_SUSPEND) {
                dev->mode = set_mode;
-               return 0;
+
+               /* FIXME: add suspend support for ac97 */
+
+               return em28xx_gpio_set(dev, dev->board.suspend_gpio);
        }
 
        dev->mode = set_mode;
index 09c15cc088a627b41411701366c3c155bb756c97..211156d458f0de94622bb7acd093895bfb577899 100644 (file)
@@ -161,7 +161,7 @@ static int stop_streaming(struct em28xx_dvb *dvb)
 
        em28xx_uninit_isoc(dev);
 
-       em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+       em28xx_set_mode(dev, EM28XX_SUSPEND);
 
        return 0;
 }
@@ -215,7 +215,7 @@ static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
        if (acquire)
                return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
        else
-               return em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+               return em28xx_set_mode(dev, EM28XX_SUSPEND);
 }
 
 /* ------------------------------------------------------------------ */
@@ -466,12 +466,12 @@ static int dvb_init(struct em28xx *dev)
        if (result < 0)
                goto out_free;
 
-       em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+       em28xx_set_mode(dev, EM28XX_SUSPEND);
        printk(KERN_INFO "Successfully loaded em28xx-dvb\n");
        return 0;
 
 out_free:
-       em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+       em28xx_set_mode(dev, EM28XX_SUSPEND);
        kfree(dvb);
        dev->dvb = NULL;
        return result;
index 87e9f1d7a95889e58ef095b3f1555588579c1f97..efa4c82532235307a4c921f3c4fd6306945ffb87 100644 (file)
@@ -1697,7 +1697,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
 
                /* do this before setting alternate! */
                em28xx_uninit_isoc(dev);
-               em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED);
+               em28xx_set_mode(dev, EM28XX_SUSPEND);
 
                /* set alternate 0 */
                dev->alt = 0;
index b2b41b3635e23ada03564c2f0d0d1258126c79ba..b505d44fed87317f96c95064ff53d03c8af25845 100644 (file)
 #define EM2800_I2C_WRITE_TIMEOUT 20
 
 enum em28xx_mode {
-       EM28XX_MODE_UNDEFINED,
+       EM28XX_SUSPEND,
        EM28XX_ANALOG_MODE,
        EM28XX_DIGITAL_MODE,
 };
@@ -336,6 +336,7 @@ struct em28xx_board {
        unsigned int tda9887_conf;
 
        struct em28xx_reg_seq *dvb_gpio;
+       struct em28xx_reg_seq *suspend_gpio;
 
        unsigned int is_em2800:1;
        unsigned int has_msp34xx:1;