From 83f859c5a6d6e01d671f002c0ade3498b4a4b245 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Fri, 25 Jun 2010 01:33:39 -0300 Subject: [media] au0828: set max packets per URB to match Windows driver We had the max packets per URB set to an incredibly low "10" as opposed to the Windows driver which has it as 128. Set the value to match the Windows driver, which will reduce interrupts considerably. This work was sponsored by GetWellNetwork Inc. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/video/au0828/au0828.h') diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index 9905bc4f5f59..4dd8ce7f139e 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -53,7 +53,7 @@ /* Defination for AU0828 USB transfer */ #define AU0828_MAX_ISO_BUFS 12 /* maybe resize this value in the future */ -#define AU0828_ISO_PACKETS_PER_URB 10 +#define AU0828_ISO_PACKETS_PER_URB 128 #define AU0828_MIN_BUF 4 #define AU0828_DEF_BUF 8 -- cgit v1.2.3 From 6e04b7b95a5bd2da0aa5df05fc09a1f0d6615666 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Wed, 1 Sep 2010 22:03:43 -0300 Subject: [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 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-video.c | 61 +++++++++++++++++++++++++++++++ drivers/media/video/au0828/au0828.h | 2 + 2 files changed, 63 insertions(+) (limited to 'drivers/media/video/au0828/au0828.h') 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; -- cgit v1.2.3 From 78ca500559b5a4f16a95c198b3e7bdfac8455bf8 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sat, 9 Oct 2010 14:43:53 -0300 Subject: [media] au0828: fixes for timeout on no video The first pass of fixes to cause the driver to continue streaming even when there is no video arriving over the ITU656 bus were not adequate. Continue the work from the previous patch. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/au0828-video.c | 82 ++++++++++++++++++++----------- drivers/media/video/au0828/au0828.h | 2 + 2 files changed, 56 insertions(+), 28 deletions(-) (limited to 'drivers/media/video/au0828/au0828.h') diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 8d11e544c879..cf8fc6274713 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -122,6 +122,7 @@ static void au0828_irq_callback(struct urb *urb) { struct au0828_dmaqueue *dma_q = urb->context; struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq); + unsigned long flags = 0; int rc, i; switch (urb->status) { @@ -139,9 +140,9 @@ static void au0828_irq_callback(struct urb *urb) } /* Copy data from URB */ - spin_lock(&dev->slock); + spin_lock_irqsave(&dev->slock, flags); rc = dev->isoc_ctl.isoc_copy(dev, urb); - spin_unlock(&dev->slock); + spin_unlock_irqrestore(&dev->slock, flags); /* Reset urb buffers */ for (i = 0; i < urb->number_of_packets; i++) { @@ -312,9 +313,6 @@ 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, @@ -332,9 +330,6 @@ 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)); } /* @@ -603,6 +598,15 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb) outp = NULL; else outp = videobuf_to_vmalloc(&buf->vb); + + /* As long as isoc traffic is arriving, keep + resetting the timer */ + 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 (buf != NULL) { @@ -922,18 +926,22 @@ void au0828_vid_buffer_timeout(unsigned long data) struct au0828_dmaqueue *dma_q = &dev->vidq; struct au0828_buffer *buf; unsigned char *vid_data; + unsigned long flags = 0; - spin_lock(&dev->slock); + spin_lock_irqsave(&dev->slock, flags); 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); } + get_next_buf(dma_q, &buf); + + if (dev->vid_timeout_running == 1) + mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); - spin_unlock(&dev->slock); + spin_unlock_irqrestore(&dev->slock, flags); } void au0828_vbi_buffer_timeout(unsigned long data) @@ -942,18 +950,21 @@ void au0828_vbi_buffer_timeout(unsigned long data) struct au0828_dmaqueue *dma_q = &dev->vbiq; struct au0828_buffer *buf; unsigned char *vbi_data; + unsigned long flags = 0; - spin_lock(&dev->slock); + spin_lock_irqsave(&dev->slock, flags); 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); } + vbi_get_next_buf(dma_q, &buf); - spin_unlock(&dev->slock); + if (dev->vbi_timeout_running == 1) + mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); + spin_unlock_irqrestore(&dev->slock, flags); } @@ -1026,16 +1037,6 @@ 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; } @@ -1046,13 +1047,19 @@ 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); + /* Cancel timeout thread in case they didn't call streamoff */ + dev->vid_timeout_running = 0; + del_timer_sync(&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); + /* Cancel timeout thread in case they didn't call streamoff */ + dev->vbi_timeout_running = 0; + del_timer_sync(&dev->vbi_timeout); + videobuf_stop(&fh->vb_vbiq); res_free(fh, AU0828_RESOURCE_VBI); } @@ -1638,10 +1645,15 @@ static int vidioc_streamon(struct file *file, void *priv, v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); } - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { rc = videobuf_streamon(&fh->vb_vidq); - else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + dev->vid_timeout_running = 1; + mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); + } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { rc = videobuf_streamon(&fh->vb_vbiq); + dev->vbi_timeout_running = 1; + mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); + } return rc; } @@ -1668,6 +1680,9 @@ static int vidioc_streamoff(struct file *file, void *priv, fh, type, fh->resources, dev->resources); if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + dev->vid_timeout_running = 0; + del_timer_sync(&dev->vid_timeout); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); rc = au0828_stream_interrupt(dev); if (rc != 0) @@ -1682,6 +1697,9 @@ static int vidioc_streamoff(struct file *file, void *priv, videobuf_streamoff(&fh->vb_vidq); res_free(fh, AU0828_RESOURCE_VIDEO); } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { + dev->vbi_timeout_running = 0; + del_timer_sync(&dev->vbi_timeout); + videobuf_streamoff(&fh->vb_vbiq); res_free(fh, AU0828_RESOURCE_VBI); } @@ -1901,6 +1919,14 @@ int au0828_analog_register(struct au0828_dev *dev, INIT_LIST_HEAD(&dev->vbiq.active); INIT_LIST_HEAD(&dev->vbiq.queued); + dev->vid_timeout.function = au0828_vid_buffer_timeout; + dev->vid_timeout.data = (unsigned long) dev; + init_timer(&dev->vid_timeout); + + dev->vbi_timeout.function = au0828_vbi_buffer_timeout; + dev->vbi_timeout.data = (unsigned long) dev; + init_timer(&dev->vbi_timeout); + dev->width = NTSC_STD_W; dev->height = NTSC_STD_H; dev->field_size = dev->width * dev->height; diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h index ef46a889da20..9cde35321824 100644 --- a/drivers/media/video/au0828/au0828.h +++ b/drivers/media/video/au0828/au0828.h @@ -205,7 +205,9 @@ struct au0828_dev { struct video_device *vdev; struct video_device *vbi_dev; struct timer_list vid_timeout; + int vid_timeout_running; struct timer_list vbi_timeout; + int vbi_timeout_running; int width; int height; int vbi_width; -- cgit v1.2.3