linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/32] VSP: Add R-Car Gen3 support
@ 2015-09-13 20:56 Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 01/32] v4l: vsp1: Change the type of the rwpf field in struct vsp1_video Laurent Pinchart
                   ` (32 more replies)
  0 siblings, 33 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

Hello,

This patch set adds support for the Renesas R-Car Gen3 SoC family to the VSP1
driver. The large number of patches is caused by a change in the display
controller architecture that makes usage of the VSP mandatory as the display
controller has lost the ability to read data from memory.

Patch 01/31 to 26/31 prepare for the implementation of an API exported to the
DRM driver in patch 27/31. Patches 30/31 enables support for the R-Car Gen3
family, and patch 31/31 finally enhances perfomances by implementing support
for display lists.

Laurent Pinchart (31):
  v4l: vsp1: Change the type of the rwpf field in struct vsp1_video
  v4l: vsp1: Store the memory format in struct vsp1_rwpf
  v4l: vsp1: Move video operations to vsp1_rwpf
  v4l: vsp1: Rename vsp1_video_buffer to vsp1_vb2_buffer
  v4l: vsp1: Move video device out of struct vsp1_rwpf
  v4l: vsp1: Make rwpf operations independent of video device
  v4l: vsp1: Support VSP1 instances without any UDS
  v4l: vsp1: Move vsp1_video pointer from vsp1_entity to vsp1_rwpf
  v4l: vsp1: Remove struct vsp1_pipeline num_video field
  v4l: vsp1: Decouple pipeline end of frame processing from vsp1_video
  v4l: vsp1: Split pipeline management code from vsp1_video.c
  v4l: vsp1: Rename video pipeline functions to use vsp1_video prefix
  v4l: vsp1: Extract pipeline initialization code into a function
  v4l: vsp1: Reuse local variable instead of recomputing it
  v4l: vsp1: Extract link creation to separate function
  v4l: vsp1: Document the vsp1_pipeline structure
  v4l: vsp1: Fix typo in VI6_DISP_IRQ_STA_DST register name
  v4l: vsp1: Set the SRU CTRL0 register when starting the stream
  v4l: vsp1: Remove unused module write functions
  v4l: vsp1: Move entity route setup function to vsp1_entity.c
  v4l: vsp1: Make number of BRU inputs configurable
  v4l: vsp1: Make the BRU optional
  v4l: vsp1: Move format info to vsp1_pipe.c
  v4l: vsp1: Make the userspace API optional
  v4l: vsp1: Make pipeline inputs array index by RPF index
  v4l: vsp1: Set the alpha value manually in RPF and WPF s_stream
    handlers
  v4l: vsp1: Don't validate links when the userspace API is disabled
  v4l: vsp1: Add VSP+DU support
  v4l: vsp1: Disconnect unused RPFs from the DRM pipeline
  v4l: vsp1: Implement atomic update for the DRM driver
  v4l: vsp1: Add support for the R-Car Gen3 VSP2

Takashi Saito (1):
  v4l: vsp1: Add display list support

 .../devicetree/bindings/media/renesas,vsp1.txt     |  11 +-
 drivers/media/platform/vsp1/Makefile               |   3 +-
 drivers/media/platform/vsp1/vsp1.h                 |  28 +
 drivers/media/platform/vsp1/vsp1_bru.c             |  33 +-
 drivers/media/platform/vsp1/vsp1_bru.h             |   3 +-
 drivers/media/platform/vsp1/vsp1_dl.c              | 304 +++++++++++
 drivers/media/platform/vsp1/vsp1_dl.h              |  42 ++
 drivers/media/platform/vsp1/vsp1_drm.c             | 595 +++++++++++++++++++++
 drivers/media/platform/vsp1/vsp1_drm.h             |  38 ++
 drivers/media/platform/vsp1/vsp1_drv.c             | 255 +++++++--
 drivers/media/platform/vsp1/vsp1_entity.c          |  31 +-
 drivers/media/platform/vsp1/vsp1_entity.h          |  14 +-
 drivers/media/platform/vsp1/vsp1_hsit.c            |   2 +-
 drivers/media/platform/vsp1/vsp1_lif.c             |  11 +-
 drivers/media/platform/vsp1/vsp1_lut.c             |   7 +-
 drivers/media/platform/vsp1/vsp1_pipe.c            | 405 ++++++++++++++
 drivers/media/platform/vsp1/vsp1_pipe.h            | 134 +++++
 drivers/media/platform/vsp1/vsp1_regs.h            |  14 +-
 drivers/media/platform/vsp1/vsp1_rpf.c             |  77 ++-
 drivers/media/platform/vsp1/vsp1_rwpf.h            |  24 +-
 drivers/media/platform/vsp1/vsp1_sru.c             |   9 +-
 drivers/media/platform/vsp1/vsp1_uds.c             |   8 +-
 drivers/media/platform/vsp1/vsp1_video.c           | 515 ++++--------------
 drivers/media/platform/vsp1/vsp1_video.h           | 110 +---
 drivers/media/platform/vsp1/vsp1_wpf.c             |  88 ++-
 include/media/vsp1.h                               |  33 ++
 26 files changed, 2050 insertions(+), 744 deletions(-)
 create mode 100644 drivers/media/platform/vsp1/vsp1_dl.c
 create mode 100644 drivers/media/platform/vsp1/vsp1_dl.h
 create mode 100644 drivers/media/platform/vsp1/vsp1_drm.c
 create mode 100644 drivers/media/platform/vsp1/vsp1_drm.h
 create mode 100644 drivers/media/platform/vsp1/vsp1_pipe.c
 create mode 100644 drivers/media/platform/vsp1/vsp1_pipe.h
 create mode 100644 include/media/vsp1.h

-- 
Regards,

Laurent Pinchart


^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH 01/32] v4l: vsp1: Change the type of the rwpf field in struct vsp1_video
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 02/32] v4l: vsp1: Store the memory format in struct vsp1_rwpf Laurent Pinchart
                   ` (31 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

The rwpf field contains a pointer to the rpf or wpf associated with the
video node. Instead of storing it as a vsp1_entity, store the
corresponding vsp1_rwpf pointer to allow accessing the vsp1_rwpf fields
directly.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_rpf.c   | 2 +-
 drivers/media/platform/vsp1/vsp1_video.c | 4 ++--
 drivers/media/platform/vsp1/vsp1_video.h | 5 +++--
 drivers/media/platform/vsp1/vsp1_wpf.c   | 2 +-
 4 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index 3294529a3108..a1093cc1b9a1 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -271,7 +271,7 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
 	video->vsp1 = vsp1;
 	video->ops = &rpf_vdev_ops;
 
-	ret = vsp1_video_init(video, &rpf->entity);
+	ret = vsp1_video_init(video, rpf);
 	if (ret < 0)
 		goto error;
 
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 3c124c14ce14..48480e66fad6 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -1187,7 +1187,7 @@ static struct v4l2_file_operations vsp1_video_fops = {
  * Initialization and Cleanup
  */
 
-int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf)
+int vsp1_video_init(struct vsp1_video *video, struct vsp1_rwpf *rwpf)
 {
 	const char *direction;
 	int ret;
@@ -1242,7 +1242,7 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf)
 	video->video.v4l2_dev = &video->vsp1->v4l2_dev;
 	video->video.fops = &vsp1_video_fops;
 	snprintf(video->video.name, sizeof(video->video.name), "%s %s",
-		 rwpf->subdev.name, direction);
+		 rwpf->entity.subdev.name, direction);
 	video->video.vfl_type = VFL_TYPE_GRABBER;
 	video->video.release = video_device_release_empty;
 	video->video.ioctl_ops = &vsp1_video_ioctl_ops;
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index 0887a4d2742c..5f48eec5562c 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -20,6 +20,7 @@
 #include <media/media-entity.h>
 #include <media/videobuf2-core.h>
 
+struct vsp1_rwpf;
 struct vsp1_video;
 
 /*
@@ -113,7 +114,7 @@ struct vsp1_video_operations {
 
 struct vsp1_video {
 	struct vsp1_device *vsp1;
-	struct vsp1_entity *rwpf;
+	struct vsp1_rwpf *rwpf;
 
 	const struct vsp1_video_operations *ops;
 
@@ -140,7 +141,7 @@ static inline struct vsp1_video *to_vsp1_video(struct video_device *vdev)
 	return container_of(vdev, struct vsp1_video, video);
 }
 
-int vsp1_video_init(struct vsp1_video *video, struct vsp1_entity *rwpf);
+int vsp1_video_init(struct vsp1_video *video, struct vsp1_rwpf *rwpf);
 void vsp1_video_cleanup(struct vsp1_video *video);
 
 void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe);
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index 1d2b3a2f1573..50dfb3060156 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -271,7 +271,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
 	video->vsp1 = vsp1;
 	video->ops = &wpf_vdev_ops;
 
-	ret = vsp1_video_init(video, &wpf->entity);
+	ret = vsp1_video_init(video, wpf);
 	if (ret < 0)
 		goto error;
 
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 02/32] v4l: vsp1: Store the memory format in struct vsp1_rwpf
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 01/32] v4l: vsp1: Change the type of the rwpf field in struct vsp1_video Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 03/32] v4l: vsp1: Move video operations to vsp1_rwpf Laurent Pinchart
                   ` (30 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

Move the format from struct vsp1_video to struct vsp1_rwpf to prepare
for VSPD KMS support that will not instantiate V4L2 video device nodes.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_bru.c   |  4 ++--
 drivers/media/platform/vsp1/vsp1_rpf.c   |  4 ++--
 drivers/media/platform/vsp1/vsp1_rwpf.h  |  2 ++
 drivers/media/platform/vsp1/vsp1_video.c | 40 ++++++++++++++++----------------
 drivers/media/platform/vsp1/vsp1_video.h |  2 --
 drivers/media/platform/vsp1/vsp1_wpf.c   |  4 ++--
 6 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c
index 7dd763311c0f..1308dfef0f92 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.c
+++ b/drivers/media/platform/vsp1/vsp1_bru.c
@@ -94,7 +94,7 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
 	/* Disable dithering and enable color data normalization unless the
 	 * format at the pipeline output is premultiplied.
 	 */
-	flags = pipe->output ? pipe->output->video.format.flags : 0;
+	flags = pipe->output ? pipe->output->format.flags : 0;
 	vsp1_bru_write(bru, VI6_BRU_INCTRL,
 		       flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ?
 		       0 : VI6_BRU_INCTRL_NRM);
@@ -125,7 +125,7 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
 		if (bru->inputs[i].rpf) {
 			ctrl |= VI6_BRU_CTRL_RBC;
 
-			premultiplied = bru->inputs[i].rpf->video.format.flags
+			premultiplied = bru->inputs[i].rpf->format.flags
 				      & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA;
 		} else {
 			ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP)
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index a1093cc1b9a1..6e0564b5b37b 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -75,8 +75,8 @@ static const struct v4l2_ctrl_ops rpf_ctrl_ops = {
 static int rpf_s_stream(struct v4l2_subdev *subdev, int enable)
 {
 	struct vsp1_rwpf *rpf = to_rwpf(subdev);
-	const struct vsp1_format_info *fmtinfo = rpf->video.fmtinfo;
-	const struct v4l2_pix_format_mplane *format = &rpf->video.format;
+	const struct vsp1_format_info *fmtinfo = rpf->fmtinfo;
+	const struct v4l2_pix_format_mplane *format = &rpf->format;
 	const struct v4l2_rect *crop = &rpf->crop;
 	u32 pstride;
 	u32 infmt;
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index f452dce1a931..8609c3d02679 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -32,6 +32,8 @@ struct vsp1_rwpf {
 	unsigned int max_width;
 	unsigned int max_height;
 
+	struct v4l2_pix_format_mplane format;
+	const struct vsp1_format_info *fmtinfo;
 	struct {
 		unsigned int left;
 		unsigned int top;
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 48480e66fad6..90d5791c80b6 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -185,9 +185,9 @@ static int vsp1_video_verify_format(struct vsp1_video *video)
 	if (ret < 0)
 		return ret == -ENOIOCTLCMD ? -EINVAL : ret;
 
-	if (video->fmtinfo->mbus != fmt.format.code ||
-	    video->format.height != fmt.format.height ||
-	    video->format.width != fmt.format.width)
+	if (video->rwpf->fmtinfo->mbus != fmt.format.code ||
+	    video->rwpf->format.height != fmt.format.height ||
+	    video->rwpf->format.width != fmt.format.width)
 		return -EINVAL;
 
 	return 0;
@@ -805,7 +805,7 @@ vsp1_video_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
 
 		format = &pix_mp;
 	} else {
-		format = &video->format;
+		format = &video->rwpf->format;
 	}
 
 	*nplanes = format->num_planes;
@@ -822,7 +822,7 @@ static int vsp1_video_buffer_prepare(struct vb2_buffer *vb)
 {
 	struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue);
 	struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vb);
-	const struct v4l2_pix_format_mplane *format = &video->format;
+	const struct v4l2_pix_format_mplane *format = &video->rwpf->format;
 	unsigned int i;
 
 	if (vb->num_planes < format->num_planes)
@@ -904,7 +904,7 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
 				struct vsp1_rwpf *rpf =
 					to_rwpf(&pipe->uds_input->subdev);
 
-				uds->scale_alpha = rpf->video.fmtinfo->alpha;
+				uds->scale_alpha = rpf->fmtinfo->alpha;
 			}
 		}
 
@@ -1008,7 +1008,7 @@ vsp1_video_get_format(struct file *file, void *fh, struct v4l2_format *format)
 		return -EINVAL;
 
 	mutex_lock(&video->lock);
-	format->fmt.pix_mp = video->format;
+	format->fmt.pix_mp = video->rwpf->format;
 	mutex_unlock(&video->lock);
 
 	return 0;
@@ -1048,8 +1048,8 @@ vsp1_video_set_format(struct file *file, void *fh, struct v4l2_format *format)
 		goto done;
 	}
 
-	video->format = format->fmt.pix_mp;
-	video->fmtinfo = info;
+	video->rwpf->format = format->fmt.pix_mp;
+	video->rwpf->fmtinfo = info;
 
 done:
 	mutex_unlock(&video->lock);
@@ -1226,17 +1226,17 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_rwpf *rwpf)
 		return ret;
 
 	/* ... and the format ... */
-	video->fmtinfo = vsp1_get_format_info(VSP1_VIDEO_DEF_FORMAT);
-	video->format.pixelformat = video->fmtinfo->fourcc;
-	video->format.colorspace = V4L2_COLORSPACE_SRGB;
-	video->format.field = V4L2_FIELD_NONE;
-	video->format.width = VSP1_VIDEO_DEF_WIDTH;
-	video->format.height = VSP1_VIDEO_DEF_HEIGHT;
-	video->format.num_planes = 1;
-	video->format.plane_fmt[0].bytesperline =
-		video->format.width * video->fmtinfo->bpp[0] / 8;
-	video->format.plane_fmt[0].sizeimage =
-		video->format.plane_fmt[0].bytesperline * video->format.height;
+	rwpf->fmtinfo = vsp1_get_format_info(VSP1_VIDEO_DEF_FORMAT);
+	rwpf->format.pixelformat = rwpf->fmtinfo->fourcc;
+	rwpf->format.colorspace = V4L2_COLORSPACE_SRGB;
+	rwpf->format.field = V4L2_FIELD_NONE;
+	rwpf->format.width = VSP1_VIDEO_DEF_WIDTH;
+	rwpf->format.height = VSP1_VIDEO_DEF_HEIGHT;
+	rwpf->format.num_planes = 1;
+	rwpf->format.plane_fmt[0].bytesperline =
+		rwpf->format.width * rwpf->fmtinfo->bpp[0] / 8;
+	rwpf->format.plane_fmt[0].sizeimage =
+		rwpf->format.plane_fmt[0].bytesperline * rwpf->format.height;
 
 	/* ... and the video node... */
 	video->video.v4l2_dev = &video->vsp1->v4l2_dev;
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index 5f48eec5562c..dbcb7b5b6c95 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -123,8 +123,6 @@ struct vsp1_video {
 	struct media_pad pad;
 
 	struct mutex lock;
-	struct v4l2_pix_format_mplane format;
-	const struct vsp1_format_info *fmtinfo;
 
 	struct vsp1_pipeline pipe;
 	unsigned int pipe_index;
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index 50dfb3060156..b14070d1e457 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -112,7 +112,7 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
 
 	/* Destination stride. */
 	if (!pipe->lif) {
-		struct v4l2_pix_format_mplane *format = &wpf->video.format;
+		struct v4l2_pix_format_mplane *format = &wpf->format;
 
 		vsp1_wpf_write(wpf, VI6_WPF_DSTM_STRIDE_Y,
 			       format->plane_fmt[0].bytesperline);
@@ -130,7 +130,7 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
 
 	/* Format */
 	if (!pipe->lif) {
-		const struct vsp1_format_info *fmtinfo = wpf->video.fmtinfo;
+		const struct vsp1_format_info *fmtinfo = wpf->fmtinfo;
 
 		outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT;
 
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 03/32] v4l: vsp1: Move video operations to vsp1_rwpf
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 01/32] v4l: vsp1: Change the type of the rwpf field in struct vsp1_video Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 02/32] v4l: vsp1: Store the memory format in struct vsp1_rwpf Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 04/32] v4l: vsp1: Rename vsp1_video_buffer to vsp1_vb2_buffer Laurent Pinchart
                   ` (29 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

This removes the dependency of vsp1_rpf and vsp1_wpf on vsp1_video,
making it possible to reuse the operations without a V4L2 video device
node.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_rpf.c   | 11 +++++------
 drivers/media/platform/vsp1/vsp1_rwpf.h  |  9 +++++++++
 drivers/media/platform/vsp1/vsp1_video.c |  4 ++--
 drivers/media/platform/vsp1/vsp1_video.h |  6 ------
 drivers/media/platform/vsp1/vsp1_wpf.c   | 12 +++++-------
 5 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index 6e0564b5b37b..a17154d98a54 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -186,10 +186,8 @@ static struct v4l2_subdev_ops rpf_ops = {
  * Video Device Operations
  */
 
-static void rpf_vdev_queue(struct vsp1_video *video,
-			   struct vsp1_video_buffer *buf)
+static void rpf_buf_queue(struct vsp1_rwpf *rpf, struct vsp1_video_buffer *buf)
 {
-	struct vsp1_rwpf *rpf = container_of(video, struct vsp1_rwpf, video);
 	unsigned int i;
 
 	for (i = 0; i < 3; ++i)
@@ -208,8 +206,8 @@ static void rpf_vdev_queue(struct vsp1_video *video,
 			       buf->addr[2] + rpf->offsets[1]);
 }
 
-static const struct vsp1_video_operations rpf_vdev_ops = {
-	.queue = rpf_vdev_queue,
+static const struct vsp1_rwpf_operations rpf_vdev_ops = {
+	.queue = rpf_buf_queue,
 };
 
 /* -----------------------------------------------------------------------------
@@ -227,6 +225,8 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
 	if (rpf == NULL)
 		return ERR_PTR(-ENOMEM);
 
+	rpf->ops = &rpf_vdev_ops;
+
 	rpf->max_width = RPF_MAX_WIDTH;
 	rpf->max_height = RPF_MAX_HEIGHT;
 
@@ -269,7 +269,6 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
 
 	video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
 	video->vsp1 = vsp1;
-	video->ops = &rpf_vdev_ops;
 
 	ret = vsp1_video_init(video, rpf);
 	if (ret < 0)
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index 8609c3d02679..3cc80be03524 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -24,11 +24,20 @@
 #define RWPF_PAD_SINK				0
 #define RWPF_PAD_SOURCE				1
 
+struct vsp1_rwpf;
+struct vsp1_video_buffer;
+
+struct vsp1_rwpf_operations {
+	void (*queue)(struct vsp1_rwpf *rwpf, struct vsp1_video_buffer *buf);
+};
+
 struct vsp1_rwpf {
 	struct vsp1_entity entity;
 	struct vsp1_video video;
 	struct v4l2_ctrl_handler ctrls;
 
+	const struct vsp1_rwpf_operations *ops;
+
 	unsigned int max_width;
 	unsigned int max_height;
 
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 90d5791c80b6..2ddbcbaf498f 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -631,7 +631,7 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe,
 
 	spin_lock_irqsave(&pipe->irqlock, flags);
 
-	video->ops->queue(video, buf);
+	video->rwpf->ops->queue(video->rwpf, buf);
 	pipe->buffers_ready |= 1 << video->pipe_index;
 
 	spin_unlock_irqrestore(&pipe->irqlock, flags);
@@ -857,7 +857,7 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb)
 
 	spin_lock_irqsave(&pipe->irqlock, flags);
 
-	video->ops->queue(video, buf);
+	video->rwpf->ops->queue(video->rwpf, buf);
 	pipe->buffers_ready |= 1 << video->pipe_index;
 
 	if (vb2_is_streaming(&video->queue) &&
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index dbcb7b5b6c95..34efc471351c 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -108,16 +108,10 @@ to_vsp1_video_buffer(struct vb2_buffer *vb)
 	return container_of(vb, struct vsp1_video_buffer, buf);
 }
 
-struct vsp1_video_operations {
-	void (*queue)(struct vsp1_video *video, struct vsp1_video_buffer *buf);
-};
-
 struct vsp1_video {
 	struct vsp1_device *vsp1;
 	struct vsp1_rwpf *rwpf;
 
-	const struct vsp1_video_operations *ops;
-
 	struct video_device video;
 	enum v4l2_buf_type type;
 	struct media_pad pad;
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index b14070d1e457..f93b545949b6 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -195,11 +195,8 @@ static struct v4l2_subdev_ops wpf_ops = {
  * Video Device Operations
  */
 
-static void wpf_vdev_queue(struct vsp1_video *video,
-			   struct vsp1_video_buffer *buf)
+static void wpf_buf_queue(struct vsp1_rwpf *wpf, struct vsp1_video_buffer *buf)
 {
-	struct vsp1_rwpf *wpf = container_of(video, struct vsp1_rwpf, video);
-
 	vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, buf->addr[0]);
 	if (buf->buf.num_planes > 1)
 		vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, buf->addr[1]);
@@ -207,8 +204,8 @@ static void wpf_vdev_queue(struct vsp1_video *video,
 		vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, buf->addr[2]);
 }
 
-static const struct vsp1_video_operations wpf_vdev_ops = {
-	.queue = wpf_vdev_queue,
+static const struct vsp1_rwpf_operations wpf_vdev_ops = {
+	.queue = wpf_buf_queue,
 };
 
 /* -----------------------------------------------------------------------------
@@ -227,6 +224,8 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
 	if (wpf == NULL)
 		return ERR_PTR(-ENOMEM);
 
+	wpf->ops = &wpf_vdev_ops;
+
 	wpf->max_width = WPF_MAX_WIDTH;
 	wpf->max_height = WPF_MAX_HEIGHT;
 
@@ -269,7 +268,6 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
 
 	video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 	video->vsp1 = vsp1;
-	video->ops = &wpf_vdev_ops;
 
 	ret = vsp1_video_init(video, wpf);
 	if (ret < 0)
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 04/32] v4l: vsp1: Rename vsp1_video_buffer to vsp1_vb2_buffer
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (2 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 03/32] v4l: vsp1: Move video operations to vsp1_rwpf Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 05/32] v4l: vsp1: Move video device out of struct vsp1_rwpf Laurent Pinchart
                   ` (28 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

The structure represent a vsp1 videobuf2 buffer, name it accordingly.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_rpf.c   |  2 +-
 drivers/media/platform/vsp1/vsp1_rwpf.h  |  4 ++--
 drivers/media/platform/vsp1/vsp1_video.c | 20 ++++++++++----------
 drivers/media/platform/vsp1/vsp1_video.h |  7 +++----
 drivers/media/platform/vsp1/vsp1_wpf.c   |  2 +-
 5 files changed, 17 insertions(+), 18 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index a17154d98a54..9c2e34374c60 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -186,7 +186,7 @@ static struct v4l2_subdev_ops rpf_ops = {
  * Video Device Operations
  */
 
-static void rpf_buf_queue(struct vsp1_rwpf *rpf, struct vsp1_video_buffer *buf)
+static void rpf_buf_queue(struct vsp1_rwpf *rpf, struct vsp1_vb2_buffer *buf)
 {
 	unsigned int i;
 
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index 3cc80be03524..aa22cc062ff3 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -25,10 +25,10 @@
 #define RWPF_PAD_SOURCE				1
 
 struct vsp1_rwpf;
-struct vsp1_video_buffer;
+struct vsp1_vb2_buffer;
 
 struct vsp1_rwpf_operations {
-	void (*queue)(struct vsp1_rwpf *rwpf, struct vsp1_video_buffer *buf);
+	void (*queue)(struct vsp1_rwpf *rwpf, struct vsp1_vb2_buffer *buf);
 };
 
 struct vsp1_rwpf {
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 2ddbcbaf498f..d02cd63a9c5e 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -577,12 +577,12 @@ static bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe)
  *
  * Return the next queued buffer or NULL if the queue is empty.
  */
-static struct vsp1_video_buffer *
+static struct vsp1_vb2_buffer *
 vsp1_video_complete_buffer(struct vsp1_video *video)
 {
 	struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity);
-	struct vsp1_video_buffer *next = NULL;
-	struct vsp1_video_buffer *done;
+	struct vsp1_vb2_buffer *next = NULL;
+	struct vsp1_vb2_buffer *done;
 	unsigned long flags;
 	unsigned int i;
 
@@ -594,7 +594,7 @@ vsp1_video_complete_buffer(struct vsp1_video *video)
 	}
 
 	done = list_first_entry(&video->irqqueue,
-				struct vsp1_video_buffer, queue);
+				struct vsp1_vb2_buffer, queue);
 
 	/* In DU output mode reuse the buffer if the list is singular. */
 	if (pipe->lif && list_is_singular(&video->irqqueue)) {
@@ -606,7 +606,7 @@ vsp1_video_complete_buffer(struct vsp1_video *video)
 
 	if (!list_empty(&video->irqqueue))
 		next = list_first_entry(&video->irqqueue,
-					struct vsp1_video_buffer, queue);
+					struct vsp1_vb2_buffer, queue);
 
 	spin_unlock_irqrestore(&video->irqlock, flags);
 
@@ -622,7 +622,7 @@ vsp1_video_complete_buffer(struct vsp1_video *video)
 static void vsp1_video_frame_end(struct vsp1_pipeline *pipe,
 				 struct vsp1_video *video)
 {
-	struct vsp1_video_buffer *buf;
+	struct vsp1_vb2_buffer *buf;
 	unsigned long flags;
 
 	buf = vsp1_video_complete_buffer(video);
@@ -821,7 +821,7 @@ vsp1_video_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
 static int vsp1_video_buffer_prepare(struct vb2_buffer *vb)
 {
 	struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue);
-	struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vb);
+	struct vsp1_vb2_buffer *buf = to_vsp1_vb2_buffer(vb);
 	const struct v4l2_pix_format_mplane *format = &video->rwpf->format;
 	unsigned int i;
 
@@ -843,7 +843,7 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb)
 {
 	struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue);
 	struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity);
-	struct vsp1_video_buffer *buf = to_vsp1_video_buffer(vb);
+	struct vsp1_vb2_buffer *buf = to_vsp1_vb2_buffer(vb);
 	unsigned long flags;
 	bool empty;
 
@@ -935,7 +935,7 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq)
 {
 	struct vsp1_video *video = vb2_get_drv_priv(vq);
 	struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity);
-	struct vsp1_video_buffer *buffer;
+	struct vsp1_vb2_buffer *buffer;
 	unsigned long flags;
 	int ret;
 
@@ -1260,7 +1260,7 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_rwpf *rwpf)
 	video->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
 	video->queue.lock = &video->lock;
 	video->queue.drv_priv = video;
-	video->queue.buf_struct_size = sizeof(struct vsp1_video_buffer);
+	video->queue.buf_struct_size = sizeof(struct vsp1_vb2_buffer);
 	video->queue.ops = &vsp1_video_queue_qops;
 	video->queue.mem_ops = &vb2_dma_contig_memops;
 	video->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index 34efc471351c..e66ee14c596d 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -94,7 +94,7 @@ static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e)
 		return NULL;
 }
 
