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 <dheitmueller@kernellabs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
{
struct au0828_dmaqueue *dma_q = urb->context;
struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
{
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) {
int rc, i;
switch (urb->status) {
}
/* Copy data from URB */
}
/* Copy data from URB */
- spin_lock(&dev->slock);
+ spin_lock_irqsave(&dev->slock, flags);
rc = dev->isoc_ctl.isoc_copy(dev, urb);
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++) {
/* Reset urb buffers */
for (i = 0; i < urb->number_of_packets; i++) {
list_del(&buf->vb.queue);
wake_up(&buf->vb.done);
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,
}
static inline void vbi_buffer_filled(struct au0828_dev *dev,
list_del(&buf->vb.queue);
wake_up(&buf->vb.done);
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));
outp = NULL;
else
outp = videobuf_to_vmalloc(&buf->vb);
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));
struct au0828_dmaqueue *dma_q = &dev->vidq;
struct au0828_buffer *buf;
unsigned char *vid_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);
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)
}
void au0828_vbi_buffer_timeout(unsigned long data)
struct au0828_dmaqueue *dma_q = &dev->vbiq;
struct au0828_buffer *buf;
unsigned char *vbi_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);
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);
V4L2_FIELD_SEQ_TB,
sizeof(struct au0828_buffer), fh, NULL);
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);
- }
-
struct au0828_dev *dev = fh->dev;
if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
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)) {
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);
}
videobuf_stop(&fh->vb_vbiq);
res_free(fh, AU0828_RESOURCE_VBI);
}
v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
}
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);
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);
rc = videobuf_streamon(&fh->vb_vbiq);
+ dev->vbi_timeout_running = 1;
+ mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
+ }
fh, type, fh->resources, dev->resources);
if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
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)
v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
rc = au0828_stream_interrupt(dev);
if (rc != 0)
videobuf_streamoff(&fh->vb_vidq);
res_free(fh, AU0828_RESOURCE_VIDEO);
} else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
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);
}
videobuf_streamoff(&fh->vb_vbiq);
res_free(fh, AU0828_RESOURCE_VBI);
}
INIT_LIST_HEAD(&dev->vbiq.active);
INIT_LIST_HEAD(&dev->vbiq.queued);
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;
dev->width = NTSC_STD_W;
dev->height = NTSC_STD_H;
dev->field_size = dev->width * dev->height;
struct video_device *vdev;
struct video_device *vbi_dev;
struct timer_list vid_timeout;
struct video_device *vdev;
struct video_device *vbi_dev;
struct timer_list vid_timeout;
+ int vid_timeout_running;
struct timer_list vbi_timeout;
struct timer_list vbi_timeout;
+ int vbi_timeout_running;
int width;
int height;
int vbi_width;
int width;
int height;
int vbi_width;