diff options
-rw-r--r-- | drivers/media/video/au0828/au0828-video.c | 82 | ||||
-rw-r--r-- | drivers/media/video/au0828/au0828.h | 2 |
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 | ||
320 | static inline void vbi_buffer_filled(struct au0828_dev *dev, | 318 | static 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 | ||
939 | void au0828_vbi_buffer_timeout(unsigned long data) | 947 | void 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; |