-struct vsp1_video_buffer {
+struct vsp1_vb2_buffer {
 	struct vb2_buffer buf;
 	struct list_head queue;
 
@@ -102,10 +102,9 @@ struct vsp1_video_buffer {
 	unsigned int length[3];
 };
 
-static inline struct vsp1_video_buffer *
-to_vsp1_video_buffer(struct vb2_buffer *vb)
+static inline struct vsp1_vb2_buffer *to_vsp1_vb2_buffer(struct vb2_buffer *vb)
 {
-	return container_of(vb, struct vsp1_video_buffer, buf);
+	return container_of(vb, struct vsp1_vb2_buffer, buf);
 }
 
 struct vsp1_video {
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index f93b545949b6..1bb389529f24 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -195,7 +195,7 @@ static struct v4l2_subdev_ops wpf_ops = {
  * Video Device Operations
  */
 
-static void wpf_buf_queue(struct vsp1_rwpf *wpf, struct vsp1_video_buffer *buf)
+static void wpf_buf_queue(struct vsp1_rwpf *wpf, struct vsp1_vb2_buffer *buf)
 {
 	vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, buf->addr[0]);
 	if (buf->buf.num_planes > 1)
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 05/32] v4l: vsp1: Move video device out of struct vsp1_rwpf
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (3 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 04/32] v4l: vsp1: Rename vsp1_video_buffer to vsp1_vb2_buffer Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 06/32] v4l: vsp1: Make rwpf operations independent of video device Laurent Pinchart
                   ` (27 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

To make the video device nodes optional we need to decouple the [rw]pf
instances from the video devices. Move video devices out of struct
vsp1_rwpf and instantiate them dynamically in the core driver code.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1.h        |  1 +
 drivers/media/platform/vsp1/vsp1_bru.c    |  1 +
 drivers/media/platform/vsp1/vsp1_drv.c    | 63 +++++++++++++++++++++++++++++--
 drivers/media/platform/vsp1/vsp1_entity.c |  3 --
 drivers/media/platform/vsp1/vsp1_rpf.c    | 22 -----------
 drivers/media/platform/vsp1/vsp1_rwpf.h   |  2 -
 drivers/media/platform/vsp1/vsp1_video.c  | 45 ++++++++++++----------
 drivers/media/platform/vsp1/vsp1_video.h  |  4 +-
 drivers/media/platform/vsp1/vsp1_wpf.c    | 29 --------------
 9 files changed, 90 insertions(+), 80 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 989e96f7e360..b25032bd37a7 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -71,6 +71,7 @@ struct vsp1_device {
 	struct vsp1_rwpf *wpf[VSP1_MAX_WPF];
 
 	struct list_head entities;
+	struct list_head videos;
 
 	struct v4l2_device v4l2_dev;
 	struct media_device media_dev;
diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c
index 1308dfef0f92..b4cc9bc478af 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.c
+++ b/drivers/media/platform/vsp1/vsp1_bru.c
@@ -19,6 +19,7 @@
 #include "vsp1.h"
 #include "vsp1_bru.h"
 #include "vsp1_rwpf.h"
+#include "vsp1_video.h"
 
 #define BRU_MIN_SIZE				1U
 #define BRU_MAX_SIZE				8190U
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 4e61886384e3..de0b80e8d048 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -28,6 +28,7 @@
 #include "vsp1_rwpf.h"
 #include "vsp1_sru.h"
 #include "vsp1_uds.h"
+#include "vsp1_video.h"
 
 /* -----------------------------------------------------------------------------
  * Interrupt Handling
@@ -117,14 +118,19 @@ static int vsp1_create_links(struct vsp1_device *vsp1, struct vsp1_entity *sink)
 
 static void vsp1_destroy_entities(struct vsp1_device *vsp1)
 {
-	struct vsp1_entity *entity;
-	struct vsp1_entity *next;
+	struct vsp1_entity *entity, *_entity;
+	struct vsp1_video *video, *_video;
 
-	list_for_each_entry_safe(entity, next, &vsp1->entities, list_dev) {
+	list_for_each_entry_safe(entity, _entity, &vsp1->entities, list_dev) {
 		list_del(&entity->list_dev);
 		vsp1_entity_destroy(entity);
 	}
 
+	list_for_each_entry_safe(video, _video, &vsp1->videos, list) {
+		list_del(&video->list);
+		vsp1_video_cleanup(video);
+	}
+
 	v4l2_device_unregister(&vsp1->v4l2_dev);
 	media_device_unregister(&vsp1->media_dev);
 }
@@ -202,6 +208,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 	}
 
 	for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
+		struct vsp1_video *video;
 		struct vsp1_rwpf *rpf;
 
 		rpf = vsp1_rpf_create(vsp1, i);
@@ -212,6 +219,14 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 
 		vsp1->rpf[i] = rpf;
 		list_add_tail(&rpf->entity.list_dev, &vsp1->entities);
+
+		video = vsp1_video_create(vsp1, rpf);
+		if (IS_ERR(video)) {
+			ret = PTR_ERR(video);
+			goto done;
+		}
+
+		list_add_tail(&video->list, &vsp1->videos);
 	}
 
 	if (vsp1->pdata.features & VSP1_HAS_SRU) {
@@ -238,6 +253,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 	}
 
 	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
+		struct vsp1_video *video;
 		struct vsp1_rwpf *wpf;
 
 		wpf = vsp1_wpf_create(vsp1, i);
@@ -248,6 +264,15 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 
 		vsp1->wpf[i] = wpf;
 		list_add_tail(&wpf->entity.list_dev, &vsp1->entities);
+
+		video = vsp1_video_create(vsp1, wpf);
+		if (IS_ERR(video)) {
+			ret = PTR_ERR(video);
+			goto done;
+		}
+
+		list_add_tail(&video->list, &vsp1->videos);
+		wpf->entity.sink = &video->video.entity;
 	}
 
 	/* Create links. */
@@ -261,6 +286,37 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 			goto done;
 	}
 
+	for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
+		struct vsp1_rwpf *rpf = vsp1->rpf[i];
+
+		ret = media_entity_create_link(&rpf->entity.video->video.entity,
+					       0, &rpf->entity.subdev.entity,
+					       RWPF_PAD_SINK,
+					       MEDIA_LNK_FL_ENABLED |
+					       MEDIA_LNK_FL_IMMUTABLE);
+		if (ret < 0)
+			goto done;
+	}
+
+	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
+		/* Connect the video device to the WPF. All connections are
+		 * immutable except for the WPF0 source link if a LIF is
+		 * present.
+		 */
+		struct vsp1_rwpf *wpf = vsp1->wpf[i];
+		unsigned int flags = MEDIA_LNK_FL_ENABLED;
+
+		if (!(vsp1->pdata.features & VSP1_HAS_LIF) || i != 0)
+			flags |= MEDIA_LNK_FL_IMMUTABLE;
+
+		ret = media_entity_create_link(&wpf->entity.subdev.entity,
+					       RWPF_PAD_SOURCE,
+					       &wpf->entity.video->video.entity,
+					       0, flags);
+		if (ret < 0)
+			goto done;
+	}
+
 	if (vsp1->pdata.features & VSP1_HAS_LIF) {
 		ret = media_entity_create_link(
 			&vsp1->wpf[0]->entity.subdev.entity, RWPF_PAD_SOURCE,
@@ -486,6 +542,7 @@ static int vsp1_probe(struct platform_device *pdev)
 	vsp1->dev = &pdev->dev;
 	mutex_init(&vsp1->lock);
 	INIT_LIST_HEAD(&vsp1->entities);
+	INIT_LIST_HEAD(&vsp1->videos);
 
 	ret = vsp1_parse_dt(vsp1);
 	if (ret < 0)
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index fd95a75b04f4..0c52e4b71a98 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -20,7 +20,6 @@
 
 #include "vsp1.h"
 #include "vsp1_entity.h"
-#include "vsp1_video.h"
 
 bool vsp1_entity_is_streaming(struct vsp1_entity *entity)
 {
@@ -225,8 +224,6 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
 
 void vsp1_entity_destroy(struct vsp1_entity *entity)
 {
-	if (entity->video)
-		vsp1_video_cleanup(entity->video);
 	if (entity->subdev.ctrl_handler)
 		v4l2_ctrl_handler_free(entity->subdev.ctrl_handler);
 	media_entity_cleanup(&entity->subdev.entity);
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index 9c2e34374c60..ae51c31112aa 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -217,7 +217,6 @@ static const struct vsp1_rwpf_operations rpf_vdev_ops = {
 struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
 {
 	struct v4l2_subdev *subdev;
-	struct vsp1_video *video;
 	struct vsp1_rwpf *rpf;
 	int ret;
 
@@ -264,27 +263,6 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
 		goto error;
 	}
 
-	/* Initialize the video device. */
-	video = &rpf->video;
-
-	video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-	video->vsp1 = vsp1;
-
-	ret = vsp1_video_init(video, rpf);
-	if (ret < 0)
-		goto error;
-
-	rpf->entity.video = video;
-
-	/* Connect the video device to the RPF. */
-	ret = media_entity_create_link(&rpf->video.video.entity, 0,
-				       &rpf->entity.subdev.entity,
-				       RWPF_PAD_SINK,
-				       MEDIA_LNK_FL_ENABLED |
-				       MEDIA_LNK_FL_IMMUTABLE);
-	if (ret < 0)
-		goto error;
-
 	return rpf;
 
 error:
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index aa22cc062ff3..ee2a8bf269fa 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -19,7 +19,6 @@
 
 #include "vsp1.h"
 #include "vsp1_entity.h"
-#include "vsp1_video.h"
 
 #define RWPF_PAD_SINK				0
 #define RWPF_PAD_SOURCE				1
@@ -33,7 +32,6 @@ struct vsp1_rwpf_operations {
 
 struct vsp1_rwpf {
 	struct vsp1_entity entity;
-	struct vsp1_video video;
 	struct v4l2_ctrl_handler ctrls;
 
 	const struct vsp1_rwpf_operations *ops;
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index d02cd63a9c5e..216894cee2e7 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -435,11 +435,11 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
 		if (e->type == VSP1_ENTITY_RPF) {
 			rwpf = to_rwpf(subdev);
 			pipe->inputs[pipe->num_inputs++] = rwpf;
-			rwpf->video.pipe_index = pipe->num_inputs;
+			rwpf->entity.video->pipe_index = pipe->num_inputs;
 		} else if (e->type == VSP1_ENTITY_WPF) {
 			rwpf = to_rwpf(subdev);
 			pipe->output = to_rwpf(subdev);
-			rwpf->video.pipe_index = 0;
+			rwpf->entity.video->pipe_index = 0;
 		} else if (e->type == VSP1_ENTITY_LIF) {
 			pipe->lif = e;
 		} else if (e->type == VSP1_ENTITY_BRU) {
@@ -648,10 +648,10 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
 
 	/* Complete buffers on all video nodes. */
 	for (i = 0; i < pipe->num_inputs; ++i)
-		vsp1_video_frame_end(pipe, &pipe->inputs[i]->video);
+		vsp1_video_frame_end(pipe, pipe->inputs[i]->entity.video);
 
 	if (!pipe->lif)
-		vsp1_video_frame_end(pipe, &pipe->output->video);
+		vsp1_video_frame_end(pipe, pipe->output->entity.video);
 
 	spin_lock_irqsave(&pipe->irqlock, flags);
 
@@ -1187,29 +1187,34 @@ static struct v4l2_file_operations vsp1_video_fops = {
  * Initialization and Cleanup
  */
 
-int vsp1_video_init(struct vsp1_video *video, struct vsp1_rwpf *rwpf)
+struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1,
+				     struct vsp1_rwpf *rwpf)
 {
+	struct vsp1_video *video;
 	const char *direction;
 	int ret;
 
-	switch (video->type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-		direction = "output";
-		video->pad.flags = MEDIA_PAD_FL_SINK;
-		break;
+	video = devm_kzalloc(vsp1->dev, sizeof(*video), GFP_KERNEL);
+	if (!video)
+		return ERR_PTR(-ENOMEM);
+
+	rwpf->entity.video = video;
+
+	video->vsp1 = vsp1;
+	video->rwpf = rwpf;
 
-	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+	if (rwpf->entity.type == VSP1_ENTITY_RPF) {
 		direction = "input";
+		video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
 		video->pad.flags = MEDIA_PAD_FL_SOURCE;
 		video->video.vfl_dir = VFL_DIR_TX;
-		break;
-
-	default:
-		return -EINVAL;
+	} else {
+		direction = "output";
+		video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+		video->pad.flags = MEDIA_PAD_FL_SINK;
+		video->video.vfl_dir = VFL_DIR_RX;
 	}
 
-	video->rwpf = rwpf;
-
 	mutex_init(&video->lock);
 	spin_lock_init(&video->irqlock);
 	INIT_LIST_HEAD(&video->irqqueue);
@@ -1223,7 +1228,7 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_rwpf *rwpf)
 	/* Initialize the media entity... */
 	ret = media_entity_init(&video->video.entity, 1, &video->pad, 0);
 	if (ret < 0)
-		return ret;
+		return ERR_PTR(ret);
 
 	/* ... and the format ... */
 	rwpf->fmtinfo = vsp1_get_format_info(VSP1_VIDEO_DEF_FORMAT);
@@ -1278,12 +1283,12 @@ int vsp1_video_init(struct vsp1_video *video, struct vsp1_rwpf *rwpf)
 		goto error;
 	}
 
-	return 0;
+	return video;
 
 error:
 	vb2_dma_contig_cleanup_ctx(video->alloc_ctx);
 	vsp1_video_cleanup(video);
-	return ret;
+	return ERR_PTR(ret);
 }
 
 void vsp1_video_cleanup(struct vsp1_video *video)
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index e66ee14c596d..f75c67976bcd 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -108,6 +108,7 @@ static inline struct vsp1_vb2_buffer *to_vsp1_vb2_buffer(struct vb2_buffer *vb)
 }
 
 struct vsp1_video {
+	struct list_head list;
 	struct vsp1_device *vsp1;
 	struct vsp1_rwpf *rwpf;
 
@@ -132,7 +133,8 @@ static inline struct vsp1_video *to_vsp1_video(struct video_device *vdev)
 	return container_of(vdev, struct vsp1_video, video);
 }
 
-int vsp1_video_init(struct vsp1_video *video, struct vsp1_rwpf *rwpf);
+struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1,
+				     struct vsp1_rwpf *rwpf);
 void vsp1_video_cleanup(struct vsp1_video *video);
 
 void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe);
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index 1bb389529f24..4f0e4ab0f05b 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -215,9 +215,7 @@ static const struct vsp1_rwpf_operations wpf_vdev_ops = {
 struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
 {
 	struct v4l2_subdev *subdev;
-	struct vsp1_video *video;
 	struct vsp1_rwpf *wpf;
-	unsigned int flags;
 	int ret;
 
 	wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL);
@@ -263,33 +261,6 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
 		goto error;
 	}
 
-	/* Initialize the video device. */
-	video = &wpf->video;
-
-	video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-	video->vsp1 = vsp1;
-
-	ret = vsp1_video_init(video, wpf);
-	if (ret < 0)
-		goto error;
-
-	wpf->entity.video = video;
-
-	/* Connect the video device to the WPF. All connections are immutable
-	 * except for the WPF0 source link if a LIF is present.
-	 */
-	flags = MEDIA_LNK_FL_ENABLED;
-	if (!(vsp1->pdata.features & VSP1_HAS_LIF) || index != 0)
-		flags |= MEDIA_LNK_FL_IMMUTABLE;
-
-	ret = media_entity_create_link(&wpf->entity.subdev.entity,
-				       RWPF_PAD_SOURCE,
-				       &wpf->video.video.entity, 0, flags);
-	if (ret < 0)
-		goto error;
-
-	wpf->entity.sink = &wpf->video.video.entity;
-
 	return wpf;
 
 error:
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 06/32] v4l: vsp1: Make rwpf operations independent of video device
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (4 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 05/32] v4l: vsp1: Move video device out of struct vsp1_rwpf Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 07/32] v4l: vsp1: Support VSP1 instances without any UDS Laurent Pinchart
                   ` (26 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

The rwpf queue operation doesn't queue a buffer but sets the memory
address for the next run. Rename it to set_memory and pass it a new
structure independent of the video buffer than only contains memory
information.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_rpf.c   | 16 ++++++++--------
 drivers/media/platform/vsp1/vsp1_rwpf.h  | 10 ++++++++--
 drivers/media/platform/vsp1/vsp1_video.c | 14 ++++++++------
 drivers/media/platform/vsp1/vsp1_video.h |  7 +++----
 drivers/media/platform/vsp1/vsp1_wpf.c   | 14 +++++++-------
 5 files changed, 34 insertions(+), 27 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index ae51c31112aa..c0b7f76cd0b5 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -186,28 +186,28 @@ static struct v4l2_subdev_ops rpf_ops = {
  * Video Device Operations
  */
 
-static void rpf_buf_queue(struct vsp1_rwpf *rpf, struct vsp1_vb2_buffer *buf)
+static void rpf_set_memory(struct vsp1_rwpf *rpf, struct vsp1_rwpf_memory *mem)
 {
 	unsigned int i;
 
 	for (i = 0; i < 3; ++i)
-		rpf->buf_addr[i] = buf->addr[i];
+		rpf->buf_addr[i] = mem->addr[i];
 
 	if (!vsp1_entity_is_streaming(&rpf->entity))
 		return;
 
 	vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_Y,
-		       buf->addr[0] + rpf->offsets[0]);
-	if (buf->buf.num_planes > 1)
+		       mem->addr[0] + rpf->offsets[0]);
+	if (mem->num_planes > 1)
 		vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C0,
-			       buf->addr[1] + rpf->offsets[1]);
-	if (buf->buf.num_planes > 2)
+			       mem->addr[1] + rpf->offsets[1]);
+	if (mem->num_planes > 2)
 		vsp1_rpf_write(rpf, VI6_RPF_SRCM_ADDR_C1,
-			       buf->addr[2] + rpf->offsets[1]);
+			       mem->addr[2] + rpf->offsets[1]);
 }
 
 static const struct vsp1_rwpf_operations rpf_vdev_ops = {
-	.queue = rpf_buf_queue,
+	.set_memory = rpf_set_memory,
 };
 
 /* -----------------------------------------------------------------------------
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index ee2a8bf269fa..0076920adb28 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -24,10 +24,16 @@
 #define RWPF_PAD_SOURCE				1
 
 struct vsp1_rwpf;
-struct vsp1_vb2_buffer;
+
+struct vsp1_rwpf_memory {
+	unsigned int num_planes;
+	dma_addr_t addr[3];
+	unsigned int length[3];
+};
 
 struct vsp1_rwpf_operations {
-	void (*queue)(struct vsp1_rwpf *rwpf, struct vsp1_vb2_buffer *buf);
+	void (*set_memory)(struct vsp1_rwpf *rwpf,
+			   struct vsp1_rwpf_memory *mem);
 };
 
 struct vsp1_rwpf {
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 216894cee2e7..121f8724bcf6 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -613,7 +613,7 @@ vsp1_video_complete_buffer(struct vsp1_video *video)
 	done->buf.v4l2_buf.sequence = video->sequence++;
 	v4l2_get_timestamp(&done->buf.v4l2_buf.timestamp);
 	for (i = 0; i < done->buf.num_planes; ++i)
-		vb2_set_plane_payload(&done->buf, i, done->length[i]);
+		vb2_set_plane_payload(&done->buf, i, done->mem.length[i]);
 	vb2_buffer_done(&done->buf, VB2_BUF_STATE_DONE);
 
 	return next;
@@ -631,7 +631,7 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe,
 
 	spin_lock_irqsave(&pipe->irqlock, flags);
 
-	video->rwpf->ops->queue(video->rwpf, buf);
+	video->rwpf->ops->set_memory(video->rwpf, &buf->mem);
 	pipe->buffers_ready |= 1 << video->pipe_index;
 
 	spin_unlock_irqrestore(&pipe->irqlock, flags);
@@ -828,11 +828,13 @@ static int vsp1_video_buffer_prepare(struct vb2_buffer *vb)
 	if (vb->num_planes < format->num_planes)
 		return -EINVAL;
 
+	buf->mem.num_planes = vb->num_planes;
+
 	for (i = 0; i < vb->num_planes; ++i) {
-		buf->addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
-		buf->length[i] = vb2_plane_size(vb, i);
+		buf->mem.addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
+		buf->mem.length[i] = vb2_plane_size(vb, i);
 
-		if (buf->length[i] < format->plane_fmt[i].sizeimage)
+		if (buf->mem.length[i] < format->plane_fmt[i].sizeimage)
 			return -EINVAL;
 	}
 
@@ -857,7 +859,7 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb)
 
 	spin_lock_irqsave(&pipe->irqlock, flags);
 
-	video->rwpf->ops->queue(video->rwpf, buf);
+	video->rwpf->ops->set_memory(video->rwpf, &buf->mem);
 	pipe->buffers_ready |= 1 << video->pipe_index;
 
 	if (vb2_is_streaming(&video->queue) &&
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index f75c67976bcd..b7eabe6bab70 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -20,7 +20,8 @@
 #include <media/media-entity.h>
 #include <media/videobuf2-core.h>
 
-struct vsp1_rwpf;
+#include "vsp1_rwpf.h"
+
 struct vsp1_video;
 
 /*
@@ -97,9 +98,7 @@ static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e)
 struct vsp1_vb2_buffer {
 	struct vb2_buffer buf;
 	struct list_head queue;
-
-	dma_addr_t addr[3];
-	unsigned int length[3];
+	struct vsp1_rwpf_memory mem;
 };
 
 static inline struct vsp1_vb2_buffer *to_vsp1_vb2_buffer(struct vb2_buffer *vb)
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index 4f0e4ab0f05b..d2537b46fc46 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -195,17 +195,17 @@ static struct v4l2_subdev_ops wpf_ops = {
  * Video Device Operations
  */
 
-static void wpf_buf_queue(struct vsp1_rwpf *wpf, struct vsp1_vb2_buffer *buf)
+static void wpf_set_memory(struct vsp1_rwpf *wpf, struct vsp1_rwpf_memory *mem)
 {
-	vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, buf->addr[0]);
-	if (buf->buf.num_planes > 1)
-		vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, buf->addr[1]);
-	if (buf->buf.num_planes > 2)
-		vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, buf->addr[2]);
+	vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_Y, mem->addr[0]);
+	if (mem->num_planes > 1)
+		vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C0, mem->addr[1]);
+	if (mem->num_planes > 2)
+		vsp1_wpf_write(wpf, VI6_WPF_DSTM_ADDR_C1, mem->addr[2]);
 }
 
 static const struct vsp1_rwpf_operations wpf_vdev_ops = {
-	.queue = wpf_buf_queue,
+	.set_memory = wpf_set_memory,
 };
 
 /* -----------------------------------------------------------------------------
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 07/32] v4l: vsp1: Support VSP1 instances without any UDS
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (5 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 06/32] v4l: vsp1: Make rwpf operations independent of video device Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 08/32] v4l: vsp1: Move vsp1_video pointer from vsp1_entity to vsp1_rwpf Laurent Pinchart
                   ` (25 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh, devicetree

Not all VSP1 instances include a UDS. Make the renesas,#uds DT property
optional and accept a number of UDS equal to 0 as valid.

Cc: devicetree@vger.kernel.org
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 Documentation/devicetree/bindings/media/renesas,vsp1.txt | 3 ++-
 drivers/media/platform/vsp1/vsp1_drv.c                   | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/renesas,vsp1.txt b/Documentation/devicetree/bindings/media/renesas,vsp1.txt
index 87fe08abf36d..674c8c30d046 100644
--- a/Documentation/devicetree/bindings/media/renesas,vsp1.txt
+++ b/Documentation/devicetree/bindings/media/renesas,vsp1.txt
@@ -13,12 +13,13 @@ Required properties:
   - clocks: A phandle + clock-specifier pair for the VSP1 functional clock.
 
   - renesas,#rpf: Number of Read Pixel Formatter (RPF) modules in the VSP1.
-  - renesas,#uds: Number of Up Down Scaler (UDS) modules in the VSP1.
   - renesas,#wpf: Number of Write Pixel Formatter (WPF) modules in the VSP1.
 
 
 Optional properties:
 
+  - renesas,#uds: Number of Up Down Scaler (UDS) modules in the VSP1. Defaults
+    to 0 if not present.
   - renesas,has-lif: Boolean, indicates that the LCD Interface (LIF) module is
     available.
   - renesas,has-lut: Boolean, indicates that the Look Up Table (LUT) module is
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index de0b80e8d048..5f93cbdcb0f1 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -513,7 +513,7 @@ static int vsp1_parse_dt(struct vsp1_device *vsp1)
 		return -EINVAL;
 	}
 
-	if (pdata->uds_count <= 0 || pdata->uds_count > VSP1_MAX_UDS) {
+	if (pdata->uds_count > VSP1_MAX_UDS) {
 		dev_err(vsp1->dev, "invalid number of UDS (%u)\n",
 			pdata->uds_count);
 		return -EINVAL;
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 08/32] v4l: vsp1: Move vsp1_video pointer from vsp1_entity to vsp1_rwpf
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (6 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 07/32] v4l: vsp1: Support VSP1 instances without any UDS Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 09/32] v4l: vsp1: Remove struct vsp1_pipeline num_video field Laurent Pinchart
                   ` (24 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

Only RPFs and WPFs can be associated with video nodes, don't waste
memory by storing the video pointer in all entities.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_drv.c    |  6 +++---
 drivers/media/platform/vsp1/vsp1_entity.h |  3 ---
 drivers/media/platform/vsp1/vsp1_rwpf.h   |  3 +++
 drivers/media/platform/vsp1/vsp1_video.c  | 10 +++++-----
 4 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 5f93cbdcb0f1..91ecf75119ba 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -289,8 +289,8 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 	for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
 		struct vsp1_rwpf *rpf = vsp1->rpf[i];
 
-		ret = media_entity_create_link(&rpf->entity.video->video.entity,
-					       0, &rpf->entity.subdev.entity,
+		ret = media_entity_create_link(&rpf->video->video.entity, 0,
+					       &rpf->entity.subdev.entity,
 					       RWPF_PAD_SINK,
 					       MEDIA_LNK_FL_ENABLED |
 					       MEDIA_LNK_FL_IMMUTABLE);
@@ -311,7 +311,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 
 		ret = media_entity_create_link(&wpf->entity.subdev.entity,
 					       RWPF_PAD_SOURCE,
-					       &wpf->entity.video->video.entity,
+					       &wpf->video->video.entity,
 					       0, flags);
 		if (ret < 0)
 			goto done;
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
index 8867a5787c28..9c95507ec762 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.h
+++ b/drivers/media/platform/vsp1/vsp1_entity.h
@@ -19,7 +19,6 @@
 #include <media/v4l2-subdev.h>
 
 struct vsp1_device;
-struct vsp1_video;
 
 enum vsp1_entity_type {
 	VSP1_ENTITY_BRU,
@@ -71,8 +70,6 @@ struct vsp1_entity {
 	struct v4l2_subdev subdev;
 	struct v4l2_mbus_framefmt *formats;
 
-	struct vsp1_video *video;
-
 	spinlock_t lock;		/* Protects the streaming field */
 	bool streaming;
 };
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index 0076920adb28..1a90c7c8e972 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -24,6 +24,7 @@
 #define RWPF_PAD_SOURCE				1
 
 struct vsp1_rwpf;
+struct vsp1_video;
 
 struct vsp1_rwpf_memory {
 	unsigned int num_planes;
@@ -40,6 +41,8 @@ struct vsp1_rwpf {
 	struct vsp1_entity entity;
 	struct v4l2_ctrl_handler ctrls;
 
+	struct vsp1_video *video;
+
 	const struct vsp1_rwpf_operations *ops;
 
 	unsigned int max_width;
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 121f8724bcf6..2d27e8334911 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -435,11 +435,11 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
 		if (e->type == VSP1_ENTITY_RPF) {
 			rwpf = to_rwpf(subdev);
 			pipe->inputs[pipe->num_inputs++] = rwpf;
-			rwpf->entity.video->pipe_index = pipe->num_inputs;
+			rwpf->video->pipe_index = pipe->num_inputs;
 		} else if (e->type == VSP1_ENTITY_WPF) {
 			rwpf = to_rwpf(subdev);
 			pipe->output = to_rwpf(subdev);
-			rwpf->entity.video->pipe_index = 0;
+			rwpf->video->pipe_index = 0;
 		} else if (e->type == VSP1_ENTITY_LIF) {
 			pipe->lif = e;
 		} else if (e->type == VSP1_ENTITY_BRU) {
@@ -648,10 +648,10 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
 
 	/* Complete buffers on all video nodes. */
 	for (i = 0; i < pipe->num_inputs; ++i)
-		vsp1_video_frame_end(pipe, pipe->inputs[i]->entity.video);
+		vsp1_video_frame_end(pipe, pipe->inputs[i]->video);
 
 	if (!pipe->lif)
-		vsp1_video_frame_end(pipe, pipe->output->entity.video);
+		vsp1_video_frame_end(pipe, pipe->output->video);
 
 	spin_lock_irqsave(&pipe->irqlock, flags);
 
@@ -1200,7 +1200,7 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1,
 	if (!video)
 		return ERR_PTR(-ENOMEM);
 
-	rwpf->entity.video = video;
+	rwpf->video = video;
 
 	video->vsp1 = vsp1;
 	video->rwpf = rwpf;
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 09/32] v4l: vsp1: Remove struct vsp1_pipeline num_video field
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (7 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 08/32] v4l: vsp1: Move vsp1_video pointer from vsp1_entity to vsp1_rwpf Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 10/32] v4l: vsp1: Decouple pipeline end of frame processing from vsp1_video Laurent Pinchart
                   ` (23 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

The field always has the same value as the num_inputs field, remove the
duplicate.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_video.c | 7 ++-----
 drivers/media/platform/vsp1/vsp1_video.h | 1 -
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 2d27e8334911..c726d76bd570 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -396,7 +396,6 @@ static void __vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe)
 	INIT_LIST_HEAD(&pipe->entities);
 	pipe->state = VSP1_PIPELINE_STOPPED;
 	pipe->buffers_ready = 0;
-	pipe->num_video = 0;
 	pipe->num_inputs = 0;
 	pipe->output = NULL;
 	pipe->bru = NULL;
@@ -423,10 +422,8 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
 		struct vsp1_rwpf *rwpf;
 		struct vsp1_entity *e;
 
-		if (media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV) {
-			pipe->num_video++;
+		if (media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV)
 			continue;
-		}
 
 		subdev = media_entity_to_v4l2_subdev(entity);
 		e = to_vsp1_entity(subdev);
@@ -890,7 +887,7 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
 	int ret;
 
 	mutex_lock(&pipe->lock);
-	if (pipe->stream_count == pipe->num_video - 1) {
+	if (pipe->stream_count == pipe->num_inputs - 1) {
 		if (pipe->uds) {
 			struct vsp1_uds *uds = to_uds(&pipe->uds->subdev);
 
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index b7eabe6bab70..cea6d1f3f07b 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -75,7 +75,6 @@ struct vsp1_pipeline {
 	unsigned int stream_count;
 	unsigned int buffers_ready;
 
-	unsigned int num_video;
 	unsigned int num_inputs;
 	struct vsp1_rwpf *inputs[VSP1_MAX_RPF];
 	struct vsp1_rwpf *output;
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 10/32] v4l: vsp1: Decouple pipeline end of frame processing from vsp1_video
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (8 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 09/32] v4l: vsp1: Remove struct vsp1_pipeline num_video field Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 11/32] v4l: vsp1: Split pipeline management code from vsp1_video.c Laurent Pinchart
                   ` (22 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

To make the pipeline structure and operations usable without video
devices the frame end processing must be decoupled from struct
vsp1_video. Implement this by calling the video frame end function
indirectly through a function pointer in struct vsp1_pipeline.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_video.c | 25 +++++++++++++++++--------
 drivers/media/platform/vsp1/vsp1_video.h |  2 ++
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index c726d76bd570..c86a4065ea9c 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -617,8 +617,9 @@ vsp1_video_complete_buffer(struct vsp1_video *video)
 }
 
 static void vsp1_video_frame_end(struct vsp1_pipeline *pipe,
-				 struct vsp1_video *video)
+				 struct vsp1_rwpf *rwpf)
 {
+	struct vsp1_video *video = rwpf->video;
 	struct vsp1_vb2_buffer *buf;
 	unsigned long flags;
 
@@ -634,21 +635,28 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe,
 	spin_unlock_irqrestore(&pipe->irqlock, flags);
 }
 
