Re: [PATCH v5 3/9] v4l: platform: Add Renesas CEU driver

2018-01-16 Thread jacopo mondi
Hi Hans,

On Tue, Jan 16, 2018 at 10:46:42AM +0100, Hans Verkuil wrote:
> Hi Jacopo,
>
> Sorry for the late review, but here is finally is.
>
> BTW, can you provide the v4l2-compliance output (ideally with the -f option)
> in the cover letter for v6?

Sure, it was attacched to v3 I guess, since then it has not changed.
I will include that in v6 cover letter.

> On 01/12/2018 03:04 PM, Jacopo Mondi wrote:
> > Add driver for Renesas Capture Engine Unit (CEU).
> >
> > The CEU interface supports capturing 'data' (YUV422) and 'images'
> > (NV[12|21|16|61]).
> >
> > This driver aims to replace the soc_camera-based sh_mobile_ceu one.
> >
> > Tested with ov7670 camera sensor, providing YUYV_2X8 data on Renesas RZ
> > platform GR-Peach.
> >
> > Tested with ov7725 camera sensor on SH4 platform Migo-R.
> >
> > Signed-off-by: Jacopo Mondi 
> > Reviewed-by: Laurent Pinchart 
> > ---
> >  drivers/media/platform/Kconfig   |9 +
> >  drivers/media/platform/Makefile  |1 +
> >  drivers/media/platform/renesas-ceu.c | 1648 
> > ++
> >  3 files changed, 1658 insertions(+)
> >  create mode 100644 drivers/media/platform/renesas-ceu.c
> >
> > diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
> > index fd0c998..fe7bd26 100644
> > --- a/drivers/media/platform/Kconfig
> > +++ b/drivers/media/platform/Kconfig
> > @@ -144,6 +144,15 @@ config VIDEO_STM32_DCMI
> >   To compile this driver as a module, choose M here: the module
> >   will be called stm32-dcmi.
> >
> > +config VIDEO_RENESAS_CEU
> > +   tristate "Renesas Capture Engine Unit (CEU) driver"
> > +   depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA
> > +   depends on ARCH_SHMOBILE || ARCH_R7S72100 || COMPILE_TEST
> > +   select VIDEOBUF2_DMA_CONTIG
> > +   select V4L2_FWNODE
> > +   ---help---
> > + This is a v4l2 driver for the Renesas CEU Interface
> > +
> >  source "drivers/media/platform/soc_camera/Kconfig"
> >  source "drivers/media/platform/exynos4-is/Kconfig"
> >  source "drivers/media/platform/am437x/Kconfig"
> > diff --git a/drivers/media/platform/Makefile 
> > b/drivers/media/platform/Makefile
> > index 003b0bb..6580a6b 100644
> > --- a/drivers/media/platform/Makefile
> > +++ b/drivers/media/platform/Makefile
> > @@ -62,6 +62,7 @@ obj-$(CONFIG_VIDEO_SH_VOU)+= sh_vou.o
> >  obj-$(CONFIG_SOC_CAMERA)   += soc_camera/
> >
> >  obj-$(CONFIG_VIDEO_RCAR_DRIF)  += rcar_drif.o
> > +obj-$(CONFIG_VIDEO_RENESAS_CEU)+= renesas-ceu.o
> >  obj-$(CONFIG_VIDEO_RENESAS_FCP)+= rcar-fcp.o
> >  obj-$(CONFIG_VIDEO_RENESAS_FDP1)   += rcar_fdp1.o
> >  obj-$(CONFIG_VIDEO_RENESAS_JPU)+= rcar_jpu.o
> > diff --git a/drivers/media/platform/renesas-ceu.c 
> > b/drivers/media/platform/renesas-ceu.c
> > new file mode 100644
> > index 000..ccca838
> > --- /dev/null
> > +++ b/drivers/media/platform/renesas-ceu.c
>
> 
>
> > +/*
> > + * ceu_vb2_setup() - is called to check whether the driver can accept the
> > + *  requested number of buffers and to fill in plane sizes
> > + *  for the current frame format, if required.
> > + */
> > +static int ceu_vb2_setup(struct vb2_queue *vq, unsigned int *count,
> > +unsigned int *num_planes, unsigned int sizes[],
> > +struct device *alloc_devs[])
> > +{
> > +   struct ceu_device *ceudev = vb2_get_drv_priv(vq);
> > +   struct v4l2_pix_format_mplane *pix = >v4l2_pix;
> > +   unsigned int i;
> > +
> > +   if (!*count)
> > +   *count = 2;
>
> Don't do this. Instead set the min_buffers_needed field to 2 in the vb2_queue
> struct.
>

I guess setting min_buffers_needed makes this check not required. Will
drop.

> > +
> > +   /* num_planes is set: just check plane sizes. */
> > +   if (*num_planes) {
> > +   for (i = 0; i < pix->num_planes; i++)
> > +   if (sizes[i] < pix->plane_fmt[i].sizeimage)
> > +   return -EINVAL;
> > +
> > +   return 0;
> > +   }
> > +
> > +   /* num_planes not set: called from REQBUFS, just set plane sizes. */
> > +   *num_planes = pix->num_planes;
> > +   for (i = 0; i < pix->num_planes; i++)
> > +   sizes[i] = pix->plane_fmt[i].sizeimage;
> > +
> > +   return 0;
> > +}
> > +
> > +static void ceu_vb2_queue(struct vb2_buffer *vb)
> > +{
> > +   struct ceu_device *ceudev = vb2_get_drv_priv(vb->vb2_queue);
> > +   struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> > +   struct v4l2_pix_format_mplane *pix = >v4l2_pix;
> > +   struct ceu_buffer *buf = vb2_to_ceu(vbuf);
> > +   unsigned long irqflags;
> > +   unsigned int i;
> > +
> > +   for (i = 0; i < pix->num_planes; i++) {
> > +   if (vb2_plane_size(vb, i) < pix->plane_fmt[i].sizeimage) {
> > +   vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
> > +   return;
> > +   }
> > +
> > +   

Re: [PATCH v5 3/9] v4l: platform: Add Renesas CEU driver

2018-01-16 Thread Laurent Pinchart
Hi Hans,

On Tuesday, 16 January 2018 11:46:42 EET Hans Verkuil wrote:
> Hi Jacopo,
> 
> Sorry for the late review, but here is finally is.
> 
> BTW, can you provide the v4l2-compliance output (ideally with the -f option)
> in the cover letter for v6?
> 
> On 01/12/2018 03:04 PM, Jacopo Mondi wrote:
> > Add driver for Renesas Capture Engine Unit (CEU).
> > 
> > The CEU interface supports capturing 'data' (YUV422) and 'images'
> > (NV[12|21|16|61]).
> > 
> > This driver aims to replace the soc_camera-based sh_mobile_ceu one.
> > 
> > Tested with ov7670 camera sensor, providing YUYV_2X8 data on Renesas RZ
> > platform GR-Peach.
> > 
> > Tested with ov7725 camera sensor on SH4 platform Migo-R.
> > 
> > Signed-off-by: Jacopo Mondi 
> > Reviewed-by: Laurent Pinchart 
> > ---
> > 
> >  drivers/media/platform/Kconfig   |9 +
> >  drivers/media/platform/Makefile  |1 +
> >  drivers/media/platform/renesas-ceu.c | 1648 +
> >  3 files changed, 1658 insertions(+)
> >  create mode 100644 drivers/media/platform/renesas-ceu.c

[snip]

> > diff --git a/drivers/media/platform/renesas-ceu.c
> > b/drivers/media/platform/renesas-ceu.c new file mode 100644
> > index 000..ccca838
> > --- /dev/null
> > +++ b/drivers/media/platform/renesas-ceu.c

[snip]

> > +static int ceu_s_input(struct file *file, void *priv, unsigned int i)
> > +{
> > +   struct ceu_device *ceudev = video_drvdata(file);
> > +   struct ceu_subdev *ceu_sd_old;
> > +   int ret;
> > +
> 
> Add a check:
> 
>   if (i == ceudev->sd_index)
>   return 0;
> 
> I.e. if the new input == the old input, then that's fine regardless of the
> streaming state.

On a side note this is the kind of checks that the core should handle, but 
that's out of scope for this patch.

> > +   if (vb2_is_streaming(>vb2_vq))
> > +   return -EBUSY;
> > +
> > +   if (i >= ceudev->num_sd)
> > +   return -EINVAL;
> 
> Move this up as the first test.
> 
> > +
> > +   ceu_sd_old = ceudev->sd;
> > +   ceudev->sd = >subdevs[i];
> > +
> > +   /* Make sure we can generate output image formats. */
> > +   ret = ceu_init_formats(ceudev);
> > +   if (ret) {
> > +   ceudev->sd = ceu_sd_old;
> > +   return -EINVAL;
> > +   }
> > +
> > +   /* now that we're sure we can use the sensor, power off the old one. */
> > +   v4l2_subdev_call(ceu_sd_old->v4l2_sd, core, s_power, 0);
> > +   v4l2_subdev_call(ceudev->sd->v4l2_sd, core, s_power, 1);
> > +
> > +   ceudev->sd_index = i;
> > +
> > +   return 0;
> > +}

[snip]

> > +
> > +static int ceu_notify_complete(struct v4l2_async_notifier *notifier)
> > +{
> > +   struct v4l2_device *v4l2_dev = notifier->v4l2_dev;
> > +   struct ceu_device *ceudev = v4l2_to_ceu(v4l2_dev);
> > +   struct video_device *vdev = >vdev;
> > +   struct vb2_queue *q = >vb2_vq;
> > +   struct v4l2_subdev *v4l2_sd;
> > +   int ret;
> > +
> > +   /* Initialize vb2 queue. */
> > +   q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
> > +   q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
> 
> Don't include VB2_USERPTR. It shouldn't be used with dma_contig.
> 
> You also added a read() fop (vb2_fop_read), so either add VB2_READ here
> or remove the read fop.

Agreed. I'd drop both VB2_USERPTR and vb2_fop_read().

> > +   q->drv_priv = ceudev;
> > +   q->ops  = _vb2_ops;
> > +   q->mem_ops  = _dma_contig_memops;
> > +   q->buf_struct_size  = sizeof(struct ceu_buffer);
> > +   q->timestamp_flags  = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
> > +   q->lock = >mlock;
> > +   q->dev  = ceudev->v4l2_dev.dev;
> > +
> > +   ret = vb2_queue_init(q);
> > +   if (ret)
> > +   return ret;
> > +
> > +   /*
> > +* Make sure at least one sensor is primary and use it to initialize
> > +* ceu formats.
> > +*/
> > +   if (!ceudev->sd) {
> > +   ceudev->sd = >subdevs[0];
> > +   ceudev->sd_index = 0;
> > +   }
> > +
> > +   v4l2_sd = ceudev->sd->v4l2_sd;
> > +
> > +   ret = ceu_init_formats(ceudev);
> > +   if (ret)
> > +   return ret;
> > +
> > +   ret = ceu_set_default_fmt(ceudev);
> > +   if (ret)
> > +   return ret;
> > +
> > +   /* Register the video device. */
> > +   strncpy(vdev->name, DRIVER_NAME, strlen(DRIVER_NAME));
> > +   vdev->v4l2_dev  = v4l2_dev;
> > +   vdev->lock  = >mlock;
> > +   vdev->queue = >vb2_vq;
> > +   vdev->ctrl_handler  = v4l2_sd->ctrl_handler;
> > +   vdev->fops  = _fops;
> > +   vdev->ioctl_ops = _ioctl_ops;
> > +   vdev->release   = ceu_vdev_release;
> > +   vdev->device_caps   = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
> > + V4L2_CAP_STREAMING;
> > +   video_set_drvdata(vdev, ceudev);
> > +
> > +   ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
> > +   if (ret < 0) {
> > +   

Re: [PATCH v5 3/9] v4l: platform: Add Renesas CEU driver

2018-01-16 Thread Hans Verkuil
Hi Jacopo,

Sorry for the late review, but here is finally is.

BTW, can you provide the v4l2-compliance output (ideally with the -f option)
in the cover letter for v6?

On 01/12/2018 03:04 PM, Jacopo Mondi wrote:
> Add driver for Renesas Capture Engine Unit (CEU).
> 
> The CEU interface supports capturing 'data' (YUV422) and 'images'
> (NV[12|21|16|61]).
> 
> This driver aims to replace the soc_camera-based sh_mobile_ceu one.
> 
> Tested with ov7670 camera sensor, providing YUYV_2X8 data on Renesas RZ
> platform GR-Peach.
> 
> Tested with ov7725 camera sensor on SH4 platform Migo-R.
> 
> Signed-off-by: Jacopo Mondi 
> Reviewed-by: Laurent Pinchart 
> ---
>  drivers/media/platform/Kconfig   |9 +
>  drivers/media/platform/Makefile  |1 +
>  drivers/media/platform/renesas-ceu.c | 1648 
> ++
>  3 files changed, 1658 insertions(+)
>  create mode 100644 drivers/media/platform/renesas-ceu.c
> 
> diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
> index fd0c998..fe7bd26 100644
> --- a/drivers/media/platform/Kconfig
> +++ b/drivers/media/platform/Kconfig
> @@ -144,6 +144,15 @@ config VIDEO_STM32_DCMI
> To compile this driver as a module, choose M here: the module
> will be called stm32-dcmi.
>  
> +config VIDEO_RENESAS_CEU
> + tristate "Renesas Capture Engine Unit (CEU) driver"
> + depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA
> + depends on ARCH_SHMOBILE || ARCH_R7S72100 || COMPILE_TEST
> + select VIDEOBUF2_DMA_CONTIG
> + select V4L2_FWNODE
> + ---help---
> +   This is a v4l2 driver for the Renesas CEU Interface
> +
>  source "drivers/media/platform/soc_camera/Kconfig"
>  source "drivers/media/platform/exynos4-is/Kconfig"
>  source "drivers/media/platform/am437x/Kconfig"
> diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
> index 003b0bb..6580a6b 100644
> --- a/drivers/media/platform/Makefile
> +++ b/drivers/media/platform/Makefile
> @@ -62,6 +62,7 @@ obj-$(CONFIG_VIDEO_SH_VOU)  += sh_vou.o
>  obj-$(CONFIG_SOC_CAMERA) += soc_camera/
>  
>  obj-$(CONFIG_VIDEO_RCAR_DRIF)+= rcar_drif.o
> +obj-$(CONFIG_VIDEO_RENESAS_CEU)  += renesas-ceu.o
>  obj-$(CONFIG_VIDEO_RENESAS_FCP)  += rcar-fcp.o
>  obj-$(CONFIG_VIDEO_RENESAS_FDP1) += rcar_fdp1.o
>  obj-$(CONFIG_VIDEO_RENESAS_JPU)  += rcar_jpu.o
> diff --git a/drivers/media/platform/renesas-ceu.c 
> b/drivers/media/platform/renesas-ceu.c
> new file mode 100644
> index 000..ccca838
> --- /dev/null
> +++ b/drivers/media/platform/renesas-ceu.c



> +/*
> + * ceu_vb2_setup() - is called to check whether the driver can accept the
> + *requested number of buffers and to fill in plane sizes
> + *for the current frame format, if required.
> + */
> +static int ceu_vb2_setup(struct vb2_queue *vq, unsigned int *count,
> +  unsigned int *num_planes, unsigned int sizes[],
> +  struct device *alloc_devs[])
> +{
> + struct ceu_device *ceudev = vb2_get_drv_priv(vq);
> + struct v4l2_pix_format_mplane *pix = >v4l2_pix;
> + unsigned int i;
> +
> + if (!*count)
> + *count = 2;

Don't do this. Instead set the min_buffers_needed field to 2 in the vb2_queue
struct.

> +
> + /* num_planes is set: just check plane sizes. */
> + if (*num_planes) {
> + for (i = 0; i < pix->num_planes; i++)
> + if (sizes[i] < pix->plane_fmt[i].sizeimage)
> + return -EINVAL;
> +
> + return 0;
> + }
> +
> + /* num_planes not set: called from REQBUFS, just set plane sizes. */
> + *num_planes = pix->num_planes;
> + for (i = 0; i < pix->num_planes; i++)
> + sizes[i] = pix->plane_fmt[i].sizeimage;
> +
> + return 0;
> +}
> +
> +static void ceu_vb2_queue(struct vb2_buffer *vb)
> +{
> + struct ceu_device *ceudev = vb2_get_drv_priv(vb->vb2_queue);
> + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> + struct v4l2_pix_format_mplane *pix = >v4l2_pix;
> + struct ceu_buffer *buf = vb2_to_ceu(vbuf);
> + unsigned long irqflags;
> + unsigned int i;
> +
> + for (i = 0; i < pix->num_planes; i++) {
> + if (vb2_plane_size(vb, i) < pix->plane_fmt[i].sizeimage) {
> + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
> + return;
> + }
> +
> + vb2_set_plane_payload(vb, i, pix->plane_fmt[i].sizeimage);

This is not the right vb2 op for this test, this belongs in the buf_prepare
op. There you can just return an error and you don't need to call buffer_done.

> + }
> +
> + spin_lock_irqsave(>lock, irqflags);
> + list_add_tail(>queue, >capture);
> + spin_unlock_irqrestore(>lock, irqflags);
> +}
> +
> +static int ceu_start_streaming(struct vb2_queue *vq,