Re: [PATCH v3 7/9] v4l: xilinx: dma: Add multi-planar support

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

 



Hi Satish,

Thanks for the patch.

On Wed, 2018-02-14 at 22:42:43 -0800, Satish Kumar Nagireddy wrote:
> The current v4l driver supports single plane formats. This patch
> will add support to handle multi-planar formats. Updated driver
> capabilities to multi-planar, where it can handle both single and
> multi-planar formats
> 
> Signed-off-by: Satish Kumar Nagireddy <satishna@xxxxxxxxxx>
> ---
>  drivers/media/platform/xilinx/xilinx-dma.c  | 341 +++++++++++++++++++++++-----
>  drivers/media/platform/xilinx/xilinx-dma.h  |   2 +-
>  drivers/media/platform/xilinx/xilinx-vipp.c |  22 +-
>  3 files changed, 307 insertions(+), 58 deletions(-)
> 
> diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c
> index cb20ada..664981b 100644
> --- a/drivers/media/platform/xilinx/xilinx-dma.c
> +++ b/drivers/media/platform/xilinx/xilinx-dma.c
> @@ -63,6 +63,7 @@ static int xvip_dma_verify_format(struct xvip_dma *dma)
>  	struct v4l2_subdev_format fmt;
>  	struct v4l2_subdev *subdev;
>  	int ret;
> +	int width, height;
>  
>  	subdev = xvip_dma_remote_subdev(&dma->pad, &fmt.pad);
>  	if (subdev == NULL)
> @@ -73,9 +74,18 @@ static int xvip_dma_verify_format(struct xvip_dma *dma)
>  	if (ret < 0)
>  		return ret == -ENOIOCTLCMD ? -EINVAL : ret;
>  
> -	if (dma->fmtinfo->code != fmt.format.code ||
> -	    dma->format.height != fmt.format.height ||
> -	    dma->format.width != fmt.format.width)
> +	if (dma->fmtinfo->code != fmt.format.code)
> +		return -EINVAL;
> +
> +	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type)) {

As discussed, let's plan to remove this check. :-) I think now it's
safe to assume there's no backward compatibility issue.

> +		width = dma->format.fmt.pix_mp.width;
> +		height = dma->format.fmt.pix_mp.height;
> +	} else {
> +		width = dma->format.fmt.pix.width;
> +		height = dma->format.fmt.pix.height;
> +	}
> +
> +	if (width != fmt.format.width || height != fmt.format.height)
>  		return -EINVAL;
>  
>  	return 0;
> @@ -302,6 +312,8 @@ static void xvip_dma_complete(void *param)
>  {
>  	struct xvip_dma_buffer *buf = param;
>  	struct xvip_dma *dma = buf->dma;
> +	u8 num_planes, i;
> +	int sizeimage;
>  
>  	spin_lock(&dma->queued_lock);
>  	list_del(&buf->queue);
> @@ -310,7 +322,28 @@ static void xvip_dma_complete(void *param)
>  	buf->buf.field = V4L2_FIELD_NONE;
>  	buf->buf.sequence = dma->sequence++;
>  	buf->buf.vb2_buf.timestamp = ktime_get_ns();
> -	vb2_set_plane_payload(&buf->buf.vb2_buf, 0, dma->format.sizeimage);
> +
> +	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type)) {
> +		/* Handling contiguous data with mplanes */
> +		if (dma->fmtinfo->buffers == 1) {
> +			sizeimage =
> +				dma->format.fmt.pix_mp.plane_fmt[0].sizeimage;
> +			vb2_set_plane_payload(&buf->buf.vb2_buf, 0, sizeimage);
> +		} else {
> +			/* Handling non-contiguous data with mplanes */
> +			num_planes = dma->format.fmt.pix_mp.num_planes;
> +			for (i = 0; i < num_planes; i++) {
> +				sizeimage =
> +				 dma->format.fmt.pix_mp.plane_fmt[i].sizeimage;
> +				vb2_set_plane_payload(&buf->buf.vb2_buf, i,
> +						      sizeimage);
> +			}
> +		}

Can this be done in a single loop with number of buffers?

> +	} else {
> +		sizeimage = dma->format.fmt.pix.sizeimage;
> +		vb2_set_plane_payload(&buf->buf.vb2_buf, 0, sizeimage);
> +	}
> +
>  	vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
>  }
>  
> @@ -320,13 +353,48 @@ xvip_dma_queue_setup(struct vb2_queue *vq,
>  		     unsigned int sizes[], struct device *alloc_devs[])
>  {
>  	struct xvip_dma *dma = vb2_get_drv_priv(vq);
> +	u8 i;
> +	int sizeimage;
> +
> +	/* Multi planar case: Make sure the image size is large enough */
> +	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type)) {
> +		if (*nplanes) {
> +			if (*nplanes != dma->format.fmt.pix_mp.num_planes)
> +				return -EINVAL;
> +
> +			for (i = 0; i < *nplanes; i++) {
> +			     sizeimage =
> +			      dma->format.fmt.pix_mp.plane_fmt[i].sizeimage;
> +			if (sizes[i] < sizeimage)
> +				return -EINVAL;
> +			}
> +		} else {
> +			/* Handling contiguous data with mplanes */
> +			if (dma->fmtinfo->buffers == 1) {
> +			    *nplanes = 1;

It seems a little confusing as use of 'nplanes' and 'number of buffers' is
mixed. Looks like definitions in v4l and this driver don't match exactly.
If that's the case Maybe a comment would be helpful.

> +			    sizes[0] =
> +			      dma->format.fmt.pix_mp.plane_fmt[0].sizeimage;
> +			    return 0;
> +			} else {
> +			    /* Handling non-contiguous data with mplanes */
> +			    *nplanes = dma->format.fmt.pix_mp.num_planes;
> +			    for (i = 0; i < *nplanes; i++) {
> +				 sizeimage =
> +				  dma->format.fmt.pix_mp.plane_fmt[i].sizeimage;
> +				 sizes[i] = sizeimage;
> +			    }
> +			}
> +		}

Even here, can't number of buffers instead of num_planes be used for the loop?

> +		return 0;
> +	}
>  
> -	/* Make sure the image size is large enough. */
> -	if (*nplanes)
> -		return sizes[0] < dma->format.sizeimage ? -EINVAL : 0;
> +	/* Single planar case: Make sure the image size is large enough */
> +	sizeimage = dma->format.fmt.pix.sizeimage;
> +	if (*nplanes == 1)
> +		return sizes[0] < sizeimage ? -EINVAL : 0;
>  
>  	*nplanes = 1;
> -	sizes[0] = dma->format.sizeimage;
> +	sizes[0] = sizeimage;
>  
>  	return 0;
>  }
> @@ -348,10 +416,11 @@ static void xvip_dma_buffer_queue(struct vb2_buffer *vb)
>  	struct xvip_dma *dma = vb2_get_drv_priv(vb->vb2_queue);
>  	struct xvip_dma_buffer *buf = to_xvip_dma_buffer(vbuf);
>  	struct dma_async_tx_descriptor *desc;
> +	u32 flags, luma_size;
>  	dma_addr_t addr = vb2_dma_contig_plane_dma_addr(vb, 0);
> -	u32 flags;
>  
> -	if (dma->queue.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
> +	if (dma->queue.type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
> +	    dma->queue.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {

This is missing V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE.

>  		flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
>  		dma->xt.dir = DMA_DEV_TO_MEM;
>  		dma->xt.src_sgl = false;
> @@ -365,10 +434,50 @@ static void xvip_dma_buffer_queue(struct vb2_buffer *vb)
>  		dma->xt.src_start = addr;
>  	}
>  
> -	dma->xt.frame_size = 1;
> -	dma->sgl[0].size = dma->format.width * dma->fmtinfo->bpp;
> -	dma->sgl[0].icg = dma->format.bytesperline - dma->sgl[0].size;
> -	dma->xt.numf = dma->format.height;
> +	/*
> +	 * DMA IP supports only 2 planes, so one datachunk is sufficient
> +	 * to get start address of 2nd plane
> +	 */
> +	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type)) {
> +		struct v4l2_pix_format_mplane *pix_mp;
> +
> +		pix_mp = &dma->format.fmt.pix_mp;
> +		dma->xt.frame_size = dma->fmtinfo->num_planes;
> +		dma->sgl[0].size = pix_mp->width * dma->fmtinfo->bpl_factor;
> +		dma->sgl[0].icg = pix_mp->plane_fmt[0].bytesperline -
> +							dma->sgl[0].size;
> +		dma->xt.numf = pix_mp->height;
> +
> +		/*
> +		 * dst_icg is the number of bytes to jump after last luma addr
> +		 * and before first chroma addr
> +		 */
> +
> +		/* Handling contiguous data with mplanes */
> +		if (dma->fmtinfo->buffers == 1) {
> +		    dma->sgl[0].dst_icg = 0;
> +		} else {
> +		    /* Handling non-contiguous data with mplanes */
> +		    if (vb->num_planes == 2) {

Ditto. number of buffers?

> +			dma_addr_t chroma_addr =
> +					vb2_dma_contig_plane_dma_addr(vb, 1);
> +			luma_size = pix_mp->plane_fmt[0].bytesperline *
> +								dma->xt.numf;

Nit. Please align.

> +			if (chroma_addr > addr)
> +			    dma->sgl[0].dst_icg =
> +				chroma_addr - addr - luma_size;

I don't think this is correct, assuming one memory chunk always has higher
starting address than the other. This should be removed. Please consider
proper way of doing this.

> +		    }
> +		}
> +	} else {
> +		struct v4l2_pix_format *pix;
> +
> +		pix = &dma->format.fmt.pix;
> +		dma->xt.frame_size = dma->fmtinfo->num_planes;
> +		dma->sgl[0].size = pix->width * dma->fmtinfo->bpl_factor;
> +		dma->sgl[0].icg = pix->bytesperline - dma->sgl[0].size;
> +		dma->xt.numf = pix->height;
> +		dma->sgl[0].dst_icg = dma->sgl[0].size;
> +	}
>  
>  	desc = dmaengine_prep_interleaved_dma(dma->dma, &dma->xt, flags);
>  	if (!desc) {
> @@ -496,10 +605,21 @@ xvip_dma_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
>  	cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
>  			  | dma->xdev->v4l2_caps;
>  
> -	if (dma->queue.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
> -		cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
> -	else
> -		cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
> +	cap->device_caps = V4L2_CAP_STREAMING;
> +	switch (dma->queue.type) {
> +	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> +		cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE_MPLANE;
> +		break;
> +	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
> +		cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
> +		break;
> +	case V4L2_CAP_VIDEO_OUTPUT_MPLANE:
> +		cap->device_caps |= V4L2_CAP_VIDEO_OUTPUT_MPLANE;
> +		break;
> +	case V4L2_CAP_VIDEO_OUTPUT:
> +		cap->device_caps |= V4L2_CAP_VIDEO_OUTPUT;
> +		break;
> +	}
>  
>  	strlcpy(cap->driver, "xilinx-vipp", sizeof(cap->driver));
>  	strlcpy(cap->card, dma->video.name, sizeof(cap->card));
> @@ -523,7 +643,11 @@ xvip_dma_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f)
>  	if (f->index > 0)
>  		return -EINVAL;
>  
> -	f->pixelformat = dma->format.pixelformat;
> +	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type))
> +		f->pixelformat = dma->format.fmt.pix_mp.pixelformat;
> +	else
> +		f->pixelformat = dma->format.fmt.pix.pixelformat;
> +
>  	strlcpy(f->description, dma->fmtinfo->description,
>  		sizeof(f->description));
>  
> @@ -536,13 +660,17 @@ xvip_dma_get_format(struct file *file, void *fh, struct v4l2_format *format)
>  	struct v4l2_fh *vfh = file->private_data;
>  	struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
>  
> -	format->fmt.pix = dma->format;
> +	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type))
> +		format->fmt.pix_mp = dma->format.fmt.pix_mp;
> +	else
> +		format->fmt.pix = dma->format.fmt.pix;
>  
>  	return 0;
>  }
>  
>  static void
> -__xvip_dma_try_format(struct xvip_dma *dma, struct v4l2_pix_format *pix,
> +__xvip_dma_try_format(struct xvip_dma *dma,
> +		      struct v4l2_format *format,
>  		      const struct xvip_video_format **fmtinfo)
>  {
>  	const struct xvip_video_format *info;
> @@ -553,40 +681,91 @@ __xvip_dma_try_format(struct xvip_dma *dma, struct v4l2_pix_format *pix,
>  	unsigned int width;
>  	unsigned int align;
>  	unsigned int bpl;
> +	unsigned int i, hsub, vsub, plane_width, plane_height;
>  
>  	/* Retrieve format information and select the default format if the
>  	 * requested format isn't supported.
>  	 */
> -	info = xvip_get_format_by_fourcc(pix->pixelformat);
> +	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type))
> +	    info = xvip_get_format_by_fourcc(format->fmt.pix_mp.pixelformat);
> +	else
> +	    info = xvip_get_format_by_fourcc(format->fmt.pix.pixelformat);
> +
>  	if (IS_ERR(info))
>  		info = xvip_get_format_by_fourcc(XVIP_DMA_DEF_FORMAT);
>  
> -	pix->pixelformat = info->fourcc;
> -	pix->field = V4L2_FIELD_NONE;
> -
>  	/* The transfer alignment requirements are expressed in bytes. Compute
>  	 * the minimum and maximum values, clamp the requested width and convert
>  	 * it back to pixels.
>  	 */
> -	align = lcm(dma->align, info->bpp);
> +	align = lcm(dma->align, info->bpl_factor);

This is incorrect. Use bits-per-pixel / 8.

>  	min_width = roundup(XVIP_DMA_MIN_WIDTH, align);
>  	max_width = rounddown(XVIP_DMA_MAX_WIDTH, align);
> -	width = rounddown(pix->width * info->bpp, align);
>  
> -	pix->width = clamp(width, min_width, max_width) / info->bpp;
> -	pix->height = clamp(pix->height, XVIP_DMA_MIN_HEIGHT,
> -			    XVIP_DMA_MAX_HEIGHT);
> +	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type)) {
> +		struct v4l2_pix_format_mplane *pix_mp;
> +
> +		pix_mp = &format->fmt.pix_mp;
> +		pix_mp->field = V4L2_FIELD_NONE;
> +		width = rounddown(pix_mp->width * info->bpl_factor, align);

As commented earlier, not sure what bpl_factor is for.

> +		pix_mp->width = clamp(width, min_width, max_width) /
> +							info->bpl_factor;
> +		pix_mp->height = clamp(pix_mp->height, XVIP_DMA_MIN_HEIGHT,
> +				       XVIP_DMA_MAX_HEIGHT);
> +
> +		/*
> +		 * Clamp the requested bytes per line value. If the maximum
> +		 * bytes per line value is zero, the module doesn't support
> +		 * user configurable line sizes. Override the requested value
> +		 * with the minimum in that case.
> +		 */
> +
> +		/* Handling contiguous data with mplanes */
> +		if (info->buffers == 1) {
> +			min_bpl = pix_mp->width * info->bpl_factor;
> +			max_bpl = rounddown(XVIP_DMA_MAX_WIDTH, dma->align);
> +			bpl = rounddown(pix_mp->plane_fmt[0].bytesperline,
> +					dma->align);
> +			pix_mp->plane_fmt[0].bytesperline = clamp(bpl, min_bpl,
> +								  max_bpl);
> +			pix_mp->plane_fmt[0].sizeimage =
> +			      (pix_mp->width * pix_mp->height * info->bpp) >> 3;

Nit. '/ 8' would be more clear for bits to bytes conversion in my opinion,
but up to you. Then it should be rounded up not to lose fractional,
DIV_ROUND_UP().

> +		} else {
> +			/* Handling non-contiguous data with mplanes */
> +			hsub = info->hsub;
> +			vsub = info->vsub;
> +			for (i = 0; i < info->num_planes; i++) {
> +				plane_width = pix_mp->width / (i ? hsub : 1);
> +				plane_height = pix_mp->height / (i ? vsub : 1);
> +				min_bpl = plane_width * info->bpl_factor;
> +				max_bpl = rounddown(XVIP_DMA_MAX_WIDTH,
> +						    dma->align);
> +				bpl = pix_mp->plane_fmt[i].bytesperline;
> +				bpl = rounddown(bpl, dma->align);
> +				pix_mp->plane_fmt[i].bytesperline =
> +						clamp(bpl, min_bpl, max_bpl);
> +				pix_mp->plane_fmt[i].sizeimage =
> +					pix_mp->plane_fmt[i].bytesperline *
> +								plane_height;
> +			}
> +		}
> +	} else {
> +		struct v4l2_pix_format *pix;
>  
> -	/* Clamp the requested bytes per line value. If the maximum bytes per
> -	 * line value is zero, the module doesn't support user configurable line
> -	 * sizes. Override the requested value with the minimum in that case.
> -	 */
> -	min_bpl = pix->width * info->bpp;
> -	max_bpl = rounddown(XVIP_DMA_MAX_WIDTH, dma->align);
> -	bpl = rounddown(pix->bytesperline, dma->align);
> +		pix = &format->fmt.pix;
> +		pix->field = V4L2_FIELD_NONE;
> +
> +		width = rounddown(pix->width * info->bpp, align);

'width' is number of pixels per line here, but the result is not, as info->bpp
is now bits-per-pixel.

> +		pix->width = clamp(width, min_width, max_width) / info->bpp;
> +		pix->height = clamp(pix->height, XVIP_DMA_MIN_HEIGHT,
> +				    XVIP_DMA_MAX_HEIGHT);
>  
> -	pix->bytesperline = clamp(bpl, min_bpl, max_bpl);
> -	pix->sizeimage = pix->bytesperline * pix->height;
> +		min_bpl = pix->width * info->bpl_factor;
> +		max_bpl = rounddown(XVIP_DMA_MAX_WIDTH, dma->align);
> +		bpl = rounddown(pix->bytesperline, dma->align);
> +		pix->bytesperline = clamp(bpl, min_bpl, max_bpl);
> +		pix->sizeimage = (pix->width * pix->height * info->bpp) >> 3;
> +	}
>  
>  	if (fmtinfo)
>  		*fmtinfo = info;
> @@ -598,7 +777,7 @@ xvip_dma_try_format(struct file *file, void *fh, struct v4l2_format *format)
>  	struct v4l2_fh *vfh = file->private_data;
>  	struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
>  
> -	__xvip_dma_try_format(dma, &format->fmt.pix, NULL);
> +	__xvip_dma_try_format(dma, format, NULL);
>  	return 0;
>  }
>  
> @@ -609,12 +788,16 @@ xvip_dma_set_format(struct file *file, void *fh, struct v4l2_format *format)
>  	struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
>  	const struct xvip_video_format *info;
>  
> -	__xvip_dma_try_format(dma, &format->fmt.pix, &info);
> +	__xvip_dma_try_format(dma, format, &info);
>  
>  	if (vb2_is_busy(&dma->queue))
>  		return -EBUSY;
>  
> -	dma->format = format->fmt.pix;
> +	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type))
> +		dma->format.fmt.pix_mp = format->fmt.pix_mp;
> +	else
> +		dma->format.fmt.pix = format->fmt.pix;
> +
>  	dma->fmtinfo = info;
>  
>  	return 0;
> @@ -623,11 +806,15 @@ xvip_dma_set_format(struct file *file, void *fh, struct v4l2_format *format)
>  static const struct v4l2_ioctl_ops xvip_dma_ioctl_ops = {
>  	.vidioc_querycap		= xvip_dma_querycap,
>  	.vidioc_enum_fmt_vid_cap	= xvip_dma_enum_format,
> +	.vidioc_enum_fmt_vid_cap_mplane	= xvip_dma_enum_format,
>  	.vidioc_g_fmt_vid_cap		= xvip_dma_get_format,
> +	.vidioc_g_fmt_vid_cap_mplane	= xvip_dma_get_format,
>  	.vidioc_g_fmt_vid_out		= xvip_dma_get_format,
>  	.vidioc_s_fmt_vid_cap		= xvip_dma_set_format,
> +	.vidioc_s_fmt_vid_cap_mplane	= xvip_dma_set_format,
>  	.vidioc_s_fmt_vid_out		= xvip_dma_set_format,
>  	.vidioc_try_fmt_vid_cap		= xvip_dma_try_format,
> +	.vidioc_try_fmt_vid_cap_mplane	= xvip_dma_try_format,
>  	.vidioc_try_fmt_vid_out		= xvip_dma_try_format,
>  	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
>  	.vidioc_querybuf		= vb2_ioctl_querybuf,
> @@ -661,6 +848,7 @@ int xvip_dma_init(struct xvip_composite_device *xdev, struct xvip_dma *dma,
>  {
>  	char name[16];
>  	int ret;
> +	u32 i, hsub, vsub, width, height;
>  
>  	dma->xdev = xdev;
>  	dma->port = port;
> @@ -670,17 +858,55 @@ int xvip_dma_init(struct xvip_composite_device *xdev, struct xvip_dma *dma,
>  	spin_lock_init(&dma->queued_lock);
>  
>  	dma->fmtinfo = xvip_get_format_by_fourcc(XVIP_DMA_DEF_FORMAT);
> -	dma->format.pixelformat = dma->fmtinfo->fourcc;
> -	dma->format.colorspace = V4L2_COLORSPACE_SRGB;
> -	dma->format.field = V4L2_FIELD_NONE;
> -	dma->format.width = XVIP_DMA_DEF_WIDTH;
> -	dma->format.height = XVIP_DMA_DEF_HEIGHT;
> -	dma->format.bytesperline = dma->format.width * dma->fmtinfo->bpp;
> -	dma->format.sizeimage = dma->format.bytesperline * dma->format.height;
> +	dma->format.type = type;
> +
> +	if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
> +		struct v4l2_pix_format_mplane *pix_mp;
> +
> +		pix_mp = &dma->format.fmt.pix_mp;
> +		pix_mp->pixelformat = dma->fmtinfo->fourcc;
> +		pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
> +		pix_mp->field = V4L2_FIELD_NONE;
> +		pix_mp->width = XVIP_DMA_DEF_WIDTH;
> +
> +		/* Handling contiguous data with mplanes */
> +		if (dma->fmtinfo->buffers == 1) {
> +		    pix_mp->plane_fmt[0].bytesperline =
> +		      pix_mp->width * dma->fmtinfo->bpl_factor;
> +		    pix_mp->plane_fmt[0].sizeimage =
> +		      (pix_mp->width * pix_mp->height * dma->fmtinfo->bpp) >> 3;
> +		} else {
> +		    /* Handling non-contiguous data with mplanes */
> +		    hsub = dma->fmtinfo->hsub;
> +		    vsub = dma->fmtinfo->vsub;
> +		    for (i = 0; i < dma->fmtinfo->num_planes; i++) {

Ditto. Please check num_planes vs num buffers.

> +				width  = pix_mp->width / (i ? hsub : 1);
> +				height = pix_mp->height / (i ? vsub : 1);
> +				pix_mp->plane_fmt[i].bytesperline = width *
> +						dma->fmtinfo->bpl_factor;
> +				pix_mp->plane_fmt[i].sizeimage = width * height;
> +		    }
> +		}
> +	} else {
> +		struct v4l2_pix_format *pix;
> +
> +		pix = &dma->format.fmt.pix;
> +		pix->pixelformat = dma->fmtinfo->fourcc;
> +		pix->colorspace = V4L2_COLORSPACE_SRGB;
> +		pix->field = V4L2_FIELD_NONE;
> +		pix->width = XVIP_DMA_DEF_WIDTH;
> +		pix->height = XVIP_DMA_DEF_HEIGHT;
> +		pix->bytesperline = pix->width * dma->fmtinfo->bpl_factor;
> +		pix->sizeimage =
> +			(pix->width * pix->height * dma->fmtinfo->bpp) >> 3;
> +	}
>  
>  	/* Initialize the media entity... */
> -	dma->pad.flags = type == V4L2_BUF_TYPE_VIDEO_CAPTURE
> -		       ? MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
> +	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
> +	    type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
> +		dma->pad.flags = MEDIA_PAD_FL_SINK;
> +	else
> +		dma->pad.flags = MEDIA_PAD_FL_SOURCE;
>  
>  	ret = media_entity_pads_init(&dma->video.entity, 1, &dma->pad);
>  	if (ret < 0)
> @@ -692,11 +918,18 @@ int xvip_dma_init(struct xvip_composite_device *xdev, struct xvip_dma *dma,
>  	dma->video.queue = &dma->queue;
>  	snprintf(dma->video.name, sizeof(dma->video.name), "%s %s %u",
>  		 xdev->dev->of_node->name,
> -		 type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? "output" : "input",
> +		 (type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
> +		 type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
> +					? "output" : "input",

Need to set OUTPUT_MPLANE.

>  		 port);
> +
>  	dma->video.vfl_type = VFL_TYPE_GRABBER;
> -	dma->video.vfl_dir = type == V4L2_BUF_TYPE_VIDEO_CAPTURE
> -			   ? VFL_DIR_RX : VFL_DIR_TX;
> +	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
> +	    type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
> +		dma->video.vfl_dir = VFL_DIR_RX;
> +	else
> +		dma->video.vfl_dir = VFL_DIR_TX;
> +
>  	dma->video.release = video_device_release_empty;
>  	dma->video.ioctl_ops = &xvip_dma_ioctl_ops;
>  	dma->video.lock = &dma->lock;
> diff --git a/drivers/media/platform/xilinx/xilinx-dma.h b/drivers/media/platform/xilinx/xilinx-dma.h
> index e95d136..b352bef 100644
> --- a/drivers/media/platform/xilinx/xilinx-dma.h
> +++ b/drivers/media/platform/xilinx/xilinx-dma.h
> @@ -83,7 +83,7 @@ struct xvip_dma {
>  	unsigned int port;
>  
>  	struct mutex lock;
> -	struct v4l2_pix_format format;
> +	struct v4l2_format format;
>  	const struct xvip_video_format *fmtinfo;
>  
>  	struct vb2_queue queue;
> diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
> index 6bb28cd..508cfac 100644
> --- a/drivers/media/platform/xilinx/xilinx-vipp.c
> +++ b/drivers/media/platform/xilinx/xilinx-vipp.c
> @@ -30,6 +30,15 @@
>  #define XVIPP_DMA_S2MM				0
>  #define XVIPP_DMA_MM2S				1
>  
> +/*
> + * This is for backward compatibility for existing applications,
> + * and planned to be deprecated
> + */
> +static bool xvip_is_mplane = true;
> +MODULE_PARM_DESC(is_mplane,
> +		 "v4l2 device capability to handle multi planar formats");
> +module_param_named(is_mplane, xvip_is_mplane, bool, 0444);
> +

As commented above, let's work toward removing this. It will simplify changes
a lot.

Thanks,
-hyun

>  /**
>   * struct xvip_graph_entity - Entity in the video graph
>   * @list: list entry in a graph entities list
> @@ -434,7 +443,8 @@ static int xvip_graph_dma_init_one(struct xvip_composite_device *xdev,
>  		return ret;
>  
>  	if (strcmp(direction, "input") == 0)
> -		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +		type = xvip_is_mplane ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
> +						V4L2_BUF_TYPE_VIDEO_CAPTURE;
>  	else if (strcmp(direction, "output") == 0)
>  		type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
>  	else
> @@ -454,8 +464,14 @@ static int xvip_graph_dma_init_one(struct xvip_composite_device *xdev,
>  
>  	list_add_tail(&dma->list, &xdev->dmas);
>  
> -	xdev->v4l2_caps |= type == V4L2_BUF_TYPE_VIDEO_CAPTURE
> -			 ? V4L2_CAP_VIDEO_CAPTURE : V4L2_CAP_VIDEO_OUTPUT;
> +	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
> +		xdev->v4l2_caps |= V4L2_CAP_VIDEO_CAPTURE_MPLANE;
> +	else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
> +		xdev->v4l2_caps |= V4L2_CAP_VIDEO_CAPTURE;
> +	else if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
> +		xdev->v4l2_caps |= V4L2_CAP_VIDEO_OUTPUT;
> +	else if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
> +		xdev->v4l2_caps |= V4L2_CAP_VIDEO_OUTPUT_MPLANE;
>  
>  	return 0;
>  }
> -- 
> 2.7.4
> 



[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