+static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe)
+{
+	unsigned int i;
+
+	/* Complete buffers on all video nodes. */
+	for (i = 0; i < pipe->num_inputs; ++i)
+		vsp1_video_frame_end(pipe, pipe->inputs[i]);
+
+	if (!pipe->lif)
+		vsp1_video_frame_end(pipe, pipe->output);
+}
+
 void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
 {
 	enum vsp1_pipeline_state state;
 	unsigned long flags;
-	unsigned int i;
 
 	if (pipe == NULL)
 		return;
 
-	/* Complete buffers on all video nodes. */
-	for (i = 0; i < pipe->num_inputs; ++i)
-		vsp1_video_frame_end(pipe, pipe->inputs[i]->video);
-
-	if (!pipe->lif)
-		vsp1_video_frame_end(pipe, pipe->output->video);
+	/* Signal frame end to the pipeline handler. */
+	pipe->frame_end(pipe);
 
 	spin_lock_irqsave(&pipe->irqlock, flags);
 
@@ -1223,6 +1231,7 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1,
 	INIT_LIST_HEAD(&video->pipe.entities);
 	init_waitqueue_head(&video->pipe.wq);
 	video->pipe.state = VSP1_PIPELINE_STOPPED;
+	video->pipe.frame_end = vsp1_video_pipeline_frame_end;
 
 	/* Initialize the media entity... */
 	ret = media_entity_init(&video->video.entity, 1, &video->pad, 0);
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index cea6d1f3f07b..d2d229ed8aa7 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -70,6 +70,8 @@ struct vsp1_pipeline {
 	enum vsp1_pipeline_state state;
 	wait_queue_head_t wq;
 
+	void (*frame_end)(struct vsp1_pipeline *pipe);
+
 	struct mutex lock;
 	unsigned int use_count;
 	unsigned int stream_count;
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 11/32] v4l: vsp1: Split pipeline management code from vsp1_video.c
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (9 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 10/32] v4l: vsp1: Decouple pipeline end of frame processing from vsp1_video Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 12/32] v4l: vsp1: Rename video pipeline functions to use vsp1_video prefix Laurent Pinchart
                   ` (21 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

The code will be used to control the vsp1 driver from the DU driver
without using video nodes.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/Makefile     |   3 +-
 drivers/media/platform/vsp1/vsp1_pipe.c  | 247 +++++++++++++++++++++++++++++++
 drivers/media/platform/vsp1/vsp1_pipe.h  |  85 +++++++++++
 drivers/media/platform/vsp1/vsp1_video.c | 223 +---------------------------
 drivers/media/platform/vsp1/vsp1_video.h |  59 +-------
 5 files changed, 338 insertions(+), 279 deletions(-)
 create mode 100644 drivers/media/platform/vsp1/vsp1_pipe.c
 create mode 100644 drivers/media/platform/vsp1/vsp1_pipe.h

diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile
index 6a93f928dfde..0ef0b5384125 100644
--- a/drivers/media/platform/vsp1/Makefile
+++ b/drivers/media/platform/vsp1/Makefile
@@ -1,4 +1,5 @@
-vsp1-y					:= vsp1_drv.o vsp1_entity.o vsp1_video.o
+vsp1-y					:= vsp1_drv.o vsp1_entity.o vsp1_pipe.o
+vsp1-y					+= vsp1_video.o
 vsp1-y					+= vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o
 vsp1-y					+= vsp1_hsit.o vsp1_lif.o vsp1_lut.o
 vsp1-y					+= vsp1_bru.o vsp1_sru.o vsp1_uds.o
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
new file mode 100644
index 000000000000..199d57f1fe06
--- /dev/null
+++ b/drivers/media/platform/vsp1/vsp1_pipe.c
@@ -0,0 +1,247 @@
+/*
+ * vsp1_pipe.c  --  R-Car VSP1 Pipeline
+ *
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/list.h>
+#include <linux/wait.h>
+
+#include <media/media-entity.h>
+#include <media/v4l2-subdev.h>
+
+#include "vsp1.h"
+#include "vsp1_bru.h"
+#include "vsp1_entity.h"
+#include "vsp1_pipe.h"
+#include "vsp1_rwpf.h"
+#include "vsp1_uds.h"
+
+/* -----------------------------------------------------------------------------
+ * Pipeline Management
+ */
+
+void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
+{
+	if (pipe->bru) {
+		struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
+		unsigned int i;
+
+		for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i)
+			bru->inputs[i].rpf = NULL;
+	}
+
+	INIT_LIST_HEAD(&pipe->entities);
+	pipe->state = VSP1_PIPELINE_STOPPED;
+	pipe->buffers_ready = 0;
+	pipe->num_inputs = 0;
+	pipe->output = NULL;
+	pipe->bru = NULL;
+	pipe->lif = NULL;
+	pipe->uds = NULL;
+}
+
+void vsp1_pipeline_run(struct vsp1_pipeline *pipe)
+{
+	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
+
+	vsp1_write(vsp1, VI6_CMD(pipe->output->entity.index), VI6_CMD_STRCMD);
+	pipe->state = VSP1_PIPELINE_RUNNING;
+	pipe->buffers_ready = 0;
+}
+
+bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe)
+{
+	unsigned long flags;
+	bool stopped;
+
+	spin_lock_irqsave(&pipe->irqlock, flags);
+	stopped = pipe->state == VSP1_PIPELINE_STOPPED,
+	spin_unlock_irqrestore(&pipe->irqlock, flags);
+
+	return stopped;
+}
+
+int vsp1_pipeline_stop(struct vsp1_pipeline *pipe)
+{
+	struct vsp1_entity *entity;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&pipe->irqlock, flags);
+	if (pipe->state == VSP1_PIPELINE_RUNNING)
+		pipe->state = VSP1_PIPELINE_STOPPING;
+	spin_unlock_irqrestore(&pipe->irqlock, flags);
+
+	ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe),
+				 msecs_to_jiffies(500));
+	ret = ret == 0 ? -ETIMEDOUT : 0;
+
+	list_for_each_entry(entity, &pipe->entities, list_pipe) {
+		if (entity->route && entity->route->reg)
+			vsp1_write(entity->vsp1, entity->route->reg,
+				   VI6_DPR_NODE_UNUSED);
+
+		v4l2_subdev_call(&entity->subdev, video, s_stream, 0);
+	}
+
+	return ret;
+}
+
+bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe)
+{
+	unsigned int mask;
+
+	mask = ((1 << pipe->num_inputs) - 1) << 1;
+	if (!pipe->lif)
+		mask |= 1 << 0;
+
+	return pipe->buffers_ready == mask;
+}
+
+void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
+{
+	enum vsp1_pipeline_state state;
+	unsigned long flags;
+
+	if (pipe == NULL)
+		return;
+
+	/* Signal frame end to the pipeline handler. */
+	pipe->frame_end(pipe);
+
+	spin_lock_irqsave(&pipe->irqlock, flags);
+
+	state = pipe->state;
+	pipe->state = VSP1_PIPELINE_STOPPED;
+
+	/* If a stop has been requested, mark the pipeline as stopped and
+	 * return.
+	 */
+	if (state == VSP1_PIPELINE_STOPPING) {
+		wake_up(&pipe->wq);
+		goto done;
+	}
+
+	/* Restart the pipeline if ready. */
+	if (vsp1_pipeline_ready(pipe))
+		vsp1_pipeline_run(pipe);
+
+done:
+	spin_unlock_irqrestore(&pipe->irqlock, flags);
+}
+
+/*
+ * Propagate the alpha value through the pipeline.
+ *
+ * As the UDS has restricted scaling capabilities when the alpha component needs
+ * to be scaled, we disable alpha scaling when the UDS input has a fixed alpha
+ * value. The UDS then outputs a fixed alpha value which needs to be programmed
+ * from the input RPF alpha.
+ */
+void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
+				   struct vsp1_entity *input,
+				   unsigned int alpha)
+{
+	struct vsp1_entity *entity;
+	struct media_pad *pad;
+
+	pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]);
+
+	while (pad) {
+		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+			break;
+
+		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
+
+		/* The BRU background color has a fixed alpha value set to 255,
+		 * the output alpha value is thus always equal to 255.
+		 */
+		if (entity->type == VSP1_ENTITY_BRU)
+			alpha = 255;
+
+		if (entity->type == VSP1_ENTITY_UDS) {
+			struct vsp1_uds *uds = to_uds(&entity->subdev);
+
+			vsp1_uds_set_alpha(uds, alpha);
+			break;
+		}
+
+		pad = &entity->pads[entity->source_pad];
+		pad = media_entity_remote_pad(pad);
+	}
+}
+
+void vsp1_pipelines_suspend(struct vsp1_device *vsp1)
+{
+	unsigned long flags;
+	unsigned int i;
+	int ret;
+
+	/* To avoid increasing the system suspend time needlessly, loop over the
+	 * pipelines twice, first to set them all to the stopping state, and
+	 * then to wait for the stop to complete.
+	 */
+	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
+		struct vsp1_rwpf *wpf = vsp1->wpf[i];
+		struct vsp1_pipeline *pipe;
+
+		if (wpf == NULL)
+			continue;
+
+		pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
+		if (pipe == NULL)
+			continue;
+
+		spin_lock_irqsave(&pipe->irqlock, flags);
+		if (pipe->state == VSP1_PIPELINE_RUNNING)
+			pipe->state = VSP1_PIPELINE_STOPPING;
+		spin_unlock_irqrestore(&pipe->irqlock, flags);
+	}
+
+	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
+		struct vsp1_rwpf *wpf = vsp1->wpf[i];
+		struct vsp1_pipeline *pipe;
+
+		if (wpf == NULL)
+			continue;
+
+		pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
+		if (pipe == NULL)
+			continue;
+
+		ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe),
+					 msecs_to_jiffies(500));
+		if (ret == 0)
+			dev_warn(vsp1->dev, "pipeline %u stop timeout\n",
+				 wpf->entity.index);
+	}
+}
+
+void vsp1_pipelines_resume(struct vsp1_device *vsp1)
+{
+	unsigned int i;
+
+	/* Resume pipeline all running pipelines. */
+	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
+		struct vsp1_rwpf *wpf = vsp1->wpf[i];
+		struct vsp1_pipeline *pipe;
+
+		if (wpf == NULL)
+			continue;
+
+		pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
+		if (pipe == NULL)
+			continue;
+
+		if (vsp1_pipeline_ready(pipe))
+			vsp1_pipeline_run(pipe);
+	}
+}
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
new file mode 100644
index 000000000000..f8a099fba973
--- /dev/null
+++ b/drivers/media/platform/vsp1/vsp1_pipe.h
@@ -0,0 +1,85 @@
+/*
+ * vsp1_pipe.h  --  R-Car VSP1 Pipeline
+ *
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __VSP1_PIPE_H__
+#define __VSP1_PIPE_H__
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+
+#include <media/media-entity.h>
+
+struct vsp1_rwpf;
+
+enum vsp1_pipeline_state {
+	VSP1_PIPELINE_STOPPED,
+	VSP1_PIPELINE_RUNNING,
+	VSP1_PIPELINE_STOPPING,
+};
+
+/*
+ * struct vsp1_pipeline - A VSP1 hardware pipeline
+ * @media: the media pipeline
+ * @irqlock: protects the pipeline state
+ * @lock: protects the pipeline use count and stream count
+ */
+struct vsp1_pipeline {
+	struct media_pipeline pipe;
+
+	spinlock_t irqlock;
+	enum vsp1_pipeline_state state;
+	wait_queue_head_t wq;
+
+	void (*frame_end)(struct vsp1_pipeline *pipe);
+
+	struct mutex lock;
+	unsigned int use_count;
+	unsigned int stream_count;
+	unsigned int buffers_ready;
+
+	unsigned int num_inputs;
+	struct vsp1_rwpf *inputs[VSP1_MAX_RPF];
+	struct vsp1_rwpf *output;
+	struct vsp1_entity *bru;
+	struct vsp1_entity *lif;
+	struct vsp1_entity *uds;
+	struct vsp1_entity *uds_input;
+
+	struct list_head entities;
+};
+
+static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e)
+{
+	if (likely(e->pipe))
+		return container_of(e->pipe, struct vsp1_pipeline, pipe);
+	else
+		return NULL;
+}
+
+void vsp1_pipeline_reset(struct vsp1_pipeline *pipe);
+
+void vsp1_pipeline_run(struct vsp1_pipeline *pipe);
+bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe);
+int vsp1_pipeline_stop(struct vsp1_pipeline *pipe);
+bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe);
+
+void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe);
+
+void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
+				   struct vsp1_entity *input,
+				   unsigned int alpha);
+
+void vsp1_pipelines_suspend(struct vsp1_device *vsp1);
+void vsp1_pipelines_resume(struct vsp1_device *vsp1);
+
+#endif /* __VSP1_PIPE_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index c86a4065ea9c..1a909ab34ea1 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -30,6 +30,7 @@
 #include "vsp1.h"
 #include "vsp1_bru.h"
 #include "vsp1_entity.h"
+#include "vsp1_pipe.h"
 #include "vsp1_rwpf.h"
 #include "vsp1_uds.h"
 #include "vsp1_video.h"
@@ -383,26 +384,6 @@ static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe,
 	return 0;
 }
 
-static void __vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe)
-{
-	if (pipe->bru) {
-		struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
-		unsigned int i;
-
-		for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i)
-			bru->inputs[i].rpf = NULL;
-	}
-
-	INIT_LIST_HEAD(&pipe->entities);
-	pipe->state = VSP1_PIPELINE_STOPPED;
-	pipe->buffers_ready = 0;
-	pipe->num_inputs = 0;
-	pipe->output = NULL;
-	pipe->bru = NULL;
-	pipe->lif = NULL;
-	pipe->uds = NULL;
-}
-
 static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
 				  struct vsp1_video *video)
 {
@@ -465,7 +446,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
 	return 0;
 
 error:
-	__vsp1_pipeline_cleanup(pipe);
+	vsp1_pipeline_reset(pipe);
 	return ret;
 }
 
@@ -497,69 +478,11 @@ static void vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe)
 
 	/* If we're the last user clean up the pipeline. */
 	if (--pipe->use_count == 0)
-		__vsp1_pipeline_cleanup(pipe);
+		vsp1_pipeline_reset(pipe);
 
 	mutex_unlock(&pipe->lock);
 }
 
-static void vsp1_pipeline_run(struct vsp1_pipeline *pipe)
-{
-	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
-
-	vsp1_write(vsp1, VI6_CMD(pipe->output->entity.index), VI6_CMD_STRCMD);
-	pipe->state = VSP1_PIPELINE_RUNNING;
-	pipe->buffers_ready = 0;
-}
-
-static bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe)
-{
-	unsigned long flags;
-	bool stopped;
-
-	spin_lock_irqsave(&pipe->irqlock, flags);
-	stopped = pipe->state == VSP1_PIPELINE_STOPPED,
-	spin_unlock_irqrestore(&pipe->irqlock, flags);
-
-	return stopped;
-}
-
-static int vsp1_pipeline_stop(struct vsp1_pipeline *pipe)
-{
-	struct vsp1_entity *entity;
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&pipe->irqlock, flags);
-	if (pipe->state == VSP1_PIPELINE_RUNNING)
-		pipe->state = VSP1_PIPELINE_STOPPING;
-	spin_unlock_irqrestore(&pipe->irqlock, flags);
-
-	ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe),
-				 msecs_to_jiffies(500));
-	ret = ret == 0 ? -ETIMEDOUT : 0;
-
-	list_for_each_entry(entity, &pipe->entities, list_pipe) {
-		if (entity->route && entity->route->reg)
-			vsp1_write(entity->vsp1, entity->route->reg,
-				   VI6_DPR_NODE_UNUSED);
-
-		v4l2_subdev_call(&entity->subdev, video, s_stream, 0);
-	}
-
-	return ret;
-}
-
-static bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe)
-{
-	unsigned int mask;
-
-	mask = ((1 << pipe->num_inputs) - 1) << 1;
-	if (!pipe->lif)
-		mask |= 1 << 0;
-
-	return pipe->buffers_ready == mask;
-}
-
 /*
  * vsp1_video_complete_buffer - Complete the current buffer
  * @video: the video node
@@ -647,146 +570,6 @@ static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe)
 		vsp1_video_frame_end(pipe, pipe->output);
 }
 
-void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
-{
-	enum vsp1_pipeline_state state;
-	unsigned long flags;
-
-	if (pipe == NULL)
-		return;
-
-	/* Signal frame end to the pipeline handler. */
-	pipe->frame_end(pipe);
-
-	spin_lock_irqsave(&pipe->irqlock, flags);
-
-	state = pipe->state;
-	pipe->state = VSP1_PIPELINE_STOPPED;
-
-	/* If a stop has been requested, mark the pipeline as stopped and
-	 * return.
-	 */
-	if (state == VSP1_PIPELINE_STOPPING) {
-		wake_up(&pipe->wq);
-		goto done;
-	}
-
-	/* Restart the pipeline if ready. */
-	if (vsp1_pipeline_ready(pipe))
-		vsp1_pipeline_run(pipe);
-
-done:
-	spin_unlock_irqrestore(&pipe->irqlock, flags);
-}
-
-/*
- * Propagate the alpha value through the pipeline.
- *
- * As the UDS has restricted scaling capabilities when the alpha component needs
- * to be scaled, we disable alpha scaling when the UDS input has a fixed alpha
- * value. The UDS then outputs a fixed alpha value which needs to be programmed
- * from the input RPF alpha.
- */
-void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
-				   struct vsp1_entity *input,
-				   unsigned int alpha)
-{
-	struct vsp1_entity *entity;
-	struct media_pad *pad;
-
-	pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]);
-
-	while (pad) {
-		if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
-			break;
-
-		entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
-
-		/* The BRU background color has a fixed alpha value set to 255,
-		 * the output alpha value is thus always equal to 255.
-		 */
-		if (entity->type == VSP1_ENTITY_BRU)
-			alpha = 255;
-
-		if (entity->type == VSP1_ENTITY_UDS) {
-			struct vsp1_uds *uds = to_uds(&entity->subdev);
-
-			vsp1_uds_set_alpha(uds, alpha);
-			break;
-		}
-
-		pad = &entity->pads[entity->source_pad];
-		pad = media_entity_remote_pad(pad);
-	}
-}
-
-void vsp1_pipelines_suspend(struct vsp1_device *vsp1)
-{
-	unsigned long flags;
-	unsigned int i;
-	int ret;
-
-	/* To avoid increasing the system suspend time needlessly, loop over the
-	 * pipelines twice, first to set them all to the stopping state, and then
-	 * to wait for the stop to complete.
-	 */
-	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
-		struct vsp1_rwpf *wpf = vsp1->wpf[i];
-		struct vsp1_pipeline *pipe;
-
-		if (wpf == NULL)
-			continue;
-
-		pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
-		if (pipe == NULL)
-			continue;
-
-		spin_lock_irqsave(&pipe->irqlock, flags);
-		if (pipe->state == VSP1_PIPELINE_RUNNING)
-			pipe->state = VSP1_PIPELINE_STOPPING;
-		spin_unlock_irqrestore(&pipe->irqlock, flags);
-	}
-
-	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
-		struct vsp1_rwpf *wpf = vsp1->wpf[i];
-		struct vsp1_pipeline *pipe;
-
-		if (wpf == NULL)
-			continue;
-
-		pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
-		if (pipe == NULL)
-			continue;
-
-		ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe),
-					 msecs_to_jiffies(500));
-		if (ret == 0)
-			dev_warn(vsp1->dev, "pipeline %u stop timeout\n",
-				 wpf->entity.index);
-	}
-}
-
-void vsp1_pipelines_resume(struct vsp1_device *vsp1)
-{
-	unsigned int i;
-
-	/* Resume pipeline all running pipelines. */
-	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
-		struct vsp1_rwpf *wpf = vsp1->wpf[i];
-		struct vsp1_pipeline *pipe;
-
-		if (wpf == NULL)
-			continue;
-
-		pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
-		if (pipe == NULL)
-			continue;
-
-		if (vsp1_pipeline_ready(pipe))
-			vsp1_pipeline_run(pipe);
-	}
-}
-
 /* -----------------------------------------------------------------------------
  * videobuf2 Queue Operations
  */
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index d2d229ed8aa7..f89590b83080 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -15,15 +15,12 @@
 
 #include <linux/list.h>
 #include <linux/spinlock.h>
-#include <linux/wait.h>
 
-#include <media/media-entity.h>
 #include <media/videobuf2-core.h>
 
+#include "vsp1_pipe.h"
 #include "vsp1_rwpf.h"
 
-struct vsp1_video;
-
 /*
  * struct vsp1_format_info - VSP1 video format description
  * @mbus: media bus format code
@@ -51,51 +48,6 @@ struct vsp1_format_info {
 	bool alpha;
 };
 
-enum vsp1_pipeline_state {
-	VSP1_PIPELINE_STOPPED,
-	VSP1_PIPELINE_RUNNING,
-	VSP1_PIPELINE_STOPPING,
-};
-
-/*
- * struct vsp1_pipeline - A VSP1 hardware pipeline
- * @media: the media pipeline
- * @irqlock: protects the pipeline state
- * @lock: protects the pipeline use count and stream count
- */
-struct vsp1_pipeline {
-	struct media_pipeline pipe;
-
-	spinlock_t irqlock;
-	enum vsp1_pipeline_state state;
-	wait_queue_head_t wq;
-
-	void (*frame_end)(struct vsp1_pipeline *pipe);
-
-	struct mutex lock;
-	unsigned int use_count;
-	unsigned int stream_count;
-	unsigned int buffers_ready;
-
-	unsigned int num_inputs;
-	struct vsp1_rwpf *inputs[VSP1_MAX_RPF];
-	struct vsp1_rwpf *output;
-	struct vsp1_entity *bru;
-	struct vsp1_entity *lif;
-	struct vsp1_entity *uds;
-	struct vsp1_entity *uds_input;
-
-	struct list_head entities;
-};
-
-static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e)
-{
-	if (likely(e->pipe))
-		return container_of(e->pipe, struct vsp1_pipeline, pipe);
-	else
-		return NULL;
-}
-
 struct vsp1_vb2_buffer {
 	struct vb2_buffer buf;
 	struct list_head queue;
@@ -137,13 +89,4 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1,
 				     struct vsp1_rwpf *rwpf);
 void vsp1_video_cleanup(struct vsp1_video *video);
 
-void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe);
-
-void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
-				   struct vsp1_entity *input,
-				   unsigned int alpha);
-
-void vsp1_pipelines_suspend(struct vsp1_device *vsp1);
-void vsp1_pipelines_resume(struct vsp1_device *vsp1);
-
 #endif /* __VSP1_VIDEO_H__ */
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 12/32] v4l: vsp1: Rename video pipeline functions to use vsp1_video prefix
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (10 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 11/32] v4l: vsp1: Split pipeline management code from vsp1_video.c Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 13/32] v4l: vsp1: Extract pipeline initialization code into a function Laurent Pinchart
                   ` (20 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

Those functions are specific to video nodes, rename them for
consistency.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_video.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 1a909ab34ea1..8569836ea51b 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -308,9 +308,9 @@ vsp1_video_format_adjust(struct vsp1_video *video,
  * Pipeline Management
  */
 
-static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe,
-					 struct vsp1_rwpf *input,
-					 struct vsp1_rwpf *output)
+static int vsp1_video_pipeline_validate_branch(struct vsp1_pipeline *pipe,
+					       struct vsp1_rwpf *input,
+					       struct vsp1_rwpf *output)
 {
 	struct vsp1_entity *entity;
 	unsigned int entities = 0;
@@ -384,8 +384,8 @@ static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe,
 	return 0;
 }
 
-static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
-				  struct vsp1_video *video)
+static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe,
+					struct vsp1_video *video)
 {
 	struct media_entity_graph graph;
 	struct media_entity *entity = &video->video.entity;
@@ -437,8 +437,8 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
 	 * contains no loop and that all branches end at the output WPF.
 	 */
 	for (i = 0; i < pipe->num_inputs; ++i) {
-		ret = vsp1_pipeline_validate_branch(pipe, pipe->inputs[i],
-						    pipe->output);
+		ret = vsp1_video_pipeline_validate_branch(pipe, pipe->inputs[i],
+							  pipe->output);
 		if (ret < 0)
 			goto error;
 	}
@@ -450,8 +450,8 @@ error:
 	return ret;
 }
 
-static int vsp1_pipeline_init(struct vsp1_pipeline *pipe,
-			      struct vsp1_video *video)
+static int vsp1_video_pipeline_init(struct vsp1_pipeline *pipe,
+				    struct vsp1_video *video)
 {
 	int ret;
 
@@ -459,7 +459,7 @@ static int vsp1_pipeline_init(struct vsp1_pipeline *pipe,
 
 	/* If we're the first user validate and initialize the pipeline. */
 	if (pipe->use_count == 0) {
-		ret = vsp1_pipeline_validate(pipe, video);
+		ret = vsp1_video_pipeline_validate(pipe, video);
 		if (ret < 0)
 			goto done;
 	}
@@ -472,7 +472,7 @@ done:
 	return ret;
 }
 
-static void vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe)
+static void vsp1_video_pipeline_cleanup(struct vsp1_pipeline *pipe)
 {
 	mutex_lock(&pipe->lock);
 
@@ -738,7 +738,7 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq)
 	}
 	mutex_unlock(&pipe->lock);
 
-	vsp1_pipeline_cleanup(pipe);
+	vsp1_video_pipeline_cleanup(pipe);
 	media_entity_pipeline_stop(&video->video.entity);
 
 	/* Remove all buffers from the IRQ queue. */
@@ -879,7 +879,7 @@ vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
 	if (ret < 0)
 		goto err_stop;
 
-	ret = vsp1_pipeline_init(pipe, video);
+	ret = vsp1_video_pipeline_init(pipe, video);
 	if (ret < 0)
 		goto err_stop;
 
@@ -891,7 +891,7 @@ vsp1_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
 	return 0;
 
 err_cleanup:
