summary refs log tree commit diff
path: root/drivers/media/video/cx18/cx18-ioctl.c
diff options
context:
space:
mode:
authorSimon Farnsworth <simon.farnsworth@onelan.co.uk>2011-05-03 08:57:40 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-05-20 09:30:22 -0300
commit1bf5842fe3b61d2dbbced96dbd27ad26fe93444a (patch)
tree26c19327c2668ca8690e3a47b0846f9825beb991 /drivers/media/video/cx18/cx18-ioctl.c
parent81dfea886c73ea36439672b90626a354354dadd2 (diff)
downloadlinux-1bf5842fe3b61d2dbbced96dbd27ad26fe93444a.tar.gz
[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/cx18-ioctl.c')
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c84
1 files changed, 50 insertions, 34 deletions
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 @@
 #include <media/tveeprom.h>
 #include <media/v4l2-chip-ident.h>
 
-static struct v4l2_fmtdesc formats[] = {
-	{ 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
-	  "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 }
-	},
-	{ 1, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED,
-	  "MPEG", V4L2_PIX_FMT_MPEG, { 0, 0, 0, 0 }
-	},
-	{ 2, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
-	  "YUYV 4:2:2", V4L2_PIX_FMT_YUYV, { 0, 0, 0, 0 }
-	},
-};
-
 u16 cx18_service2vbi(int type)
 {
 	switch (type) {
@@ -172,8 +160,12 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
 	pixfmt->priv = 0;
 	if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
 		pixfmt->pixelformat = s->pixelformat;
-		/* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
-		pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
+		/* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+		   UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+		if (s->pixelformat == V4L2_PIX_FMT_HM12)
+			pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
+		else
+			pixfmt->sizeimage = pixfmt->height * 720 * 2;
 		pixfmt->bytesperline = 720;
 	} else {
 		pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
@@ -296,16 +288,15 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
 	w = fmt->fmt.pix.width;
 	h = fmt->fmt.pix.height;
 
-	s->pixelformat = fmt->fmt.pix.pixelformat;
-	s->vbheight = h;
-	s->vbwidth = w;
-
-	if (cx->cxhdl.width == w && cx->cxhdl.height == h)
+	if (cx->cxhdl.width == w && cx->cxhdl.height == h &&
+	    s->pixelformat == fmt->fmt.pix.pixelformat)
 		return 0;
 
 	if (atomic_read(&cx->ana_capturing) > 0)
 		return -EBUSY;
 
+	s->pixelformat = fmt->fmt.pix.pixelformat;
+
 	mbus_fmt.width = cx->cxhdl.width = w;
 	mbus_fmt.height = cx->cxhdl.height = h;
 	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)
 static int cx18_enum_fmt_vid_cap(struct file *file, void *fh,
 					struct v4l2_fmtdesc *fmt)
 {
+	static const struct v4l2_fmtdesc formats[] = {
+		{ 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
+		  "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 }
+		},
+		{ 1, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED,
+		  "MPEG", V4L2_PIX_FMT_MPEG, { 0, 0, 0, 0 }
+		},
+		{ 2, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
+		  "UYVY 4:2:2", V4L2_PIX_FMT_UYVY, { 0, 0, 0, 0 }
+		},
+	};
+
 	if (fmt->index > ARRAY_SIZE(formats) - 1)
 		return -EINVAL;
 	*fmt = formats[fmt->index];
@@ -874,10 +877,12 @@ static int cx18_g_enc_index(struct file *file, void *fh,
 static struct videobuf_queue *cx18_vb_queue(struct cx18_open_id *id)
 {
 	struct videobuf_queue *q = NULL;
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
 
-	switch (id->vb_type) {
+	switch (s->vb_type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		q = &id->vbuf_q;
+		q = &s->vbuf_q;
 		break;
 	case V4L2_BUF_TYPE_VBI_CAPTURE:
 		break;
@@ -895,15 +900,15 @@ static int cx18_streamon(struct file *file, void *priv,
 	struct cx18_stream *s = &cx->streams[id->type];
 
 	/* Start the hardware only if we're the video device */
-	if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-		(id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+	if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
 		return -EINVAL;
 
 	if (id->type != CX18_ENC_STREAM_TYPE_YUV)
 		return -EINVAL;
 
 	/* Establish a buffer timeout */
-	mod_timer(&s->vb_timeout, jiffies + (HZ * 2));
+	mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies);
 
 	return videobuf_streamon(cx18_vb_queue(id));
 }
@@ -912,10 +917,12 @@ static int cx18_streamoff(struct file *file, void *priv,
 	enum v4l2_buf_type type)
 {
 	struct cx18_open_id *id = file->private_data;
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
 
 	/* Start the hardware only if we're the video device */
-	if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-		(id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+	if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
 		return -EINVAL;
 
 	if (id->type != CX18_ENC_STREAM_TYPE_YUV)
@@ -928,9 +935,11 @@ static int cx18_reqbufs(struct file *file, void *priv,
 	struct v4l2_requestbuffers *rb)
 {
 	struct cx18_open_id *id = file->private_data;
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
 
-	if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-		(id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+	if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
 		return -EINVAL;
 
 	return videobuf_reqbufs(cx18_vb_queue(id), rb);
@@ -940,9 +949,11 @@ static int cx18_querybuf(struct file *file, void *priv,
 	struct v4l2_buffer *b)
 {
 	struct cx18_open_id *id = file->private_data;
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
 
-	if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-		(id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+	if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
 		return -EINVAL;
 
 	return videobuf_querybuf(cx18_vb_queue(id), b);
@@ -951,9 +962,11 @@ static int cx18_querybuf(struct file *file, void *priv,
 static int cx18_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 {
 	struct cx18_open_id *id = file->private_data;
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
 
-	if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-		(id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+	if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
 		return -EINVAL;
 
 	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)
 static int cx18_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 {
 	struct cx18_open_id *id = file->private_data;
-	if ((id->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-		(id->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
+
+	if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
 		return -EINVAL;
 
 	return videobuf_dqbuf(cx18_vb_queue(id), b, file->f_flags & O_NONBLOCK);