[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>
This commit is contained in:
Mauro Carvalho Chehab 2014-08-09 21:47:15 -03:00
parent e2147d0af0
commit 1a1ba95e80
3 changed files with 67 additions and 1 deletions

View 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 */

View 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,

View 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 */