-	vsp1_pipeline_cleanup(pipe);
+	vsp1_video_pipeline_cleanup(pipe);
 err_stop:
 	media_entity_pipeline_stop(&video->video.entity);
 	return ret;
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 13/32] v4l: vsp1: Extract pipeline initialization code into a function
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (11 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 12/32] v4l: vsp1: Rename video pipeline functions to use vsp1_video prefix Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 14/32] v4l: vsp1: Reuse local variable instead of recomputing it Laurent Pinchart
                   ` (19 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

The code will be reused outside of vsp1_video.c.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_pipe.c  | 10 ++++++++++
 drivers/media/platform/vsp1/vsp1_pipe.h  |  1 +
 drivers/media/platform/vsp1/vsp1_video.c |  6 +-----
 3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
index 199d57f1fe06..524420ed6333 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.c
+++ b/drivers/media/platform/vsp1/vsp1_pipe.c
@@ -48,6 +48,16 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
 	pipe->uds = NULL;
 }
 
+void vsp1_pipeline_init(struct vsp1_pipeline *pipe)
+{
+	mutex_init(&pipe->lock);
+	spin_lock_init(&pipe->irqlock);
+	init_waitqueue_head(&pipe->wq);
+
+	INIT_LIST_HEAD(&pipe->entities);
+	pipe->state = VSP1_PIPELINE_STOPPED;
+}
+
 void vsp1_pipeline_run(struct vsp1_pipeline *pipe)
 {
 	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
index f8a099fba973..8553d5a03aa3 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.h
+++ b/drivers/media/platform/vsp1/vsp1_pipe.h
@@ -67,6 +67,7 @@ static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e)
 }
 
 void vsp1_pipeline_reset(struct vsp1_pipeline *pipe);
+void vsp1_pipeline_init(struct vsp1_pipeline *pipe);
 
 void vsp1_pipeline_run(struct vsp1_pipeline *pipe);
 bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe);
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 8569836ea51b..ec68890af14b 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -1009,11 +1009,7 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1,
 	spin_lock_init(&video->irqlock);
 	INIT_LIST_HEAD(&video->irqqueue);
 
-	mutex_init(&video->pipe.lock);
-	spin_lock_init(&video->pipe.irqlock);
-	INIT_LIST_HEAD(&video->pipe.entities);
-	init_waitqueue_head(&video->pipe.wq);
-	video->pipe.state = VSP1_PIPELINE_STOPPED;
+	vsp1_pipeline_init(&video->pipe);
 	video->pipe.frame_end = vsp1_video_pipeline_frame_end;
 
 	/* Initialize the media entity... */
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 14/32] v4l: vsp1: Reuse local variable instead of recomputing it
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (12 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 13/32] v4l: vsp1: Extract pipeline initialization code into a function Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 15/32] v4l: vsp1: Extract link creation to separate function Laurent Pinchart
                   ` (18 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

No need to waste CPU cycles when the value we need is already available.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_video.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index ec68890af14b..c0afbf81d9aa 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -416,7 +416,7 @@ static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe,
 			rwpf->video->pipe_index = pipe->num_inputs;
 		} else if (e->type == VSP1_ENTITY_WPF) {
 			rwpf = to_rwpf(subdev);
-			pipe->output = to_rwpf(subdev);
+			pipe->output = rwpf;
 			rwpf->video->pipe_index = 0;
 		} else if (e->type == VSP1_ENTITY_LIF) {
 			pipe->lif = e;
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 15/32] v4l: vsp1: Extract link creation to separate function
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (13 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 14/32] v4l: vsp1: Reuse local variable instead of recomputing it Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 16/32] v4l: vsp1: Document the vsp1_pipeline structure Laurent Pinchart
                   ` (17 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

Link creation will be handled differently for the DU pipeline.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_drv.c | 114 ++++++++++++++++++---------------
 1 file changed, 64 insertions(+), 50 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 91ecf75119ba..d1e42260a871 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -67,7 +67,7 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data)
  */
 
 /*
- * vsp1_create_links - Create links from all sources to the given sink
+ * vsp1_create_sink_links - Create links from all sources to the given sink
  *
  * This function creates media links from all valid sources to the given sink
  * pad. Links that would be invalid according to the VSP1 hardware capabilities
@@ -76,7 +76,8 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data)
  * - from a UDS to a UDS (UDS entities can't be chained)
  * - from an entity to itself (no loops are allowed)
  */
-static int vsp1_create_links(struct vsp1_device *vsp1, struct vsp1_entity *sink)
+static int vsp1_create_sink_links(struct vsp1_device *vsp1,
+				  struct vsp1_entity *sink)
 {
 	struct media_entity *entity = &sink->subdev.entity;
 	struct vsp1_entity *source;
@@ -116,6 +117,64 @@ static int vsp1_create_links(struct vsp1_device *vsp1, struct vsp1_entity *sink)
 	return 0;
 }
 
+static int vsp1_create_links(struct vsp1_device *vsp1)
+{
+	struct vsp1_entity *entity;
+	unsigned int i;
+	int ret;
+
+	list_for_each_entry(entity, &vsp1->entities, list_dev) {
+		if (entity->type == VSP1_ENTITY_LIF ||
+		    entity->type == VSP1_ENTITY_RPF)
+			continue;
+
+		ret = vsp1_create_sink_links(vsp1, entity);
+		if (ret < 0)
+			return ret;
+	}
+
+	for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
+		struct vsp1_rwpf *rpf = vsp1->rpf[i];
+
+		ret = media_entity_create_link(&rpf->video->video.entity, 0,
+					       &rpf->entity.subdev.entity,
+					       RWPF_PAD_SINK,
+					       MEDIA_LNK_FL_ENABLED |
+					       MEDIA_LNK_FL_IMMUTABLE);
+		if (ret < 0)
+			return ret;
+	}
+
+	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
+		/* Connect the video device to the WPF. All connections are
+		 * immutable except for the WPF0 source link if a LIF is
+		 * present.
+		 */
+		struct vsp1_rwpf *wpf = vsp1->wpf[i];
+		unsigned int flags = MEDIA_LNK_FL_ENABLED;
+
+		if (!(vsp1->pdata.features & VSP1_HAS_LIF) || i != 0)
+			flags |= MEDIA_LNK_FL_IMMUTABLE;
+
+		ret = media_entity_create_link(&wpf->entity.subdev.entity,
+					       RWPF_PAD_SOURCE,
+					       &wpf->video->video.entity,
+					       0, flags);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (vsp1->pdata.features & VSP1_HAS_LIF) {
+		ret = media_entity_create_link(
+			&vsp1->wpf[0]->entity.subdev.entity, RWPF_PAD_SOURCE,
+			&vsp1->lif->entity.subdev.entity, LIF_PAD_SINK, 0);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
 static void vsp1_destroy_entities(struct vsp1_device *vsp1)
 {
 	struct vsp1_entity *entity, *_entity;
@@ -276,54 +335,9 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 	}
 
 	/* Create links. */
-	list_for_each_entry(entity, &vsp1->entities, list_dev) {
-		if (entity->type == VSP1_ENTITY_LIF ||
-		    entity->type == VSP1_ENTITY_RPF)
-			continue;
-
-		ret = vsp1_create_links(vsp1, entity);
-		if (ret < 0)
-			goto done;
-	}
-
-	for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
-		struct vsp1_rwpf *rpf = vsp1->rpf[i];
-
-		ret = media_entity_create_link(&rpf->video->video.entity, 0,
-					       &rpf->entity.subdev.entity,
-					       RWPF_PAD_SINK,
-					       MEDIA_LNK_FL_ENABLED |
-					       MEDIA_LNK_FL_IMMUTABLE);
-		if (ret < 0)
-			goto done;
-	}
-
-	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
-		/* Connect the video device to the WPF. All connections are
-		 * immutable except for the WPF0 source link if a LIF is
-		 * present.
-		 */
-		struct vsp1_rwpf *wpf = vsp1->wpf[i];
-		unsigned int flags = MEDIA_LNK_FL_ENABLED;
-
-		if (!(vsp1->pdata.features & VSP1_HAS_LIF) || i != 0)
-			flags |= MEDIA_LNK_FL_IMMUTABLE;
-
-		ret = media_entity_create_link(&wpf->entity.subdev.entity,
-					       RWPF_PAD_SOURCE,
-					       &wpf->video->video.entity,
-					       0, flags);
-		if (ret < 0)
-			goto done;
-	}
-
-	if (vsp1->pdata.features & VSP1_HAS_LIF) {
-		ret = media_entity_create_link(
-			&vsp1->wpf[0]->entity.subdev.entity, RWPF_PAD_SOURCE,
-			&vsp1->lif->entity.subdev.entity, LIF_PAD_SINK, 0);
-		if (ret < 0)
-			return ret;
-	}
+	ret = vsp1_create_links(vsp1);
+	if (ret < 0)
+		goto done;
 
 	/* Register all subdevs. */
 	list_for_each_entry(entity, &vsp1->entities, list_dev) {
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 16/32] v4l: vsp1: Document the vsp1_pipeline structure
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (14 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 15/32] v4l: vsp1: Extract link creation to separate function Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 17/32] v4l: vsp1: Fix typo in VI6_DISP_IRQ_STA_DST register name Laurent Pinchart
                   ` (16 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_pipe.h | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
index 8553d5a03aa3..9c8ded1c29f6 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.h
+++ b/drivers/media/platform/vsp1/vsp1_pipe.h
@@ -29,9 +29,23 @@ enum vsp1_pipeline_state {
 
 /*
  * struct vsp1_pipeline - A VSP1 hardware pipeline
- * @media: the media pipeline
+ * @pipe: the media pipeline
  * @irqlock: protects the pipeline state
+ * @state: current state
+ * @wq: work queue to wait for state change completion
+ * @frame_end: frame end interrupt handler
  * @lock: protects the pipeline use count and stream count
+ * @use_count: number of video nodes using the pipeline
+ * @stream_count: number of streaming video nodes
+ * @buffers_ready: bitmask of RPFs and WPFs with at least one buffer available
+ * @num_inputs: number of RPFs
+ * @inputs: array of RPFs in the pipeline
+ * @output: WPF at the output of the pipeline
+ * @bru: BRU entity, if present
+ * @lif: LIF entity, if present
+ * @uds: UDS entity, if present
+ * @uds_input: entity at the input of the UDS, if the UDS is present
+ * @entities: list of entities in the pipeline
  */
 struct vsp1_pipeline {
 	struct media_pipeline pipe;
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 17/32] v4l: vsp1: Fix typo in VI6_DISP_IRQ_STA_DST register name
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (15 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 16/32] v4l: vsp1: Document the vsp1_pipeline structure Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 18/32] v4l: vsp1: Set the SRU CTRL0 register when starting the stream Laurent Pinchart
                   ` (15 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

Rename the VI6_DISP_IRQ_STA_DSE register to VI6_DISP_IRQ_STA_DST to fix
a typo and match the datasheet.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_regs.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h
index 25b48738b147..8173ceaab9f9 100644
--- a/drivers/media/platform/vsp1/vsp1_regs.h
+++ b/drivers/media/platform/vsp1/vsp1_regs.h
@@ -46,7 +46,7 @@
 #define VI6_DISP_IRQ_ENB_LNEE(n)	(1 << (n))
 
 #define VI6_DISP_IRQ_STA		0x007c
-#define VI6_DISP_IRQ_STA_DSE		(1 << 8)
+#define VI6_DISP_IRQ_STA_DST		(1 << 8)
 #define VI6_DISP_IRQ_STA_MAE		(1 << 5)
 #define VI6_DISP_IRQ_STA_LNE(n)		(1 << (n))
 
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 18/32] v4l: vsp1: Set the SRU CTRL0 register when starting the stream
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (16 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 17/32] v4l: vsp1: Fix typo in VI6_DISP_IRQ_STA_DST register name Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 19/32] v4l: vsp1: Remove unused module write functions Laurent Pinchart
                   ` (14 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

Commit 58f896d859ce ("[media] v4l: vsp1: sru: Make the intensity
controllable during streaming") refactored the stream start code and
removed the SRU CTRL0 register write by mistake. Add it back.

Fixes: 58f896d859ce ("[media] v4l: vsp1: sru: Make the intensity controllable during streaming")
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_sru.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c
index 6310acab60e7..d41ae950d1a1 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.c
+++ b/drivers/media/platform/vsp1/vsp1_sru.c
@@ -154,6 +154,7 @@ static int sru_s_stream(struct v4l2_subdev *subdev, int enable)
 	mutex_lock(sru->ctrls.lock);
 	ctrl0 |= vsp1_sru_read(sru, VI6_SRU_CTRL0)
 	       & (VI6_SRU_CTRL0_PARAM0_MASK | VI6_SRU_CTRL0_PARAM1_MASK);
+	vsp1_sru_write(sru, VI6_SRU_CTRL0, ctrl0);
 	mutex_unlock(sru->ctrls.lock);
 
 	vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5);
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 19/32] v4l: vsp1: Remove unused module write functions
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (17 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 18/32] v4l: vsp1: Set the SRU CTRL0 register when starting the stream Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 20/32] v4l: vsp1: Move entity route setup function to vsp1_entity.c Laurent Pinchart
                   ` (13 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

Several module write functions are not used, remove them.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_bru.c | 5 -----
 drivers/media/platform/vsp1/vsp1_lif.c | 5 -----
 drivers/media/platform/vsp1/vsp1_lut.c | 5 -----
 drivers/media/platform/vsp1/vsp1_rpf.c | 6 ------
 drivers/media/platform/vsp1/vsp1_uds.c | 6 ------
 5 files changed, 27 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c
index b4cc9bc478af..841bc6664bca 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.c
+++ b/drivers/media/platform/vsp1/vsp1_bru.c
@@ -28,11 +28,6 @@
  * Device Access
  */
 
-static inline u32 vsp1_bru_read(struct vsp1_bru *bru, u32 reg)
-{
-	return vsp1_read(bru->entity.vsp1, reg);
-}
-
 static inline void vsp1_bru_write(struct vsp1_bru *bru, u32 reg, u32 data)
 {
 	vsp1_write(bru->entity.vsp1, reg, data);
diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c
index 39fa5ef20fbb..b868bce08982 100644
--- a/drivers/media/platform/vsp1/vsp1_lif.c
+++ b/drivers/media/platform/vsp1/vsp1_lif.c
@@ -26,11 +26,6 @@
  * Device Access
  */
 
-static inline u32 vsp1_lif_read(struct vsp1_lif *lif, u32 reg)
-{
-	return vsp1_read(lif->entity.vsp1, reg);
-}
-
 static inline void vsp1_lif_write(struct vsp1_lif *lif, u32 reg, u32 data)
 {
 	vsp1_write(lif->entity.vsp1, reg, data);
diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c
index 656ec272a414..9e33caa9c616 100644
--- a/drivers/media/platform/vsp1/vsp1_lut.c
+++ b/drivers/media/platform/vsp1/vsp1_lut.c
@@ -27,11 +27,6 @@
  * Device Access
  */
 
-static inline u32 vsp1_lut_read(struct vsp1_lut *lut, u32 reg)
-{
-	return vsp1_read(lut->entity.vsp1, reg);
-}
-
 static inline void vsp1_lut_write(struct vsp1_lut *lut, u32 reg, u32 data)
 {
 	vsp1_write(lut->entity.vsp1, reg, data);
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index c0b7f76cd0b5..b9c39f9e4458 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -26,12 +26,6 @@
  * Device Access
  */
 
-static inline u32 vsp1_rpf_read(struct vsp1_rwpf *rpf, u32 reg)
-{
-	return vsp1_read(rpf->entity.vsp1,
-			 reg + rpf->entity.index * VI6_RPF_OFFSET);
-}
-
 static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, u32 reg, u32 data)
 {
 	vsp1_write(rpf->entity.vsp1,
diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c
index ccc8243e3493..27ad07466ebd 100644
--- a/drivers/media/platform/vsp1/vsp1_uds.c
+++ b/drivers/media/platform/vsp1/vsp1_uds.c
@@ -29,12 +29,6 @@
  * Device Access
  */
 
-static inline u32 vsp1_uds_read(struct vsp1_uds *uds, u32 reg)
-{
-	return vsp1_read(uds->entity.vsp1,
-			 reg + uds->entity.index * VI6_UDS_OFFSET);
-}
-
 static inline void vsp1_uds_write(struct vsp1_uds *uds, u32 reg, u32 data)
 {
 	vsp1_write(uds->entity.vsp1,
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 20/32] v4l: vsp1: Move entity route setup function to vsp1_entity.c
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (18 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 19/32] v4l: vsp1: Remove unused module write functions Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:56 ` [PATCH 21/32] v4l: vsp1: Make number of BRU inputs configurable Laurent Pinchart
                   ` (12 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

The function will be used by the DU code, move it out of vsp1_video.c.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_entity.c | 12 ++++++++++++
 drivers/media/platform/vsp1/vsp1_entity.h |  2 ++
 drivers/media/platform/vsp1/vsp1_video.c  | 12 ------------
 3 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index 0c52e4b71a98..cb9d480d8ee5 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -58,6 +58,18 @@ int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming)
 	return ret;
 }
 
+void vsp1_entity_route_setup(struct vsp1_entity *source)
+{
+	struct vsp1_entity *sink;
+
+	if (source->route->reg == 0)
+		return;
+
+	sink = container_of(source->sink, struct vsp1_entity, subdev.entity);
+	vsp1_write(source->vsp1, source->route->reg,
+		   sink->route->inputs[source->sink_pad]);
+}
+
 /* -----------------------------------------------------------------------------
  * V4L2 Subdevice Operations
  */
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
index 9c95507ec762..9606d0d21263 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.h
+++ b/drivers/media/platform/vsp1/vsp1_entity.h
@@ -96,4 +96,6 @@ void vsp1_entity_init_formats(struct v4l2_subdev *subdev,
 bool vsp1_entity_is_streaming(struct vsp1_entity *entity);
 int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming);
 
+void vsp1_entity_route_setup(struct vsp1_entity *source);
+
 #endif /* __VSP1_ENTITY_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index c0afbf81d9aa..589ce49e8688 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -657,18 +657,6 @@ static void vsp1_video_buffer_queue(struct vb2_buffer *vb)
 	spin_unlock_irqrestore(&pipe->irqlock, flags);
 }
 
-static void vsp1_entity_route_setup(struct vsp1_entity *source)
-{
-	struct vsp1_entity *sink;
-
-	if (source->route->reg == 0)
-		return;
-
-	sink = container_of(source->sink, struct vsp1_entity, subdev.entity);
-	vsp1_write(source->vsp1, source->route->reg,
-		   sink->route->inputs[source->sink_pad]);
-}
-
 static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct vsp1_video *video = vb2_get_drv_priv(vq);
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 21/32] v4l: vsp1: Make number of BRU inputs configurable
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (19 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 20/32] v4l: vsp1: Move entity route setup function to vsp1_entity.c Laurent Pinchart
@ 2015-09-13 20:56 ` Laurent Pinchart
  2015-09-13 20:57 ` [PATCH 22/32] v4l: vsp1: Make the BRU optional Laurent Pinchart
                   ` (11 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:56 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

The R-Car Gen3 family has 5-inputs BRUs, support them by making the
number of BRU inputs configurable.

As the driver assumes that the number of BRU inputs is equal to the
number of RPFs, replace the BRU_MAX_INPUTS macro with VSP1_MAX_RPF to
make the assumption apparent.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

---
 drivers/media/platform/vsp1/vsp1.h        |  5 +++++
 drivers/media/platform/vsp1/vsp1_bru.c    | 19 ++++++++++---------
 drivers/media/platform/vsp1/vsp1_bru.h    |  3 +--
 drivers/media/platform/vsp1/vsp1_drv.c    |  9 ++++++++-
 drivers/media/platform/vsp1/vsp1_entity.h |  4 +++-
 5 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index b25032bd37a7..3b2b2387e085 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -50,9 +50,14 @@ struct vsp1_platform_data {
 	unsigned int wpf_count;
 };
 
+struct vsp1_device_info {
+	unsigned int num_bru_inputs;
+};
+
 struct vsp1_device {
 	struct device *dev;
 	struct vsp1_platform_data pdata;
+	const struct vsp1_device_info *info;
 
 	void __iomem *mmio;
 	struct clk *clock;
diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c
index 841bc6664bca..2d31284dfc3f 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.c
+++ b/drivers/media/platform/vsp1/vsp1_bru.c
@@ -79,7 +79,7 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
 	if (!enable)
 		return 0;
 
-	format = &bru->entity.formats[BRU_PAD_SOURCE];
+	format = &bru->entity.formats[bru->entity.source_pad];
 
 	/* The hardware is extremely flexible but we have no userspace API to
 	 * expose all the parameters, nor is it clear whether we would have use
@@ -109,7 +109,7 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
 		       VI6_BRU_ROP_CROP(VI6_ROP_NOP) |
 		       VI6_BRU_ROP_AROP(VI6_ROP_NOP));
 
-	for (i = 0; i < 4; ++i) {
+	for (i = 0; i < bru->entity.source_pad; ++i) {
 		bool premultiplied = false;
 		u32 ctrl = 0;
 
@@ -291,7 +291,7 @@ static int bru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_con
 	*format = fmt->format;
 
 	/* Reset the compose rectangle */
-	if (fmt->pad != BRU_PAD_SOURCE) {
+	if (fmt->pad != bru->entity.source_pad) {
 		struct v4l2_rect *compose;
 
 		compose = bru_get_compose(bru, cfg, fmt->pad, fmt->which);
@@ -305,7 +305,7 @@ static int bru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_con
 	if (fmt->pad == BRU_PAD_SINK(0)) {
 		unsigned int i;
 
-		for (i = 0; i <= BRU_PAD_SOURCE; ++i) {
+		for (i = 0; i <= bru->entity.source_pad; ++i) {
 			format = vsp1_entity_get_pad_format(&bru->entity, cfg,
 							    i, fmt->which);
 			format->code = fmt->format.code;
@@ -321,7 +321,7 @@ static int bru_get_selection(struct v4l2_subdev *subdev,
 {
 	struct vsp1_bru *bru = to_bru(subdev);
 
-	if (sel->pad == BRU_PAD_SOURCE)
+	if (sel->pad == bru->entity.source_pad)
 		return -EINVAL;
 
 	switch (sel->target) {
@@ -349,7 +349,7 @@ static int bru_set_selection(struct v4l2_subdev *subdev,
 	struct v4l2_mbus_framefmt *format;
 	struct v4l2_rect *compose;
 
-	if (sel->pad == BRU_PAD_SOURCE)
+	if (sel->pad == bru->entity.source_pad)
 		return -EINVAL;
 
 	if (sel->target != V4L2_SEL_TGT_COMPOSE)
@@ -358,8 +358,8 @@ static int bru_set_selection(struct v4l2_subdev *subdev,
 	/* The compose rectangle top left corner must be inside the output
 	 * frame.
 	 */
-	format = vsp1_entity_get_pad_format(&bru->entity, cfg, BRU_PAD_SOURCE,
-					    sel->which);
+	format = vsp1_entity_get_pad_format(&bru->entity, cfg,
+					    bru->entity.source_pad, sel->which);
 	sel->r.left = clamp_t(unsigned int, sel->r.left, 0, format->width - 1);
 	sel->r.top = clamp_t(unsigned int, sel->r.top, 0, format->height - 1);
 
@@ -415,7 +415,8 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1)
 
 	bru->entity.type = VSP1_ENTITY_BRU;
 
-	ret = vsp1_entity_init(vsp1, &bru->entity, 5);
+	ret = vsp1_entity_init(vsp1, &bru->entity,
+			       vsp1->info->num_bru_inputs + 1);
 	if (ret < 0)
 		return ERR_PTR(ret);
 
diff --git a/drivers/media/platform/vsp1/vsp1_bru.h b/drivers/media/platform/vsp1/vsp1_bru.h
index 16b1c6554911..dbac9686ea69 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.h
+++ b/drivers/media/platform/vsp1/vsp1_bru.h
@@ -23,7 +23,6 @@ struct vsp1_device;
 struct vsp1_rwpf;
 
 #define BRU_PAD_SINK(n)				(n)
-#define BRU_PAD_SOURCE				4
 
 struct vsp1_bru {
 	struct vsp1_entity entity;
@@ -33,7 +32,7 @@ struct vsp1_bru {
 	struct {
 		struct vsp1_rwpf *rpf;
 		struct v4l2_rect compose;
-	} inputs[4];
+	} inputs[VSP1_MAX_RPF];
 };
 
 static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev)
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index d1e42260a871..bd22457bf392 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/videodev2.h>
 
@@ -510,6 +511,8 @@ static int vsp1_parse_dt(struct vsp1_device *vsp1)
 	struct device_node *np = vsp1->dev->of_node;
 	struct vsp1_platform_data *pdata = &vsp1->pdata;
 
+	vsp1->info = of_device_get_match_data(vsp1->dev);
+
 	if (of_property_read_bool(np, "renesas,has-lif"))
 		pdata->features |= VSP1_HAS_LIF;
 	if (of_property_read_bool(np, "renesas,has-lut"))
@@ -608,8 +611,12 @@ static int vsp1_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct vsp1_device_info vsp1_gen2_info = {
+	.num_bru_inputs = 4,
+};
+
 static const struct of_device_id vsp1_of_match[] = {
-	{ .compatible = "renesas,vsp1" },
+	{ .compatible = "renesas,vsp1", .data = &vsp1_gen2_info },
 	{ },
 };
 
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
index 9606d0d21263..360a2e668ac2 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.h
+++ b/drivers/media/platform/vsp1/vsp1_entity.h
@@ -32,6 +32,8 @@ enum vsp1_entity_type {
 	VSP1_ENTITY_WPF,
 };
 
+#define VSP1_ENTITY_MAX_INPUTS		5	/* For the BRU */
+
 /*
  * struct vsp1_route - Entity routing configuration
  * @type: Entity type this routing entry is associated with
@@ -48,7 +50,7 @@ struct vsp1_route {
 	enum vsp1_entity_type type;
 	unsigned int index;
 	unsigned int reg;
-	unsigned int inputs[4];
+	unsigned int inputs[VSP1_ENTITY_MAX_INPUTS];
 };
 
 struct vsp1_entity {
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 22/32] v4l: vsp1: Make the BRU optional
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (20 preceding siblings ...)
  2015-09-13 20:56 ` [PATCH 21/32] v4l: vsp1: Make number of BRU inputs configurable Laurent Pinchart
@ 2015-09-13 20:57 ` Laurent Pinchart
  2015-09-13 20:57 ` [PATCH 23/32] v4l: vsp1: Move format info to vsp1_pipe.c Laurent Pinchart
                   ` (10 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:57 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh, devicetree

Not all VSP instances have a BRU on R-Car Gen3, make it optional. For
backward compatibility with older DT bindings default to BRU
availability on R-Car Gen2.

Cc: devicetree@vger.kernel.org
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 .../devicetree/bindings/media/renesas,vsp1.txt     |  3 +++
 drivers/media/platform/vsp1/vsp1.h                 |  1 +
 drivers/media/platform/vsp1/vsp1_drv.c             | 23 ++++++++++++++++------
 3 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/renesas,vsp1.txt b/Documentation/devicetree/bindings/media/renesas,vsp1.txt
index 674c8c30d046..766f034c1e45 100644
--- a/Documentation/devicetree/bindings/media/renesas,vsp1.txt
+++ b/Documentation/devicetree/bindings/media/renesas,vsp1.txt
@@ -20,6 +20,9 @@ Optional properties:
 
   - renesas,#uds: Number of Up Down Scaler (UDS) modules in the VSP1. Defaults
     to 0 if not present.
+  - renesas,has-bru: Boolean, indicates that the Blending & ROP Unit (BRU)
+    module is available. Defaults to true on R-Car Gen2 and false on R-Car Gen3
+    if not present.
   - renesas,has-lif: Boolean, indicates that the LCD Interface (LIF) module is
     available.
   - renesas,has-lut: Boolean, indicates that the Look Up Table (LUT) module is
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 3b2b2387e085..173f9f830049 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -42,6 +42,7 @@ struct vsp1_uds;
 #define VSP1_HAS_LIF		(1 << 0)
 #define VSP1_HAS_LUT		(1 << 1)
 #define VSP1_HAS_SRU		(1 << 2)
+#define VSP1_HAS_BRU		(1 << 3)
 
 struct vsp1_platform_data {
 	unsigned int features;
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index bd22457bf392..eccdacdf4f4c 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -223,13 +223,15 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 	}
 
 	/* Instantiate all the entities. */
-	vsp1->bru = vsp1_bru_create(vsp1);
-	if (IS_ERR(vsp1->bru)) {
-		ret = PTR_ERR(vsp1->bru);
-		goto done;
-	}
+	if (vsp1->pdata.features & VSP1_HAS_BRU) {
+		vsp1->bru = vsp1_bru_create(vsp1);
+		if (IS_ERR(vsp1->bru)) {
+			ret = PTR_ERR(vsp1->bru);
+			goto done;
+		}
 
-	list_add_tail(&vsp1->bru->entity.list_dev, &vsp1->entities);
+		list_add_tail(&vsp1->bru->entity.list_dev, &vsp1->entities);
+	}
 
 	vsp1->hsi = vsp1_hsit_create(vsp1, true);
 	if (IS_ERR(vsp1->hsi)) {
@@ -513,6 +515,8 @@ static int vsp1_parse_dt(struct vsp1_device *vsp1)
 
 	vsp1->info = of_device_get_match_data(vsp1->dev);
 
+	if (of_property_read_bool(np, "renesas,has-bru"))
+		pdata->features |= VSP1_HAS_BRU;
 	if (of_property_read_bool(np, "renesas,has-lif"))
 		pdata->features |= VSP1_HAS_LIF;
 	if (of_property_read_bool(np, "renesas,has-lut"))
@@ -542,6 +546,13 @@ static int vsp1_parse_dt(struct vsp1_device *vsp1)
 		return -EINVAL;
 	}
 
+	/* Backward compatibility: all Gen2 VSP instances have a BRU, the
+	 * renesas,has-bru property was thus not available. Set the HAS_BRU
+	 * feature automatically in that case.
+	 */
+	if (vsp1->info->num_bru_inputs == 4)
+		pdata->features |= VSP1_HAS_BRU;
+
 	return 0;
 }
 
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 23/32] v4l: vsp1: Move format info to vsp1_pipe.c
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (21 preceding siblings ...)
  2015-09-13 20:57 ` [PATCH 22/32] v4l: vsp1: Make the BRU optional Laurent Pinchart
@ 2015-09-13 20:57 ` Laurent Pinchart
  2015-09-13 20:57 ` [PATCH 24/32] v4l: vsp1: Make the userspace API optional Laurent Pinchart
                   ` (9 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:57 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

Format information and the related helper function are not specific to
the V4L2 API, move them from vsp1_video.c to vsp1_pipe.c.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_pipe.c  | 110 +++++++++++++++++++++++++++++++
 drivers/media/platform/vsp1/vsp1_pipe.h  |  29 ++++++++
 drivers/media/platform/vsp1/vsp1_video.c | 107 ------------------------------
 drivers/media/platform/vsp1/vsp1_video.h |  27 --------
 4 files changed, 139 insertions(+), 134 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
index 524420ed6333..df11259dcc0a 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.c
+++ b/drivers/media/platform/vsp1/vsp1_pipe.c
@@ -25,6 +25,116 @@
 #include "vsp1_uds.h"
 
 /* -----------------------------------------------------------------------------
+ * Helper Functions
+ */
+
+static const struct vsp1_format_info vsp1_video_formats[] = {
+	{ V4L2_PIX_FMT_RGB332, MEDIA_BUS_FMT_ARGB8888_1X32,
+	  VI6_FMT_RGB_332, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+	  1, { 8, 0, 0 }, false, false, 1, 1, false },
+	{ V4L2_PIX_FMT_ARGB444, MEDIA_BUS_FMT_ARGB8888_1X32,
+	  VI6_FMT_ARGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS,
+	  1, { 16, 0, 0 }, false, false, 1, 1, true },
+	{ V4L2_PIX_FMT_XRGB444, MEDIA_BUS_FMT_ARGB8888_1X32,
+	  VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS,
+	  1, { 16, 0, 0 }, false, false, 1, 1, true },
+	{ V4L2_PIX_FMT_ARGB555, MEDIA_BUS_FMT_ARGB8888_1X32,
+	  VI6_FMT_ARGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS,
+	  1, { 16, 0, 0 }, false, false, 1, 1, true },
+	{ V4L2_PIX_FMT_XRGB555, MEDIA_BUS_FMT_ARGB8888_1X32,
+	  VI6_FMT_XRGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS,
+	  1, { 16, 0, 0 }, false, false, 1, 1, false },
+	{ V4L2_PIX_FMT_RGB565, MEDIA_BUS_FMT_ARGB8888_1X32,
+	  VI6_FMT_RGB_565, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS,
+	  1, { 16, 0, 0 }, false, false, 1, 1, false },
+	{ V4L2_PIX_FMT_BGR24, MEDIA_BUS_FMT_ARGB8888_1X32,
+	  VI6_FMT_BGR_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+	  1, { 24, 0, 0 }, false, false, 1, 1, false },
+	{ V4L2_PIX_FMT_RGB24, MEDIA_BUS_FMT_ARGB8888_1X32,
+	  VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+	  1, { 24, 0, 0 }, false, false, 1, 1, false },
+	{ V4L2_PIX_FMT_ABGR32, MEDIA_BUS_FMT_ARGB8888_1X32,
+	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
+	  1, { 32, 0, 0 }, false, false, 1, 1, true },
+	{ V4L2_PIX_FMT_XBGR32, MEDIA_BUS_FMT_ARGB8888_1X32,
+	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
+	  1, { 32, 0, 0 }, false, false, 1, 1, false },
+	{ V4L2_PIX_FMT_ARGB32, MEDIA_BUS_FMT_ARGB8888_1X32,
+	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+	  1, { 32, 0, 0 }, false, false, 1, 1, true },
+	{ V4L2_PIX_FMT_XRGB32, MEDIA_BUS_FMT_ARGB8888_1X32,
+	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+	  1, { 32, 0, 0 }, false, false, 1, 1, false },
+	{ V4L2_PIX_FMT_UYVY, MEDIA_BUS_FMT_AYUV8_1X32,
+	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+	  1, { 16, 0, 0 }, false, false, 2, 1, false },
+	{ V4L2_PIX_FMT_VYUY, MEDIA_BUS_FMT_AYUV8_1X32,
+	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+	  1, { 16, 0, 0 }, false, true, 2, 1, false },
+	{ V4L2_PIX_FMT_YUYV, MEDIA_BUS_FMT_AYUV8_1X32,
+	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+	  1, { 16, 0, 0 }, true, false, 2, 1, false },
+	{ V4L2_PIX_FMT_YVYU, MEDIA_BUS_FMT_AYUV8_1X32,
+	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+	  1, { 16, 0, 0 }, true, true, 2, 1, false },
+	{ V4L2_PIX_FMT_NV12M, MEDIA_BUS_FMT_AYUV8_1X32,
+	  VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+	  2, { 8, 16, 0 }, false, false, 2, 2, false },
+	{ V4L2_PIX_FMT_NV21M, MEDIA_BUS_FMT_AYUV8_1X32,
+	  VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+	  2, { 8, 16, 0 }, false, true, 2, 2, false },
+	{ V4L2_PIX_FMT_NV16M, MEDIA_BUS_FMT_AYUV8_1X32,
+	  VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+	  2, { 8, 16, 0 }, false, false, 2, 1, false },
+	{ V4L2_PIX_FMT_NV61M, MEDIA_BUS_FMT_AYUV8_1X32,
+	  VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+	  2, { 8, 16, 0 }, false, true, 2, 1, false },
+	{ V4L2_PIX_FMT_YUV420M, MEDIA_BUS_FMT_AYUV8_1X32,
+	  VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+	  3, { 8, 8, 8 }, false, false, 2, 2, false },
+};
+
+/*
+ * vsp1_get_format_info - Retrieve format information for a 4CC
+ * @fourcc: the format 4CC
+ *
+ * Return a pointer to the format information structure corresponding to the
+ * given V4L2 format 4CC, or NULL if no corresponding format can be found.
+ */
+const struct vsp1_format_info *vsp1_get_format_info(u32 fourcc)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(vsp1_video_formats); ++i) {
+		const struct vsp1_format_info *info = &vsp1_video_formats[i];
+
+		if (info->fourcc == fourcc)
+			return info;
+	}
+
+	return NULL;
+}
+
+/* -----------------------------------------------------------------------------
  * Pipeline Management
  */
 
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
index 9c8ded1c29f6..f9035c739e9a 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.h
+++ b/drivers/media/platform/vsp1/vsp1_pipe.h
@@ -21,6 +21,33 @@
 
 struct vsp1_rwpf;
 
+/*
+ * struct vsp1_format_info - VSP1 video format description
+ * @mbus: media bus format code
+ * @fourcc: V4L2 pixel format FCC identifier
+ * @planes: number of planes
+ * @bpp: bits per pixel
+ * @hwfmt: VSP1 hardware format
+ * @swap_yc: the Y and C components are swapped (Y comes before C)
+ * @swap_uv: the U and V components are swapped (V comes before U)
+ * @hsub: horizontal subsampling factor
+ * @vsub: vertical subsampling factor
+ * @alpha: has an alpha channel
+ */
+struct vsp1_format_info {
+	u32 fourcc;
+	unsigned int mbus;
+	unsigned int hwfmt;
+	unsigned int swap;
+	unsigned int planes;
+	unsigned int bpp[3];
+	bool swap_yc;
+	bool swap_uv;
+	unsigned int hsub;
+	unsigned int vsub;
+	bool alpha;
+};
+
 enum vsp1_pipeline_state {
 	VSP1_PIPELINE_STOPPED,
 	VSP1_PIPELINE_RUNNING,
@@ -97,4 +124,6 @@ void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
 void vsp1_pipelines_suspend(struct vsp1_device *vsp1);
 void vsp1_pipelines_resume(struct vsp1_device *vsp1);
 
+const struct vsp1_format_info *vsp1_get_format_info(u32 fourcc);
+
 #endif /* __VSP1_PIPE_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 589ce49e8688..e0d4f84bc26d 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -48,113 +48,6 @@
  * Helper functions
  */
 
-static const struct vsp1_format_info vsp1_video_formats[] = {
-	{ V4L2_PIX_FMT_RGB332, MEDIA_BUS_FMT_ARGB8888_1X32,
-	  VI6_FMT_RGB_332, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  1, { 8, 0, 0 }, false, false, 1, 1, false },
-	{ V4L2_PIX_FMT_ARGB444, MEDIA_BUS_FMT_ARGB8888_1X32,
-	  VI6_FMT_ARGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS,
-	  1, { 16, 0, 0 }, false, false, 1, 1, true },
-	{ V4L2_PIX_FMT_XRGB444, MEDIA_BUS_FMT_ARGB8888_1X32,
-	  VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS,
-	  1, { 16, 0, 0 }, false, false, 1, 1, true },
-	{ V4L2_PIX_FMT_ARGB555, MEDIA_BUS_FMT_ARGB8888_1X32,
-	  VI6_FMT_ARGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS,
-	  1, { 16, 0, 0 }, false, false, 1, 1, true },
-	{ V4L2_PIX_FMT_XRGB555, MEDIA_BUS_FMT_ARGB8888_1X32,
-	  VI6_FMT_XRGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS,
-	  1, { 16, 0, 0 }, false, false, 1, 1, false },
-	{ V4L2_PIX_FMT_RGB565, MEDIA_BUS_FMT_ARGB8888_1X32,
-	  VI6_FMT_RGB_565, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS,
-	  1, { 16, 0, 0 }, false, false, 1, 1, false },
-	{ V4L2_PIX_FMT_BGR24, MEDIA_BUS_FMT_ARGB8888_1X32,
-	  VI6_FMT_BGR_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  1, { 24, 0, 0 }, false, false, 1, 1, false },
-	{ V4L2_PIX_FMT_RGB24, MEDIA_BUS_FMT_ARGB8888_1X32,
-	  VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  1, { 24, 0, 0 }, false, false, 1, 1, false },
-	{ V4L2_PIX_FMT_ABGR32, MEDIA_BUS_FMT_ARGB8888_1X32,
-	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
-	  1, { 32, 0, 0 }, false, false, 1, 1, true },
-	{ V4L2_PIX_FMT_XBGR32, MEDIA_BUS_FMT_ARGB8888_1X32,
-	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
-	  1, { 32, 0, 0 }, false, false, 1, 1, false },
-	{ V4L2_PIX_FMT_ARGB32, MEDIA_BUS_FMT_ARGB8888_1X32,
-	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  1, { 32, 0, 0 }, false, false, 1, 1, true },
-	{ V4L2_PIX_FMT_XRGB32, MEDIA_BUS_FMT_ARGB8888_1X32,
-	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  1, { 32, 0, 0 }, false, false, 1, 1, false },
-	{ V4L2_PIX_FMT_UYVY, MEDIA_BUS_FMT_AYUV8_1X32,
-	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  1, { 16, 0, 0 }, false, false, 2, 1, false },
-	{ V4L2_PIX_FMT_VYUY, MEDIA_BUS_FMT_AYUV8_1X32,
-	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  1, { 16, 0, 0 }, false, true, 2, 1, false },
-	{ V4L2_PIX_FMT_YUYV, MEDIA_BUS_FMT_AYUV8_1X32,
-	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  1, { 16, 0, 0 }, true, false, 2, 1, false },
-	{ V4L2_PIX_FMT_YVYU, MEDIA_BUS_FMT_AYUV8_1X32,
-	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  1, { 16, 0, 0 }, true, true, 2, 1, false },
-	{ V4L2_PIX_FMT_NV12M, MEDIA_BUS_FMT_AYUV8_1X32,
-	  VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  2, { 8, 16, 0 }, false, false, 2, 2, false },
-	{ V4L2_PIX_FMT_NV21M, MEDIA_BUS_FMT_AYUV8_1X32,
-	  VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  2, { 8, 16, 0 }, false, true, 2, 2, false },
-	{ V4L2_PIX_FMT_NV16M, MEDIA_BUS_FMT_AYUV8_1X32,
-	  VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  2, { 8, 16, 0 }, false, false, 2, 1, false },
-	{ V4L2_PIX_FMT_NV61M, MEDIA_BUS_FMT_AYUV8_1X32,
-	  VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  2, { 8, 16, 0 }, false, true, 2, 1, false },
-	{ V4L2_PIX_FMT_YUV420M, MEDIA_BUS_FMT_AYUV8_1X32,
-	  VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
-	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
-	  3, { 8, 8, 8 }, false, false, 2, 2, false },
-};
-
-/*
- * vsp1_get_format_info - Retrieve format information for a 4CC
- * @fourcc: the format 4CC
- *
- * Return a pointer to the format information structure corresponding to the
- * given V4L2 format 4CC, or NULL if no corresponding format can be found.
- */
-static const struct vsp1_format_info *vsp1_get_format_info(u32 fourcc)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(vsp1_video_formats); ++i) {
-		const struct vsp1_format_info *info = &vsp1_video_formats[i];
-
-		if (info->fourcc == fourcc)
-			return info;
-	}
-
-	return NULL;
-}
-
-
 static struct v4l2_subdev *
 vsp1_video_remote_subdev(struct media_pad *local, u32 *pad)
 {
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index f89590b83080..9624f952e095 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -21,33 +21,6 @@
 #include "vsp1_pipe.h"
 #include "vsp1_rwpf.h"
 
-/*
- * struct vsp1_format_info - VSP1 video format description
- * @mbus: media bus format code
- * @fourcc: V4L2 pixel format FCC identifier
- * @planes: number of planes
- * @bpp: bits per pixel
- * @hwfmt: VSP1 hardware format
- * @swap_yc: the Y and C components are swapped (Y comes before C)
- * @swap_uv: the U and V components are swapped (V comes before U)
- * @hsub: horizontal subsampling factor
- * @vsub: vertical subsampling factor
- * @alpha: has an alpha channel
- */
-struct vsp1_format_info {
-	u32 fourcc;
-	unsigned int mbus;
-	unsigned int hwfmt;
-	unsigned int swap;
-	unsigned int planes;
-	unsigned int bpp[3];
-	bool swap_yc;
-	bool swap_uv;
-	unsigned int hsub;
-	unsigned int vsub;
-	bool alpha;
-};
-
 struct vsp1_vb2_buffer {
 	struct vb2_buffer buf;
 	struct list_head queue;
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 24/32] v4l: vsp1: Make the userspace API optional
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (22 preceding siblings ...)
  2015-09-13 20:57 ` [PATCH 23/32] v4l: vsp1: Move format info to vsp1_pipe.c Laurent Pinchart
@ 2015-09-13 20:57 ` Laurent Pinchart
  2015-09-13 20:57 ` [PATCH 25/32] v4l: vsp1: Make pipeline inputs array index by RPF index Laurent Pinchart
                   ` (8 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:57 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

The R-Car Gen3 SoCs include VSP instances dedicated to the DU that will
be controlled entirely by the rcar-du-drm driver through the KMS API. To
support that use case make the userspace V4L2 API optional.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1.h        |  1 +
 drivers/media/platform/vsp1/vsp1_drv.c    | 57 ++++++++++++++++++-------------
 drivers/media/platform/vsp1/vsp1_entity.c |  2 +-
 drivers/media/platform/vsp1/vsp1_sru.c    |  6 ++--
 drivers/media/platform/vsp1/vsp1_wpf.c    |  6 ++--
 5 files changed, 43 insertions(+), 29 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 173f9f830049..791d24c2c8d1 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -53,6 +53,7 @@ struct vsp1_platform_data {
 
 struct vsp1_device_info {
 	unsigned int num_bru_inputs;
+	bool uapi;
 };
 
 struct vsp1_device {
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index eccdacdf4f4c..5a18f69c90c2 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -134,6 +134,17 @@ static int vsp1_create_links(struct vsp1_device *vsp1)
 			return ret;
 	}
 
+	if (vsp1->pdata.features & VSP1_HAS_LIF) {
+		ret = media_entity_create_link(
+			&vsp1->wpf[0]->entity.subdev.entity, RWPF_PAD_SOURCE,
+			&vsp1->lif->entity.subdev.entity, LIF_PAD_SINK, 0);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (!vsp1->info->uapi)
+		return 0;
+
 	for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
 		struct vsp1_rwpf *rpf = vsp1->rpf[i];
 
@@ -165,14 +176,6 @@ static int vsp1_create_links(struct vsp1_device *vsp1)
 			return ret;
 	}
 
-	if (vsp1->pdata.features & VSP1_HAS_LIF) {
-		ret = media_entity_create_link(
-			&vsp1->wpf[0]->entity.subdev.entity, RWPF_PAD_SOURCE,
-			&vsp1->lif->entity.subdev.entity, LIF_PAD_SINK, 0);
-		if (ret < 0)
-			return ret;
-	}
-
 	return 0;
 }
 
@@ -270,7 +273,6 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 	}
 
 	for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
-		struct vsp1_video *video;
 		struct vsp1_rwpf *rpf;
 
 		rpf = vsp1_rpf_create(vsp1, i);
@@ -282,13 +284,16 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 		vsp1->rpf[i] = rpf;
 		list_add_tail(&rpf->entity.list_dev, &vsp1->entities);
 
-		video = vsp1_video_create(vsp1, rpf);
-		if (IS_ERR(video)) {
-			ret = PTR_ERR(video);
-			goto done;
-		}
+		if (vsp1->info->uapi) {
+			struct vsp1_video *video = vsp1_video_create(vsp1, rpf);
 
-		list_add_tail(&video->list, &vsp1->videos);
+			if (IS_ERR(video)) {
+				ret = PTR_ERR(video);
+				goto done;
+			}
+
+			list_add_tail(&video->list, &vsp1->videos);
+		}
 	}
 
 	if (vsp1->pdata.features & VSP1_HAS_SRU) {
@@ -315,7 +320,6 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 	}
 
 	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
-		struct vsp1_video *video;
 		struct vsp1_rwpf *wpf;
 
 		wpf = vsp1_wpf_create(vsp1, i);
@@ -327,14 +331,17 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 		vsp1->wpf[i] = wpf;
 		list_add_tail(&wpf->entity.list_dev, &vsp1->entities);
 
-		video = vsp1_video_create(vsp1, wpf);
-		if (IS_ERR(video)) {
-			ret = PTR_ERR(video);
-			goto done;
-		}
+		if (vsp1->info->uapi) {
+			struct vsp1_video *video = vsp1_video_create(vsp1, wpf);
+
+			if (IS_ERR(video)) {
+				ret = PTR_ERR(video);
+				goto done;
+			}
 
-		list_add_tail(&video->list, &vsp1->videos);
-		wpf->entity.sink = &video->video.entity;
+			list_add_tail(&video->list, &vsp1->videos);
+			wpf->entity.sink = &video->video.entity;
+		}
 	}
 
 	/* Create links. */
@@ -350,7 +357,8 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 			goto done;
 	}
 
-	ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev);
+	if (vsp1->info->uapi)
+		ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev);
 
 done:
 	if (ret < 0)
@@ -624,6 +632,7 @@ static int vsp1_remove(struct platform_device *pdev)
 
 static const struct vsp1_device_info vsp1_gen2_info = {
 	.num_bru_inputs = 4,
+	.uapi = true,
 };
 
 static const struct of_device_id vsp1_of_match[] = {
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index cb9d480d8ee5..7068ba1e89e9 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -45,7 +45,7 @@ int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming)
 	if (!streaming)
 		return 0;
 
-	if (!entity->subdev.ctrl_handler)
+	if (!entity->vsp1->info->uapi || !entity->subdev.ctrl_handler)
 		return 0;
 
 	ret = v4l2_ctrl_handler_setup(entity->subdev.ctrl_handler);
diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c
index d41ae950d1a1..4e1db5a3c928 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.c
+++ b/drivers/media/platform/vsp1/vsp1_sru.c
@@ -151,11 +151,13 @@ static int sru_s_stream(struct v4l2_subdev *subdev, int enable)
 	/* Take the control handler lock to ensure that the CTRL0 value won't be
 	 * changed behind our back by a set control operation.
 	 */
-	mutex_lock(sru->ctrls.lock);
+	if (sru->entity.vsp1->info->uapi)
+		mutex_lock(sru->ctrls.lock);
 	ctrl0 |= vsp1_sru_read(sru, VI6_SRU_CTRL0)
 	       & (VI6_SRU_CTRL0_PARAM0_MASK | VI6_SRU_CTRL0_PARAM1_MASK);
 	vsp1_sru_write(sru, VI6_SRU_CTRL0, ctrl0);
-	mutex_unlock(sru->ctrls.lock);
+	if (sru->entity.vsp1->info->uapi)
+		mutex_unlock(sru->ctrls.lock);
 
 	vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5);
 
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index d2537b46fc46..451ca37930e0 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -151,10 +151,12 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
 	/* Take the control handler lock to ensure that the PDV value won't be
 	 * changed behind our back by a set control operation.
 	 */
-	mutex_lock(wpf->ctrls.lock);
+	if (vsp1->info->uapi)
+		mutex_lock(wpf->ctrls.lock);
 	outfmt |= vsp1_wpf_read(wpf, VI6_WPF_OUTFMT) & VI6_WPF_OUTFMT_PDV_MASK;
 	vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt);
