aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@kernellabs.com>2010-10-09 13:43:53 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-12-29 05:16:34 -0500
commit78ca500559b5a4f16a95c198b3e7bdfac8455bf8 (patch)
tree8b8c826cf436b5cbdb0d586dda7abcfa4f596768
parent6e04b7b95a5bd2da0aa5df05fc09a1f0d6615666 (diff)
[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 <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/au0828/au0828-video.c82
-rw-r--r--drivers/media/video/au0828/au0828.h2
2 files changed, 56 insertions, 28 deletions
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)
122{ 122{
123 struct au0828_dmaqueue *dma_q = urb->context; 123 struct au0828_dmaqueue *dma_q = urb->context;
124 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq); 124 struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
125 unsigned long flags = 0;
125 int rc, i; 126 int rc, i;
126 127
127 switch (urb->status) { 128 switch (urb->status) {
@@ -139,9 +140,9 @@ static void au0828_irq_callback(struct urb *urb)
139 } 140 }
140 141
141 /* Copy data from URB */ 142 /* Copy data from URB */
142 spin_lock(&dev->slock); 143 spin_lock_irqsave(&dev->slock, flags);
143 rc = dev->isoc_ctl.isoc_copy(dev, urb); 144 rc = dev->isoc_ctl.isoc_copy(dev, urb);
144 spin_unlock(&dev->slock); 145 spin_unlock_irqrestore(&dev->slock, flags);
145 146
146 /* Reset urb buffers */ 147 /* Reset urb buffers */
147 for (i = 0; i < urb->number_of_packets; i++) { 148 for (i = 0; i < urb->number_of_packets; i++) {
@@ -312,9 +313,6 @@ static inline void buffer_filled(struct au0828_dev *dev,
312 313
313 list_del(&buf->vb.queue); 314 list_del(&buf->vb.queue);
314 wake_up(&buf->vb.done); 315 wake_up(&buf->vb.done);
315
316 /* Reset the timer for "no video condition" */
317 mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
318} 316}
319 317
320static inline void vbi_buffer_filled(struct au0828_dev *dev, 318static inline void vbi_buffer_filled(struct au0828_dev *dev,
@@ -332,9 +330,6 @@ static inline void vbi_buffer_filled(struct au0828_dev *dev,
332 330
333 list_del(&buf->vb.queue); 331 list_del(&buf->vb.queue);
334 wake_up(&buf->vb.done); 332 wake_up(&buf->vb.done);
335
336 /* Reset the timer for "no video condition" */
337 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
338} 333}
339 334
340/* 335/*
@@ -603,6 +598,15 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
603 outp = NULL; 598 outp = NULL;
604 else 599 else
605 outp = videobuf_to_vmalloc(&buf->vb); 600 outp = videobuf_to_vmalloc(&buf->vb);
601
602 /* As long as isoc traffic is arriving, keep
603 resetting the timer */
604 if (dev->vid_timeout_running)
605 mod_timer(&dev->vid_timeout,
606 jiffies + (HZ / 10));
607 if (dev->vbi_timeout_running)
608 mod_timer(&dev->vbi_timeout,
609 jiffies + (HZ / 10));
606 } 610 }
607 611
608 if (buf != NULL) { 612 if (buf != NULL) {
@@ -922,18 +926,22 @@ void au0828_vid_buffer_timeout(unsigned long data)
922 struct au0828_dmaqueue *dma_q = &dev->vidq; 926 struct au0828_dmaqueue *dma_q = &dev->vidq;
923 struct au0828_buffer *buf; 927 struct au0828_buffer *buf;
924 unsigned char *vid_data; 928 unsigned char *vid_data;
929 unsigned long flags = 0;
925 930
926 spin_lock(&dev->slock); 931 spin_lock_irqsave(&dev->slock, flags);
927 932
928 buf = dev->isoc_ctl.buf; 933 buf = dev->isoc_ctl.buf;
929 if (buf != NULL) { 934 if (buf != NULL) {
930 vid_data = videobuf_to_vmalloc(&buf->vb); 935 vid_data = videobuf_to_vmalloc(&buf->vb);
931 memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */ 936 memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */
932 buffer_filled(dev, dma_q, buf); 937 buffer_filled(dev, dma_q, buf);
933 get_next_buf(dma_q, &buf);
934 } 938 }
939 get_next_buf(dma_q, &buf);
940
941 if (dev->vid_timeout_running == 1)
942 mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
935 943
936 spin_unlock(&dev->slock); 944 spin_unlock_irqrestore(&dev->slock, flags);
937} 945}
938 946
939void au0828_vbi_buffer_timeout(unsigned long data) 947void au0828_vbi_buffer_timeout(unsigned long data)
@@ -942,18 +950,21 @@ void au0828_vbi_buffer_timeout(unsigned long data)
942 struct au0828_dmaqueue *dma_q = &dev->vbiq; 950 struct au0828_dmaqueue *dma_q = &dev->vbiq;
943 struct au0828_buffer *buf; 951 struct au0828_buffer *buf;
944 unsigned char *vbi_data; 952 unsigned char *vbi_data;
953 unsigned long flags = 0;
945 954
946 spin_lock(&dev->slock); 955 spin_lock_irqsave(&dev->slock, flags);
947 956
948 buf = dev->isoc_ctl.vbi_buf; 957 buf = dev->isoc_ctl.vbi_buf;
949 if (buf != NULL) { 958 if (buf != NULL) {
950 vbi_data = videobuf_to_vmalloc(&buf->vb); 959 vbi_data = videobuf_to_vmalloc(&buf->vb);
951 memset(vbi_data, 0x00, buf->vb.size); 960 memset(vbi_data, 0x00, buf->vb.size);
952 vbi_buffer_filled(dev, dma_q, buf); 961 vbi_buffer_filled(dev, dma_q, buf);
953 vbi_get_next_buf(dma_q, &buf);
954 } 962 }
963 vbi_get_next_buf(dma_q, &buf);
955 964
956 spin_unlock(&dev->slock); 965 if (dev->vbi_timeout_running == 1)
966 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
967 spin_unlock_irqrestore(&dev->slock, flags);
957} 968}
958 969
959 970
@@ -1026,16 +1037,6 @@ static int au0828_v4l2_open(struct file *filp)
1026 V4L2_FIELD_SEQ_TB, 1037 V4L2_FIELD_SEQ_TB,
1027 sizeof(struct au0828_buffer), fh, NULL); 1038 sizeof(struct au0828_buffer), fh, NULL);
1028 1039
1029 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1030 dev->vid_timeout.function = au0828_vid_buffer_timeout;
1031 dev->vid_timeout.data = (unsigned long) dev;
1032 init_timer(&dev->vid_timeout);
1033 } else {
1034 dev->vbi_timeout.function = au0828_vbi_buffer_timeout;
1035 dev->vbi_timeout.data = (unsigned long) dev;
1036 init_timer(&dev->vbi_timeout);
1037 }
1038
1039 return ret; 1040 return ret;
1040} 1041}
1041 1042
@@ -1046,13 +1047,19 @@ static int au0828_v4l2_close(struct file *filp)
1046 struct au0828_dev *dev = fh->dev; 1047 struct au0828_dev *dev = fh->dev;
1047 1048
1048 if (res_check(fh, AU0828_RESOURCE_VIDEO)) { 1049 if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
1049 del_timer(&dev->vid_timeout); 1050 /* Cancel timeout thread in case they didn't call streamoff */
1051 dev->vid_timeout_running = 0;
1052 del_timer_sync(&dev->vid_timeout);
1053
1050 videobuf_stop(&fh->vb_vidq); 1054 videobuf_stop(&fh->vb_vidq);
1051 res_free(fh, AU0828_RESOURCE_VIDEO); 1055 res_free(fh, AU0828_RESOURCE_VIDEO);
1052 } 1056 }
1053 1057
1054 if (res_check(fh, AU0828_RESOURCE_VBI)) { 1058 if (res_check(fh, AU0828_RESOURCE_VBI)) {
1055 del_timer(&dev->vbi_timeout); 1059 /* Cancel timeout thread in case they didn't call streamoff */
1060 dev->vbi_timeout_running = 0;
1061 del_timer_sync(&dev->vbi_timeout);
1062
1056 videobuf_stop(&fh->vb_vbiq); 1063 videobuf_stop(&fh->vb_vbiq);
1057 res_free(fh, AU0828_RESOURCE_VBI); 1064 res_free(fh, AU0828_RESOURCE_VBI);
1058 } 1065 }
@@ -1638,10 +1645,15 @@ static int vidioc_streamon(struct file *file, void *priv,
1638 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); 1645 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
1639 } 1646 }
1640 1647
1641 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1648 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1642 rc = videobuf_streamon(&fh->vb_vidq); 1649 rc = videobuf_streamon(&fh->vb_vidq);
1643 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) 1650 dev->vid_timeout_running = 1;
1651 mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
1652 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1644 rc = videobuf_streamon(&fh->vb_vbiq); 1653 rc = videobuf_streamon(&fh->vb_vbiq);
1654 dev->vbi_timeout_running = 1;
1655 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
1656 }
1645 1657
1646 return rc; 1658 return rc;
1647} 1659}
@@ -1668,6 +1680,9 @@ static int vidioc_streamoff(struct file *file, void *priv,
1668 fh, type, fh->resources, dev->resources); 1680 fh, type, fh->resources, dev->resources);
1669 1681
1670 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { 1682 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1683 dev->vid_timeout_running = 0;
1684 del_timer_sync(&dev->vid_timeout);
1685
1671 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); 1686 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
1672 rc = au0828_stream_interrupt(dev); 1687 rc = au0828_stream_interrupt(dev);
1673 if (rc != 0) 1688 if (rc != 0)
@@ -1682,6 +1697,9 @@ static int vidioc_streamoff(struct file *file, void *priv,
1682 videobuf_streamoff(&fh->vb_vidq); 1697 videobuf_streamoff(&fh->vb_vidq);
1683 res_free(fh, AU0828_RESOURCE_VIDEO); 1698 res_free(fh, AU0828_RESOURCE_VIDEO);
1684 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { 1699 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1700 dev->vbi_timeout_running = 0;
1701 del_timer_sync(&dev->vbi_timeout);
1702
1685 videobuf_streamoff(&fh->vb_vbiq); 1703 videobuf_streamoff(&fh->vb_vbiq);
1686 res_free(fh, AU0828_RESOURCE_VBI); 1704 res_free(fh, AU0828_RESOURCE_VBI);
1687 } 1705 }
@@ -1901,6 +1919,14 @@ int au0828_analog_register(struct au0828_dev *dev,
1901 INIT_LIST_HEAD(&dev->vbiq.active); 1919 INIT_LIST_HEAD(&dev->vbiq.active);
1902 INIT_LIST_HEAD(&dev->vbiq.queued); 1920 INIT_LIST_HEAD(&dev->vbiq.queued);
1903 1921
1922 dev->vid_timeout.function = au0828_vid_buffer_timeout;
1923 dev->vid_timeout.data = (unsigned long) dev;
1924 init_timer(&dev->vid_timeout);
1925
1926 dev->vbi_timeout.function = au0828_vbi_buffer_timeout;
1927 dev->vbi_timeout.data = (unsigned long) dev;
1928 init_timer(&dev->vbi_timeout);
1929
1904 dev->width = NTSC_STD_W; 1930 dev->width = NTSC_STD_W;
1905 dev->height = NTSC_STD_H; 1931 dev->height = NTSC_STD_H;
1906 dev->field_size = dev->width * dev->height; 1932 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 {
205 struct video_device *vdev; 205 struct video_device *vdev;
206 struct video_device *vbi_dev; 206 struct video_device *vbi_dev;
207 struct timer_list vid_timeout; 207 struct timer_list vid_timeout;
208 int vid_timeout_running;
208 struct timer_list vbi_timeout; 209 struct timer_list vbi_timeout;
210 int vbi_timeout_running;
209 int width; 211 int width;
210 int height; 212 int height;
211 int vbi_width; 213 int vbi_width;