Hi Hans,

Thank you for the very quick review.

On Wednesday 10 July 2013 14:34:24 Hans Verkuil wrote:
> On Wed 10 July 2013 12:19:32 Laurent Pinchart wrote:
> > The VSP1 is a video processing engine that includes a blender, scalers,
> > filters and statistics computation. Configurable data path routing logic
> > allows ordering the internal blocks in a flexible way.
> > 
> > Due to the configurable nature of the pipeline the driver implements the
> > media controller API and doesn't use the V4L2 mem-to-mem framework, even
> > though the device usually operates in memory to memory mode.
> > 
> > Only the read pixel formatters, up/down scalers, write pixel formatters
> > and LCDC interface are supported at this stage.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+rene...@ideasonboard.com>
> > ---
> > 
> >  drivers/media/platform/Kconfig            |   10 +
> >  drivers/media/platform/Makefile           |    2 +
> >  drivers/media/platform/vsp1/Makefile      |    5 +
> >  drivers/media/platform/vsp1/vsp1.h        |   73 ++
> >  drivers/media/platform/vsp1/vsp1_drv.c    |  475 ++++++++++++
> >  drivers/media/platform/vsp1/vsp1_entity.c |  186 +++++
> >  drivers/media/platform/vsp1/vsp1_entity.h |   68 ++
> >  drivers/media/platform/vsp1/vsp1_lif.c    |  237 ++++++
> >  drivers/media/platform/vsp1/vsp1_lif.h    |   38 +
> >  drivers/media/platform/vsp1/vsp1_regs.h   |  581 +++++++++++++++
> >  drivers/media/platform/vsp1/vsp1_rpf.c    |  209 ++++++
> >  drivers/media/platform/vsp1/vsp1_rwpf.c   |  124 ++++
> >  drivers/media/platform/vsp1/vsp1_rwpf.h   |   56 ++
> >  drivers/media/platform/vsp1/vsp1_uds.c    |  346 +++++++++
> >  drivers/media/platform/vsp1/vsp1_uds.h    |   41 +
> >  drivers/media/platform/vsp1/vsp1_video.c  | 1154 ++++++++++++++++++++++++
> >  drivers/media/platform/vsp1/vsp1_video.h  |  144 ++++
> >  drivers/media/platform/vsp1/vsp1_wpf.c    |  233 ++++++
> >  include/linux/platform_data/vsp1.h        |   25 +
> >  19 files changed, 4007 insertions(+)
> >  create mode 100644 drivers/media/platform/vsp1/Makefile
> >  create mode 100644 drivers/media/platform/vsp1/vsp1.h
> >  create mode 100644 drivers/media/platform/vsp1/vsp1_drv.c
> >  create mode 100644 drivers/media/platform/vsp1/vsp1_entity.c
> >  create mode 100644 drivers/media/platform/vsp1/vsp1_entity.h
> >  create mode 100644 drivers/media/platform/vsp1/vsp1_lif.c
> >  create mode 100644 drivers/media/platform/vsp1/vsp1_lif.h
> >  create mode 100644 drivers/media/platform/vsp1/vsp1_regs.h
> >  create mode 100644 drivers/media/platform/vsp1/vsp1_rpf.c
> >  create mode 100644 drivers/media/platform/vsp1/vsp1_rwpf.c
> >  create mode 100644 drivers/media/platform/vsp1/vsp1_rwpf.h
> >  create mode 100644 drivers/media/platform/vsp1/vsp1_uds.c
> >  create mode 100644 drivers/media/platform/vsp1/vsp1_uds.h
> >  create mode 100644 drivers/media/platform/vsp1/vsp1_video.c
> >  create mode 100644 drivers/media/platform/vsp1/vsp1_video.h
> >  create mode 100644 drivers/media/platform/vsp1/vsp1_wpf.c
> >  create mode 100644 include/linux/platform_data/vsp1.h
> 
> Hi Laurent,
> 
> It took some effort, but I finally did find some things to complain about
> :-)

:-)

> > diff --git a/drivers/media/platform/vsp1/vsp1_video.c
> > b/drivers/media/platform/vsp1/vsp1_video.c new file mode 100644
> > index 0000000..47a739a
> > --- /dev/null
> > +++ b/drivers/media/platform/vsp1/vsp1_video.c

[snip]