-	mutex_unlock(wpf->ctrls.lock);
+	if (vsp1->info->uapi)
+		mutex_unlock(wpf->ctrls.lock);
 
 	vsp1_write(vsp1, VI6_DPR_WPF_FPORCH(wpf->entity.index),
 		   VI6_DPR_WPF_FPORCH_FP_WPFN);
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 25/32] v4l: vsp1: Make pipeline inputs array index by RPF index
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (23 preceding siblings ...)
  2015-09-13 20:57 ` [PATCH 24/32] v4l: vsp1: Make the userspace API optional Laurent Pinchart
@ 2015-09-13 20:57 ` Laurent Pinchart
  2015-09-13 20:57 ` [PATCH 26/32] v4l: vsp1: Set the alpha value manually in RPF and WPF s_stream handlers Laurent Pinchart
                   ` (7 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:57 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

The pipeline inputs array stores pointers to all RPFs contained in the
pipeline. It's currently indexed contiguously by adding RPFs in the
order they are found during graph walk. This can't easily support
dynamic addition and removal of RPFs while streaming, which will be
required for combined VSP+DU support.

Make the array indexed by RPF index instead and skip NULL elements when
iterating over RPFs.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_pipe.c  |  6 +++++-
 drivers/media/platform/vsp1/vsp1_pipe.h  |  2 +-
 drivers/media/platform/vsp1/vsp1_video.c | 16 ++++++++++++----
 drivers/media/platform/vsp1/vsp1_wpf.c   |  5 ++++-
 4 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
index df11259dcc0a..d41e4ca94a02 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.c
+++ b/drivers/media/platform/vsp1/vsp1_pipe.c
@@ -140,14 +140,18 @@ const struct vsp1_format_info *vsp1_get_format_info(u32 fourcc)
 
 void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
 {
+	unsigned int i;
+
 	if (pipe->bru) {
 		struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
-		unsigned int i;
 
 		for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i)
 			bru->inputs[i].rpf = NULL;
 	}
 
+	for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i)
+		pipe->inputs[i] = NULL;
+
 	INIT_LIST_HEAD(&pipe->entities);
 	pipe->state = VSP1_PIPELINE_STOPPED;
 	pipe->buffers_ready = 0;
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
index f9035c739e9a..c4c300561c5c 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.h
+++ b/drivers/media/platform/vsp1/vsp1_pipe.h
@@ -66,7 +66,7 @@ enum vsp1_pipeline_state {
  * @stream_count: number of streaming video nodes
  * @buffers_ready: bitmask of RPFs and WPFs with at least one buffer available
  * @num_inputs: number of RPFs
- * @inputs: array of RPFs in the pipeline
+ * @inputs: array of RPFs in the pipeline (indexed by RPF index)
  * @output: WPF at the output of the pipeline
  * @bru: BRU entity, if present
  * @lif: LIF entity, if present
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index e0d4f84bc26d..78926c9f4125 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -305,8 +305,8 @@ static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe,
 
 		if (e->type == VSP1_ENTITY_RPF) {
 			rwpf = to_rwpf(subdev);
-			pipe->inputs[pipe->num_inputs++] = rwpf;
-			rwpf->video->pipe_index = pipe->num_inputs;
+			pipe->inputs[rwpf->entity.index] = rwpf;
+			rwpf->video->pipe_index = ++pipe->num_inputs;
 		} else if (e->type == VSP1_ENTITY_WPF) {
 			rwpf = to_rwpf(subdev);
 			pipe->output = rwpf;
@@ -329,7 +329,10 @@ static int vsp1_video_pipeline_validate(struct vsp1_pipeline *pipe,
 	/* Follow links downstream for each input and make sure the graph
 	 * contains no loop and that all branches end at the output WPF.
 	 */
-	for (i = 0; i < pipe->num_inputs; ++i) {
+	for (i = 0; i < video->vsp1->pdata.rpf_count; ++i) {
+		if (!pipe->inputs[i])
+			continue;
+
 		ret = vsp1_video_pipeline_validate_branch(pipe, pipe->inputs[i],
 							  pipe->output);
 		if (ret < 0)
@@ -453,11 +456,16 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe,
 
 static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe)
 {
+	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
 	unsigned int i;
 
 	/* Complete buffers on all video nodes. */
-	for (i = 0; i < pipe->num_inputs; ++i)
+	for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
+		if (!pipe->inputs[i])
+			continue;
+
 		vsp1_video_frame_end(pipe, pipe->inputs[i]);
+	}
 
 	if (!pipe->lif)
 		vsp1_video_frame_end(pipe, pipe->output);
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index 451ca37930e0..5996a35143b8 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -97,9 +97,12 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
 	 * inputs as sub-layers and select the virtual RPF as the master
 	 * layer.
 	 */
-	for (i = 0; i < pipe->num_inputs; ++i) {
+	for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
 		struct vsp1_rwpf *input = pipe->inputs[i];
 
+		if (!input)
+			continue;
+
 		srcrpf |= (!pipe->bru && pipe->num_inputs == 1)
 			? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index)
 			: VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index);
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 26/32] v4l: vsp1: Set the alpha value manually in RPF and WPF s_stream handlers
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (24 preceding siblings ...)
  2015-09-13 20:57 ` [PATCH 25/32] v4l: vsp1: Make pipeline inputs array index by RPF index Laurent Pinchart
@ 2015-09-13 20:57 ` Laurent Pinchart
  2015-09-13 20:57 ` [PATCH 27/32] v4l: vsp1: Don't validate links when the userspace API is disabled Laurent Pinchart
                   ` (6 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:57 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

The RPF and WPF alpha values are set through V4L2 controls and applied
when starting the video stream by a call to v4l2_ctrl_handler_setup().
As that function uses the control handler mutex it can't be called in
interrupt context, where the VSP+DU pipeline handler might need to
reconfigure the pipeline.

Set the alpha value manually in the RPF and WPF s_stream handler to
ensure that the hardware is properly configured even when controlled
without the userspace API. If the userspace API is enabled protect that
with the control lock to avoid race conditions with userspace.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_rpf.c  | 16 ++++++++++++++--
 drivers/media/platform/vsp1/vsp1_rwpf.h |  2 ++
 drivers/media/platform/vsp1/vsp1_wpf.c  |  7 ++++---
 3 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index b9c39f9e4458..7ccec87b1139 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -68,7 +68,9 @@ static const struct v4l2_ctrl_ops rpf_ctrl_ops = {
 
 static int rpf_s_stream(struct v4l2_subdev *subdev, int enable)
 {
+	struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity);
 	struct vsp1_rwpf *rpf = to_rwpf(subdev);
+	struct vsp1_device *vsp1 = rpf->entity.vsp1;
 	const struct vsp1_format_info *fmtinfo = rpf->fmtinfo;
 	const struct v4l2_pix_format_mplane *format = &rpf->format;
 	const struct v4l2_rect *crop = &rpf->crop;
@@ -148,6 +150,15 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable)
 	vsp1_rpf_write(rpf, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_AEXT_EXT |
 		       (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED
 				       : VI6_RPF_ALPH_SEL_ASEL_FIXED));
+
+	if (vsp1->info->uapi)
+		mutex_lock(rpf->ctrls.lock);
+	vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET,
+		       rpf->alpha->cur.val << VI6_RPF_VRTCOL_SET_LAYA_SHIFT);
+	vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, rpf->alpha->cur.val);
+	if (vsp1->info->uapi)
+		mutex_unlock(rpf->ctrls.lock);
+
 	vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0);
 	vsp1_rpf_write(rpf, VI6_RPF_CKEY_CTRL, 0);
 
@@ -245,8 +256,9 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
 
 	/* Initialize the control handler. */
 	v4l2_ctrl_handler_init(&rpf->ctrls, 1);
-	v4l2_ctrl_new_std(&rpf->ctrls, &rpf_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
-			  0, 255, 1, 255);
+	rpf->alpha = v4l2_ctrl_new_std(&rpf->ctrls, &rpf_ctrl_ops,
+				       V4L2_CID_ALPHA_COMPONENT,
+				       0, 255, 1, 255);
 
 	rpf->entity.subdev.ctrl_handler = &rpf->ctrls;
 
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index 1a90c7c8e972..8e8235682ada 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -23,6 +23,7 @@
 #define RWPF_PAD_SINK				0
 #define RWPF_PAD_SOURCE				1
 
+struct v4l2_ctrl;
 struct vsp1_rwpf;
 struct vsp1_video;
 
@@ -40,6 +41,7 @@ struct vsp1_rwpf_operations {
 struct vsp1_rwpf {
 	struct vsp1_entity entity;
 	struct v4l2_ctrl_handler ctrls;
+	struct v4l2_ctrl *alpha;
 
 	struct vsp1_video *video;
 
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index 5996a35143b8..6212fc714a7c 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -156,7 +156,7 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
 	 */
 	if (vsp1->info->uapi)
 		mutex_lock(wpf->ctrls.lock);
-	outfmt |= vsp1_wpf_read(wpf, VI6_WPF_OUTFMT) & VI6_WPF_OUTFMT_PDV_MASK;
+	outfmt |= wpf->alpha->cur.val << VI6_WPF_OUTFMT_PDV_SHIFT;
 	vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt);
 	if (vsp1->info->uapi)
 		mutex_unlock(wpf->ctrls.lock);
@@ -254,8 +254,9 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
 
 	/* Initialize the control handler. */
 	v4l2_ctrl_handler_init(&wpf->ctrls, 1);
-	v4l2_ctrl_new_std(&wpf->ctrls, &wpf_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
-			  0, 255, 1, 255);
+	wpf->alpha = v4l2_ctrl_new_std(&wpf->ctrls, &wpf_ctrl_ops,
+				       V4L2_CID_ALPHA_COMPONENT,
+				       0, 255, 1, 255);
 
 	wpf->entity.subdev.ctrl_handler = &wpf->ctrls;
 
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 27/32] v4l: vsp1: Don't validate links when the userspace API is disabled
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (25 preceding siblings ...)
  2015-09-13 20:57 ` [PATCH 26/32] v4l: vsp1: Set the alpha value manually in RPF and WPF s_stream handlers Laurent Pinchart
@ 2015-09-13 20:57 ` Laurent Pinchart
  2015-09-13 20:57 ` [PATCH 28/32] v4l: vsp1: Add VSP+DU support Laurent Pinchart
                   ` (5 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:57 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

As the pipeline is configured internally by the driver when the
userspace API is disabled its configuration can be trusted and link
validation isn't needed.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1.h        |  2 ++
 drivers/media/platform/vsp1/vsp1_bru.c    |  2 +-
 drivers/media/platform/vsp1/vsp1_drv.c    | 10 ++++++++++
 drivers/media/platform/vsp1/vsp1_entity.c | 11 +++--------
 drivers/media/platform/vsp1/vsp1_entity.h |  5 ++++-
 drivers/media/platform/vsp1/vsp1_hsit.c   |  2 +-
 drivers/media/platform/vsp1/vsp1_lif.c    |  2 +-
 drivers/media/platform/vsp1/vsp1_lut.c    |  2 +-
 drivers/media/platform/vsp1/vsp1_rpf.c    |  2 +-
 drivers/media/platform/vsp1/vsp1_sru.c    |  2 +-
 drivers/media/platform/vsp1/vsp1_uds.c    |  2 +-
 drivers/media/platform/vsp1/vsp1_wpf.c    |  2 +-
 12 files changed, 27 insertions(+), 17 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 791d24c2c8d1..6102ade125bb 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -82,6 +82,8 @@ struct vsp1_device {
 
 	struct v4l2_device v4l2_dev;
 	struct media_device media_dev;
+
+	struct media_entity_operations media_ops;
 };
 
 int vsp1_device_get(struct vsp1_device *vsp1);
diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c
index 2d31284dfc3f..99b742ff53c9 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.c
+++ b/drivers/media/platform/vsp1/vsp1_bru.c
@@ -424,7 +424,7 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1)
 	subdev = &bru->entity.subdev;
 	v4l2_subdev_init(subdev, &bru_ops);
 
-	subdev->entity.ops = &vsp1_media_ops;
+	subdev->entity.ops = &vsp1->media_ops;
 	subdev->internal_ops = &vsp1_subdev_internal_ops;
 	snprintf(subdev->name, sizeof(subdev->name), "%s bru",
 		 dev_name(vsp1->dev));
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 5a18f69c90c2..fb9c8f59e3b0 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -21,6 +21,8 @@
 #include <linux/platform_device.h>
 #include <linux/videodev2.h>
 
+#include <media/v4l2-subdev.h>
+
 #include "vsp1.h"
 #include "vsp1_bru.h"
 #include "vsp1_hsit.h"
@@ -217,6 +219,14 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 		return ret;
 	}
 
+	vsp1->media_ops.link_setup = vsp1_entity_link_setup;
+	/* Don't perform link validation when the userspace API is disabled as
+	 * the pipeline is configured internally by the driver in that case, and
+	 * its configuration can thus be trusted.
+	 */
+	if (vsp1->info->uapi)
+		vsp1->media_ops.link_validate = v4l2_subdev_link_validate;
+
 	vdev->mdev = mdev;
 	ret = v4l2_device_register(vsp1->dev, vdev);
 	if (ret < 0) {
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index 7068ba1e89e9..79e05b76d6e3 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -131,9 +131,9 @@ const struct v4l2_subdev_internal_ops vsp1_subdev_internal_ops = {
  * Media Operations
  */
 
-static int vsp1_entity_link_setup(struct media_entity *entity,
-				  const struct media_pad *local,
-				  const struct media_pad *remote, u32 flags)
+int vsp1_entity_link_setup(struct media_entity *entity,
+			   const struct media_pad *local,
+			   const struct media_pad *remote, u32 flags)
 {
 	struct vsp1_entity *source;
 
@@ -158,11 +158,6 @@ static int vsp1_entity_link_setup(struct media_entity *entity,
 	return 0;
 }
 
-const struct media_entity_operations vsp1_media_ops = {
-	.link_setup = vsp1_entity_link_setup,
-	.link_validate = v4l2_subdev_link_validate,
-};
-
 /* -----------------------------------------------------------------------------
  * Initialization
  */
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
index 360a2e668ac2..83570dfde8ec 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.h
+++ b/drivers/media/platform/vsp1/vsp1_entity.h
@@ -86,7 +86,10 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
 void vsp1_entity_destroy(struct vsp1_entity *entity);
 
 extern const struct v4l2_subdev_internal_ops vsp1_subdev_internal_ops;
-extern const struct media_entity_operations vsp1_media_ops;
+
+int vsp1_entity_link_setup(struct media_entity *entity,
+			   const struct media_pad *local,
+			   const struct media_pad *remote, u32 flags);
 
 struct v4l2_mbus_framefmt *
 vsp1_entity_get_pad_format(struct vsp1_entity *entity,
diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c
index 8ffb817ae525..c1087cff31a0 100644
--- a/drivers/media/platform/vsp1/vsp1_hsit.c
+++ b/drivers/media/platform/vsp1/vsp1_hsit.c
@@ -203,7 +203,7 @@ struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device *vsp1, bool inverse)
 	subdev = &hsit->entity.subdev;
 	v4l2_subdev_init(subdev, &hsit_ops);
 
-	subdev->entity.ops = &vsp1_media_ops;
+	subdev->entity.ops = &vsp1->media_ops;
 	subdev->internal_ops = &vsp1_subdev_internal_ops;
 	snprintf(subdev->name, sizeof(subdev->name), "%s %s",
 		 dev_name(vsp1->dev), inverse ? "hsi" : "hst");
diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c
index b868bce08982..b8e73d32d14d 100644
--- a/drivers/media/platform/vsp1/vsp1_lif.c
+++ b/drivers/media/platform/vsp1/vsp1_lif.c
@@ -223,7 +223,7 @@ struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1)
 	subdev = &lif->entity.subdev;
 	v4l2_subdev_init(subdev, &lif_ops);
 
-	subdev->entity.ops = &vsp1_media_ops;
+	subdev->entity.ops = &vsp1->media_ops;
 	subdev->internal_ops = &vsp1_subdev_internal_ops;
 	snprintf(subdev->name, sizeof(subdev->name), "%s lif",
 		 dev_name(vsp1->dev));
diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c
index 9e33caa9c616..4b89095e7b5f 100644
--- a/drivers/media/platform/vsp1/vsp1_lut.c
+++ b/drivers/media/platform/vsp1/vsp1_lut.c
@@ -237,7 +237,7 @@ struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1)
 	subdev = &lut->entity.subdev;
 	v4l2_subdev_init(subdev, &lut_ops);
 
-	subdev->entity.ops = &vsp1_media_ops;
+	subdev->entity.ops = &vsp1->media_ops;
 	subdev->internal_ops = &vsp1_subdev_internal_ops;
 	snprintf(subdev->name, sizeof(subdev->name), "%s lut",
 		 dev_name(vsp1->dev));
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index 7ccec87b1139..56177628a17c 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -245,7 +245,7 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
 	subdev = &rpf->entity.subdev;
 	v4l2_subdev_init(subdev, &rpf_ops);
 
-	subdev->entity.ops = &vsp1_media_ops;
+	subdev->entity.ops = &vsp1->media_ops;
 	subdev->internal_ops = &vsp1_subdev_internal_ops;
 	snprintf(subdev->name, sizeof(subdev->name), "%s rpf.%u",
 		 dev_name(vsp1->dev), index);
diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c
index 4e1db5a3c928..cc09efbfb24f 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.c
+++ b/drivers/media/platform/vsp1/vsp1_sru.c
@@ -363,7 +363,7 @@ struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1)
 	subdev = &sru->entity.subdev;
 	v4l2_subdev_init(subdev, &sru_ops);
 
-	subdev->entity.ops = &vsp1_media_ops;
+	subdev->entity.ops = &vsp1->media_ops;
 	subdev->internal_ops = &vsp1_subdev_internal_ops;
 	snprintf(subdev->name, sizeof(subdev->name), "%s sru",
 		 dev_name(vsp1->dev));
diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c
index 27ad07466ebd..bba67770cf95 100644
--- a/drivers/media/platform/vsp1/vsp1_uds.c
+++ b/drivers/media/platform/vsp1/vsp1_uds.c
@@ -338,7 +338,7 @@ struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index)
 	subdev = &uds->entity.subdev;
 	v4l2_subdev_init(subdev, &uds_ops);
 
-	subdev->entity.ops = &vsp1_media_ops;
+	subdev->entity.ops = &vsp1->media_ops;
 	subdev->internal_ops = &vsp1_subdev_internal_ops;
 	snprintf(subdev->name, sizeof(subdev->name), "%s uds.%u",
 		 dev_name(vsp1->dev), index);
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index 6212fc714a7c..7d06e84bcb9f 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -243,7 +243,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
 	subdev = &wpf->entity.subdev;
 	v4l2_subdev_init(subdev, &wpf_ops);
 
-	subdev->entity.ops = &vsp1_media_ops;
+	subdev->entity.ops = &vsp1->media_ops;
 	subdev->internal_ops = &vsp1_subdev_internal_ops;
 	snprintf(subdev->name, sizeof(subdev->name), "%s wpf.%u",
 		 dev_name(vsp1->dev), index);
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 28/32] v4l: vsp1: Add VSP+DU support
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (26 preceding siblings ...)
  2015-09-13 20:57 ` [PATCH 27/32] v4l: vsp1: Don't validate links when the userspace API is disabled Laurent Pinchart
@ 2015-09-13 20:57 ` Laurent Pinchart
  2015-09-13 20:57 ` [PATCH 29/32] v4l: vsp1: Disconnect unused RPFs from the DRM pipeline Laurent Pinchart
                   ` (4 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:57 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

Implement internal control of the VSP pipeline to be used by the DU
DRM/KMS driver when using the VSP as an internal composer handled
through DRM/KMS only.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

---
 drivers/media/platform/vsp1/Makefile   |   2 +-
 drivers/media/platform/vsp1/vsp1.h     |   3 +-
 drivers/media/platform/vsp1/vsp1_drm.c | 550 +++++++++++++++++++++++++++++++++
 drivers/media/platform/vsp1/vsp1_drm.h |  26 ++
 drivers/media/platform/vsp1/vsp1_drv.c |  13 +-
 include/media/vsp1.h                   |  30 ++
 6 files changed, 617 insertions(+), 7 deletions(-)
 create mode 100644 drivers/media/platform/vsp1/vsp1_drm.c
 create mode 100644 drivers/media/platform/vsp1/vsp1_drm.h
 create mode 100644 include/media/vsp1.h

diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile
index 0ef0b5384125..447e72a2ef43 100644
--- a/drivers/media/platform/vsp1/Makefile
+++ b/drivers/media/platform/vsp1/Makefile
@@ -1,5 +1,5 @@
 vsp1-y					:= vsp1_drv.o vsp1_entity.o vsp1_pipe.o
-vsp1-y					+= vsp1_video.o
+vsp1-y					+= vsp1_drm.o vsp1_video.o
 vsp1-y					+= vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o
 vsp1-y					+= vsp1_hsit.o vsp1_lif.o vsp1_lut.o
 vsp1-y					+= vsp1_bru.o vsp1_sru.o vsp1_uds.o
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 6102ade125bb..61a24e4a0848 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -26,6 +26,7 @@
 struct clk;
 struct device;
 
+struct vsp1_drm;
 struct vsp1_platform_data;
 struct vsp1_bru;
 struct vsp1_hsit;
@@ -82,8 +83,8 @@ struct vsp1_device {
 
 	struct v4l2_device v4l2_dev;
 	struct media_device media_dev;
-
 	struct media_entity_operations media_ops;
+	struct vsp1_drm *drm;
 };
 
 int vsp1_device_get(struct vsp1_device *vsp1);
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
new file mode 100644
index 000000000000..2969d570f462
--- /dev/null
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -0,0 +1,550 @@
+/*
+ * vsp1_drm.c  --  R-Car VSP1 DRM API
+ *
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/vsp1.h>
+
+#include <media/media-entity.h>
+#include <media/v4l2-subdev.h>
+
+#include "vsp1.h"
+#include "vsp1_bru.h"
+#include "vsp1_drm.h"
+#include "vsp1_lif.h"
+#include "vsp1_pipe.h"
+#include "vsp1_rwpf.h"
+
+/* -----------------------------------------------------------------------------
+ * Runtime Handling
+ */
+
+static int vsp1_drm_pipeline_run(struct vsp1_pipeline *pipe)
+{
+	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
+	int ret;
+
+	if (vsp1->drm->update) {
+		struct vsp1_entity *entity;
+
+		list_for_each_entry(entity, &pipe->entities, list_pipe) {
+			/* Skip unused RPFs. */
+			if (entity->type == VSP1_ENTITY_RPF) {
+				struct vsp1_rwpf *rpf =
+					to_rwpf(&entity->subdev);
+
+				if (!pipe->inputs[rpf->entity.index])
+					continue;
+			}
+
+			vsp1_entity_route_setup(entity);
+
+			ret = v4l2_subdev_call(&entity->subdev, video,
+					       s_stream, 1);
+			if (ret < 0) {
+				dev_err(vsp1->dev,
+					"DRM pipeline start failure on entity %s\n",
+					entity->subdev.name);
+				return ret;
+			}
+		}
+
+		vsp1->drm->update = false;
+	}
+
+	vsp1_pipeline_run(pipe);
+
+	return 0;
+}
+
+static void vsp1_drm_pipeline_frame_end(struct vsp1_pipeline *pipe)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pipe->irqlock, flags);
+	if (pipe->num_inputs)
+		vsp1_drm_pipeline_run(pipe);
+	spin_unlock_irqrestore(&pipe->irqlock, flags);
+}
+
+/* -----------------------------------------------------------------------------
+ * DU Driver API
+ */
+
+int vsp1_du_init(struct device *dev)
+{
+	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
+
+	if (!vsp1)
+		return -EPROBE_DEFER;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vsp1_du_init);
+
+/**
+ * vsp1_du_setup_lif - Setup the output part of the VSP pipeline
+ * @dev: the VSP device
+ * @width: output frame width in pixels
+ * @height: output frame height in pixels
+ *
+ * Configure the output part of VSP DRM pipeline for the given frame @width and
+ * @height. This sets up formats on the BRU source pad, the WPF0 sink and source
+ * pads, and the LIF sink pad.
+ *
+ * As the media bus code on the BRU source pad is conditioned by the
+ * configuration of the BRU sink 0 pad, we also set up the formats on all BRU
+ * sinks, even if the configuration will be overwritten later by
+ * vsp1_du_setup_rpf(). This ensures that the BRU configuration is set to a well
+ * defined state.
+ *
+ * Return 0 on success or a negative error code on failure.
+ */
+int vsp1_du_setup_lif(struct device *dev, unsigned int width,
+		      unsigned int height)
+{
+	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
+	struct vsp1_pipeline *pipe = &vsp1->drm->pipe;
+	struct vsp1_bru *bru = vsp1->bru;
+	struct v4l2_subdev_format format;
+	unsigned int i;
+	int ret;
+
+	dev_dbg(vsp1->dev, "%s: configuring LIF with format %ux%u\n",
+		__func__, width, height);
+
+	if (width == 0 || height == 0) {
+		/* Zero width or height means the CRTC is being disabled, stop
+		 * the pipeline and turn the light off.
+		 */
+		ret = vsp1_pipeline_stop(pipe);
+		if (ret == -ETIMEDOUT)
+			dev_err(vsp1->dev, "DRM pipeline stop timeout\n");
+
+		media_entity_pipeline_stop(&pipe->output->entity.subdev.entity);
+
+		for (i = 0; i < bru->entity.source_pad; ++i) {
+			bru->inputs[i].rpf = NULL;
+			pipe->inputs[i] = NULL;
+		}
+
+		pipe->num_inputs = 0;
+
+		vsp1_device_put(vsp1);
+
+		dev_dbg(vsp1->dev, "%s: pipeline disabled\n", __func__);
+
+		return 0;
+	}
+
+	/* Configure the format at the BRU sinks and propagate it through the
+	 * pipeline.
+	 */
+	memset(&format, 0, sizeof(format));
+	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+
+	for (i = 0; i < bru->entity.source_pad; ++i) {
+		format.pad = i;
+
+		format.format.width = width;
+		format.format.height = height;
+		format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
+		format.format.field = V4L2_FIELD_NONE;
+
+		ret = v4l2_subdev_call(&bru->entity.subdev, pad,
+				       set_fmt, NULL, &format);
+		if (ret < 0)
+			return ret;
+
+		dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on BRU pad %u\n",
+			__func__, format.format.width, format.format.height,
+			format.format.code, i);
+	}
+
+	format.pad = bru->entity.source_pad;
+	format.format.width = width;
+	format.format.height = height;
+	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
+	format.format.field = V4L2_FIELD_NONE;
+
+	ret = v4l2_subdev_call(&bru->entity.subdev, pad, set_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on BRU pad %u\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code, i);
+
+	format.pad = RWPF_PAD_SINK;
+	ret = v4l2_subdev_call(&vsp1->wpf[0]->entity.subdev, pad, set_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF0 sink\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code);
+
+	format.pad = RWPF_PAD_SOURCE;
+	ret = v4l2_subdev_call(&vsp1->wpf[0]->entity.subdev, pad, get_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF0 source\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code);
+
+	format.pad = LIF_PAD_SINK;
+	ret = v4l2_subdev_call(&vsp1->lif->entity.subdev, pad, set_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF sink\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code);
+
+	/* Verify that the format at the output of the pipeline matches the
+	 * requested frame size and media bus code.
+	 */
+	if (format.format.width != width || format.format.height != height ||
+	    format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) {
+		dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__);
+		return -EPIPE;
+	}
+
+	/* Mark the pipeline as streaming and enable the VSP1. This will store
+	 * the pipeline pointer in all entities, which the s_stream handlers
+	 * will need. We don't start the entities themselves right at this point
+	 * as there's no plane configured yet, so we can't start processing
+	 * buffers.
+	 */
+	ret = vsp1_device_get(vsp1);
+	if (ret < 0)
+		return ret;
+
+	ret = media_entity_pipeline_start(&pipe->output->entity.subdev.entity,
+					  &pipe->pipe);
+	if (ret < 0) {
+		dev_dbg(vsp1->dev, "%s: pipeline start failed\n", __func__);
+		vsp1_device_put(vsp1);
+		return ret;
+	}
+
+	dev_dbg(vsp1->dev, "%s: pipeline enabled\n", __func__);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
+
+/**
+ * vsp1_du_setup_rpf - Setup one RPF input of the VSP pipeline
+ * @dev: the VSP device
+ * @rpf_index: index of the RPF to setup (0-based)
+ * @pixelformat: V4L2 pixel format for the RPF memory input
+ * @pitch: number of bytes per line in the image stored in memory
+ * @mem: DMA addresses of the memory buffers (one per plane)
+ * @src: the source crop rectangle for the RPF
+ * @dst: the destination compose rectangle for the BRU input
+ *
+ * Configure the VSP to perform composition of the image referenced by @mem
+ * through RPF @rpf_index, using the @src crop rectangle and the @dst
+ * composition rectangle. The Z-order is fixed with RPF 0 at the bottom.
+ *
+ * Image format as stored in memory is expressed as a V4L2 @pixelformat value.
+ * As a special case, setting the pixel format to 0 will disable the RPF. The
+ * @pitch, @mem, @src and @dst parameters are ignored in that case. Calling the
+ * function on a disabled RPF is allowed.
+ *
+ * The memory pitch is configurable to allow for padding at end of lines, or
+ * simple for images that extend beyond the crop rectangle boundaries. The
+ * @pitch value is expressed in bytes and applies to all planes for multiplanar
+ * formats.
+ *
+ * The source memory buffer is referenced by the DMA address of its planes in
+ * the @mem array. Up to two planes are supported. The second plane DMA address
+ * is ignored for formats using a single plane.
+ *
+ * This function isn't reentrant, the caller needs to serialize calls.
+ *
+ * TODO: Implement Z-order control by decoupling the RPF index from the BRU
+ * input index.
+ *
+ * Return 0 on success or a negative error code on failure.
+ */
+int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index,
+		      u32 pixelformat, unsigned int pitch,
+		      dma_addr_t mem[2], const struct v4l2_rect *src,
+		      const struct v4l2_rect *dst)
+{
+	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
+	struct vsp1_pipeline *pipe = &vsp1->drm->pipe;
+	const struct vsp1_format_info *fmtinfo;
+	struct v4l2_subdev_selection sel;
+	struct v4l2_subdev_format format;
+	struct vsp1_rwpf_memory memory;
+	struct vsp1_rwpf *rpf;
+	unsigned long flags;
+	bool start_stop = false;
+	int ret;
+
+	if (rpf_index >= vsp1->pdata.rpf_count)
+		return -EINVAL;
+
+	rpf = vsp1->rpf[rpf_index];
+
+	if (pixelformat == 0) {
+		dev_dbg(vsp1->dev, "%s: RPF%u: disable requested\n", __func__,
+			rpf_index);
+
+		spin_lock_irqsave(&pipe->irqlock, flags);
+
+		if (pipe->inputs[rpf_index]) {
+			/* Remove the RPF from the pipeline if it was previously
+			 * enabled.
+			 */
+			vsp1->bru->inputs[rpf_index].rpf = NULL;
+			pipe->inputs[rpf_index] = NULL;
+
+			vsp1->drm->update = true;
+			start_stop = --pipe->num_inputs == 0;
+		}
+
+		spin_unlock_irqrestore(&pipe->irqlock, flags);
+
+		/* Stop the pipeline if we're the last user. */
+		if (start_stop)
+			vsp1_pipeline_stop(pipe);
+
+		return 0;
+	}
+
+	dev_dbg(vsp1->dev,
+		"%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad }\n",
+		__func__, rpf_index,
+		src->left, src->top, src->width, src->height,
+		dst->left, dst->top, dst->width, dst->height,
+		pixelformat, pitch, &mem[0], &mem[1]);
+
+	/* Set the stride at the RPF input. */
+	fmtinfo = vsp1_get_format_info(pixelformat);
+	if (!fmtinfo) {
+		dev_dbg(vsp1->dev, "Unsupport pixel format %08x for RPF\n",
+			pixelformat);
+		return -EINVAL;
+	}
+
+	rpf->fmtinfo = fmtinfo;
+	rpf->format.num_planes = fmtinfo->planes;
+	rpf->format.plane_fmt[0].bytesperline = pitch;
+	rpf->format.plane_fmt[1].bytesperline = pitch;
+
+	/* Configure the format on the RPF sink pad and propagate it up to the
+	 * BRU sink pad.
+	 */
+	memset(&format, 0, sizeof(format));
+	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	format.pad = RWPF_PAD_SINK;
+	format.format.width = src->width + src->left;
+	format.format.height = src->height + src->top;
+	format.format.code = fmtinfo->mbus;
+	format.format.field = V4L2_FIELD_NONE;
+
+	ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev,
+		"%s: set format %ux%u (%x) on RPF%u sink\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code, rpf->entity.index);
+
+	memset(&sel, 0, sizeof(sel));
+	sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	sel.pad = RWPF_PAD_SINK;
+	sel.target = V4L2_SEL_TGT_CROP;
+	sel.r = *src;
+
+	ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_selection, NULL,
+			       &sel);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev,
+		"%s: set selection (%u,%u)/%ux%u on RPF%u sink\n",
+		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
+		rpf->entity.index);
+
+	/* RPF source, hardcode the format to ARGB8888 to turn on format
+	 * conversion if needed.
+	 */
+	format.pad = RWPF_PAD_SOURCE;
+
+	ret = v4l2_subdev_call(&rpf->entity.subdev, pad, get_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev,
+		"%s: got format %ux%u (%x) on RPF%u source\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code, rpf->entity.index);
+
+	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
+
+	ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	/* BRU sink, propagate the format from the RPF source. */
+	format.pad = rpf->entity.index;
+
+	ret = v4l2_subdev_call(&vsp1->bru->entity.subdev, pad, set_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on BRU pad %u\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code, format.pad);
+
+	sel.pad = rpf->entity.index;
+	sel.target = V4L2_SEL_TGT_COMPOSE;
+	sel.r = *dst;
+
+	ret = v4l2_subdev_call(&vsp1->bru->entity.subdev, pad, set_selection,
+			       NULL, &sel);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev,
+		"%s: set selection (%u,%u)/%ux%u on BRU pad %u\n",
+		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
+		sel.pad);
+
+	/* Store the compose rectangle coordinates in the RPF. */
+	rpf->location.left = dst->left;
+	rpf->location.top = dst->top;
+
+	/* Set the memory buffer address. */
+	memory.num_planes = fmtinfo->planes;
+	memory.addr[0] = mem[0];
+	memory.addr[1] = mem[1];
+
+	rpf->ops->set_memory(rpf, &memory);
+
+	spin_lock_irqsave(&pipe->irqlock, flags);
+
+	/* If the RPF was previously stopped set the BRU input to the RPF and
+	 * store the RPF in the pipeline inputs array.
+	 */
+	if (!pipe->inputs[rpf->entity.index]) {
+		vsp1->bru->inputs[rpf_index].rpf = rpf;
+		pipe->inputs[rpf->entity.index] = rpf;
+		start_stop = pipe->num_inputs++ == 0;
+	}
+
+	/* Start the pipeline if it's currently stopped. */
+	vsp1->drm->update = true;
+	if (start_stop)
+		vsp1_drm_pipeline_run(pipe);
+
+	spin_unlock_irqrestore(&pipe->irqlock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vsp1_du_setup_rpf);
+
+/* -----------------------------------------------------------------------------
+ * Initialization
+ */
+
+int vsp1_drm_create_links(struct vsp1_device *vsp1)
+{
+	const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE;
+	unsigned int i;
+	int ret;
+
+	/* VSPD instances require a BRU to perform composition. */
+	if (!vsp1->bru)
+		return -ENXIO;
+
+	for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
+		struct vsp1_rwpf *rpf = vsp1->rpf[i];
+
+		ret = media_entity_create_link(&rpf->entity.subdev.entity,
+					       RWPF_PAD_SOURCE,
+					       &vsp1->bru->entity.subdev.entity,
+					       i, flags);
+		if (ret < 0)
+			return ret;
+
+		rpf->entity.sink = &vsp1->bru->entity.subdev.entity;
+		rpf->entity.sink_pad = i;
+	}
+
+	ret = media_entity_create_link(&vsp1->bru->entity.subdev.entity,
+				       vsp1->bru->entity.source_pad,
+				       &vsp1->wpf[0]->entity.subdev.entity,
+				       RWPF_PAD_SINK, flags);
+	if (ret < 0)
+		return ret;
+
+	vsp1->bru->entity.sink = &vsp1->wpf[0]->entity.subdev.entity;
+	vsp1->bru->entity.sink_pad = RWPF_PAD_SINK;
+
+	ret = media_entity_create_link(&vsp1->wpf[0]->entity.subdev.entity,
+				       RWPF_PAD_SOURCE,
+				       &vsp1->lif->entity.subdev.entity,
+				       LIF_PAD_SINK, flags);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+int vsp1_drm_init(struct vsp1_device *vsp1)
+{
+	struct vsp1_pipeline *pipe;
+	unsigned int i;
+
+	vsp1->drm = devm_kzalloc(vsp1->dev, sizeof(*vsp1->drm), GFP_KERNEL);
+	if (!vsp1->drm)
+		return -ENOMEM;
+
+	pipe = &vsp1->drm->pipe;
+
+	vsp1_pipeline_init(pipe);
+	pipe->frame_end = vsp1_drm_pipeline_frame_end;
+
+	/* The DRM pipeline is static, add entities manually. */
+	for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
+		struct vsp1_rwpf *input = vsp1->rpf[i];
+
+		list_add_tail(&input->entity.list_pipe, &pipe->entities);
+	}
+
+	list_add_tail(&vsp1->bru->entity.list_pipe, &pipe->entities);
+	list_add_tail(&vsp1->wpf[0]->entity.list_pipe, &pipe->entities);
+	list_add_tail(&vsp1->lif->entity.list_pipe, &pipe->entities);
+
+	pipe->bru = &vsp1->bru->entity;
+	pipe->lif = &vsp1->lif->entity;
+	pipe->output = vsp1->wpf[0];
+
+	return 0;
+}
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
new file mode 100644
index 000000000000..2ad320ab1e45
--- /dev/null
+++ b/drivers/media/platform/vsp1/vsp1_drm.h
@@ -0,0 +1,26 @@
+/*
+ * vsp1_drm.h  --  R-Car VSP1 DRM/KMS Interface
+ *
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __VSP1_DRM_H__
+#define __VSP1_DRM_H__
+
+#include "vsp1_pipe.h"
+
+struct vsp1_drm {
+	struct vsp1_pipeline pipe;
+	bool update;
+};
+
+int vsp1_drm_init(struct vsp1_device *vsp1);
+int vsp1_drm_create_links(struct vsp1_device *vsp1);
+
+#endif /* __VSP1_DRM_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index fb9c8f59e3b0..5d58cad5b125 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -25,6 +25,7 @@
 
 #include "vsp1.h"
 #include "vsp1_bru.h"
+#include "vsp1_drm.h"
 #include "vsp1_hsit.h"
 #include "vsp1_lif.h"
 #include "vsp1_lut.h"
@@ -120,7 +121,7 @@ static int vsp1_create_sink_links(struct vsp1_device *vsp1,
 	return 0;
 }
 
-static int vsp1_create_links(struct vsp1_device *vsp1)
+static int vsp1_uapi_create_links(struct vsp1_device *vsp1)
 {
 	struct vsp1_entity *entity;
 	unsigned int i;
@@ -144,9 +145,6 @@ static int vsp1_create_links(struct vsp1_device *vsp1)
 			return ret;
 	}
 
-	if (!vsp1->info->uapi)
-		return 0;
-
 	for (i = 0; i < vsp1->pdata.rpf_count; ++i) {
 		struct vsp1_rwpf *rpf = vsp1->rpf[i];
 
@@ -355,7 +353,10 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 	}
 
 	/* Create links. */
-	ret = vsp1_create_links(vsp1);
+	if (vsp1->info->uapi)
+		ret = vsp1_uapi_create_links(vsp1);
+	else
+		ret = vsp1_drm_create_links(vsp1);
 	if (ret < 0)
 		goto done;
 
@@ -369,6 +370,8 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 
 	if (vsp1->info->uapi)
 		ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev);
+	else
+		ret = vsp1_drm_init(vsp1);
 
 done:
 	if (ret < 0)
diff --git a/include/media/vsp1.h b/include/media/vsp1.h
new file mode 100644
index 000000000000..2c1aea7066be
--- /dev/null
+++ b/include/media/vsp1.h
@@ -0,0 +1,30 @@
+/*
+ * vsp1.h  --  R-Car VSP1 API
+ *
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __MEDIA_VSP1_H__
+#define __MEDIA_VSP1_H__
+
+#include <linux/types.h>
+
+struct device;
+struct v4l2_rect;
+
+int vsp1_du_init(struct device *dev);
+
+int vsp1_du_setup_lif(struct device *dev, unsigned int width,
+		      unsigned int height);
+
+int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf, u32 pixelformat,
+		      unsigned int pitch, dma_addr_t mem[2],
+		      const struct v4l2_rect *src, const struct v4l2_rect *dst);
+
+#endif /* __MEDIA_VSP1_H__ */
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 29/32] v4l: vsp1: Disconnect unused RPFs from the DRM pipeline
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (27 preceding siblings ...)
  2015-09-13 20:57 ` [PATCH 28/32] v4l: vsp1: Add VSP+DU support Laurent Pinchart
@ 2015-09-13 20:57 ` Laurent Pinchart
  2015-09-13 20:57 ` [PATCH 30/32] v4l: vsp1: Implement atomic update for the DRM driver Laurent Pinchart
                   ` (3 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:57 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_drm.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 2969d570f462..5cef619b708d 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -38,13 +38,17 @@ static int vsp1_drm_pipeline_run(struct vsp1_pipeline *pipe)
 		struct vsp1_entity *entity;
 
 		list_for_each_entry(entity, &pipe->entities, list_pipe) {
-			/* Skip unused RPFs. */
+			/* Disconnect unused RPFs from the pipeline. */
 			if (entity->type == VSP1_ENTITY_RPF) {
 				struct vsp1_rwpf *rpf =
 					to_rwpf(&entity->subdev);
 
-				if (!pipe->inputs[rpf->entity.index])
+				if (!pipe->inputs[rpf->entity.index]) {
+					vsp1_write(entity->vsp1,
+						   entity->route->reg,
+						   VI6_DPR_NODE_UNUSED);
 					continue;
+				}
 			}
 
 			vsp1_entity_route_setup(entity);
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 30/32] v4l: vsp1: Implement atomic update for the DRM driver
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (28 preceding siblings ...)
  2015-09-13 20:57 ` [PATCH 29/32] v4l: vsp1: Disconnect unused RPFs from the DRM pipeline Laurent Pinchart
@ 2015-09-13 20:57 ` Laurent Pinchart
  2015-09-13 20:57 ` [PATCH 31/32] v4l: vsp1: Add support for the R-Car Gen3 VSP2 Laurent Pinchart
                   ` (2 subsequent siblings)
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:57 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

Add two API functions named vsp1_du_atomic_begin() and
vsp1_du_atomic_flush() to signal the start and end of an atomic update.
The vsp1_du_setup_rpf() function is renamed to vsp1_du_atomic_update()
for consistency.

With this new API, the driver will reprogram all modified inputs
atomically before restarting the video stream.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_drm.c | 70 +++++++++++++++++++++++++---------
 drivers/media/platform/vsp1/vsp1_drm.h |  7 ++++
 include/media/vsp1.h                   |  9 +++--
 3 files changed, 66 insertions(+), 20 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 5cef619b708d..ef8e91d65209 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -254,7 +254,26 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width,
 EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
 
 /**
- * vsp1_du_setup_rpf - Setup one RPF input of the VSP pipeline
+ * vsp1_du_atomic_begin - Prepare for an atomic update
+ * @dev: the VSP device
+ */
+void vsp1_du_atomic_begin(struct device *dev)
+{
+	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
+	struct vsp1_pipeline *pipe = &vsp1->drm->pipe;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pipe->irqlock, flags);
+
+	vsp1->drm->num_inputs = pipe->num_inputs;
+	vsp1->drm->update = false;
+
+	spin_unlock_irqrestore(&pipe->irqlock, flags);
+}
+EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
+
+/**
+ * vsp1_du_atomic_update - Setup one RPF input of the VSP pipeline
  * @dev: the VSP device
  * @rpf_index: index of the RPF to setup (0-based)
  * @pixelformat: V4L2 pixel format for the RPF memory input
@@ -288,10 +307,10 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
  *
  * Return 0 on success or a negative error code on failure.
  */
-int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index,
-		      u32 pixelformat, unsigned int pitch,
-		      dma_addr_t mem[2], const struct v4l2_rect *src,
-		      const struct v4l2_rect *dst)
+int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index,
+			  u32 pixelformat, unsigned int pitch,
+			  dma_addr_t mem[2], const struct v4l2_rect *src,
+			  const struct v4l2_rect *dst)
 {
 	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
 	struct vsp1_pipeline *pipe = &vsp1->drm->pipe;
@@ -301,7 +320,6 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index,
 	struct vsp1_rwpf_memory memory;
 	struct vsp1_rwpf *rpf;
 	unsigned long flags;
-	bool start_stop = false;
 	int ret;
 
 	if (rpf_index >= vsp1->pdata.rpf_count)
@@ -322,16 +340,11 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index,
 			vsp1->bru->inputs[rpf_index].rpf = NULL;
 			pipe->inputs[rpf_index] = NULL;
 
-			vsp1->drm->update = true;
-			start_stop = --pipe->num_inputs == 0;
+			pipe->num_inputs--;
 		}
 
 		spin_unlock_irqrestore(&pipe->irqlock, flags);
 
-		/* Stop the pipeline if we're the last user. */
-		if (start_stop)
-			vsp1_pipeline_stop(pipe);
-
 		return 0;
 	}
 
@@ -459,19 +472,42 @@ int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf_index,
 	if (!pipe->inputs[rpf->entity.index]) {
 		vsp1->bru->inputs[rpf_index].rpf = rpf;
 		pipe->inputs[rpf->entity.index] = rpf;
-		start_stop = pipe->num_inputs++ == 0;
+		pipe->num_inputs++;
 	}
 
-	/* Start the pipeline if it's currently stopped. */
+	spin_unlock_irqrestore(&pipe->irqlock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vsp1_du_atomic_update);
+
+/**
+ * vsp1_du_atomic_flush - Commit an atomic update
+ * @dev: the VSP device
+ */
+void vsp1_du_atomic_flush(struct device *dev)
+{
+	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
+	struct vsp1_pipeline *pipe = &vsp1->drm->pipe;
+	unsigned long flags;
+	bool stop = false;
+
+	spin_lock_irqsave(&pipe->irqlock, flags);
+
 	vsp1->drm->update = true;
-	if (start_stop)
+
+	/* Start or stop the pipeline if needed. */
+	if (!vsp1->drm->num_inputs && pipe->num_inputs)
 		vsp1_drm_pipeline_run(pipe);
+	else if (vsp1->drm->num_inputs && !pipe->num_inputs)
+		stop = true;
 
 	spin_unlock_irqrestore(&pipe->irqlock, flags);
 
-	return 0;
+	if (stop)
+		vsp1_pipeline_stop(pipe);
 }
-EXPORT_SYMBOL_GPL(vsp1_du_setup_rpf);
+EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
 
 /* -----------------------------------------------------------------------------
  * Initialization
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
index 2ad320ab1e45..25d7f017feb4 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.h
+++ b/drivers/media/platform/vsp1/vsp1_drm.h
@@ -15,8 +15,15 @@
 
 #include "vsp1_pipe.h"
 
+/**
+ * vsp1_drm - State for the API exposed to the DRM driver
+ * @pipe: the VSP1 pipeline used for display
+ * @num_inputs: number of active pipeline inputs at the beginning of an update
+ * @update: the pipeline configuration has been updated
+ */
 struct vsp1_drm {
 	struct vsp1_pipeline pipe;
+	unsigned int num_inputs;
 	bool update;
 };
 
diff --git a/include/media/vsp1.h b/include/media/vsp1.h
index 2c1aea7066be..cc541753896f 100644
--- a/include/media/vsp1.h
+++ b/include/media/vsp1.h
@@ -23,8 +23,11 @@ int vsp1_du_init(struct device *dev);
 int vsp1_du_setup_lif(struct device *dev, unsigned int width,
 		      unsigned int height);
 
-int vsp1_du_setup_rpf(struct device *dev, unsigned int rpf, u32 pixelformat,
-		      unsigned int pitch, dma_addr_t mem[2],
-		      const struct v4l2_rect *src, const struct v4l2_rect *dst);
+int vsp1_du_atomic_begin(struct device *dev);
+int vsp1_du_atomic_update(struct device *dev, unsigned int rpf, u32 pixelformat,
+			  unsigned int pitch, dma_addr_t mem[2],
+			  const struct v4l2_rect *src,
+			  const struct v4l2_rect *dst);
+int vsp1_du_atomic_flush(struct device *dev);
 
 #endif /* __MEDIA_VSP1_H__ */
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 31/32] v4l: vsp1: Add support for the R-Car Gen3 VSP2
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (29 preceding siblings ...)
  2015-09-13 20:57 ` [PATCH 30/32] v4l: vsp1: Implement atomic update for the DRM driver Laurent Pinchart
@ 2015-09-13 20:57 ` Laurent Pinchart
  2015-09-13 20:57 ` [PATCH 32/32] v4l: vsp1: Add display list support Laurent Pinchart
  2015-09-13 22:53 ` [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:57 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh, devicetree

Add DT compatible strings for the VSP2 instances found in the R-Car Gen3
SoCs and support them in the vsp1 driver.

Cc: devicetree@vger.kernel.org
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 Documentation/devicetree/bindings/media/renesas,vsp1.txt |  5 ++++-
 drivers/media/platform/vsp1/vsp1_drv.c                   | 12 ++++++++++++
 drivers/media/platform/vsp1/vsp1_entity.c                |  3 ++-
 drivers/media/platform/vsp1/vsp1_regs.h                  | 12 ++++++------
 4 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/renesas,vsp1.txt b/Documentation/devicetree/bindings/media/renesas,vsp1.txt
index 766f034c1e45..dc7fc142aada 100644
--- a/Documentation/devicetree/bindings/media/renesas,vsp1.txt
+++ b/Documentation/devicetree/bindings/media/renesas,vsp1.txt
@@ -6,7 +6,10 @@ It can be found in the Renesas R-Car second generation SoCs.
 
 Required properties:
 
-  - compatible: Must contain "renesas,vsp1"
+  - compatible: Must contain one of the following values
+    - "renesas,vsp1" for the R-Car Gen2 VSP1
+    - "renesas,vsp2" for the R-Car Gen3 VSP2BC, VSP2BD or VSP2I
+    - "renesas,vsp2d" for the R-Car Gen3 VSP2D
 
   - reg: Base address and length of the registers block for the VSP1.
   - interrupts: VSP1 interrupt specifier.
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 5d58cad5b125..75cdf8715d9a 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -648,8 +648,20 @@ static const struct vsp1_device_info vsp1_gen2_info = {
 	.uapi = true,
 };
 
+static const struct vsp1_device_info vsp1_gen3_info = {
+	.num_bru_inputs = 5,
+	.uapi = true,
+};
+
+static const struct vsp1_device_info vsp1_gen3_vspd_info = {
+	.num_bru_inputs = 5,
+	.uapi = false,
+};
+
 static const struct of_device_id vsp1_of_match[] = {
 	{ .compatible = "renesas,vsp1", .data = &vsp1_gen2_info },
+	{ .compatible = "renesas,vsp2", .data = &vsp1_gen3_info },
+	{ .compatible = "renesas,vsp2d", .data = &vsp1_gen3_vspd_info },
 	{ },
 };
 
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index 79e05b76d6e3..8947c1883bf4 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -165,7 +165,8 @@ int vsp1_entity_link_setup(struct media_entity *entity,
 static const struct vsp1_route vsp1_routes[] = {
 	{ VSP1_ENTITY_BRU, 0, VI6_DPR_BRU_ROUTE,
 	  { VI6_DPR_NODE_BRU_IN(0), VI6_DPR_NODE_BRU_IN(1),
-	    VI6_DPR_NODE_BRU_IN(2), VI6_DPR_NODE_BRU_IN(3), } },
+	    VI6_DPR_NODE_BRU_IN(2), VI6_DPR_NODE_BRU_IN(3),
+	    VI6_DPR_NODE_BRU_IN(4) } },
 	{ VSP1_ENTITY_HSI, 0, VI6_DPR_HSI_ROUTE, { VI6_DPR_NODE_HSI, } },
 	{ VSP1_ENTITY_HST, 0, VI6_DPR_HST_ROUTE, { VI6_DPR_NODE_HST, } },
 	{ VSP1_ENTITY_LIF, 0, 0, { VI6_DPR_NODE_LIF, } },
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h
index 8173ceaab9f9..f94050224aa0 100644
--- a/drivers/media/platform/vsp1/vsp1_regs.h
+++ b/drivers/media/platform/vsp1/vsp1_regs.h
@@ -322,7 +322,7 @@
 #define VI6_DPR_NODE_SRU		16
 #define VI6_DPR_NODE_UDS(n)		(17 + (n))
 #define VI6_DPR_NODE_LUT		22
-#define VI6_DPR_NODE_BRU_IN(n)		(23 + (n))
+#define VI6_DPR_NODE_BRU_IN(n)		(((n) <= 3) ? 23 + (n) : 49)
 #define VI6_DPR_NODE_BRU_OUT		27
 #define VI6_DPR_NODE_CLU		29
 #define VI6_DPR_NODE_HST		30
@@ -504,12 +504,12 @@
 #define VI6_BRU_VIRRPF_COL_BCB_MASK	(0xff << 0)
 #define VI6_BRU_VIRRPF_COL_BCB_SHIFT	0
 
-#define VI6_BRU_CTRL(n)			(0x2c10 + (n) * 8)
+#define VI6_BRU_CTRL(n)			(0x2c10 + (n) * 8 + ((n) <= 3 ? 0 : 4))
 #define VI6_BRU_CTRL_RBC		(1 << 31)
-#define VI6_BRU_CTRL_DSTSEL_BRUIN(n)	((n) << 20)
+#define VI6_BRU_CTRL_DSTSEL_BRUIN(n)	(((n) <= 3 ? (n) : (n)+1) << 20)
 #define VI6_BRU_CTRL_DSTSEL_VRPF	(4 << 20)
 #define VI6_BRU_CTRL_DSTSEL_MASK	(7 << 20)
-#define VI6_BRU_CTRL_SRCSEL_BRUIN(n)	((n) << 16)
+#define VI6_BRU_CTRL_SRCSEL_BRUIN(n)	(((n) <= 3 ? (n) : (n)+1) << 16)
 #define VI6_BRU_CTRL_SRCSEL_VRPF	(4 << 16)
 #define VI6_BRU_CTRL_SRCSEL_MASK	(7 << 16)
 #define VI6_BRU_CTRL_CROP(rop)		((rop) << 4)
@@ -517,7 +517,7 @@
 #define VI6_BRU_CTRL_AROP(rop)		((rop) << 0)
 #define VI6_BRU_CTRL_AROP_MASK		(0xf << 0)
 
-#define VI6_BRU_BLD(n)			(0x2c14 + (n) * 8)
+#define VI6_BRU_BLD(n)			(0x2c14 + (n) * 8 + ((n) <= 3 ? 0 : 4))
 #define VI6_BRU_BLD_CBES		(1 << 31)
 #define VI6_BRU_BLD_CCMDX_DST_A		(0 << 28)
 #define VI6_BRU_BLD_CCMDX_255_DST_A	(1 << 28)
@@ -551,7 +551,7 @@
 #define VI6_BRU_BLD_COEFY_SHIFT		0
 
 #define VI6_BRU_ROP			0x2c30
-#define VI6_BRU_ROP_DSTSEL_BRUIN(n)	((n) << 20)
+#define VI6_BRU_ROP_DSTSEL_BRUIN(n)	(((n) <= 3 ? (n) : (n)+1) << 20)
 #define VI6_BRU_ROP_DSTSEL_VRPF		(4 << 20)
 #define VI6_BRU_ROP_DSTSEL_MASK		(7 << 20)
 #define VI6_BRU_ROP_CROP(rop)		((rop) << 4)
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 32/32] v4l: vsp1: Add display list support
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (30 preceding siblings ...)
  2015-09-13 20:57 ` [PATCH 31/32] v4l: vsp1: Add support for the R-Car Gen3 VSP2 Laurent Pinchart
@ 2015-09-13 20:57 ` Laurent Pinchart
  2015-09-13 22:53 ` [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 20:57 UTC (permalink / raw)
  To: linux-media; +Cc: linux-sh

From: Takashi Saito <takashi.saitou.ry@renesas.com>

Display lists contain lists of registers and associated values to be
applied atomically by the hardware. They lower the pressure on interrupt
processing delays when reprogramming the device as settings can be
prepared well in advance and queued to the hardware without waiting for
the end of the current frame.

Display list support is currently limited to the DRM pipeline.

Signed-off-by: Koji Matsuoka <koji.matsuoka.xm@renesas.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/platform/vsp1/Makefile      |   2 +-
 drivers/media/platform/vsp1/vsp1.h        |  17 ++
 drivers/media/platform/vsp1/vsp1_bru.c    |   2 +-
 drivers/media/platform/vsp1/vsp1_dl.c     | 304 ++++++++++++++++++++++++++++++
 drivers/media/platform/vsp1/vsp1_dl.h     |  42 +++++
 drivers/media/platform/vsp1/vsp1_drm.c    | 105 ++++++-----
 drivers/media/platform/vsp1/vsp1_drm.h    |   5 +
 drivers/media/platform/vsp1/vsp1_drv.c    |  76 +++++---
 drivers/media/platform/vsp1/vsp1_entity.c |   4 +-
 drivers/media/platform/vsp1/vsp1_lif.c    |   4 +-
 drivers/media/platform/vsp1/vsp1_pipe.c   |  54 +++++-
 drivers/media/platform/vsp1/vsp1_pipe.h   |   5 +
 drivers/media/platform/vsp1/vsp1_rpf.c    |   4 +-
 drivers/media/platform/vsp1/vsp1_wpf.c    |  13 +-
 14 files changed, 542 insertions(+), 95 deletions(-)
 create mode 100644 drivers/media/platform/vsp1/vsp1_dl.c
 create mode 100644 drivers/media/platform/vsp1/vsp1_dl.h

diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile
index 447e72a2ef43..95b3ac2ea7ef 100644
--- a/drivers/media/platform/vsp1/Makefile
+++ b/drivers/media/platform/vsp1/Makefile
@@ -1,5 +1,5 @@
 vsp1-y					:= vsp1_drv.o vsp1_entity.o vsp1_pipe.o
-vsp1-y					+= vsp1_drm.o vsp1_video.o
+vsp1-y					+= vsp1_dl.o vsp1_drm.o vsp1_video.o
 vsp1-y					+= vsp1_rpf.o vsp1_rwpf.o vsp1_wpf.o
 vsp1-y					+= vsp1_hsit.o vsp1_lif.o vsp1_lut.o
 vsp1-y					+= vsp1_bru.o vsp1_sru.o vsp1_uds.o
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 61a24e4a0848..358018a97827 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -26,7 +26,9 @@
 struct clk;
 struct device;
 
+struct vsp1_dl;
 struct vsp1_drm;
+struct vsp1_entity;
 struct vsp1_platform_data;
 struct vsp1_bru;
 struct vsp1_hsit;
@@ -84,12 +86,17 @@ struct vsp1_device {
 	struct v4l2_device v4l2_dev;
 	struct media_device media_dev;
 	struct media_entity_operations media_ops;
+
 	struct vsp1_drm *drm;
+
+	bool use_dl;
 };
 
 int vsp1_device_get(struct vsp1_device *vsp1);
 void vsp1_device_put(struct vsp1_device *vsp1);
 
+int vsp1_reset_wpf(struct vsp1_device *vsp1, unsigned int index);
+
 static inline u32 vsp1_read(struct vsp1_device *vsp1, u32 reg)
 {
 	return ioread32(vsp1->mmio + reg);
@@ -100,4 +107,14 @@ static inline void vsp1_write(struct vsp1_device *vsp1, u32 reg, u32 data)
 	iowrite32(data, vsp1->mmio + reg);
 }
 
+#include "vsp1_dl.h"
+
+static inline void vsp1_mod_write(struct vsp1_entity *e, u32 reg, u32 data)
+{
+	if (e->vsp1->use_dl)
+		vsp1_dl_add(e, reg, data);
+	else
+		vsp1_write(e->vsp1, reg, data);
+}
+
 #endif /* __VSP1_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c
index 99b742ff53c9..cb0dbc15ddad 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.c
+++ b/drivers/media/platform/vsp1/vsp1_bru.c
@@ -30,7 +30,7 @@
 
 static inline void vsp1_bru_write(struct vsp1_bru *bru, u32 reg, u32 data)
 {
-	vsp1_write(bru->entity.vsp1, reg, data);
+	vsp1_mod_write(&bru->entity, reg, data);
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c
new file mode 100644
index 000000000000..a4dcccf0778b
--- /dev/null
+++ b/drivers/media/platform/vsp1/vsp1_dl.c
@@ -0,0 +1,304 @@
+/*
+ * vsp1_dl.h  --  R-Car VSP1 Display List
+ *
+ * Copyright (C) 2015 Renesas Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gfp.h>
+
+#include "vsp1.h"
+#include "vsp1_dl.h"
+#include "vsp1_pipe.h"
+
+/*
+ * Global resources
+ *
+ * - Display-related interrupts (can be used for vblank evasion ?)
+ * - Display-list enable
+ * - Header-less for WPF0
+ * - DL swap
+ */
+
+#define VSP1_DL_BODY_SIZE		(2 * 4 * 256)
+#define VSP1_DL_NUM_LISTS		3
+
+struct vsp1_dl_entry {
+	u32 addr;
+	u32 data;
+} __attribute__((__packed__));
+
+struct vsp1_dl_list {
+	size_t size;
+	int reg_count;
+
+	bool in_use;
+
+	struct vsp1_dl_entry *body;
+	dma_addr_t dma;
+};
+
+/**
+ * struct vsp1_dl - Display List manager
+ * @vsp1: the VSP1 device
+ * @lock: protects the active, queued and pending lists
+ * @lists.all: array of all allocate display lists
+ * @lists.active: list currently being processed (loaded) by hardware
+ * @lists.queued: list queued to the hardware (written to the DL registers)
+ * @lists.pending: list waiting to be queued to the hardware
+ * @lists.write: list being written to by software
+ */
+struct vsp1_dl {
+	struct vsp1_device *vsp1;
+
+	spinlock_t lock;
+
+	size_t size;
+	dma_addr_t dma;
+	void *mem;
+
+	struct {
+		struct vsp1_dl_list all[VSP1_DL_NUM_LISTS];
+
+		struct vsp1_dl_list *active;
+		struct vsp1_dl_list *queued;
+		struct vsp1_dl_list *pending;
+		struct vsp1_dl_list *write;
+	} lists;
+};
+
+/* -----------------------------------------------------------------------------
+ * Display List Transaction Management
+ */
+
+static void vsp1_dl_free_list(struct vsp1_dl_list *list)
+{
+	if (!list)
+		return;
+
+	list->in_use = false;
+}
+
+void vsp1_dl_reset(struct vsp1_dl *dl)
+{
+	unsigned int i;
+
+	dl->lists.active = NULL;
+	dl->lists.queued = NULL;
+	dl->lists.pending = NULL;
+	dl->lists.write = NULL;
+
+	for (i = 0; i < ARRAY_SIZE(dl->lists.all); ++i)
+		dl->lists.all[i].in_use = false;
+}
+
+void vsp1_dl_begin(struct vsp1_dl *dl)
+{
+	struct vsp1_dl_list *list = NULL;
+	unsigned long flags;
+	unsigned int i;
+
+	spin_lock_irqsave(&dl->lock, flags);
+
+	for (i = 0; i < ARRAY_SIZE(dl->lists.all); ++i) {
+		if (!dl->lists.all[i].in_use) {
+			list = &dl->lists.all[i];
+			break;
+		}
+	}
+
+	if (!list) {
+		list = dl->lists.pending;
+		dl->lists.pending = NULL;
+	}
+
+	spin_unlock_irqrestore(&dl->lock, flags);
+
+	dl->lists.write = list;
+
+	list->in_use = true;
+	list->reg_count = 0;
+}
+
+void vsp1_dl_add(struct vsp1_entity *e, u32 reg, u32 data)
+{
+	struct vsp1_pipeline *pipe = to_vsp1_pipeline(&e->subdev.entity);
+	struct vsp1_dl *dl = pipe->dl;
+	struct vsp1_dl_list *list = dl->lists.write;
+
+	list->body[list->reg_count].addr = reg;
+	list->body[list->reg_count].data = data;
+	list->reg_count++;
+}
+
+void vsp1_dl_commit(struct vsp1_dl *dl)
+{
+	struct vsp1_device *vsp1 = dl->vsp1;
+	struct vsp1_dl_list *list;
+	unsigned long flags;
+	bool update;
+
+	list = dl->lists.write;
+	dl->lists.write = NULL;
+
+	spin_lock_irqsave(&dl->lock, flags);
+
+	/* Once the UPD bit has been set the hardware can start processing the
+	 * display list at any time and we can't touch the address and size
+	 * registers. In that case mark the update as pending, it will be
+	 * queued up to the hardware by the frame end interrupt handler.
+	 */
+	update = !!(vsp1_read(vsp1, VI6_DL_BODY_SIZE) & VI6_DL_BODY_SIZE_UPD);
+	if (update) {
+		vsp1_dl_free_list(dl->lists.pending);
+		dl->lists.pending = list;
+		goto done;
+	}
+
+	/* Program the hardware with the display list body address and size.
+	 * The UPD bit will be cleared by the device when the display list is
+	 * processed.
+	 */
+	vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), list->dma);
+	vsp1_write(vsp1, VI6_DL_BODY_SIZE, VI6_DL_BODY_SIZE_UPD |
+		   (list->reg_count * 8));
+
+	vsp1_dl_free_list(dl->lists.queued);
+	dl->lists.queued = list;
+
+done:
+	spin_unlock_irqrestore(&dl->lock, flags);
+}
+
+/* -----------------------------------------------------------------------------
+ * Interrupt Handling
+ */
+
+void vsp1_dl_irq_display_start(struct vsp1_dl *dl)
+{
+	spin_lock(&dl->lock);
+
+	/* The display start interrupt signals the end of the display list
+	 * processing by the device. The active display list, if any, won't be
+	 * accessed anymore and can be reused.
+	 */
+	if (dl->lists.active) {
+		vsp1_dl_free_list(dl->lists.active);
+		dl->lists.active = NULL;
+	}
+
+	spin_unlock(&dl->lock);
+}
+
+void vsp1_dl_irq_frame_end(struct vsp1_dl *dl)
+{
+	struct vsp1_device *vsp1 = dl->vsp1;
+
+	spin_lock(&dl->lock);
+
+	/* The UPD bit set indicates that the commit operation raced with the
+	 * interrupt and occurred after the frame end event and UPD clear but
+	 * before interrupt processing. The hardware hasn't taken the update
+	 * into account yet, we'll thus skip one frame and retry.
+	 */
+	if (vsp1_read(vsp1, VI6_DL_BODY_SIZE) & VI6_DL_BODY_SIZE_UPD)
+		goto done;
+
+	/* The device starts processing the queued display list right after the
+	 * frame end interrupt. The display list thus becomes active.
+	 */
+	if (dl->lists.queued) {
+		WARN_ON(dl->lists.active);
+		dl->lists.active = dl->lists.queued;
+		dl->lists.queued = NULL;
+	}
+
+	/* Now that the UPD bit has been cleared we can queue the next display
+	 * list to the hardware if one has been prepared.
+	 */
+	if (dl->lists.pending) {
+		struct vsp1_dl_list *list = dl->lists.pending;
+
+		vsp1_write(vsp1, VI6_DL_HDR_ADDR(0), list->dma);
+		vsp1_write(vsp1, VI6_DL_BODY_SIZE, VI6_DL_BODY_SIZE_UPD |
+			   (list->reg_count * 8));
+
+		dl->lists.queued = list;
+		dl->lists.pending = NULL;
+	}
+
+done:
+	spin_unlock(&dl->lock);
+}
+
+/* -----------------------------------------------------------------------------
+ * Hardware Setup
+ */
+
+void vsp1_dl_setup(struct vsp1_device *vsp1)
+{
+	u32 ctrl = (256 << VI6_DL_CTRL_AR_WAIT_SHIFT)
+		 | VI6_DL_CTRL_DC2 | VI6_DL_CTRL_DC1 | VI6_DL_CTRL_DC0
+		 | VI6_DL_CTRL_DLE;
+
+	/* The DRM pipeline operates with header-less display lists in
+	 * Continuous Frame Mode.
+	 */
+	if (vsp1->drm)
+		ctrl |= VI6_DL_CTRL_CFM0 | VI6_DL_CTRL_NH0;
+
+	vsp1_write(vsp1, VI6_DL_CTRL, ctrl);
+	vsp1_write(vsp1, VI6_DL_SWAP, VI6_DL_SWAP_LWS);
+}
+
+/* -----------------------------------------------------------------------------
+ * Initialization and Cleanup
+ */
+
+struct vsp1_dl *vsp1_dl_create(struct vsp1_device *vsp1)
+{
+	struct vsp1_dl *dl;
+	unsigned int i;
+
+	dl = kzalloc(sizeof(*dl), GFP_KERNEL);
+	if (!dl)
+		return NULL;
+
+	spin_lock_init(&dl->lock);
+
+	dl->vsp1 = vsp1;
+	dl->size = VSP1_DL_BODY_SIZE * ARRAY_SIZE(dl->lists.all);
+
+	dl->mem = dma_alloc_writecombine(vsp1->dev, dl->size, &dl->dma,
+					 GFP_KERNEL);
+	if (!dl->mem) {
+		kfree(dl);
+		return NULL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(dl->lists.all); ++i) {
+		struct vsp1_dl_list *list = &dl->lists.all[i];
+
+		list->size = VSP1_DL_BODY_SIZE;
+		list->reg_count = 0;
+		list->in_use = false;
+		list->dma = dl->dma + VSP1_DL_BODY_SIZE * i;
+		list->body = dl->mem + VSP1_DL_BODY_SIZE * i;
+	}
+
+	return dl;
+}
+
+void vsp1_dl_destroy(struct vsp1_dl *dl)
+{
+	dma_free_writecombine(dl->vsp1->dev, dl->size, dl->mem, dl->dma);
+	kfree(dl);
+}
diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h
new file mode 100644
index 000000000000..448c4250e54c
--- /dev/null
+++ b/drivers/media/platform/vsp1/vsp1_dl.h
@@ -0,0 +1,42 @@
+/*
+ * vsp1_dl.h  --  R-Car VSP1 Display List
+ *
+ * Copyright (C) 2015 Renesas Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __VSP1_DL_H__
+#define __VSP1_DL_H__
+
+#include "vsp1_entity.h"
+
+struct vsp1_device;
+struct vsp1_dl;
+
+struct vsp1_dl *vsp1_dl_create(struct vsp1_device *vsp1);
+void vsp1_dl_destroy(struct vsp1_dl *dl);
+
+void vsp1_dl_setup(struct vsp1_device *vsp1);
+
+void vsp1_dl_reset(struct vsp1_dl *dl);
+void vsp1_dl_begin(struct vsp1_dl *dl);
+void vsp1_dl_add(struct vsp1_entity *e, u32 reg, u32 data);
+void vsp1_dl_commit(struct vsp1_dl *dl);
+
+void vsp1_dl_irq_display_start(struct vsp1_dl *dl);
+void vsp1_dl_irq_frame_end(struct vsp1_dl *dl);
+
+static inline void vsp1_dl_mod_write(struct vsp1_entity *e, u32 reg, u32 data)
+{
+	if (e->vsp1->use_dl)
+		vsp1_dl_add(e, reg, data);
+	else
+		vsp1_write(e->vsp1, reg, data);
+}
+
+#endif /* __VSP1_DL_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index ef8e91d65209..618e129c9d2b 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -20,6 +20,7 @@
 
 #include "vsp1.h"
 #include "vsp1_bru.h"
+#include "vsp1_dl.h"
 #include "vsp1_drm.h"
 #include "vsp1_lif.h"
 #include "vsp1_pipe.h"
@@ -29,55 +30,13 @@
  * Runtime Handling
  */
 
-static int vsp1_drm_pipeline_run(struct vsp1_pipeline *pipe)
-{
-	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
-	int ret;
-
-	if (vsp1->drm->update) {
-		struct vsp1_entity *entity;
-
-		list_for_each_entry(entity, &pipe->entities, list_pipe) {
-			/* Disconnect unused RPFs from the pipeline. */
-			if (entity->type == VSP1_ENTITY_RPF) {
-				struct vsp1_rwpf *rpf =
-					to_rwpf(&entity->subdev);
-
-				if (!pipe->inputs[rpf->entity.index]) {
-					vsp1_write(entity->vsp1,
-						   entity->route->reg,
-						   VI6_DPR_NODE_UNUSED);
-					continue;
-				}
-			}
-
-			vsp1_entity_route_setup(entity);
-
-			ret = v4l2_subdev_call(&entity->subdev, video,
-					       s_stream, 1);
-			if (ret < 0) {
-				dev_err(vsp1->dev,
-					"DRM pipeline start failure on entity %s\n",
-					entity->subdev.name);
-				return ret;
-			}
-		}
-
-		vsp1->drm->update = false;
-	}
-
-	vsp1_pipeline_run(pipe);
-
-	return 0;
-}
-
 static void vsp1_drm_pipeline_frame_end(struct vsp1_pipeline *pipe)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&pipe->irqlock, flags);
 	if (pipe->num_inputs)
-		vsp1_drm_pipeline_run(pipe);
+		vsp1_pipeline_run(pipe);
 	spin_unlock_irqrestore(&pipe->irqlock, flags);
 }
 
@@ -151,6 +110,8 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width,
 		return 0;
 	}
 
+	vsp1_dl_reset(vsp1->drm->dl);
+
 	/* Configure the format at the BRU sinks and propagate it through the
 	 * pipeline.
 	 */
@@ -266,7 +227,6 @@ void vsp1_du_atomic_begin(struct device *dev)
 	spin_lock_irqsave(&pipe->irqlock, flags);
 
 	vsp1->drm->num_inputs = pipe->num_inputs;
-	vsp1->drm->update = false;
 
 	spin_unlock_irqrestore(&pipe->irqlock, flags);
 }
@@ -489,23 +449,57 @@ void vsp1_du_atomic_flush(struct device *dev)
 {
 	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
 	struct vsp1_pipeline *pipe = &vsp1->drm->pipe;
+	struct vsp1_entity *entity;
 	unsigned long flags;
 	bool stop = false;
+	int ret;
 
-	spin_lock_irqsave(&pipe->irqlock, flags);
+	/* Prepare the display list. */
+	vsp1_dl_begin(vsp1->drm->dl);
 
-	vsp1->drm->update = true;
+	list_for_each_entry(entity, &pipe->entities, list_pipe) {
+		/* Disconnect unused RPFs from the pipeline. */
+		if (entity->type == VSP1_ENTITY_RPF) {
+			struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev);
+
+			if (!pipe->inputs[rpf->entity.index]) {
+				vsp1_mod_write(entity, entity->route->reg,
+					   VI6_DPR_NODE_UNUSED);
+				continue;
+			}
+		}
+
+		vsp1_entity_route_setup(entity);
+
+		ret = v4l2_subdev_call(&entity->subdev, video,
+				       s_stream, 1);
+		if (ret < 0) {
+			dev_err(vsp1->dev,
+				"DRM pipeline start failure on entity %s\n",
+				entity->subdev.name);
+			return;
+		}
+	}
+
+	vsp1_dl_commit(vsp1->drm->dl);
+
+	spin_lock_irqsave(&pipe->irqlock, flags);
 
 	/* Start or stop the pipeline if needed. */
-	if (!vsp1->drm->num_inputs && pipe->num_inputs)
-		vsp1_drm_pipeline_run(pipe);
-	else if (vsp1->drm->num_inputs && !pipe->num_inputs)
+	if (!vsp1->drm->num_inputs && pipe->num_inputs) {
+		vsp1_write(vsp1, VI6_DISP_IRQ_STA, 0);
+		vsp1_write(vsp1, VI6_DISP_IRQ_ENB, VI6_DISP_IRQ_ENB_DSTE);
+		vsp1_pipeline_run(pipe);
+	} else if (vsp1->drm->num_inputs && !pipe->num_inputs) {
 		stop = true;
+	}
 
 	spin_unlock_irqrestore(&pipe->irqlock, flags);
 
-	if (stop)
+	if (stop) {
+		vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0);
 		vsp1_pipeline_stop(pipe);
+	}
 }
 EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
 
@@ -566,6 +560,10 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
 	if (!vsp1->drm)
 		return -ENOMEM;
 
+	vsp1->drm->dl = vsp1_dl_create(vsp1);
+	if (!vsp1->drm->dl)
+		return -ENOMEM;
+
 	pipe = &vsp1->drm->pipe;
 
 	vsp1_pipeline_init(pipe);
@@ -586,5 +584,12 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
 	pipe->lif = &vsp1->lif->entity;
 	pipe->output = vsp1->wpf[0];
 
+	pipe->dl = vsp1->drm->dl;
+
 	return 0;
 }
+
+void vsp1_drm_cleanup(struct vsp1_device *vsp1)
+{
+	vsp1_dl_destroy(vsp1->drm->dl);
+}
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
index 25d7f017feb4..7704038c3add 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.h
+++ b/drivers/media/platform/vsp1/vsp1_drm.h
@@ -15,19 +15,24 @@
 
 #include "vsp1_pipe.h"
 
+struct vsp1_dl;
+
 /**
  * vsp1_drm - State for the API exposed to the DRM driver
+ * @dl: display list for DRM pipeline operation
  * @pipe: the VSP1 pipeline used for display
  * @num_inputs: number of active pipeline inputs at the beginning of an update
  * @update: the pipeline configuration has been updated
  */
 struct vsp1_drm {
+	struct vsp1_dl *dl;
 	struct vsp1_pipeline pipe;
 	unsigned int num_inputs;
 	bool update;
 };
 
 int vsp1_drm_init(struct vsp1_device *vsp1);
+void vsp1_drm_cleanup(struct vsp1_device *vsp1);
 int vsp1_drm_create_links(struct vsp1_device *vsp1);
 
 #endif /* __VSP1_DRM_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 75cdf8715d9a..553a70c23356 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -25,6 +25,7 @@
 
 #include "vsp1.h"
 #include "vsp1_bru.h"
+#include "vsp1_dl.h"
 #include "vsp1_drm.h"
 #include "vsp1_hsit.h"
 #include "vsp1_lif.h"
@@ -44,11 +45,11 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data)
 	struct vsp1_device *vsp1 = data;
 	irqreturn_t ret = IRQ_NONE;
 	unsigned int i;
+	u32 status;
 
 	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
 		struct vsp1_rwpf *wpf = vsp1->wpf[i];
 		struct vsp1_pipeline *pipe;
-		u32 status;
 
 		if (wpf == NULL)
 			continue;
@@ -63,6 +64,21 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data)
 		}
 	}
 
+	status = vsp1_read(vsp1, VI6_DISP_IRQ_STA);
+	vsp1_write(vsp1, VI6_DISP_IRQ_STA, ~status & VI6_DISP_IRQ_STA_DST);
+
+	if (status & VI6_DISP_IRQ_STA_DST) {
+		struct vsp1_rwpf *wpf = vsp1->wpf[0];
+		struct vsp1_pipeline *pipe;
+
+		if (wpf) {
+			pipe = to_vsp1_pipeline(&wpf->entity.subdev.entity);
+			vsp1_pipeline_display_start(pipe);
+		}
+
+		ret = IRQ_HANDLED;
+	}
+
 	return ret;
 }
 
@@ -196,6 +212,9 @@ static void vsp1_destroy_entities(struct vsp1_device *vsp1)
 
 	v4l2_device_unregister(&vsp1->v4l2_dev);
 	media_device_unregister(&vsp1->media_dev);
+
+	if (!vsp1->info->uapi)
+		vsp1_drm_cleanup(vsp1);
 }
 
 static int vsp1_create_entities(struct vsp1_device *vsp1)
@@ -368,10 +387,13 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 			goto done;
 	}
 
-	if (vsp1->info->uapi)
+	if (vsp1->info->uapi) {
+		vsp1->use_dl = false;
 		ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev);
-	else
+	} else {
+		vsp1->use_dl = true;
 		ret = vsp1_drm_init(vsp1);
+	}
 
 done:
 	if (ret < 0)
@@ -380,33 +402,42 @@ done:
 	return ret;
 }
 
-static int vsp1_device_init(struct vsp1_device *vsp1)
+int vsp1_reset_wpf(struct vsp1_device *vsp1, unsigned int index)
 {
-	unsigned int i;
+	unsigned int timeout;
 	u32 status;
 
-	/* Reset any channel that might be running. */
 	status = vsp1_read(vsp1, VI6_STATUS);
+	if (!(status & VI6_STATUS_SYS_ACT(index)))
+		return 0;
 
-	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
-		unsigned int timeout;
+	vsp1_write(vsp1, VI6_SRESET, VI6_SRESET_SRTS(index));
+	for (timeout = 10; timeout > 0; --timeout) {
+		status = vsp1_read(vsp1, VI6_STATUS);
+		if (!(status & VI6_STATUS_SYS_ACT(index)))
+			break;
 
-		if (!(status & VI6_STATUS_SYS_ACT(i)))
-			continue;
+		usleep_range(1000, 2000);
+	}
 
-		vsp1_write(vsp1, VI6_SRESET, VI6_SRESET_SRTS(i));
-		for (timeout = 10; timeout > 0; --timeout) {
-			status = vsp1_read(vsp1, VI6_STATUS);
-			if (!(status & VI6_STATUS_SYS_ACT(i)))
-				break;
+	if (!timeout) {
+		dev_err(vsp1->dev, "failed to reset wpf.%u\n", index);
+		return -ETIMEDOUT;
+	}
 
-			usleep_range(1000, 2000);
-		}
+	return 0;
+}
 
-		if (!timeout) {
-			dev_err(vsp1->dev, "failed to reset wpf.%u\n", i);
-			return -ETIMEDOUT;
-		}
+static int vsp1_device_init(struct vsp1_device *vsp1)
+{
+	unsigned int i;
+	int ret;
+
+	/* Reset any channel that might be running. */
+	for (i = 0; i < vsp1->pdata.wpf_count; ++i) {
+		ret = vsp1_reset_wpf(vsp1, i);
+		if (ret < 0)
+			return ret;
 	}
 
 	vsp1_write(vsp1, VI6_CLK_DCSWT, (8 << VI6_CLK_DCSWT_CSTPW_SHIFT) |
@@ -430,6 +461,9 @@ static int vsp1_device_init(struct vsp1_device *vsp1)
 	vsp1_write(vsp1, VI6_DPR_HGT_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) |
 		   (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT));
 
+	if (vsp1->use_dl)
+		vsp1_dl_setup(vsp1);
+
 	return 0;
 }
 
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index 8947c1883bf4..d65cf8035a92 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -66,8 +66,8 @@ void vsp1_entity_route_setup(struct vsp1_entity *source)
 		return;
 
 	sink = container_of(source->sink, struct vsp1_entity, subdev.entity);
-	vsp1_write(source->vsp1, source->route->reg,
-		   sink->route->inputs[source->sink_pad]);
+	vsp1_mod_write(source, source->route->reg,
+		       sink->route->inputs[source->sink_pad]);
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c
index b8e73d32d14d..433853ce8dbf 100644
--- a/drivers/media/platform/vsp1/vsp1_lif.c
+++ b/drivers/media/platform/vsp1/vsp1_lif.c
@@ -28,7 +28,7 @@
 
 static inline void vsp1_lif_write(struct vsp1_lif *lif, u32 reg, u32 data)
 {
-	vsp1_write(lif->entity.vsp1, reg, data);
+	vsp1_mod_write(&lif->entity, reg, data);
 }
 
 /* -----------------------------------------------------------------------------
@@ -44,7 +44,7 @@ static int lif_s_stream(struct v4l2_subdev *subdev, int enable)
 	unsigned int lbth = 200;
 
 	if (!enable) {
-		vsp1_lif_write(lif, VI6_LIF_CTRL, 0);
+		vsp1_write(lif->entity.vsp1, VI6_LIF_CTRL, 0);
 		return 0;
 	}
 
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
index d41e4ca94a02..2e4a31072100 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.c
+++ b/drivers/media/platform/vsp1/vsp1_pipe.c
@@ -11,6 +11,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/wait.h>
 
@@ -19,6 +20,7 @@
 
 #include "vsp1.h"
 #include "vsp1_bru.h"
+#include "vsp1_dl.h"
 #include "vsp1_entity.h"
 #include "vsp1_pipe.h"
 #include "vsp1_rwpf.h"
@@ -176,8 +178,12 @@ void vsp1_pipeline_run(struct vsp1_pipeline *pipe)
 {
 	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
 
-	vsp1_write(vsp1, VI6_CMD(pipe->output->entity.index), VI6_CMD_STRCMD);
-	pipe->state = VSP1_PIPELINE_RUNNING;
+	if (pipe->state == VSP1_PIPELINE_STOPPED) {
+		vsp1_write(vsp1, VI6_CMD(pipe->output->entity.index),
+			   VI6_CMD_STRCMD);
+		pipe->state = VSP1_PIPELINE_RUNNING;
+	}
+
 	pipe->buffers_ready = 0;
 }
 
@@ -199,14 +205,28 @@ int vsp1_pipeline_stop(struct vsp1_pipeline *pipe)
 	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&pipe->irqlock, flags);
-	if (pipe->state == VSP1_PIPELINE_RUNNING)
-		pipe->state = VSP1_PIPELINE_STOPPING;
-	spin_unlock_irqrestore(&pipe->irqlock, flags);
+	if (pipe->dl) {
+		/* When using display lists in continuous frame mode the only
+		 * way to stop the pipeline is to reset the hardware.
+		 */
+		ret = vsp1_reset_wpf(pipe->output->entity.vsp1,
+				     pipe->output->entity.index);
+		if (ret == 0) {
+			spin_lock_irqsave(&pipe->irqlock, flags);
+			pipe->state = VSP1_PIPELINE_STOPPED;
+			spin_unlock_irqrestore(&pipe->irqlock, flags);
+		}
+	} else {
+		/* Otherwise just request a stop and wait. */
+		spin_lock_irqsave(&pipe->irqlock, flags);
+		if (pipe->state == VSP1_PIPELINE_RUNNING)
+			pipe->state = VSP1_PIPELINE_STOPPING;
+		spin_unlock_irqrestore(&pipe->irqlock, flags);
 
-	ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe),
-				 msecs_to_jiffies(500));
-	ret = ret == 0 ? -ETIMEDOUT : 0;
+		ret = wait_event_timeout(pipe->wq, vsp1_pipeline_stopped(pipe),
+					 msecs_to_jiffies(500));
+		ret = ret == 0 ? -ETIMEDOUT : 0;
+	}
 
 	list_for_each_entry(entity, &pipe->entities, list_pipe) {
 		if (entity->route && entity->route->reg)
@@ -230,6 +250,12 @@ bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe)
 	return pipe->buffers_ready == mask;
 }
 
+void vsp1_pipeline_display_start(struct vsp1_pipeline *pipe)
+{
+	if (pipe->dl)
+		vsp1_dl_irq_display_start(pipe->dl);
+}
+
 void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
 {
 	enum vsp1_pipeline_state state;
@@ -238,13 +264,21 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
 	if (pipe == NULL)
 		return;
 
+	if (pipe->dl)
+		vsp1_dl_irq_frame_end(pipe->dl);
+
 	/* Signal frame end to the pipeline handler. */
 	pipe->frame_end(pipe);
 
 	spin_lock_irqsave(&pipe->irqlock, flags);
 
 	state = pipe->state;
-	pipe->state = VSP1_PIPELINE_STOPPED;
+
+	/* When using display lists in continuous frame mode the pipeline is
+	 * automatically restarted by the hardware.
+	 */
+	if (!pipe->dl)
+		pipe->state = VSP1_PIPELINE_STOPPED;
 
 	/* If a stop has been requested, mark the pipeline as stopped and
 	 * return.
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
index c4c300561c5c..b2f3a8a896c9 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.h
+++ b/drivers/media/platform/vsp1/vsp1_pipe.h
@@ -19,6 +19,7 @@
 
 #include <media/media-entity.h>
 
+struct vsp1_dl;
 struct vsp1_rwpf;
 
 /*
@@ -73,6 +74,7 @@ enum vsp1_pipeline_state {
  * @uds: UDS entity, if present
  * @uds_input: entity at the input of the UDS, if the UDS is present
  * @entities: list of entities in the pipeline
+ * @dl: display list associated with the pipeline
  */
 struct vsp1_pipeline {
 	struct media_pipeline pipe;
@@ -97,6 +99,8 @@ struct vsp1_pipeline {
 	struct vsp1_entity *uds_input;
 
 	struct list_head entities;
+
+	struct vsp1_dl *dl;
 };
 
 static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e)
@@ -115,6 +119,7 @@ bool vsp1_pipeline_stopped(struct vsp1_pipeline *pipe);
 int vsp1_pipeline_stop(struct vsp1_pipeline *pipe);
 bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe);
 
+void vsp1_pipeline_display_start(struct vsp1_pipeline *pipe);
 void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe);
 
 void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index 56177628a17c..5bc1d1574a43 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -28,8 +28,8 @@
 
 static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, u32 reg, u32 data)
 {
-	vsp1_write(rpf->entity.vsp1,
-		   reg + rpf->entity.index * VI6_RPF_OFFSET, data);
+	vsp1_mod_write(&rpf->entity, reg + rpf->entity.index * VI6_RPF_OFFSET,
+		       data);
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index 7d06e84bcb9f..92d53c02ccc2 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -34,8 +34,8 @@ static inline u32 vsp1_wpf_read(struct vsp1_rwpf *wpf, u32 reg)
 
 static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf, u32 reg, u32 data)
 {
-	vsp1_write(wpf->entity.vsp1,
-		   reg + wpf->entity.index * VI6_WPF_OFFSET, data);
+	vsp1_mod_write(&wpf->entity,
+		       reg + wpf->entity.index * VI6_WPF_OFFSET, data);
 }
 
 /* -----------------------------------------------------------------------------
@@ -88,7 +88,8 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
 
 	if (!enable) {
 		vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0);
-		vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, 0);
+		vsp1_write(vsp1, wpf->entity.index * VI6_WPF_OFFSET +
+			   VI6_WPF_SRCRPF, 0);
 		return 0;
 	}
 
@@ -161,10 +162,10 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
 	if (vsp1->info->uapi)
 		mutex_unlock(wpf->ctrls.lock);
 
-	vsp1_write(vsp1, VI6_DPR_WPF_FPORCH(wpf->entity.index),
-		   VI6_DPR_WPF_FPORCH_FP_WPFN);
+	vsp1_mod_write(&wpf->entity, VI6_DPR_WPF_FPORCH(wpf->entity.index),
+		       VI6_DPR_WPF_FPORCH_FP_WPFN);
 
-	vsp1_write(vsp1, VI6_WPF_WRBCK_CTRL, 0);
+	vsp1_mod_write(&wpf->entity, VI6_WPF_WRBCK_CTRL, 0);
 
 	/* Enable interrupts */
 	vsp1_write(vsp1, VI6_WPF_IRQ_STA(wpf->entity.index), 0);
-- 
2.4.6


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [PATCH 00/32] VSP: Add R-Car Gen3 support
  2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
                   ` (31 preceding siblings ...)
  2015-09-13 20:57 ` [PATCH 32/32] v4l: vsp1: Add display list support Laurent Pinchart
@ 2015-09-13 22:53 ` Laurent Pinchart
  32 siblings, 0 replies; 34+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:53 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, linux-sh

