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 Hyun,

Thanks a lot for the comments. I will fix them in v4 patch-set.

Regards,
Satish

> -----Original Message-----
> From: Hyun Kwon [mailto:hyun.kwon@xxxxxxxxxx]
> Sent: Friday, February 16, 2018 9:05 AM
> To: Satish Kumar Nagireddy <SATISHNA@xxxxxxxxxx>
> Cc: linux-media@xxxxxxxxxxxxxxx; laurent.pinchart@xxxxxxxxxxxxxxxx;
> michal.simek@xxxxxxxxxx; Hyun Kwon <hyunk@xxxxxxxxxx>; Satish Kumar
> Nagireddy <SATISHNA@xxxxxxxxxx>
> Subject: Re: [PATCH v3 7/9] v4l: xilinx: dma: Add multi-planar support
> 
> 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