aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18
diff options
context:
space:
mode:
authorSimon Farnsworth <simon.farnsworth@onelan.co.uk>2011-05-03 07:57:40 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-05-20 08:30:22 -0400
commit1bf5842fe3b61d2dbbced96dbd27ad26fe93444a (patch)
tree26c19327c2668ca8690e3a47b0846f9825beb991 /drivers/media/video/cx18
parent81dfea886c73ea36439672b90626a354354dadd2 (diff)
[media] cx18: Clean up mmap() support for raw YUV
The initial version of this patch (commit d5976931639176bb6777755d96b9f8d959f79e9e) had some issues: * It didn't correctly calculate the size of the YUV buffer for 4:2:2, resulting in capture sometimes being offset by 1/3rd of a picture. * There were a lot of variables duplicating information the driver already knew, which have been removed. * There was an in-kernel format conversion - libv4l can do this one, and is the right place to do format conversions anyway. * Some magic numbers weren't properly explained. Fix all these issues, leaving just the move from videobuf to videobuf2 to do. Signed-off-by: Simon Farnsworth <simon.farnsworth@onelan.co.uk> Acked-by: Andy Walls <awalls@md.metrocast.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx18')
-rw-r--r--drivers/media/video/cx18/Kconfig1
-rw-r--r--drivers/media/video/cx18/cx18-driver.h8
-rw-r--r--drivers/media/video/cx18/cx18-fileops.c167
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c84
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.c17
-rw-r--r--drivers/media/video/cx18/cx18-streams.c160
6 files changed, 225 insertions, 212 deletions
diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig
index 9c232022403a..53b3c7702573 100644
--- a/drivers/media/video/cx18/Kconfig
+++ b/drivers/media/video/cx18/Kconfig
@@ -2,7 +2,6 @@ config VIDEO_CX18
2 tristate "Conexant cx23418 MPEG encoder support" 2 tristate "Conexant cx23418 MPEG encoder support"
3 depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL 3 depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL
4 select I2C_ALGOBIT 4 select I2C_ALGOBIT
5 select VIDEOBUF_DVB
6 select VIDEOBUF_VMALLOC 5 select VIDEOBUF_VMALLOC
7 depends on RC_CORE 6 depends on RC_CORE
8 select VIDEO_TUNER 7 select VIDEO_TUNER
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index 70e1e0401645..086427288de8 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -412,11 +412,11 @@ struct cx18_stream {
412 u32 pixelformat; 412 u32 pixelformat;
413 struct list_head vb_capture; /* video capture queue */ 413 struct list_head vb_capture; /* video capture queue */
414 spinlock_t vb_lock; 414 spinlock_t vb_lock;
415 struct v4l2_framebuffer fbuf;
416 v4l2_std_id tvnorm; /* selected tv norm */
417 struct timer_list vb_timeout; 415 struct timer_list vb_timeout;
418 int vbwidth; 416
419 int vbheight; 417 struct videobuf_queue vbuf_q;
418 spinlock_t vbuf_q_lock; /* Protect vbuf_q */
419 enum v4l2_buf_type vb_type;
420}; 420};
421 421
422struct cx18_videobuf_buffer { 422struct cx18_videobuf_buffer {
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index c74eafd67f98..6609222eccf8 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -598,9 +598,9 @@ ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
598 if (rc) 598 if (rc)
599 return rc; 599 return rc;
600 600
601 if ((id->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) && 601 if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
602 (id->type == CX18_ENC_STREAM_TYPE_YUV)) { 602 (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
603 return videobuf_read_stream(&id->vbuf_q, buf, count, pos, 0, 603 return videobuf_read_stream(&s->vbuf_q, buf, count, pos, 0,
604 filp->f_flags & O_NONBLOCK); 604 filp->f_flags & O_NONBLOCK);
605 } 605 }
606 606
@@ -629,9 +629,13 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
629 CX18_DEBUG_FILE("Encoder poll started capture\n"); 629 CX18_DEBUG_FILE("Encoder poll started capture\n");
630 } 630 }
631 631
632 if ((id->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) && 632 if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
633 (id->type == CX18_ENC_STREAM_TYPE_YUV)) { 633 (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
634 return videobuf_poll_stream(filp, &id->vbuf_q, wait); 634 int videobuf_poll = videobuf_poll_stream(filp, &s->vbuf_q, wait);
635 if (eof && videobuf_poll == POLLERR)
636 return POLLHUP;
637 else
638 return videobuf_poll;
635 } 639 }
636 640
637 /* add stream's waitq to the poll list */ 641 /* add stream's waitq to the poll list */
@@ -652,7 +656,7 @@ int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
652 struct cx18_stream *s = &cx->streams[id->type]; 656 struct cx18_stream *s = &cx->streams[id->type];
653 int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags); 657 int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
654 658
655 if ((id->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) && 659 if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
656 (id->type == CX18_ENC_STREAM_TYPE_YUV)) { 660 (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
657 661
658 /* Start a capture if there is none */ 662 /* Start a capture if there is none */
@@ -668,10 +672,10 @@ int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
668 s->name, rc); 672 s->name, rc);
669 return -EINVAL; 673 return -EINVAL;
670 } 674 }
671 CX18_DEBUG_FILE("Encoder poll started capture\n"); 675 CX18_DEBUG_FILE("Encoder mmap started capture\n");
672 } 676 }
673 677
674 return videobuf_mmap_mapper(&id->vbuf_q, vma); 678 return videobuf_mmap_mapper(&s->vbuf_q, vma);
675 } 679 }
676 680
677 return -EINVAL; 681 return -EINVAL;
@@ -788,142 +792,6 @@ int cx18_v4l2_close(struct file *filp)
788 return 0; 792 return 0;
789} 793}
790 794
791void cx18_dma_free(struct videobuf_queue *q,
792 struct cx18_stream *s, struct cx18_videobuf_buffer *buf)
793{
794 videobuf_waiton(q, &buf->vb, 0, 0);
795 videobuf_vmalloc_free(&buf->vb);
796 buf->vb.state = VIDEOBUF_NEEDS_INIT;
797}
798
799static int cx18_prepare_buffer(struct videobuf_queue *q,
800 struct cx18_stream *s,
801 struct cx18_videobuf_buffer *buf,
802 u32 pixelformat,
803 unsigned int width, unsigned int height,
804 enum v4l2_field field)
805{
806 int rc = 0;
807
808 /* check settings */
809 buf->bytes_used = 0;
810
811 if ((width < 48) || (height < 32))
812 return -EINVAL;
813
814 buf->vb.size = (width * height * 16 /*fmt->depth*/) >> 3;
815 if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))
816 return -EINVAL;
817
818 /* alloc + fill struct (if changed) */
819 if (buf->vb.width != width || buf->vb.height != height ||
820 buf->vb.field != field || s->pixelformat != pixelformat ||
821 buf->tvnorm != s->tvnorm) {
822
823 buf->vb.width = width;
824 buf->vb.height = height;
825 buf->vb.field = field;
826 buf->tvnorm = s->tvnorm;
827 s->pixelformat = pixelformat;
828
829 cx18_dma_free(q, s, buf);
830 }
831
832 if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))
833 return -EINVAL;
834
835 if (buf->vb.field == 0)
836 buf->vb.field = V4L2_FIELD_INTERLACED;
837
838 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
839 buf->vb.width = width;
840 buf->vb.height = height;
841 buf->vb.field = field;
842 buf->tvnorm = s->tvnorm;
843 s->pixelformat = pixelformat;
844
845 rc = videobuf_iolock(q, &buf->vb, &s->fbuf);
846 if (rc != 0)
847 goto fail;
848 }
849 buf->vb.state = VIDEOBUF_PREPARED;
850 return 0;
851
852fail:
853 cx18_dma_free(q, s, buf);
854 return rc;
855
856}
857
858#define VB_MIN_BUFFERS 32
859#define VB_MIN_BUFSIZE 0x208000
860
861static int buffer_setup(struct videobuf_queue *q,
862 unsigned int *count, unsigned int *size)
863{
864 struct cx18_open_id *id = q->priv_data;
865 struct cx18 *cx = id->cx;
866 struct cx18_stream *s = &cx->streams[id->type];
867
868 *size = 2 * s->vbwidth * s->vbheight;
869 if (*count == 0)
870 *count = VB_MIN_BUFFERS;
871
872 while (*size * *count > VB_MIN_BUFFERS * VB_MIN_BUFSIZE)
873 (*count)--;
874
875 q->field = V4L2_FIELD_INTERLACED;
876 q->last = V4L2_FIELD_INTERLACED;
877
878 return 0;
879}
880
881static int buffer_prepare(struct videobuf_queue *q,
882 struct videobuf_buffer *vb,
883 enum v4l2_field field)
884{
885 struct cx18_videobuf_buffer *buf =
886 container_of(vb, struct cx18_videobuf_buffer, vb);
887 struct cx18_open_id *id = q->priv_data;
888 struct cx18 *cx = id->cx;
889 struct cx18_stream *s = &cx->streams[id->type];
890
891 return cx18_prepare_buffer(q, s, buf, s->pixelformat,
892 s->vbwidth, s->vbheight, field);
893}
894
895static void buffer_release(struct videobuf_queue *q,
896 struct videobuf_buffer *vb)
897{
898 struct cx18_videobuf_buffer *buf =
899 container_of(vb, struct cx18_videobuf_buffer, vb);
900 struct cx18_open_id *id = q->priv_data;
901 struct cx18 *cx = id->cx;
902 struct cx18_stream *s = &cx->streams[id->type];
903
904 cx18_dma_free(q, s, buf);
905}
906
907static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
908{
909 struct cx18_videobuf_buffer *buf =
910 container_of(vb, struct cx18_videobuf_buffer, vb);
911 struct cx18_open_id *id = q->priv_data;
912 struct cx18 *cx = id->cx;
913 struct cx18_stream *s = &cx->streams[id->type];
914
915 buf->vb.state = VIDEOBUF_QUEUED;
916
917 list_add_tail(&buf->vb.queue, &s->vb_capture);
918}
919
920static struct videobuf_queue_ops cx18_videobuf_qops = {
921 .buf_setup = buffer_setup,
922 .buf_prepare = buffer_prepare,
923 .buf_queue = buffer_queue,
924 .buf_release = buffer_release,
925};
926
927static int cx18_serialized_open(struct cx18_stream *s, struct file *filp) 795static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
928{ 796{
929 struct cx18 *cx = s->cx; 797 struct cx18 *cx = s->cx;
@@ -942,8 +810,8 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
942 item->cx = cx; 810 item->cx = cx;
943 item->type = s->type; 811 item->type = s->type;
944 812
945 spin_lock_init(&item->s_lock); 813 spin_lock_init(&s->vbuf_q_lock);
946 item->vb_type = 0; 814 s->vb_type = 0;
947 815
948 item->open_id = cx->open_id++; 816 item->open_id = cx->open_id++;
949 filp->private_data = &item->fh; 817 filp->private_data = &item->fh;
@@ -979,15 +847,6 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
979 /* Done! Unmute and continue. */ 847 /* Done! Unmute and continue. */
980 cx18_unmute(cx); 848 cx18_unmute(cx);
981 } 849 }
982 if (item->type == CX18_ENC_STREAM_TYPE_YUV) {
983 item->vb_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
984 videobuf_queue_vmalloc_init(&item->vbuf_q, &cx18_videobuf_qops,
985 &cx->pci_dev->dev, &item->s_lock,
986 V4L2_BUF_TYPE_VIDEO_CAPTURE,
987 V4L2_FIELD_INTERLACED,
988 sizeof(struct cx18_videobuf_buffer),
989 item, &cx->serialize_lock);
990 }
991 v4l2_fh_add(&item->fh); 850 v4l2_fh_add(&item->fh);
992 return 0; 851 return 0;
993} 852}
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index 777d7265c8a8..1933d4d11bf2 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -41,18 +41,6 @@
41#include <media/tveeprom.h> 41#include <media/tveeprom.h>
42#include <media/v4l2-chip-ident.h> 42#include <media/v4l2-chip-ident.h>
43 43
44static struct v4l2_fmtdesc formats[] = {
45 { 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
46 "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 }
47 },
48 { 1, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED,
49 "MPEG", V4L2_PIX_FMT_MPEG, { 0, 0, 0, 0 }
50 },
51 { 2, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
52 "YUYV 4:2:2", V4L2_PIX_FMT_YUYV, { 0, 0, 0, 0 }
53 },
54};
55
56u16 cx18_service2vbi(int type) 44u16 cx18_service2vbi(int type)
57{ 45{
58 switch (type) { 46 switch (type) {
@@ -172,8 +160,12 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
172 pixfmt->priv = 0; 160 pixfmt->priv = 0;
173 if (id->type == CX18_ENC_STREAM_TYPE_YUV) { 161 if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
174 pixfmt->pixelformat = s->pixelformat; 162 pixfmt->pixelformat = s->pixelformat;
175 /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */ 163 /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
176 pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2; 164 UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
165 if (s->pixelformat == V4L2_PIX_FMT_HM12)
166 pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
167 else
168 pixfmt->sizeimage = pixfmt->height * 720 * 2;
177 pixfmt->bytesperline = 720; 169 pixfmt->bytesperline = 720;
178 } else { 170 } else {
179 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; 171 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
@@ -296,16 +288,15 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
296 w = fmt->fmt.pix.width; 288 w = fmt->fmt.pix.width;
297 h = fmt->fmt.pix.height; 289 h = fmt->fmt.pix.height;
298 290
299 s->pixelformat = fmt->fmt.pix.pixelformat; 291 if (cx->cxhdl.width == w && cx->cxhdl.height == h &&
300 s->vbheight = h; 292 s->pixelformat == fmt->fmt.pix.pixelformat)
301 s->vbwidth = w;
302
303 if (cx->cxhdl.width == w && cx->cxhdl.height == h)
304 return 0; 293 return 0;
305 294
306 if (atomic_read(&cx->ana_capturing) > 0) 295 if (atomic_read(&cx->ana_capturing) > 0)
307 return -EBUSY; 296 return -EBUSY;
308 297
298 s->pixelformat = fmt->fmt.pix.pixelformat;
299
309 mbus_fmt.width = cx->cxhdl.width = w; 300 mbus_fmt.width = cx->cxhdl.width = w;
310 mbus_fmt.height = cx->cxhdl.height = h; 301 mbus_fmt.height = cx->cxhdl.height = h;
311 mbus_fmt.code = V4L2_MBUS_FMT_FIXED; 302 mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
@@ -557,6 +548,18 @@ static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
557static int cx18_enum_fmt_vid_cap(struct file *file, void *fh, 548static int cx18_enum_fmt_vid_cap(struct file *file, void *fh,
558 struct v4l2_fmtdesc *fmt) 549 struct v4l2_fmtdesc *fmt)
559{ 550{
551 static const struct v4l2_fmtdesc formats[] = {
552 { 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
553 "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 }
554 },
555 { 1, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED,
556 "MPEG", V4L2_PIX_FMT_MPEG, { 0, 0, 0, 0 }
557 },
558 { 2, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
559 "UYVY 4:2:2", V4L2_PIX_FMT_UYVY, { 0, 0, 0, 0 }
560 },
561 };
562
560 if (fmt->index > ARRAY_SIZE(formats) - 1) 563 if (fmt->index > ARRAY_SIZE(formats) - 1)
561 return -EINVAL; 564 return -EINVAL;
562 *fmt = formats[fmt->index]; 565 *fmt = formats[fmt->index];
@@ -874,10 +877,12 @@ static int cx18_g_enc_index(struct file *file, void *fh,
874static struct videobuf_queue *cx18_vb_queue(struct cx18_open_id *id) 877static struct videobuf_queue *cx18_vb_queue(struct cx18_open_id *id)
875{ 878{
876 struct videobuf_queue *q = NULL; 879 struct videobuf_queue *q = NULL;
880 struct cx18 *cx = id->cx;
881 struct cx18_stream *s = &cx->streams[id->type];
877 882
878 switch (id->vb_type) { 883 switch (s->vb_type) {
879 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 884 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
880 q = &id->vbuf_q; 885 q = &s->vbuf_q;
881 break; 886 break;
882 case V4L2_BUF_TYPE_VBI_CAPTURE: 887 case V4L2_BUF_TYPE_VBI_CAPTURE:
883 break; 888 break;
@@ -895,15 +900,15 @@ static int cx18_streamon(struct file *file, void *priv,
895 struct cx18_stream *s = &cx->streams[id->type]; 900 struct cx18_stream *s = &cx->streams[id->type];
896 901
897 /* Start the hardware only if we're the video device */ 902 /* Start the hardware only if we're the video device */
898 if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && 903 if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
899 (id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) 904 (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
900 return -EINVAL; 905 return -EINVAL;
901 906
902 if (id->type != CX18_ENC_STREAM_TYPE_YUV) 907 if (id->type != CX18_ENC_STREAM_TYPE_YUV)
903 return -EINVAL; 908 return -EINVAL;
904 909
905 /* Establish a buffer timeout */ 910 /* Establish a buffer timeout */
906 mod_timer(&s->vb_timeout, jiffies + (HZ * 2)); 911 mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies);
907 912
908 return videobuf_streamon(cx18_vb_queue(id)); 913 return videobuf_streamon(cx18_vb_queue(id));
909} 914}
@@ -912,10 +917,12 @@ static int cx18_streamoff(struct file *file, void *priv,
912 enum v4l2_buf_type type) 917 enum v4l2_buf_type type)
913{ 918{
914 struct cx18_open_id *id = file->private_data; 919 struct cx18_open_id *id = file->private_data;
920 struct cx18 *cx = id->cx;
921 struct cx18_stream *s = &cx->streams[id->type];
915 922
916 /* Start the hardware only if we're the video device */ 923 /* Start the hardware only if we're the video device */
917 if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && 924 if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
918 (id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) 925 (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
919 return -EINVAL; 926 return -EINVAL;
920 927
921 if (id->type != CX18_ENC_STREAM_TYPE_YUV) 928 if (id->type != CX18_ENC_STREAM_TYPE_YUV)
@@ -928,9 +935,11 @@ static int cx18_reqbufs(struct file *file, void *priv,
928 struct v4l2_requestbuffers *rb) 935 struct v4l2_requestbuffers *rb)
929{ 936{
930 struct cx18_open_id *id = file->private_data; 937 struct cx18_open_id *id = file->private_data;
938 struct cx18 *cx = id->cx;
939 struct cx18_stream *s = &cx->streams[id->type];
931 940
932 if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && 941 if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
933 (id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) 942 (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
934 return -EINVAL; 943 return -EINVAL;
935 944
936 return videobuf_reqbufs(cx18_vb_queue(id), rb); 945 return videobuf_reqbufs(cx18_vb_queue(id), rb);
@@ -940,9 +949,11 @@ static int cx18_querybuf(struct file *file, void *priv,
940 struct v4l2_buffer *b) 949 struct v4l2_buffer *b)
941{ 950{
942 struct cx18_open_id *id = file->private_data; 951 struct cx18_open_id *id = file->private_data;
952 struct cx18 *cx = id->cx;
953 struct cx18_stream *s = &cx->streams[id->type];
943 954
944 if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && 955 if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
945 (id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) 956 (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
946 return -EINVAL; 957 return -EINVAL;
947 958
948 return videobuf_querybuf(cx18_vb_queue(id), b); 959 return videobuf_querybuf(cx18_vb_queue(id), b);
@@ -951,9 +962,11 @@ static int cx18_querybuf(struct file *file, void *priv,
951static int cx18_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) 962static int cx18_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
952{ 963{
953 struct cx18_open_id *id = file->private_data; 964 struct cx18_open_id *id = file->private_data;
965 struct cx18 *cx = id->cx;
966 struct cx18_stream *s = &cx->streams[id->type];
954 967
955 if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && 968 if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
956 (id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) 969 (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
957 return -EINVAL; 970 return -EINVAL;
958 971
959 return videobuf_qbuf(cx18_vb_queue(id), b); 972 return videobuf_qbuf(cx18_vb_queue(id), b);
@@ -962,8 +975,11 @@ static int cx18_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
962static int cx18_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) 975static int cx18_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
963{ 976{
964 struct cx18_open_id *id = file->private_data; 977 struct cx18_open_id *id = file->private_data;
965 if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && 978 struct cx18 *cx = id->cx;
966 (id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE)) 979 struct cx18_stream *s = &cx->streams[id->type];
980
981 if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
982 (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
967 return -EINVAL; 983 return -EINVAL;
968 984
969 return videobuf_dqbuf(cx18_vb_queue(id), b, file->f_flags & O_NONBLOCK); 985 return videobuf_dqbuf(cx18_vb_queue(id), b, file->f_flags & O_NONBLOCK);
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
index d4d88738d893..5ecae931ac36 100644
--- a/drivers/media/video/cx18/cx18-mailbox.c
+++ b/drivers/media/video/cx18/cx18-mailbox.c
@@ -177,7 +177,7 @@ static void cx18_mdl_send_to_videobuf(struct cx18_stream *s,
177 if (list_empty(&s->vb_capture)) 177 if (list_empty(&s->vb_capture))
178 goto out; 178 goto out;
179 179
180 vb_buf = list_entry(s->vb_capture.next, struct cx18_videobuf_buffer, 180 vb_buf = list_first_entry(&s->vb_capture, struct cx18_videobuf_buffer,
181 vb.queue); 181 vb.queue);
182 182
183 p = videobuf_to_vmalloc(&vb_buf->vb); 183 p = videobuf_to_vmalloc(&vb_buf->vb);
@@ -202,25 +202,14 @@ static void cx18_mdl_send_to_videobuf(struct cx18_stream *s,
202 vb_buf->bytes_used = 0; 202 vb_buf->bytes_used = 0;
203 } 203 }
204 204
205 /* */
206 if (dispatch) { 205 if (dispatch) {
207 206 ktime_get_ts(&vb_buf->vb.ts);
208 if (s->pixelformat == V4L2_PIX_FMT_YUYV) {
209 /* UYVY to YUYV */
210 for (i = 0; i < (720 * 480 * 2); i += 2) {
211 u = *(p + i);
212 *(p + i) = *(p + i + 1);
213 *(p + i + 1) = u;
214 }
215 }
216
217 do_gettimeofday(&vb_buf->vb.ts);
218 list_del(&vb_buf->vb.queue); 207 list_del(&vb_buf->vb.queue);
219 vb_buf->vb.state = VIDEOBUF_DONE; 208 vb_buf->vb.state = VIDEOBUF_DONE;
220 wake_up(&vb_buf->vb.done); 209 wake_up(&vb_buf->vb.done);
221 } 210 }
222 211
223 mod_timer(&s->vb_timeout, jiffies + (HZ / 10)); 212 mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies);
224 213
225out: 214out:
226 spin_unlock(&s->vb_lock); 215 spin_unlock(&s->vb_lock);
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index eeb455a8b726..3995af71b820 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -98,6 +98,141 @@ static struct {
98 }, 98 },
99}; 99};
100 100
101
102void cx18_dma_free(struct videobuf_queue *q,
103 struct cx18_stream *s, struct cx18_videobuf_buffer *buf)
104{
105 videobuf_waiton(q, &buf->vb, 0, 0);
106 videobuf_vmalloc_free(&buf->vb);
107 buf->vb.state = VIDEOBUF_NEEDS_INIT;
108}
109
110static int cx18_prepare_buffer(struct videobuf_queue *q,
111 struct cx18_stream *s,
112 struct cx18_videobuf_buffer *buf,
113 u32 pixelformat,
114 unsigned int width, unsigned int height,
115 enum v4l2_field field)
116{
117 struct cx18 *cx = s->cx;
118 int rc = 0;
119
120 /* check settings */
121 buf->bytes_used = 0;
122
123 if ((width < 48) || (height < 32))
124 return -EINVAL;
125
126 buf->vb.size = (width * height * 2);
127 if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))
128 return -EINVAL;
129
130 /* alloc + fill struct (if changed) */
131 if (buf->vb.width != width || buf->vb.height != height ||
132 buf->vb.field != field || s->pixelformat != pixelformat ||
133 buf->tvnorm != cx->std) {
134
135 buf->vb.width = width;
136 buf->vb.height = height;
137 buf->vb.field = field;
138 buf->tvnorm = cx->std;
139 s->pixelformat = pixelformat;
140
141 cx18_dma_free(q, s, buf);
142 }
143
144 if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))
145 return -EINVAL;
146
147 if (buf->vb.field == 0)
148 buf->vb.field = V4L2_FIELD_INTERLACED;
149
150 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
151 buf->vb.width = width;
152 buf->vb.height = height;
153 buf->vb.field = field;
154 buf->tvnorm = cx->std;
155 s->pixelformat = pixelformat;
156
157 rc = videobuf_iolock(q, &buf->vb, NULL);
158 if (rc != 0)
159 goto fail;
160 }
161 buf->vb.state = VIDEOBUF_PREPARED;
162 return 0;
163
164fail:
165 cx18_dma_free(q, s, buf);
166 return rc;
167
168}
169
170/* VB_MIN_BUFSIZE is lcm(1440 * 480, 1440 * 576)
171 1440 is a single line of 4:2:2 YUV at 720 luma samples wide
172*/
173#define VB_MIN_BUFFERS 32
174#define VB_MIN_BUFSIZE 4147200
175
176static int buffer_setup(struct videobuf_queue *q,
177 unsigned int *count, unsigned int *size)
178{
179 struct cx18_stream *s = q->priv_data;
180 struct cx18 *cx = s->cx;
181
182 *size = 2 * cx->cxhdl.width * cx->cxhdl.height;
183 if (*count == 0)
184 *count = VB_MIN_BUFFERS;
185
186 while (*size * *count > VB_MIN_BUFFERS * VB_MIN_BUFSIZE)
187 (*count)--;
188
189 q->field = V4L2_FIELD_INTERLACED;
190 q->last = V4L2_FIELD_INTERLACED;
191
192 return 0;
193}
194
195static int buffer_prepare(struct videobuf_queue *q,
196 struct videobuf_buffer *vb,
197 enum v4l2_field field)
198{
199 struct cx18_videobuf_buffer *buf =
200 container_of(vb, struct cx18_videobuf_buffer, vb);
201 struct cx18_stream *s = q->priv_data;
202 struct cx18 *cx = s->cx;
203
204 return cx18_prepare_buffer(q, s, buf, s->pixelformat,
205 cx->cxhdl.width, cx->cxhdl.height, field);
206}
207
208static void buffer_release(struct videobuf_queue *q,
209 struct videobuf_buffer *vb)
210{
211 struct cx18_videobuf_buffer *buf =
212 container_of(vb, struct cx18_videobuf_buffer, vb);
213 struct cx18_stream *s = q->priv_data;
214
215 cx18_dma_free(q, s, buf);
216}
217
218static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
219{
220 struct cx18_videobuf_buffer *buf =
221 container_of(vb, struct cx18_videobuf_buffer, vb);
222 struct cx18_stream *s = q->priv_data;
223
224 buf->vb.state = VIDEOBUF_QUEUED;
225
226 list_add_tail(&buf->vb.queue, &s->vb_capture);
227}
228
229static struct videobuf_queue_ops cx18_videobuf_qops = {
230 .buf_setup = buffer_setup,
231 .buf_prepare = buffer_prepare,
232 .buf_queue = buffer_queue,
233 .buf_release = buffer_release,
234};
235
101static void cx18_stream_init(struct cx18 *cx, int type) 236static void cx18_stream_init(struct cx18 *cx, int type)
102{ 237{
103 struct cx18_stream *s = &cx->streams[type]; 238 struct cx18_stream *s = &cx->streams[type];
@@ -139,9 +274,18 @@ static void cx18_stream_init(struct cx18 *cx, int type)
139 s->vb_timeout.data = (unsigned long)s; 274 s->vb_timeout.data = (unsigned long)s;
140 init_timer(&s->vb_timeout); 275 init_timer(&s->vb_timeout);
141 spin_lock_init(&s->vb_lock); 276 spin_lock_init(&s->vb_lock);
142 277 if (type == CX18_ENC_STREAM_TYPE_YUV) {
143 /* Assume the previous pixel default */ 278 s->vb_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
144 s->pixelformat = V4L2_PIX_FMT_HM12; 279 videobuf_queue_vmalloc_init(&s->vbuf_q, &cx18_videobuf_qops,
280 &cx->pci_dev->dev, &s->vbuf_q_lock,
281 V4L2_BUF_TYPE_VIDEO_CAPTURE,
282 V4L2_FIELD_INTERLACED,
283 sizeof(struct cx18_videobuf_buffer),
284 s, &cx->serialize_lock);
285
286 /* Assume the previous pixel default */
287 s->pixelformat = V4L2_PIX_FMT_HM12;
288 }
145} 289}
146 290
147static int cx18_prep_dev(struct cx18 *cx, int type) 291static int cx18_prep_dev(struct cx18 *cx, int type)
@@ -382,6 +526,9 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
382 if (vdev == NULL) 526 if (vdev == NULL)
383 continue; 527 continue;
384 528
529 if (type == CX18_ENC_STREAM_TYPE_YUV)
530 videobuf_mmap_free(&cx->streams[type].vbuf_q);
531
385 cx18_stream_free(&cx->streams[type]); 532 cx18_stream_free(&cx->streams[type]);
386 533
387 /* Unregister or release device */ 534 /* Unregister or release device */
@@ -591,7 +738,10 @@ static void cx18_stream_configure_mdls(struct cx18_stream *s)
591 * Set the MDL size to the exact size needed for one frame. 738 * Set the MDL size to the exact size needed for one frame.
592 * Use enough buffers per MDL to cover the MDL size 739 * Use enough buffers per MDL to cover the MDL size
593 */ 740 */
594 s->mdl_size = 720 * s->cx->cxhdl.height * 3 / 2; 741 if (s->pixelformat == V4L2_PIX_FMT_HM12)
742 s->mdl_size = 720 * s->cx->cxhdl.height * 3 / 2;
743 else
744 s->mdl_size = 720 * s->cx->cxhdl.height * 2;
595 s->bufs_per_mdl = s->mdl_size / s->buf_size; 745 s->bufs_per_mdl = s->mdl_size / s->buf_size;
596 if (s->mdl_size % s->buf_size) 746 if (s->mdl_size % s->buf_size)
597 s->bufs_per_mdl++; 747 s->bufs_per_mdl++;
@@ -744,7 +894,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
744 * rather than the default HM12 Macroblovk 4:2:0 support. 894 * rather than the default HM12 Macroblovk 4:2:0 support.
745 */ 895 */
746 if (captype == CAPTURE_CHANNEL_TYPE_YUV) { 896 if (captype == CAPTURE_CHANNEL_TYPE_YUV) {
747 if (s->pixelformat == V4L2_PIX_FMT_YUYV) 897 if (s->pixelformat == V4L2_PIX_FMT_UYVY)
748 cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2, 898 cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2,
749 s->handle, 1); 899 s->handle, 1);
750 else 900 else