Commit 2fe3e2ee authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

V4L/DVB (9764): em28xx: Add support for suspend the device when not used

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: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent f502e861
...@@ -1456,7 +1456,7 @@ void em28xx_pre_card_setup(struct em28xx *dev) ...@@ -1456,7 +1456,7 @@ void em28xx_pre_card_setup(struct em28xx *dev)
em28xx_set_mode(dev, EM28XX_ANALOG_MODE); em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
/* Unlock device */ /* 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) static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
......
...@@ -737,12 +737,14 @@ int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio) ...@@ -737,12 +737,14 @@ int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio)
if (!gpio) if (!gpio)
return rc; return rc;
em28xx_write_reg(dev, 0x48, 0x00); if (dev->mode != EM28XX_SUSPEND) {
if (dev->mode == EM28XX_ANALOG_MODE) em28xx_write_reg(dev, 0x48, 0x00);
em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67); if (dev->mode == EM28XX_ANALOG_MODE)
else em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67);
em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37); else
msleep(6); em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37);
msleep(6);
}
/* Send GPIO reset sequences specified at board entry */ /* Send GPIO reset sequences specified at board entry */
while (gpio->sleep >= 0) { while (gpio->sleep >= 0) {
...@@ -767,9 +769,12 @@ int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode) ...@@ -767,9 +769,12 @@ int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode)
if (dev->mode == set_mode) if (dev->mode == set_mode)
return 0; return 0;
if (set_mode == EM28XX_MODE_UNDEFINED) { if (set_mode == EM28XX_SUSPEND) {
dev->mode = set_mode; 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; dev->mode = set_mode;
......
...@@ -161,7 +161,7 @@ static int stop_streaming(struct em28xx_dvb *dvb) ...@@ -161,7 +161,7 @@ static int stop_streaming(struct em28xx_dvb *dvb)
em28xx_uninit_isoc(dev); em28xx_uninit_isoc(dev);
em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); em28xx_set_mode(dev, EM28XX_SUSPEND);
return 0; return 0;
} }
...@@ -215,7 +215,7 @@ static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) ...@@ -215,7 +215,7 @@ static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
if (acquire) if (acquire)
return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
else 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) ...@@ -466,12 +466,12 @@ static int dvb_init(struct em28xx *dev)
if (result < 0) if (result < 0)
goto out_free; goto out_free;
em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); em28xx_set_mode(dev, EM28XX_SUSPEND);
printk(KERN_INFO "Successfully loaded em28xx-dvb\n"); printk(KERN_INFO "Successfully loaded em28xx-dvb\n");
return 0; return 0;
out_free: out_free:
em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); em28xx_set_mode(dev, EM28XX_SUSPEND);
kfree(dvb); kfree(dvb);
dev->dvb = NULL; dev->dvb = NULL;
return result; return result;
......
...@@ -1697,7 +1697,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) ...@@ -1697,7 +1697,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
/* do this before setting alternate! */ /* do this before setting alternate! */
em28xx_uninit_isoc(dev); em28xx_uninit_isoc(dev);
em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); em28xx_set_mode(dev, EM28XX_SUSPEND);
/* set alternate 0 */ /* set alternate 0 */
dev->alt = 0; dev->alt = 0;
......
...@@ -160,7 +160,7 @@ ...@@ -160,7 +160,7 @@
#define EM2800_I2C_WRITE_TIMEOUT 20 #define EM2800_I2C_WRITE_TIMEOUT 20
enum em28xx_mode { enum em28xx_mode {
EM28XX_MODE_UNDEFINED, EM28XX_SUSPEND,
EM28XX_ANALOG_MODE, EM28XX_ANALOG_MODE,
EM28XX_DIGITAL_MODE, EM28XX_DIGITAL_MODE,
}; };
...@@ -336,6 +336,7 @@ struct em28xx_board { ...@@ -336,6 +336,7 @@ struct em28xx_board {
unsigned int tda9887_conf; unsigned int tda9887_conf;
struct em28xx_reg_seq *dvb_gpio; struct em28xx_reg_seq *dvb_gpio;
struct em28xx_reg_seq *suspend_gpio;
unsigned int is_em2800:1; unsigned int is_em2800:1;
unsigned int has_msp34xx:1; unsigned int has_msp34xx:1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment