Skip to content

Commit

Permalink
[media] au0828: fixes for timeout on no video
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Devin Heitmueller authored and Mauro Carvalho Chehab committed Dec 29, 2010
1 parent 6e04b7b commit 78ca500
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 28 deletions.
82 changes: 54 additions & 28 deletions drivers/media/video/au0828/au0828-video.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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++) {
Expand Down Expand Up @@ -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,
Expand All @@ -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));
}

/*
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
Expand All @@ -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);
}


Expand Down Expand Up @@ -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;
}

Expand All @@ -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);
}
Expand Down Expand Up @@ -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;
}
Expand All @@ -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)
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions drivers/media/video/au0828/au0828.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 78ca500

Please sign in to comment.