summaryrefslogtreecommitdiff
path: root/drivers/media/video/au0828
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@kernellabs.com>2010-09-02 05:03:43 +0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-12-29 13:16:34 +0300
commit6e04b7b95a5bd2da0aa5df05fc09a1f0d6615666 (patch)
tree6ff016a1e6ba80408feeaef9ee5c5db8368565e0 /drivers/media/video/au0828
parent301c9f26d7ded6e274a99c3a447a9a36790a3f3e (diff)
downloadlinux-6e04b7b95a5bd2da0aa5df05fc09a1f0d6615666.tar.xz
[media] au0828: continue video streaming even when no ITU-656 coming in
We need the au0828 to continue delivering frames even when the device is not delivering video, or else applications such as tvtime will block indefinitely. Unfortunately, the au8522 doesn't have any sort of free-running mode or "blue screen on no video" like some other decoders. This work was sponsored by GetWellNetwork Inc. Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/au0828')
-rw-r--r--drivers/media/video/au0828/au0828-video.c61
-rw-r--r--drivers/media/video/au0828/au0828.h2
2 files changed, 63 insertions, 0 deletions
diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c
index 20ba5915542f..8d11e544c879 100644
--- a/drivers/media/video/au0828/au0828-video.c
+++ b/drivers/media/video/au0828/au0828-video.c
@@ -312,6 +312,9 @@ static inline void buffer_filled(struct au0828_dev *dev,
list_del(&buf->vb.queue);
wake_up(&buf->vb.done);
+
+ /* Reset the timer for "no video condition" */
+ mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
}
static inline void vbi_buffer_filled(struct au0828_dev *dev,
@@ -329,6 +332,9 @@ static inline void vbi_buffer_filled(struct au0828_dev *dev,
list_del(&buf->vb.queue);
wake_up(&buf->vb.done);
+
+ /* Reset the timer for "no video condition" */
+ mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
}
/*
@@ -907,6 +913,50 @@ static int get_ressource(struct au0828_fh *fh)
}
}
+/* This function ensures that video frames continue to be delivered even if
+ the ITU-656 input isn't receiving any data (thereby preventing applications
+ such as tvtime from hanging) */
+void au0828_vid_buffer_timeout(unsigned long data)
+{
+ struct au0828_dev *dev = (struct au0828_dev *) data;
+ struct au0828_dmaqueue *dma_q = &dev->vidq;
+ struct au0828_buffer *buf;
+ unsigned char *vid_data;
+
+ spin_lock(&dev->slock);
+
+ buf = dev->isoc_ctl.buf;
+ if (buf != NULL) {
+ vid_data = videobuf_to_vmalloc(&buf->vb);
+ memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */
+ buffer_filled(dev, dma_q, buf);
+ get_next_buf(dma_q, &buf);
+ }
+
+ spin_unlock(&dev->slock);
+}
+
+void au0828_vbi_buffer_timeout(unsigned long data)
+{
+ struct au0828_dev *dev = (struct au0828_dev *) data;
+ struct au0828_dmaqueue *dma_q = &dev->vbiq;
+ struct au0828_buffer *buf;
+ unsigned char *vbi_data;
+
+ spin_lock(&dev->slock);
+
+ buf = dev->isoc_ctl.vbi_buf;
+ if (buf != NULL) {
+ vbi_data = videobuf_to_vmalloc(&buf->vb);
+ memset(vbi_data, 0x00, buf->vb.size);
+ vbi_buffer_filled(dev, dma_q, buf);
+ vbi_get_next_buf(dma_q, &buf);
+ }
+
+ spin_unlock(&dev->slock);
+}
+
+
static int au0828_v4l2_open(struct file *filp)
{
int ret = 0;
@@ -976,6 +1026,15 @@ static int au0828_v4l2_open(struct file *filp)
V4L2_FIELD_SEQ_TB,
sizeof(struct au0828_buffer), fh, NULL);
+ if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ dev->vid_timeout.function = au0828_vid_buffer_timeout;
+ dev->vid_timeout.data = (unsigned long) dev;
+ init_timer(&dev->vid_timeout);
+ } else {
+ dev->vbi_timeout.function = au0828_vbi_buffer_timeout;
+ dev->vbi_timeout.data = (unsigned long) dev;
+ init_timer(&dev->vbi_timeout);
+ }
return ret;
}
@@ -987,11 +1046,13 @@ static int au0828_v4l2_close(struct file *filp)
struct au0828_dev *dev = fh->dev;
if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
+ del_timer(&dev->vid_timeout);
videobuf_stop(&fh->vb_vidq);
res_free(fh, AU0828_RESOURCE_VIDEO);
}
if (res_check(fh, AU0828_RESOURCE_VBI)) {
+ del_timer(&dev->vbi_timeout);
videobuf_stop(&fh->vb_vbiq);
res_free(fh, AU0828_RESOURCE_VBI);
}
diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h
index 4dd8ce7f139e..ef46a889da20 100644
--- a/drivers/media/video/au0828/au0828.h
+++ b/drivers/media/video/au0828/au0828.h
@@ -204,6 +204,8 @@ struct au0828_dev {
unsigned int resources; /* resources in use */
struct video_device *vdev;
struct video_device *vbi_dev;
+ struct timer_list vid_timeout;
+ struct timer_list vbi_timeout;
int width;
int height;
int vbi_width;