On Sunday 13 September 2015 23:56:38 Laurent Pinchart wrote:
> Hello,
> 
> This patch set adds support for the Renesas R-Car Gen3 SoC family to the
> VSP1 driver. The large number of patches is caused by a change in the
> display controller architecture that makes usage of the VSP mandatory as
> the display controller has lost the ability to read data from memory.
> 
> Patch 01/31 to 26/31 prepare for the implementation of an API exported to
> the DRM driver in patch 27/31. Patches 30/31 enables support for the R-Car
> Gen3 family, and patch 31/31 finally enhances perfomances by implementing
> support for display lists.

For reference, the patch set that introduces usage of the VSP exported API in 
the DRM driver has been posted to the dri-devel mailing list and is available 
in the list archive at http://lists.freedesktop.org/archives/dri-devel/2015-September/090218.html

> Laurent Pinchart (31):
>   v4l: vsp1: Change the type of the rwpf field in struct vsp1_video
>   v4l: vsp1: Store the memory format in struct vsp1_rwpf
>   v4l: vsp1: Move video operations to vsp1_rwpf
>   v4l: vsp1: Rename vsp1_video_buffer to vsp1_vb2_buffer
>   v4l: vsp1: Move video device out of struct vsp1_rwpf
>   v4l: vsp1: Make rwpf operations independent of video device
>   v4l: vsp1: Support VSP1 instances without any UDS
>   v4l: vsp1: Move vsp1_video pointer from vsp1_entity to vsp1_rwpf
>   v4l: vsp1: Remove struct vsp1_pipeline num_video field
>   v4l: vsp1: Decouple pipeline end of frame processing from vsp1_video
>   v4l: vsp1: Split pipeline management code from vsp1_video.c
>   v4l: vsp1: Rename video pipeline functions to use vsp1_video prefix
>   v4l: vsp1: Extract pipeline initialization code into a function
>   v4l: vsp1: Reuse local variable instead of recomputing it
>   v4l: vsp1: Extract link creation to separate function
>   v4l: vsp1: Document the vsp1_pipeline structure
>   v4l: vsp1: Fix typo in VI6_DISP_IRQ_STA_DST register name
>   v4l: vsp1: Set the SRU CTRL0 register when starting the stream
>   v4l: vsp1: Remove unused module write functions
>   v4l: vsp1: Move entity route setup function to vsp1_entity.c
>   v4l: vsp1: Make number of BRU inputs configurable
>   v4l: vsp1: Make the BRU optional
>   v4l: vsp1: Move format info to vsp1_pipe.c
>   v4l: vsp1: Make the userspace API optional
>   v4l: vsp1: Make pipeline inputs array index by RPF index
>   v4l: vsp1: Set the alpha value manually in RPF and WPF s_stream
>     handlers
>   v4l: vsp1: Don't validate links when the userspace API is disabled
>   v4l: vsp1: Add VSP+DU support
>   v4l: vsp1: Disconnect unused RPFs from the DRM pipeline
>   v4l: vsp1: Implement atomic update for the DRM driver
>   v4l: vsp1: Add support for the R-Car Gen3 VSP2
> 
> Takashi Saito (1):
>   v4l: vsp1: Add display list support
> 
>  .../devicetree/bindings/media/renesas,vsp1.txt     |  11 +-
>  drivers/media/platform/vsp1/Makefile               |   3 +-
>  drivers/media/platform/vsp1/vsp1.h                 |  28 +
>  drivers/media/platform/vsp1/vsp1_bru.c             |  33 +-
>  drivers/media/platform/vsp1/vsp1_bru.h             |   3 +-
>  drivers/media/platform/vsp1/vsp1_dl.c              | 304 +++++++++++
>  drivers/media/platform/vsp1/vsp1_dl.h              |  42 ++
>  drivers/media/platform/vsp1/vsp1_drm.c             | 595 ++++++++++++++++++
>  drivers/media/platform/vsp1/vsp1_drm.h             |  38 ++
>  drivers/media/platform/vsp1/vsp1_drv.c             | 255 +++++++--
>  drivers/media/platform/vsp1/vsp1_entity.c          |  31 +-
>  drivers/media/platform/vsp1/vsp1_entity.h          |  14 +-
>  drivers/media/platform/vsp1/vsp1_hsit.c            |   2 +-
>  drivers/media/platform/vsp1/vsp1_lif.c             |  11 +-
>  drivers/media/platform/vsp1/vsp1_lut.c             |   7 +-
>  drivers/media/platform/vsp1/vsp1_pipe.c            | 405 ++++++++++++++
>  drivers/media/platform/vsp1/vsp1_pipe.h            | 134 +++++
>  drivers/media/platform/vsp1/vsp1_regs.h            |  14 +-
>  drivers/media/platform/vsp1/vsp1_rpf.c             |  77 ++-
>  drivers/media/platform/vsp1/vsp1_rwpf.h            |  24 +-
>  drivers/media/platform/vsp1/vsp1_sru.c             |   9 +-
>  drivers/media/platform/vsp1/vsp1_uds.c             |   8 +-
>  drivers/media/platform/vsp1/vsp1_video.c           | 515 ++++--------------
>  drivers/media/platform/vsp1/vsp1_video.h           | 110 +---
>  drivers/media/platform/vsp1/vsp1_wpf.c             |  88 ++-
>  include/media/vsp1.h                               |  33 ++
>  26 files changed, 2050 insertions(+), 744 deletions(-)
>  create mode 100644 drivers/media/platform/vsp1/vsp1_dl.c
>  create mode 100644 drivers/media/platform/vsp1/vsp1_dl.h
>  create mode 100644 drivers/media/platform/vsp1/vsp1_drm.c
>  create mode 100644 drivers/media/platform/vsp1/vsp1_drm.h
>  create mode 100644 drivers/media/platform/vsp1/vsp1_pipe.c
>  create mode 100644 drivers/media/platform/vsp1/vsp1_pipe.h
>  create mode 100644 include/media/vsp1.h

-- 
Regards,

Laurent Pinchart


^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2015-09-13 22:52 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-13 20:56 [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart
2015-09-13 20:56 ` [PATCH 01/32] v4l: vsp1: Change the type of the rwpf field in struct vsp1_video Laurent Pinchart
2015-09-13 20:56 ` [PATCH 02/32] v4l: vsp1: Store the memory format in struct vsp1_rwpf Laurent Pinchart
2015-09-13 20:56 ` [PATCH 03/32] v4l: vsp1: Move video operations to vsp1_rwpf Laurent Pinchart
2015-09-13 20:56 ` [PATCH 04/32] v4l: vsp1: Rename vsp1_video_buffer to vsp1_vb2_buffer Laurent Pinchart
2015-09-13 20:56 ` [PATCH 05/32] v4l: vsp1: Move video device out of struct vsp1_rwpf Laurent Pinchart
2015-09-13 20:56 ` [PATCH 06/32] v4l: vsp1: Make rwpf operations independent of video device Laurent Pinchart
2015-09-13 20:56 ` [PATCH 07/32] v4l: vsp1: Support VSP1 instances without any UDS Laurent Pinchart
2015-09-13 20:56 ` [PATCH 08/32] v4l: vsp1: Move vsp1_video pointer from vsp1_entity to vsp1_rwpf Laurent Pinchart
2015-09-13 20:56 ` [PATCH 09/32] v4l: vsp1: Remove struct vsp1_pipeline num_video field Laurent Pinchart
2015-09-13 20:56 ` [PATCH 10/32] v4l: vsp1: Decouple pipeline end of frame processing from vsp1_video Laurent Pinchart
2015-09-13 20:56 ` [PATCH 11/32] v4l: vsp1: Split pipeline management code from vsp1_video.c Laurent Pinchart
2015-09-13 20:56 ` [PATCH 12/32] v4l: vsp1: Rename video pipeline functions to use vsp1_video prefix Laurent Pinchart
2015-09-13 20:56 ` [PATCH 13/32] v4l: vsp1: Extract pipeline initialization code into a function Laurent Pinchart
2015-09-13 20:56 ` [PATCH 14/32] v4l: vsp1: Reuse local variable instead of recomputing it Laurent Pinchart
2015-09-13 20:56 ` [PATCH 15/32] v4l: vsp1: Extract link creation to separate function Laurent Pinchart
2015-09-13 20:56 ` [PATCH 16/32] v4l: vsp1: Document the vsp1_pipeline structure Laurent Pinchart
2015-09-13 20:56 ` [PATCH 17/32] v4l: vsp1: Fix typo in VI6_DISP_IRQ_STA_DST register name Laurent Pinchart
2015-09-13 20:56 ` [PATCH 18/32] v4l: vsp1: Set the SRU CTRL0 register when starting the stream Laurent Pinchart
2015-09-13 20:56 ` [PATCH 19/32] v4l: vsp1: Remove unused module write functions Laurent Pinchart
2015-09-13 20:56 ` [PATCH 20/32] v4l: vsp1: Move entity route setup function to vsp1_entity.c Laurent Pinchart
2015-09-13 20:56 ` [PATCH 21/32] v4l: vsp1: Make number of BRU inputs configurable Laurent Pinchart
2015-09-13 20:57 ` [PATCH 22/32] v4l: vsp1: Make the BRU optional Laurent Pinchart
2015-09-13 20:57 ` [PATCH 23/32] v4l: vsp1: Move format info to vsp1_pipe.c Laurent Pinchart
2015-09-13 20:57 ` [PATCH 24/32] v4l: vsp1: Make the userspace API optional Laurent Pinchart
2015-09-13 20:57 ` [PATCH 25/32] v4l: vsp1: Make pipeline inputs array index by RPF index Laurent Pinchart
2015-09-13 20:57 ` [PATCH 26/32] v4l: vsp1: Set the alpha value manually in RPF and WPF s_stream handlers Laurent Pinchart
2015-09-13 20:57 ` [PATCH 27/32] v4l: vsp1: Don't validate links when the userspace API is disabled Laurent Pinchart
2015-09-13 20:57 ` [PATCH 28/32] v4l: vsp1: Add VSP+DU support Laurent Pinchart
2015-09-13 20:57 ` [PATCH 29/32] v4l: vsp1: Disconnect unused RPFs from the DRM pipeline Laurent Pinchart
2015-09-13 20:57 ` [PATCH 30/32] v4l: vsp1: Implement atomic update for the DRM driver Laurent Pinchart
2015-09-13 20:57 ` [PATCH 31/32] v4l: vsp1: Add support for the R-Car Gen3 VSP2 Laurent Pinchart
2015-09-13 20:57 ` [PATCH 32/32] v4l: vsp1: Add display list support Laurent Pinchart
2015-09-13 22:53 ` [PATCH 00/32] VSP: Add R-Car Gen3 support Laurent Pinchart

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).