aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/au0828/au0828-video.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/au0828/au0828-video.c')
-rw-r--r--drivers/media/video/au0828/au0828-video.c118
1 files changed, 100 insertions, 18 deletions
diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c
index 162fd5f9d448..e41e4ad5cc40 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++) {
@@ -576,7 +577,7 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
576 p += 4; 577 p += 4;
577 au0828_isocdbg("Video frame %s\n", 578 au0828_isocdbg("Video frame %s\n",
578 (fbyte & 0x40) ? "odd" : "even"); 579 (fbyte & 0x40) ? "odd" : "even");
579 if (!(fbyte & 0x40)) { 580 if (fbyte & 0x40) {
580 /* VBI */ 581 /* VBI */
581 if (vbi_buf != NULL) 582 if (vbi_buf != NULL)
582 vbi_buffer_filled(dev, 583 vbi_buffer_filled(dev,
@@ -597,6 +598,15 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
597 outp = NULL; 598 outp = NULL;
598 else 599 else
599 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));
600 } 610 }
601 611
602 if (buf != NULL) { 612 if (buf != NULL) {
@@ -907,6 +917,57 @@ static int get_ressource(struct au0828_fh *fh)
907 } 917 }
908} 918}
909 919
920/* This function ensures that video frames continue to be delivered even if
921 the ITU-656 input isn't receiving any data (thereby preventing applications
922 such as tvtime from hanging) */
923void au0828_vid_buffer_timeout(unsigned long data)
924{
925 struct au0828_dev *dev = (struct au0828_dev *) data;
926 struct au0828_dmaqueue *dma_q = &dev->vidq;
927 struct au0828_buffer *buf;
928 unsigned char *vid_data;
929 unsigned long flags = 0;
930
931 spin_lock_irqsave(&dev->slock, flags);
932
933 buf = dev->isoc_ctl.buf;
934 if (buf != NULL) {
935 vid_data = videobuf_to_vmalloc(&buf->vb);
936 memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */
937 buffer_filled(dev, dma_q, buf);
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));
943
944 spin_unlock_irqrestore(&dev->slock, flags);
945}
946
947void au0828_vbi_buffer_timeout(unsigned long data)
948{
949 struct au0828_dev *dev = (struct au0828_dev *) data;
950 struct au0828_dmaqueue *dma_q = &dev->vbiq;
951 struct au0828_buffer *buf;
952 unsigned char *vbi_data;
953 unsigned long flags = 0;
954
955 spin_lock_irqsave(&dev->slock, flags);
956
957 buf = dev->isoc_ctl.vbi_buf;
958 if (buf != NULL) {
959 vbi_data = videobuf_to_vmalloc(&buf->vb);
960 memset(vbi_data, 0x00, buf->vb.size);
961 vbi_buffer_filled(dev, dma_q, buf);
962 }
963 vbi_get_next_buf(dma_q, &buf);
964
965 if (dev->vbi_timeout_running == 1)
966 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
967 spin_unlock_irqrestore(&dev->slock, flags);
968}
969
970
910static int au0828_v4l2_open(struct file *filp) 971static int au0828_v4l2_open(struct file *filp)
911{ 972{
912 int ret = 0; 973 int ret = 0;
@@ -976,7 +1037,6 @@ static int au0828_v4l2_open(struct file *filp)
976 V4L2_FIELD_SEQ_TB, 1037 V4L2_FIELD_SEQ_TB,
977 sizeof(struct au0828_buffer), fh, NULL); 1038 sizeof(struct au0828_buffer), fh, NULL);
978 1039
979
980 return ret; 1040 return ret;
981} 1041}
982 1042
@@ -987,11 +1047,19 @@ static int au0828_v4l2_close(struct file *filp)
987 struct au0828_dev *dev = fh->dev; 1047 struct au0828_dev *dev = fh->dev;
988 1048
989 if (res_check(fh, AU0828_RESOURCE_VIDEO)) { 1049 if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
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
990 videobuf_stop(&fh->vb_vidq); 1054 videobuf_stop(&fh->vb_vidq);
991 res_free(fh, AU0828_RESOURCE_VIDEO); 1055 res_free(fh, AU0828_RESOURCE_VIDEO);
992 } 1056 }
993 1057
994 if (res_check(fh, AU0828_RESOURCE_VBI)) { 1058 if (res_check(fh, AU0828_RESOURCE_VBI)) {
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
995 videobuf_stop(&fh->vb_vbiq); 1063 videobuf_stop(&fh->vb_vbiq);
996 res_free(fh, AU0828_RESOURCE_VBI); 1064 res_free(fh, AU0828_RESOURCE_VBI);
997 } 1065 }
@@ -1048,6 +1116,13 @@ static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
1048 if (!res_get(fh, AU0828_RESOURCE_VBI)) 1116 if (!res_get(fh, AU0828_RESOURCE_VBI))
1049 return -EBUSY; 1117 return -EBUSY;
1050 1118
1119 if (dev->vbi_timeout_running == 0) {
1120 /* Handle case where caller tries to read without
1121 calling streamon first */
1122 dev->vbi_timeout_running = 1;
1123 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
1124 }
1125
1051 return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0, 1126 return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
1052 filp->f_flags & O_NONBLOCK); 1127 filp->f_flags & O_NONBLOCK);
1053 } 1128 }
@@ -1577,10 +1652,15 @@ static int vidioc_streamon(struct file *file, void *priv,
1577 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); 1652 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
1578 } 1653 }
1579 1654
1580 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1655 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1581 rc = videobuf_streamon(&fh->vb_vidq); 1656 rc = videobuf_streamon(&fh->vb_vidq);
1582 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) 1657 dev->vid_timeout_running = 1;
1658 mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
1659 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1583 rc = videobuf_streamon(&fh->vb_vbiq); 1660 rc = videobuf_streamon(&fh->vb_vbiq);
1661 dev->vbi_timeout_running = 1;
1662 mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
1663 }
1584 1664
1585 return rc; 1665 return rc;
1586} 1666}
@@ -1607,6 +1687,9 @@ static int vidioc_streamoff(struct file *file, void *priv,
1607 fh, type, fh->resources, dev->resources); 1687 fh, type, fh->resources, dev->resources);
1608 1688
1609 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { 1689 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1690 dev->vid_timeout_running = 0;
1691 del_timer_sync(&dev->vid_timeout);
1692
1610 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); 1693 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
1611 rc = au0828_stream_interrupt(dev); 1694 rc = au0828_stream_interrupt(dev);
1612 if (rc != 0) 1695 if (rc != 0)
@@ -1621,6 +1704,9 @@ static int vidioc_streamoff(struct file *file, void *priv,
1621 videobuf_streamoff(&fh->vb_vidq); 1704 videobuf_streamoff(&fh->vb_vidq);
1622 res_free(fh, AU0828_RESOURCE_VIDEO); 1705 res_free(fh, AU0828_RESOURCE_VIDEO);
1623 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { 1706 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1707 dev->vbi_timeout_running = 0;
1708 del_timer_sync(&dev->vbi_timeout);
1709
1624 videobuf_streamoff(&fh->vb_vbiq); 1710 videobuf_streamoff(&fh->vb_vbiq);
1625 res_free(fh, AU0828_RESOURCE_VBI); 1711 res_free(fh, AU0828_RESOURCE_VBI);
1626 } 1712 }
@@ -1723,15 +1809,6 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1723 return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK); 1809 return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
1724} 1810}
1725 1811
1726#ifdef CONFIG_VIDEO_V4L1_COMPAT
1727static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
1728{
1729 struct au0828_fh *fh = priv;
1730
1731 return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
1732}
1733#endif
1734
1735static struct v4l2_file_operations au0828_v4l_fops = { 1812static struct v4l2_file_operations au0828_v4l_fops = {
1736 .owner = THIS_MODULE, 1813 .owner = THIS_MODULE,
1737 .open = au0828_v4l2_open, 1814 .open = au0828_v4l2_open,
@@ -1775,9 +1852,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
1775 .vidioc_s_register = vidioc_s_register, 1852 .vidioc_s_register = vidioc_s_register,
1776#endif 1853#endif
1777 .vidioc_g_chip_ident = vidioc_g_chip_ident, 1854 .vidioc_g_chip_ident = vidioc_g_chip_ident,
1778#ifdef CONFIG_VIDEO_V4L1_COMPAT
1779 .vidiocgmbuf = vidiocgmbuf,
1780#endif
1781}; 1855};
1782 1856
1783static const struct video_device au0828_video_template = { 1857static const struct video_device au0828_video_template = {
@@ -1840,6 +1914,14 @@ int au0828_analog_register(struct au0828_dev *dev,
1840 INIT_LIST_HEAD(&dev->vbiq.active); 1914 INIT_LIST_HEAD(&dev->vbiq.active);
1841 INIT_LIST_HEAD(&dev->vbiq.queued); 1915 INIT_LIST_HEAD(&dev->vbiq.queued);
1842 1916
1917 dev->vid_timeout.function = au0828_vid_buffer_timeout;
1918 dev->vid_timeout.data = (unsigned long) dev;
1919 init_timer(&dev->vid_timeout);
1920
1921 dev->vbi_timeout.function = au0828_vbi_buffer_timeout;
1922 dev->vbi_timeout.data = (unsigned long) dev;
1923 init_timer(&dev->vbi_timeout);
1924
1843 dev->width = NTSC_STD_W; 1925 dev->width = NTSC_STD_W;
1844 dev->height = NTSC_STD_H; 1926 dev->height = NTSC_STD_H;
1845 dev->field_size = dev->width * dev->height; 1927 dev->field_size = dev->width * dev->height;