Re: [git:v4l-dvb/for_v2.6.40] [media] cx18: mmap() support for raw YUV video capture

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Em 02-05-2011 16:11, Hans Verkuil escreveu:
> NACK.
> 
> For two reasons: first of all it is not signed off by Andy Walls, the cx18
> maintainer. I know he has had other things on his plate recently which is
> probably why he hasn't had the chance to review this.
> 
> Secondly, while doing a quick scan myself I noticed that this code does a
> conversion from UYVY format to YUYV *in the driver*. Format conversion is
> not allowed in the kernel, we have libv4lconvert for that. So at the minimum
> this conversion code must be removed first.

Patch is there at the ML since Apr, 6 and nobody acked/nacked it. If you or
andy were against it, why none of you commented it there?

Now that the patch were committed, I won't revert it without a very good reason.

With respect to the "conversion from UYVY format to YUYV", a simple patch could
fix it, instead of removing the entire patchset.

Steven/Simon,
could you please work on such change?

Thanks,
Mauro.

> 
> Regards,
> 
> 	Hans
> 
> On Monday, May 02, 2011 19:17:57 Mauro Carvalho Chehab wrote:
>> This is an automatic generated email to let you know that the following patch were queued at the 
>> http://git.linuxtv.org/media_tree.git tree:
>>
>> Subject: [media] cx18: mmap() support for raw YUV video capture
>> Author:  Steven Toth <stoth@xxxxxxxxxxxxxx>
>> Date:    Wed Apr 6 08:32:56 2011 -0300
>>
>> Add support for mmap method streaming of raw YUV video on cx18-based
>> hardware, in addition to the existing support for read() streaming of
>> raw YUV and MPEG-2 encoded video.
>>
>> [simon.farnsworth@xxxxxxxxxxxx: I forward-ported this from Steven's original work,
>>  done under contract to ONELAN. The original code is at
>>  http://www.kernellabs.com/hg/~stoth/cx18-videobuf]
>>
>> Signed-off-by: Steven Toth <stoth@xxxxxxxxxxxxxx>
>> Signed-off-by: Simon Farnsworth <simon.farnsworth@xxxxxxxxxxxx>
>> Signed-off-by: Mauro Carvalho Chehab <mchehab@xxxxxxxxxx>
>>
>>  drivers/media/video/cx18/Kconfig        |    2 +
>>  drivers/media/video/cx18/cx18-driver.h  |   25 ++++
>>  drivers/media/video/cx18/cx18-fileops.c |  214 +++++++++++++++++++++++++++++++
>>  drivers/media/video/cx18/cx18-fileops.h |    2 +
>>  drivers/media/video/cx18/cx18-ioctl.c   |  136 ++++++++++++++++++--
>>  drivers/media/video/cx18/cx18-mailbox.c |   70 ++++++++++
>>  drivers/media/video/cx18/cx18-streams.c |   23 ++++
>>  drivers/media/video/cx18/cx23418.h      |    6 +
>>  8 files changed, 466 insertions(+), 12 deletions(-)
>>
>> ---
>>
>> http://git.linuxtv.org/media_tree.git?a=commitdiff;h=fa8f1381764d83222333cb67b8d93b9cb1605bf3
>>
>> diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig
>> index d788ad6..9c23202 100644
>> --- a/drivers/media/video/cx18/Kconfig
>> +++ b/drivers/media/video/cx18/Kconfig
>> @@ -2,6 +2,8 @@ config VIDEO_CX18
>>  	tristate "Conexant cx23418 MPEG encoder support"
>>  	depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL
>>  	select I2C_ALGOBIT
>> +	select VIDEOBUF_DVB
>> +	select VIDEOBUF_VMALLOC
>>  	depends on RC_CORE
>>  	select VIDEO_TUNER
>>  	select VIDEO_TVEEPROM
>> diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
>> index b86a740..70e1e04 100644
>> --- a/drivers/media/video/cx18/cx18-driver.h
>> +++ b/drivers/media/video/cx18/cx18-driver.h
>> @@ -65,6 +65,10 @@
>>  #include "dvb_net.h"
>>  #include "dvbdev.h"
>>  
>> +/* Videobuf / YUV support */
>> +#include <media/videobuf-core.h>
>> +#include <media/videobuf-vmalloc.h>
>> +
>>  #ifndef CONFIG_PCI
>>  #  error "This driver requires kernel PCI support."
>>  #endif
>> @@ -403,6 +407,23 @@ struct cx18_stream {
>>  	struct cx18_queue q_idle;	/* idle - not in rotation */
>>  
>>  	struct work_struct out_work_order;
>> +
>> +	/* Videobuf for YUV video */
>> +	u32 pixelformat;
>> +	struct list_head vb_capture;    /* video capture queue */
>> +	spinlock_t vb_lock;
>> +	struct v4l2_framebuffer fbuf;
>> +	v4l2_std_id tvnorm; /* selected tv norm */
>> +	struct timer_list vb_timeout;
>> +	int vbwidth;
>> +	int vbheight;
>> +};
>> +
>> +struct cx18_videobuf_buffer {
>> +	/* Common video buffer sub-system struct */
>> +	struct videobuf_buffer vb;
>> +	v4l2_std_id tvnorm; /* selected tv norm */
>> +	u32 bytes_used;
>>  };
>>  
>>  struct cx18_open_id {
>> @@ -410,6 +431,10 @@ struct cx18_open_id {
>>  	u32 open_id;
>>  	int type;
>>  	struct cx18 *cx;
>> +
>> +	struct videobuf_queue vbuf_q;
>> +	spinlock_t s_lock; /* Protect vbuf_q */
>> +	enum v4l2_buf_type vb_type;
>>  };
>>  
>>  static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh)
>> diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
>> index e9802d9..c74eafd 100644
>> --- a/drivers/media/video/cx18/cx18-fileops.c
>> +++ b/drivers/media/video/cx18/cx18-fileops.c
>> @@ -597,6 +597,13 @@ ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
>>  	mutex_unlock(&cx->serialize_lock);
>>  	if (rc)
>>  		return rc;
>> +
>> +	if ((id->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
>> +		(id->type == CX18_ENC_STREAM_TYPE_YUV)) {
>> +		return videobuf_read_stream(&id->vbuf_q, buf, count, pos, 0,
>> +			filp->f_flags & O_NONBLOCK);
>> +	}
>> +
>>  	return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
>>  }
>>  
>> @@ -622,6 +629,11 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
>>  		CX18_DEBUG_FILE("Encoder poll started capture\n");
>>  	}
>>  
>> +	if ((id->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
>> +		(id->type == CX18_ENC_STREAM_TYPE_YUV)) {
>> +		return videobuf_poll_stream(filp, &id->vbuf_q, wait);
>> +	}
>> +
>>  	/* add stream's waitq to the poll list */
>>  	CX18_DEBUG_HI_FILE("Encoder poll\n");
>>  	poll_wait(filp, &s->waitq, wait);
>> @@ -633,6 +645,58 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
>>  	return 0;
>>  }
>>  
>> +int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
>> +{
>> +	struct cx18_open_id *id = file->private_data;
>> +	struct cx18 *cx = id->cx;
>> +	struct cx18_stream *s = &cx->streams[id->type];
>> +	int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
>> +
>> +	if ((id->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
>> +		(id->type == CX18_ENC_STREAM_TYPE_YUV)) {
>> +
>> +		/* Start a capture if there is none */
>> +		if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
>> +			int rc;
>> +
>> +			mutex_lock(&cx->serialize_lock);
>> +			rc = cx18_start_capture(id);
>> +			mutex_unlock(&cx->serialize_lock);
>> +			if (rc) {
>> +				CX18_DEBUG_INFO(
>> +					"Could not start capture for %s (%d)\n",
>> +					s->name, rc);
>> +				return -EINVAL;
>> +			}
>> +			CX18_DEBUG_FILE("Encoder poll started capture\n");
>> +		}
>> +
>> +		return videobuf_mmap_mapper(&id->vbuf_q, vma);
>> +	}
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +void cx18_vb_timeout(unsigned long data)
>> +{
>> +	struct cx18_stream *s = (struct cx18_stream *)data;
>> +	struct cx18_videobuf_buffer *buf;
>> +	unsigned long flags;
>> +
>> +	/* Return all of the buffers in error state, so the vbi/vid inode
>> +	 * can return from blocking.
>> +	 */
>> +	spin_lock_irqsave(&s->vb_lock, flags);
>> +	while (!list_empty(&s->vb_capture)) {
>> +		buf = list_entry(s->vb_capture.next,
>> +			struct cx18_videobuf_buffer, vb.queue);
>> +		list_del(&buf->vb.queue);
>> +		buf->vb.state = VIDEOBUF_ERROR;
>> +		wake_up(&buf->vb.done);
>> +	}
>> +	spin_unlock_irqrestore(&s->vb_lock, flags);
>> +}
>> +
>>  void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
>>  {
>>  	struct cx18 *cx = id->cx;
>> @@ -716,12 +780,150 @@ int cx18_v4l2_close(struct file *filp)
>>  		cx18_release_stream(s);
>>  	} else {
>>  		cx18_stop_capture(id, 0);
>> +		if (id->type == CX18_ENC_STREAM_TYPE_YUV)
>> +			videobuf_mmap_free(&id->vbuf_q);
>>  	}
>>  	kfree(id);
>>  	mutex_unlock(&cx->serialize_lock);
>>  	return 0;
>>  }
>>  
>> +void cx18_dma_free(struct videobuf_queue *q,
>> +	struct cx18_stream *s, struct cx18_videobuf_buffer *buf)
>> +{
>> +	videobuf_waiton(q, &buf->vb, 0, 0);
>> +	videobuf_vmalloc_free(&buf->vb);
>> +	buf->vb.state = VIDEOBUF_NEEDS_INIT;
>> +}
>> +
>> +static int cx18_prepare_buffer(struct videobuf_queue *q,
>> +	struct cx18_stream *s,
>> +	struct cx18_videobuf_buffer *buf,
>> +	u32 pixelformat,
>> +	unsigned int width, unsigned int height,
>> +	enum v4l2_field field)
>> +{
>> +	int rc = 0;
>> +
>> +	/* check settings */
>> +	buf->bytes_used = 0;
>> +
>> +	if ((width  < 48) || (height < 32))
>> +		return -EINVAL;
>> +
>> +	buf->vb.size = (width * height * 16 /*fmt->depth*/) >> 3;
>> +	if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))
>> +		return -EINVAL;
>> +
>> +	/* alloc + fill struct (if changed) */
>> +	if (buf->vb.width != width || buf->vb.height != height ||
>> +	    buf->vb.field != field || s->pixelformat != pixelformat ||
>> +	    buf->tvnorm != s->tvnorm) {
>> +
>> +		buf->vb.width  = width;
>> +		buf->vb.height = height;
>> +		buf->vb.field  = field;
>> +		buf->tvnorm    = s->tvnorm;
>> +		s->pixelformat = pixelformat;
>> +
>> +		cx18_dma_free(q, s, buf);
>> +	}
>> +
>> +	if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))
>> +		return -EINVAL;
>> +
>> +	if (buf->vb.field == 0)
>> +		buf->vb.field = V4L2_FIELD_INTERLACED;
>> +
>> +	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
>> +		buf->vb.width  = width;
>> +		buf->vb.height = height;
>> +		buf->vb.field  = field;
>> +		buf->tvnorm    = s->tvnorm;
>> +		s->pixelformat = pixelformat;
>> +
>> +		rc = videobuf_iolock(q, &buf->vb, &s->fbuf);
>> +		if (rc != 0)
>> +			goto fail;
>> +	}
>> +	buf->vb.state = VIDEOBUF_PREPARED;
>> +	return 0;
>> +
>> +fail:
>> +	cx18_dma_free(q, s, buf);
>> +	return rc;
>> +
>> +}
>> +
>> +#define VB_MIN_BUFFERS 32
>> +#define VB_MIN_BUFSIZE 0x208000
>> +
>> +static int buffer_setup(struct videobuf_queue *q,
>> +	unsigned int *count, unsigned int *size)
>> +{
>> +	struct cx18_open_id *id = q->priv_data;
>> +	struct cx18 *cx = id->cx;
>> +	struct cx18_stream *s = &cx->streams[id->type];
>> +
>> +	*size = 2 * s->vbwidth * s->vbheight;
>> +	if (*count == 0)
>> +		*count = VB_MIN_BUFFERS;
>> +
>> +	while (*size * *count > VB_MIN_BUFFERS * VB_MIN_BUFSIZE)
>> +		(*count)--;
>> +
>> +	q->field = V4L2_FIELD_INTERLACED;
>> +	q->last = V4L2_FIELD_INTERLACED;
>> +
>> +	return 0;
>> +}
>> +
>> +static int buffer_prepare(struct videobuf_queue *q,
>> +	struct videobuf_buffer *vb,
>> +	enum v4l2_field field)
>> +{
>> +	struct cx18_videobuf_buffer *buf =
>> +		container_of(vb, struct cx18_videobuf_buffer, vb);
>> +	struct cx18_open_id *id = q->priv_data;
>> +	struct cx18 *cx = id->cx;
>> +	struct cx18_stream *s = &cx->streams[id->type];
>> +
>> +	return cx18_prepare_buffer(q, s, buf, s->pixelformat,
>> +		s->vbwidth, s->vbheight, field);
>> +}
>> +
>> +static void buffer_release(struct videobuf_queue *q,
>> +	struct videobuf_buffer *vb)
>> +{
>> +	struct cx18_videobuf_buffer *buf =
>> +		container_of(vb, struct cx18_videobuf_buffer, vb);
>> +	struct cx18_open_id *id = q->priv_data;
>> +	struct cx18 *cx = id->cx;
>> +	struct cx18_stream *s = &cx->streams[id->type];
>> +
>> +	cx18_dma_free(q, s, buf);
>> +}
>> +
>> +static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
>> +{
>> +	struct cx18_videobuf_buffer *buf =
>> +		container_of(vb, struct cx18_videobuf_buffer, vb);
>> +	struct cx18_open_id *id = q->priv_data;
>> +	struct cx18 *cx = id->cx;
>> +	struct cx18_stream *s = &cx->streams[id->type];
>> +
>> +	buf->vb.state = VIDEOBUF_QUEUED;
>> +
>> +	list_add_tail(&buf->vb.queue, &s->vb_capture);
>> +}
>> +
>> +static struct videobuf_queue_ops cx18_videobuf_qops = {
>> +	.buf_setup    = buffer_setup,
>> +	.buf_prepare  = buffer_prepare,
>> +	.buf_queue    = buffer_queue,
>> +	.buf_release  = buffer_release,
>> +};
>> +
>>  static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
>>  {
>>  	struct cx18 *cx = s->cx;
>> @@ -740,6 +942,9 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
>>  	item->cx = cx;
>>  	item->type = s->type;
>>  
>> +	spin_lock_init(&item->s_lock);
>> +	item->vb_type = 0;
>> +
>>  	item->open_id = cx->open_id++;
>>  	filp->private_data = &item->fh;
>>  
>> @@ -774,6 +979,15 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
>>  		/* Done! Unmute and continue. */
>>  		cx18_unmute(cx);
>>  	}
>> +	if (item->type == CX18_ENC_STREAM_TYPE_YUV) {
>> +		item->vb_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
>> +		videobuf_queue_vmalloc_init(&item->vbuf_q, &cx18_videobuf_qops,
>> +			&cx->pci_dev->dev, &item->s_lock,
>> +			V4L2_BUF_TYPE_VIDEO_CAPTURE,
>> +			V4L2_FIELD_INTERLACED,
>> +			sizeof(struct cx18_videobuf_buffer),
>> +			item, &cx->serialize_lock);
>> +	}
>>  	v4l2_fh_add(&item->fh);
>>  	return 0;
>>  }
>> diff --git a/drivers/media/video/cx18/cx18-fileops.h b/drivers/media/video/cx18/cx18-fileops.h
>> index 5c8fcb8..b9e5110 100644
>> --- a/drivers/media/video/cx18/cx18-fileops.h
>> +++ b/drivers/media/video/cx18/cx18-fileops.h
>> @@ -33,6 +33,8 @@ int cx18_start_capture(struct cx18_open_id *id);
>>  void cx18_stop_capture(struct cx18_open_id *id, int gop_end);
>>  void cx18_mute(struct cx18 *cx);
>>  void cx18_unmute(struct cx18 *cx);
>> +int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma);
>> +void cx18_vb_timeout(unsigned long data);
>>  
>>  /* Shared with cx18-alsa module */
>>  int cx18_claim_stream(struct cx18_open_id *id, int type);
>> diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
>> index 4f041c0..777d726 100644
>> --- a/drivers/media/video/cx18/cx18-ioctl.c
>> +++ b/drivers/media/video/cx18/cx18-ioctl.c
>> @@ -41,6 +41,18 @@
>>  #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) {
>> @@ -150,6 +162,7 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
>>  {
>>  	struct cx18_open_id *id = fh2id(fh);
>>  	struct cx18 *cx = id->cx;
>> +	struct cx18_stream *s = &cx->streams[id->type];
>>  	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
>>  
>>  	pixfmt->width = cx->cxhdl.width;
>> @@ -158,7 +171,7 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
>>  	pixfmt->field = V4L2_FIELD_INTERLACED;
>>  	pixfmt->priv = 0;
>>  	if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
>> -		pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
>> +		pixfmt->pixelformat = s->pixelformat;
>>  		/* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
>>  		pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
>>  		pixfmt->bytesperline = 720;
>> @@ -237,7 +250,6 @@ static int cx18_try_fmt_vid_cap(struct file *file, void *fh,
>>  	h = min(h, cx->is_50hz ? 576 : 480);
>>  	h = max(h, min_h);
>>  
>> -	cx18_g_fmt_vid_cap(file, fh, fmt);
>>  	fmt->fmt.pix.width = w;
>>  	fmt->fmt.pix.height = h;
>>  	return 0;
>> @@ -274,6 +286,7 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
>>  	struct cx18_open_id *id = fh2id(fh);
>>  	struct cx18 *cx = id->cx;
>>  	struct v4l2_mbus_framefmt mbus_fmt;
>> +	struct cx18_stream *s = &cx->streams[id->type];
>>  	int ret;
>>  	int w, h;
>>  
>> @@ -283,6 +296,10 @@ 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)
>>  		return 0;
>>  
>> @@ -540,16 +557,7 @@ 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 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 }
>> -		}
>> -	};
>> -
>> -	if (fmt->index > 1)
>> +	if (fmt->index > ARRAY_SIZE(formats) - 1)
>>  		return -EINVAL;
>>  	*fmt = formats[fmt->index];
>>  	return 0;
>> @@ -863,6 +871,104 @@ static int cx18_g_enc_index(struct file *file, void *fh,
>>  	return 0;
>>  }
>>  
>> +static struct videobuf_queue *cx18_vb_queue(struct cx18_open_id *id)
>> +{
>> +	struct videobuf_queue *q = NULL;
>> +
>> +	switch (id->vb_type) {
>> +	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
>> +		q = &id->vbuf_q;
>> +		break;
>> +	case V4L2_BUF_TYPE_VBI_CAPTURE:
>> +		break;
>> +	default:
>> +		break;
>> +	}
>> +	return q;
>> +}
>> +
>> +static int cx18_streamon(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))
>> +		return -EINVAL;
>> +
>> +	if (id->type != CX18_ENC_STREAM_TYPE_YUV)
>> +		return -EINVAL;
>> +
>> +	/* Establish a buffer timeout */
>> +	mod_timer(&s->vb_timeout, jiffies + (HZ * 2));
>> +
>> +	return videobuf_streamon(cx18_vb_queue(id));
>> +}
>> +
>> +static int cx18_streamoff(struct file *file, void *priv,
>> +	enum v4l2_buf_type type)
>> +{
>> +	struct cx18_open_id *id = file->private_data;
>> +
>> +	/* 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))
>> +		return -EINVAL;
>> +
>> +	if (id->type != CX18_ENC_STREAM_TYPE_YUV)
>> +		return -EINVAL;
>> +
>> +	return videobuf_streamoff(cx18_vb_queue(id));
>> +}
>> +
>> +static int cx18_reqbufs(struct file *file, void *priv,
>> +	struct v4l2_requestbuffers *rb)
>> +{
>> +	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))
>> +		return -EINVAL;
>> +
>> +	return videobuf_reqbufs(cx18_vb_queue(id), rb);
>> +}
>> +
>> +static int cx18_querybuf(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))
>> +		return -EINVAL;
>> +
>> +	return videobuf_querybuf(cx18_vb_queue(id), b);
>> +}
>> +
>> +static int cx18_qbuf(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))
>> +		return -EINVAL;
>> +
>> +	return videobuf_qbuf(cx18_vb_queue(id), 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))
>> +		return -EINVAL;
>> +
>> +	return videobuf_dqbuf(cx18_vb_queue(id), b, file->f_flags & O_NONBLOCK);
>> +}
>> +
>>  static int cx18_encoder_cmd(struct file *file, void *fh,
>>  				struct v4l2_encoder_cmd *enc)
>>  {
>> @@ -1081,6 +1187,12 @@ static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
>>  	.vidioc_s_register              = cx18_s_register,
>>  #endif
>>  	.vidioc_default                 = cx18_default,
>> +	.vidioc_streamon                = cx18_streamon,
>> +	.vidioc_streamoff               = cx18_streamoff,
>> +	.vidioc_reqbufs                 = cx18_reqbufs,
>> +	.vidioc_querybuf                = cx18_querybuf,
>> +	.vidioc_qbuf                    = cx18_qbuf,
>> +	.vidioc_dqbuf                   = cx18_dqbuf,
>>  };
>>  
>>  void cx18_set_funcs(struct video_device *vdev)
>> diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
>> index 9605d54..d4d8873 100644
>> --- a/drivers/media/video/cx18/cx18-mailbox.c
>> +++ b/drivers/media/video/cx18/cx18-mailbox.c
>> @@ -81,6 +81,7 @@ static const struct cx18_api_info api_info[] = {
>>  	API_ENTRY(CPU, CX18_CPU_SET_SLICED_VBI_PARAM,           0),
>>  	API_ENTRY(CPU, CX18_CPU_SET_USERDATA_PLACE_HOLDER,      0),
>>  	API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS,                    0),
>> +	API_ENTRY(CPU, CX18_CPU_SET_VFC_PARAM,                  0),
>>  	API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK,			0),
>>  	API_ENTRY(CPU, CX18_CPU_DE_SET_MDL,			API_FAST),
>>  	API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL,			API_SLOW),
>> @@ -158,6 +159,72 @@ static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl)
>>  	}
>>  }
>>  
>> +static void cx18_mdl_send_to_videobuf(struct cx18_stream *s,
>> +	struct cx18_mdl *mdl)
>> +{
>> +	struct cx18_videobuf_buffer *vb_buf;
>> +	struct cx18_buffer *buf;
>> +	u8 *p, u;
>> +	u32 offset = 0;
>> +	int dispatch = 0;
>> +	int i;
>> +
>> +	if (mdl->bytesused == 0)
>> +		return;
>> +
>> +	/* Acquire a videobuf buffer, clone to and and release it */
>> +	spin_lock(&s->vb_lock);
>> +	if (list_empty(&s->vb_capture))
>> +		goto out;
>> +
>> +	vb_buf = list_entry(s->vb_capture.next, struct cx18_videobuf_buffer,
>> +		vb.queue);
>> +
>> +	p = videobuf_to_vmalloc(&vb_buf->vb);
>> +	if (!p)
>> +		goto out;
>> +
>> +	offset = vb_buf->bytes_used;
>> +	list_for_each_entry(buf, &mdl->buf_list, list) {
>> +		if (buf->bytesused == 0)
>> +			break;
>> +
>> +		if ((offset + buf->bytesused) <= vb_buf->vb.bsize) {
>> +			memcpy(p + offset, buf->buf, buf->bytesused);
>> +			offset += buf->bytesused;
>> +			vb_buf->bytes_used += buf->bytesused;
>> +		}
>> +	}
>> +
>> +	/* If we've filled the buffer as per the callers res then dispatch it */
>> +	if (vb_buf->bytes_used >= (vb_buf->vb.width * vb_buf->vb.height * 2)) {
>> +		dispatch = 1;
>> +		vb_buf->bytes_used = 0;
>> +	}
>> +
>> +	/* */
>> +	if (dispatch) {
>> +
>> +		if (s->pixelformat == V4L2_PIX_FMT_YUYV) {
>> +			/* UYVY to YUYV */
>> +			for (i = 0; i < (720 * 480 * 2); i += 2) {
>> +				u = *(p + i);
>> +				*(p + i) = *(p + i + 1);
>> +				*(p + i + 1) = u;
>> +			}
>> +		}
>> +
>> +		do_gettimeofday(&vb_buf->vb.ts);
>> +		list_del(&vb_buf->vb.queue);
>> +		vb_buf->vb.state = VIDEOBUF_DONE;
>> +		wake_up(&vb_buf->vb.done);
>> +	}
>> +
>> +	mod_timer(&s->vb_timeout, jiffies + (HZ / 10));
>> +
>> +out:
>> +	spin_unlock(&s->vb_lock);
>> +}
>>  
>>  static void cx18_mdl_send_to_alsa(struct cx18 *cx, struct cx18_stream *s,
>>  				  struct cx18_mdl *mdl)
>> @@ -263,6 +330,9 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order)
>>  			} else {
>>  				cx18_enqueue(s, mdl, &s->q_full);
>>  			}
>> +		} else if (s->type == CX18_ENC_STREAM_TYPE_YUV) {
>> +			cx18_mdl_send_to_videobuf(s, mdl);
>> +			cx18_enqueue(s, mdl, &s->q_free);
>>  		} else {
>>  			cx18_enqueue(s, mdl, &s->q_full);
>>  			if (s->type == CX18_ENC_STREAM_TYPE_IDX)
>> diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
>> index c6e2ca3..53f5e4f 100644
>> --- a/drivers/media/video/cx18/cx18-streams.c
>> +++ b/drivers/media/video/cx18/cx18-streams.c
>> @@ -44,6 +44,7 @@ static struct v4l2_file_operations cx18_v4l2_enc_fops = {
>>  	.unlocked_ioctl = cx18_v4l2_ioctl,
>>  	.release = cx18_v4l2_close,
>>  	.poll = cx18_v4l2_enc_poll,
>> +	.mmap = cx18_v4l2_mmap,
>>  };
>>  
>>  /* offset from 0 to register ts v4l2 minors on */
>> @@ -132,6 +133,15 @@ static void cx18_stream_init(struct cx18 *cx, int type)
>>  	cx18_queue_init(&s->q_idle);
>>  
>>  	INIT_WORK(&s->out_work_order, cx18_out_work_handler);
>> +
>> +	INIT_LIST_HEAD(&s->vb_capture);
>> +	s->vb_timeout.function = cx18_vb_timeout;
>> +	s->vb_timeout.data = (unsigned long)s;
>> +	init_timer(&s->vb_timeout);
>> +	spin_lock_init(&s->vb_lock);
>> +
>> +	/* Assume the previous pixel default */
>> +	s->pixelformat = V4L2_PIX_FMT_HM12;
>>  }
>>  
>>  static int cx18_prep_dev(struct cx18 *cx, int type)
>> @@ -721,6 +731,19 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
>>  		    test_bit(CX18_F_I_RADIO_USER, &cx->i_flags))
>>  			cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
>>  			  (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8) | 1);
>> +
>> +		/* Enable the Video Format Converter for UYVY 4:2:2 support,
>> +		 * rather than the default HM12 Macroblovk 4:2:0 support.
>> +		 */
>> +		if (captype == CAPTURE_CHANNEL_TYPE_YUV) {
>> +			if (s->pixelformat == V4L2_PIX_FMT_YUYV)
>> +				cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2,
>> +					s->handle, 1);
>> +			else
>> +				/* If in doubt, default to HM12 */
>> +				cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2,
>> +					s->handle, 0);
>> +		}
>>  	}
>>  
>>  	if (atomic_read(&cx->tot_capturing) == 0) {
>> diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h
>> index 935f557..767a8d2 100644
>> --- a/drivers/media/video/cx18/cx23418.h
>> +++ b/drivers/media/video/cx18/cx23418.h
>> @@ -342,6 +342,12 @@
>>     ReturnCode */
>>  #define CX18_CPU_GET_ENC_PTS			(CPU_CMD_MASK_CAPTURE | 0x0022)
>>  
>> +/* Description: Set VFC parameters
>> +   IN[0] - task handle
>> +   IN[1] - VFC enable flag, 1 - enable, 0 - disable
>> +*/
>> +#define CX18_CPU_SET_VFC_PARAM                  (CPU_CMD_MASK_CAPTURE | 0x0023)
>> +
>>  /* Below is the list of commands related to the data exchange */
>>  #define CPU_CMD_MASK_DE 			(CPU_CMD_MASK | 0x040000)
>>  
>>
>> _______________________________________________
>> linuxtv-commits mailing list
>> linuxtv-commits@xxxxxxxxxxx
>> http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits
>>
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux