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 >