diff options
-rw-r--r-- | drivers/media/video/au0828/au0828-video.c | 61 | ||||
-rw-r--r-- | drivers/media/video/au0828/au0828.h | 2 |
2 files changed, 63 insertions, 0 deletions
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, | |||
312 | 312 | ||
313 | list_del(&buf->vb.queue); | 313 | list_del(&buf->vb.queue); |
314 | wake_up(&buf->vb.done); | 314 | wake_up(&buf->vb.done); |
315 | |||
316 | /* Reset the timer for "no video condition" */ | ||
317 | mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); | ||
315 | } | 318 | } |
316 | 319 | ||
317 | static inline void vbi_buffer_filled(struct au0828_dev *dev, | 320 | static inline void vbi_buffer_filled(struct au0828_dev *dev, |
@@ -329,6 +332,9 @@ static inline void vbi_buffer_filled(struct au0828_dev *dev, | |||
329 | 332 | ||
330 | list_del(&buf->vb.queue); | 333 | list_del(&buf->vb.queue); |
331 | wake_up(&buf->vb.done); | 334 | wake_up(&buf->vb.done); |
335 | |||
336 | /* Reset the timer for "no video condition" */ | ||
337 | mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10)); | ||
332 | } | 338 | } |
333 | 339 | ||
334 | /* | 340 | /* |
@@ -907,6 +913,50 @@ static int get_ressource(struct au0828_fh *fh) | |||
907 | } | 913 | } |
908 | } | 914 | } |
909 | 915 | ||
916 | /* This function ensures that video frames continue to be delivered even if | ||
917 | the ITU-656 input isn't receiving any data (thereby preventing applications | ||
918 | such as tvtime from hanging) */ | ||
919 | void au0828_vid_buffer_timeout(unsigned long data) | ||
920 | { | ||
921 | struct au0828_dev *dev = (struct au0828_dev *) data; | ||
922 | struct au0828_dmaqueue *dma_q = &dev->vidq; | ||
923 | struct au0828_buffer *buf; | ||
924 | unsigned char *vid_data; | ||
925 | |||
926 | spin_lock(&dev->slock); | ||
927 | |||
928 | buf = dev->isoc_ctl.buf; | ||
929 | if (buf != NULL) { | ||
930 | vid_data = videobuf_to_vmalloc(&buf->vb); | ||
931 | memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */ | ||
932 | buffer_filled(dev, dma_q, buf); | ||
933 | get_next_buf(dma_q, &buf); | ||
934 | } | ||
935 | |||
936 | spin_unlock(&dev->slock); | ||
937 | } | ||
938 | |||
939 | void au0828_vbi_buffer_timeout(unsigned long data) | ||
940 | { | ||
941 | struct au0828_dev *dev = (struct au0828_dev *) data; | ||
942 | struct au0828_dmaqueue *dma_q = &dev->vbiq; | ||
943 | struct au0828_buffer *buf; | ||
944 | unsigned char *vbi_data; | ||
945 | |||
946 | spin_lock(&dev->slock); | ||
947 | |||
948 | buf = dev->isoc_ctl.vbi_buf; | ||
949 | if (buf != NULL) { | ||
950 | vbi_data = videobuf_to_vmalloc(&buf->vb); | ||
951 | memset(vbi_data, 0x00, buf->vb.size); | ||
952 | vbi_buffer_filled(dev, dma_q, buf); | ||
953 | vbi_get_next_buf(dma_q, &buf); | ||
954 | } | ||
955 | |||
956 | spin_unlock(&dev->slock); | ||
957 | } | ||
958 | |||
959 | |||
910 | static int au0828_v4l2_open(struct file *filp) | 960 | static int au0828_v4l2_open(struct file *filp) |
911 | { | 961 | { |
912 | int ret = 0; | 962 | int ret = 0; |
@@ -976,6 +1026,15 @@ static int au0828_v4l2_open(struct file *filp) | |||
976 | V4L2_FIELD_SEQ_TB, | 1026 | V4L2_FIELD_SEQ_TB, |
977 | sizeof(struct au0828_buffer), fh, NULL); | 1027 | sizeof(struct au0828_buffer), fh, NULL); |
978 | 1028 | ||
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 | } | ||
979 | 1038 | ||
980 | return ret; | 1039 | return ret; |
981 | } | 1040 | } |
@@ -987,11 +1046,13 @@ static int au0828_v4l2_close(struct file *filp) | |||
987 | struct au0828_dev *dev = fh->dev; | 1046 | struct au0828_dev *dev = fh->dev; |
988 | 1047 | ||
989 | if (res_check(fh, AU0828_RESOURCE_VIDEO)) { | 1048 | if (res_check(fh, AU0828_RESOURCE_VIDEO)) { |
1049 | del_timer(&dev->vid_timeout); | ||
990 | videobuf_stop(&fh->vb_vidq); | 1050 | videobuf_stop(&fh->vb_vidq); |
991 | res_free(fh, AU0828_RESOURCE_VIDEO); | 1051 | res_free(fh, AU0828_RESOURCE_VIDEO); |
992 | } | 1052 | } |
993 | 1053 | ||
994 | if (res_check(fh, AU0828_RESOURCE_VBI)) { | 1054 | if (res_check(fh, AU0828_RESOURCE_VBI)) { |
1055 | del_timer(&dev->vbi_timeout); | ||
995 | videobuf_stop(&fh->vb_vbiq); | 1056 | videobuf_stop(&fh->vb_vbiq); |
996 | res_free(fh, AU0828_RESOURCE_VBI); | 1057 | res_free(fh, AU0828_RESOURCE_VBI); |
997 | } | 1058 | } |
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 { | |||
204 | unsigned int resources; /* resources in use */ | 204 | unsigned int resources; /* resources in use */ |
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; | ||
208 | struct timer_list vbi_timeout; | ||
207 | int width; | 209 | int width; |
208 | int height; | 210 | int height; |
209 | int vbi_width; | 211 | int vbi_width; |