[media] au0828: add suspend/resume code for V4L2 07/25807/1
authorMauro Carvalho Chehab <m.chehab@samsung.com>
Sat, 9 Aug 2014 13:50:44 +0000 (10:50 -0300)
committerMauro Carvalho Chehab <m.chehab@samsung.com>
Sun, 10 Aug 2014 02:32:53 +0000 (23:32 -0300)
No timers should be enabled during suspend. So,
stop them. At resume time, we should do the proper
initialization for it to keep working.

Change-Id: Ia7edbf78f685e54559d039cf1e77a5b236020abb
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
drivers/media/usb/au0828/au0828-core.c
drivers/media/usb/au0828/au0828-video.c
drivers/media/usb/au0828/au0828.h

index 26ec505..5f13888 100644 (file)
@@ -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 */
index a02469f..90c3f0e 100644 (file)
@@ -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,
index d322343..0d8cfe5 100644 (file)
@@ -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 */