summaryrefslogtreecommitdiff
path: root/drivers/media/usb
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <m.chehab@samsung.com>2014-08-09 21:47:15 -0300
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-08-21 15:25:08 -0500
commit1a1ba95e80e567176aeb2a10b2dc6d920b06a33e (patch)
tree4131cbd9989ed20213158ffdb11b7dcfcc6ff5d4 /drivers/media/usb
parente2147d0af0aa77c1a7b610224161993ef62e3ac1 (diff)
[media] au0828: add suspend/resume code for V4L2
No timers should be enabled during suspend. So, stop them. At resume time, we should do the proper initialization for it to keep working. Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/usb')
-rw-r--r--drivers/media/usb/au0828/au0828-core.c2
-rw-r--r--drivers/media/usb/au0828/au0828-video.c59
-rw-r--r--drivers/media/usb/au0828/au0828.h7
3 files changed, 67 insertions, 1 deletions
diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index 26ec50539dc4..5f13888d73a0 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -290,6 +290,7 @@ static int au0828_suspend(struct usb_interface *interface,
return 0;
au0828_rc_suspend(dev);
+ au0828_v4l2_suspend(dev);
au0828_dvb_suspend(dev);
/* FIXME: should suspend also ATV/DTV */
@@ -310,6 +311,7 @@ static int au0828_resume(struct usb_interface *interface)
au0828_gpio_setup(dev);
au0828_rc_resume(dev);
+ au0828_v4l2_resume(dev);
au0828_dvb_resume(dev);
/* FIXME: should resume also ATV/DTV */
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 36ff3b496f87..574a08c7013d 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -32,7 +32,6 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/device.h>
-#include <linux/suspend.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-event.h>
@@ -1871,6 +1870,64 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
return rc;
}
+void au0828_v4l2_suspend(struct au0828_dev *dev)
+{
+ struct urb *urb;
+ int i;
+
+ if (dev->stream_state == STREAM_ON) {
+ au0828_analog_stream_disable(dev);
+ /* stop urbs */
+ for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+ urb = dev->isoc_ctl.urb[i];
+ if (urb) {
+ if (!irqs_disabled())
+ usb_kill_urb(urb);
+ else
+ usb_unlink_urb(urb);
+ }
+ }
+ }
+
+ if (dev->vid_timeout_running)
+ del_timer_sync(&dev->vid_timeout);
+ if (dev->vbi_timeout_running)
+ del_timer_sync(&dev->vbi_timeout);
+}
+
+void au0828_v4l2_resume(struct au0828_dev *dev)
+{
+ int i, rc;
+
+ if (dev->stream_state == STREAM_ON) {
+ au0828_stream_interrupt(dev);
+ au0828_init_tuner(dev);
+ }
+
+ if (dev->vid_timeout_running)
+ mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
+ if (dev->vbi_timeout_running)
+ mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
+
+ /* If we were doing ac97 instead of i2s, it would go here...*/
+ au0828_i2s_init(dev);
+
+ au0828_analog_stream_enable(dev);
+
+ if (!(dev->stream_state == STREAM_ON)) {
+ au0828_analog_stream_reset(dev);
+ /* submit urbs */
+ for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+ rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
+ if (rc) {
+ au0828_isocdbg("submit of urb %i failed (error=%i)\n",
+ i, rc);
+ au0828_uninit_isoc(dev);
+ }
+ }
+ }
+}
+
static struct v4l2_file_operations au0828_v4l_fops = {
.owner = THIS_MODULE,
.open = au0828_v4l2_open,
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
index d32234353096..0d8cfe5cd264 100644
--- a/drivers/media/usb/au0828/au0828.h
+++ b/drivers/media/usb/au0828/au0828.h
@@ -311,6 +311,13 @@ int au0828_analog_register(struct au0828_dev *dev,
struct usb_interface *interface);
int au0828_analog_stream_disable(struct au0828_dev *d);
void au0828_analog_unregister(struct au0828_dev *dev);
+#ifdef CONFIG_VIDEO_AU0828_V4L2
+void au0828_v4l2_suspend(struct au0828_dev *dev);
+void au0828_v4l2_resume(struct au0828_dev *dev);
+#else
+static inline void au0828_v4l2_suspend(struct au0828_dev *dev) { };
+static inline void au0828_v4l2_resume(struct au0828_dev *dev) { };
+#endif
/* ----------------------------------------------------------- */
/* au0828-dvb.c */