> > +static int __vsp1_video_try_format(struct vsp1_video *video,
> > +                              struct v4l2_pix_format_mplane *pix,
> > +                              const struct vsp1_format_info **fmtinfo)
> > +{
> > +   const struct vsp1_format_info *info;
> > +   unsigned int width = pix->width;
> > +   unsigned int height = pix->height;
> > +   unsigned int i;
> > +
> > +   /* Retrieve format information and select the default format if the
> > +    * requested format isn't supported.
> > +    */
> > +   info = vsp1_get_format_info(pix->pixelformat);
> > +   if (info == NULL)
> > +           info = vsp1_get_format_info(VSP1_VIDEO_DEF_FORMAT);
> > +
> > +   pix->pixelformat = info->fourcc;
> > +   pix->colorspace = V4L2_COLORSPACE_SRGB;
> > +   pix->field = V4L2_FIELD_NONE;
> 
> pix->priv should be set to 0. v4l2-compliance catches such errors, BTW.

Isn't this handled by the CLEAR_AFTER_FIELD() macros in v4l2-ioctl2.c ?

> > +
> > +   /* Align the width and height for YUV 4:2:2 and 4:2:0 formats. */
> > +   width = round_down(width, info->hsub);
> > +   height = round_down(height, info->vsub);
> > +
> > +   /* Clamp the width and height. */
> > +   pix->width = clamp(width, VSP1_VIDEO_MIN_WIDTH,
> > VSP1_VIDEO_MAX_WIDTH);
> > +   pix->height = clamp(height, VSP1_VIDEO_MIN_HEIGHT,
> > +                       VSP1_VIDEO_MAX_HEIGHT);
> > +
> > +   /* Compute and clamp the stride and image size. */
> > +   for (i = 0; i < max(info->planes, 2U); ++i) {
> > +           unsigned int hsub = i > 0 ? info->hsub : 1;
> > +           unsigned int vsub = i > 0 ? info->vsub : 1;
> > +           unsigned int bpl;
> > +
> > +           bpl = clamp_t(unsigned int, pix->plane_fmt[i].bytesperline,
> > +                         pix->width / hsub * info->bpp[i] / 8,
> > +                         round_down(65535U, 128));
> > +
> > +           pix->plane_fmt[i].bytesperline = round_up(bpl, 128);
> > +           pix->plane_fmt[i].sizeimage = bpl * pix->height / vsub;
> > +   }
> > +
> > +   if (info->planes == 3) {
> > +           /* The second and third planes must have the same stride. */
> > +           pix->plane_fmt[2].bytesperline = pix->plane_fmt[1].bytesperline;
> > +           pix->plane_fmt[2].sizeimage = pix->plane_fmt[1].sizeimage;
> > +   }
> > +
> > +   pix->num_planes = info->planes;
> > +
> > +   if (fmtinfo)
> > +           *fmtinfo = info;
> > +
> > +   return 0;
> > +}

[snip]

> > +static int
> > +vsp1_video_reqbufs(struct file *file, void *fh, struct
> > v4l2_requestbuffers *rb)
> > +{
> > +   struct v4l2_fh *vfh = file->private_data;
> > +   struct vsp1_video *video = to_vsp1_video(vfh->vdev);
> > +   int ret;
> > +
> > +   mutex_lock(&video->lock);
> > +
> > +   if (video->queue.owner && video->queue.owner != vfh) {
> > +           ret = -EBUSY;
> > +           goto done;
> > +   }
> > +
> > +   ret = vb2_reqbufs(&video->queue, rb);
> > +   if (ret < 0)
> > +           goto done;
> > +
> > +   video->queue.owner = vfh;
> > +
> > +done:
> > +   mutex_unlock(&video->lock);
> > +   return ret ? ret : rb->count;
> 
> On success reqbufs should return 0, not the number of allocated buffers.

Oops, my bad.

> Have you considered using the vb2 helper functions in videobuf2-core.c? They
> take care of the queue ownership and often simplify drivers considerably.

I have, and mistakenly believed that they relied on using the video device 
lock. I'll use them.

> > +}

[snip]

> > +static int
> > +vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
> > +{
> > +   struct v4l2_fh *vfh = file->private_data;
> > +   struct vsp1_video *video = to_vsp1_video(vfh->vdev);
> > +   struct vsp1_pipeline *pipe;
> > +   int ret;
> > +
> > +   mutex_lock(&video->lock);
> > +
> > +   if (video->queue.owner && video->queue.owner != vfh) {
> > +           ret = -EBUSY;
> > +           goto err_unlock;
> > +   }
> > +
> > +   video->sequence = 0;
> > +
> > +   /* Start streaming on the pipeline. No link touching an entity in the
> > +    * pipeline can be activated or deactivated once streaming is
> > started.
> > +    *
> > +    * Use the VSP1 pipeline object embedded in the first video object
> > +    * that starts streaming.
> > +    */
> > +   pipe = video->video.entity.pipe
> > +        ? to_vsp1_pipeline(&video->video.entity) : &video->pipe;
> > +
> > +   ret = media_entity_pipeline_start(&video->video.entity, &pipe->pipe);
> > +   if (ret < 0)
> > +           goto err_unlock;
> > +
> > +   /* Verify that the configured format matches the output of the
> > +    * connected subdev.
> > +    */
> > +   ret = vsp1_video_verify_format(video);
> > +   if (ret < 0)
> > +           goto err_stop;
> > +
> > +   ret = vsp1_pipeline_init(pipe, video);
> > +   if (ret < 0)
> > +           goto err_stop;
> 
> Shouldn't the code above be better placed in the vb2 start_streaming op?

The code needs to be run before buffers are enqueued to the driver, that's why 
I've placed it here.

> > +
> > +   /* Start the queue. */
> > +   ret = vb2_streamon(&video->queue, type);
> > +   if (ret < 0)
> > +           goto err_cleanup;
> > +
> > +   mutex_unlock(&video->lock);
> > +   return 0;
> > +
> > +err_cleanup:
> > +   vsp1_pipeline_cleanup(pipe);
> > +err_stop:
> > +   media_entity_pipeline_stop(&video->video.entity);
> > +err_unlock:
> > +   mutex_unlock(&video->lock);
> > +   return ret;
> > +
> > +}
> > +
> > +static int
> > +vsp1_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type
> > type)
> > +{
> > +   struct v4l2_fh *vfh = file->private_data;
> > +   struct vsp1_video *video = to_vsp1_video(vfh->vdev);
> > +   int ret;
> > +
> > +   mutex_lock(&video->lock);
> > +
> > +   if (video->queue.owner && video->queue.owner != vfh) {
> > +           ret = -EBUSY;
> > +           goto done;
> > +   }
> > +
> > +   ret = vb2_streamoff(&video->queue, type);
> > +
> > +done:
> > +   mutex_unlock(&video->lock);
> > +   return ret;
> > +}

-- 
Regards,

Laurent Pinchart

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

Reply via email to