linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 0/3] vsp1 writeback prototype
@ 2016-10-27 14:01 Kieran Bingham
  2016-10-27 14:01 ` [RFC 1/3] Revert "[media] v4l: vsp1: Supply frames to the DU continuously" Kieran Bingham
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Kieran Bingham @ 2016-10-27 14:01 UTC (permalink / raw)
  To: Laurent Pinchart, Kieran Bingham
  Cc: linux-media, linux-renesas-soc, Kieran Bingham

This series presents an initial version of a write back video node for the VSP
DRM pipeline, utilising the existing vsp1_video base where possible.

The current version limits the output of the video node to match the frames
presented by updates from the CRTC atomic flush events. Matching the output rate
against the vsync/display rate has proven more difficult and I wanted to get
this out for review early.

This series is based on renesas-drivers-2016-10-25-v4.9-rc2, and has been
tested on a Salvator-H3. An updated/recent firmware is essential on this target
otherwise WPF underruns will occur.

This output can be tested with kmstest to generate frames and yavta to capture:

Terminal 1:
 # kmstest --flip --sync

Terminal 2:
 # yavta -c60 -n8 -f RGB24 -s1024x768 \
	--file=frame-rgb24-1024x768-#.bin /dev/$VIDEO

$VIDEO must be determined for your platform and represents the WPF Video node
from the VSP-D. On Salvator-H3, on renesas-drivers-2016-10-25-v4.9-rc2 this is
active at /dev/video28

Kieran Bingham (3):
  Revert "[media] v4l: vsp1: Supply frames to the DU continuously"
  v4l: vsp1: allow entities to have multiple source pads
  v4l: vsp1: Provide a writeback video device

 drivers/media/platform/vsp1/vsp1.h        |   1 +
 drivers/media/platform/vsp1/vsp1_bru.c    |   2 +-
 drivers/media/platform/vsp1/vsp1_clu.c    |   2 +-
 drivers/media/platform/vsp1/vsp1_drm.c    |  20 ++++
 drivers/media/platform/vsp1/vsp1_drv.c    |   5 +-
 drivers/media/platform/vsp1/vsp1_entity.c |  15 +--
 drivers/media/platform/vsp1/vsp1_entity.h |   3 +-
 drivers/media/platform/vsp1/vsp1_histo.c  |   2 +-
 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_rwpf.c   |  15 ++-
 drivers/media/platform/vsp1/vsp1_rwpf.h   |   2 +
 drivers/media/platform/vsp1/vsp1_sru.c    |   2 +-
 drivers/media/platform/vsp1/vsp1_uds.c    |   2 +-
 drivers/media/platform/vsp1/vsp1_video.c  | 172 +++++++++++++++++++++++++++---
 drivers/media/platform/vsp1/vsp1_video.h  |   5 +
 drivers/media/platform/vsp1/vsp1_wpf.c    |  23 +++-
 19 files changed, 238 insertions(+), 41 deletions(-)

-- 
2.7.4


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

* [RFC 1/3] Revert "[media] v4l: vsp1: Supply frames to the DU continuously"
  2016-10-27 14:01 [RFC 0/3] vsp1 writeback prototype Kieran Bingham
@ 2016-10-27 14:01 ` Kieran Bingham
  2016-11-02 23:57   ` Laurent Pinchart
  2016-10-27 14:01 ` [RFC 2/3] v4l: vsp1: allow entities to have multiple source pads Kieran Bingham
  2016-10-27 14:01 ` [RFC 3/3] v4l: vsp1: Provide a writeback video device Kieran Bingham
  2 siblings, 1 reply; 8+ messages in thread
From: Kieran Bingham @ 2016-10-27 14:01 UTC (permalink / raw)
  To: Laurent Pinchart, Kieran Bingham
  Cc: linux-media, linux-renesas-soc, Kieran Bingham

This reverts commit 3299ba5c0b213be5d911752d40251c1abc1004f7.

The DU output mode does not rely on frames being supplied on the WPF as
its pipeline is supplied from DRM. For the upcoming WPF writeback
functionality, we will choose to enable writeback mode if there is an
output buffer, or disable it (leaving the existing display pipeline
unharmed) otherwise.

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_video.c | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 94b428596c4f..f10401065cd3 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -296,11 +296,6 @@ static struct v4l2_rect vsp1_video_partition(struct vsp1_pipeline *pipe,
  * This function completes the current buffer by filling its sequence number,
  * time stamp and payload size, and hands it back to the videobuf core.
  *
- * When operating in DU output mode (deep pipeline to the DU through the LIF),
- * the VSP1 needs to constantly supply frames to the display. In that case, if
- * no other buffer is queued, reuse the one that has just been processed instead
- * of handing it back to the videobuf core.
- *
  * Return the next queued buffer or NULL if the queue is empty.
  */
 static struct vsp1_vb2_buffer *
@@ -322,12 +317,6 @@ vsp1_video_complete_buffer(struct vsp1_video *video)
 	done = list_first_entry(&video->irqqueue,
 				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)) {
-		spin_unlock_irqrestore(&video->irqlock, flags);
-		return done;
-	}
-
 	list_del(&done->queue);
 
 	if (!list_empty(&video->irqqueue))
-- 
2.7.4


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

* [RFC 2/3] v4l: vsp1: allow entities to have multiple source pads
  2016-10-27 14:01 [RFC 0/3] vsp1 writeback prototype Kieran Bingham
  2016-10-27 14:01 ` [RFC 1/3] Revert "[media] v4l: vsp1: Supply frames to the DU continuously" Kieran Bingham
@ 2016-10-27 14:01 ` Kieran Bingham
  2016-11-02 23:59   ` Laurent Pinchart
  2016-10-27 14:01 ` [RFC 3/3] v4l: vsp1: Provide a writeback video device Kieran Bingham
  2 siblings, 1 reply; 8+ messages in thread
From: Kieran Bingham @ 2016-10-27 14:01 UTC (permalink / raw)
  To: Laurent Pinchart, Kieran Bingham
  Cc: linux-media, linux-renesas-soc, Kieran Bingham

The upcoming writeback feature of the VSP1 WPF, allows the active output
of the DU to be written back to memory. On Generation 3 hardware, the DU
is fed by the LIF, which is in turn fed by the WPF.

It is the WPF which will perform memory writeback functionality, and
this brings in a second output of the entity. Configured in this mode,
the WPF will output to both the LIF, and to a memory (V4L2 video)
device.

Support this feature by extending vsp1_entity_init() to specify the
number of source and sink pads.

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_bru.c    |  2 +-
 drivers/media/platform/vsp1/vsp1_clu.c    |  2 +-
 drivers/media/platform/vsp1/vsp1_entity.c | 15 ++++++++-------
 drivers/media/platform/vsp1/vsp1_entity.h |  3 ++-
 drivers/media/platform/vsp1/vsp1_histo.c  |  2 +-
 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, 20 insertions(+), 18 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c
index ee8355c28f94..796bcc77eb44 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.c
+++ b/drivers/media/platform/vsp1/vsp1_bru.c
@@ -411,7 +411,7 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1)
 	bru->entity.type = VSP1_ENTITY_BRU;
 
 	ret = vsp1_entity_init(vsp1, &bru->entity, "bru",
-			       vsp1->info->num_bru_inputs + 1, &bru_ops,
+			       vsp1->info->num_bru_inputs, 1, &bru_ops,
 			       MEDIA_ENT_F_PROC_VIDEO_COMPOSER);
 	if (ret < 0)
 		return ERR_PTR(ret);
diff --git a/drivers/media/platform/vsp1/vsp1_clu.c b/drivers/media/platform/vsp1/vsp1_clu.c
index f2fb26e5ab4e..b38692b1f0dd 100644
--- a/drivers/media/platform/vsp1/vsp1_clu.c
+++ b/drivers/media/platform/vsp1/vsp1_clu.c
@@ -283,7 +283,7 @@ struct vsp1_clu *vsp1_clu_create(struct vsp1_device *vsp1)
 	clu->entity.ops = &clu_entity_ops;
 	clu->entity.type = VSP1_ENTITY_CLU;
 
-	ret = vsp1_entity_init(vsp1, &clu->entity, "clu", 2, &clu_ops,
+	ret = vsp1_entity_init(vsp1, &clu->entity, "clu", 1, 1, &clu_ops,
 			       MEDIA_ENT_F_PROC_VIDEO_LUT);
 	if (ret < 0)
 		return ERR_PTR(ret);
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index 5263387f7ec7..72c99de6e3a4 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -472,11 +472,13 @@ static const struct vsp1_route vsp1_routes[] = {
 };
 
 int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
-		     const char *name, unsigned int num_pads,
+		     const char *name, unsigned int num_sink_pads,
+		     unsigned int num_source_pads,
 		     const struct v4l2_subdev_ops *ops, u32 function)
 {
 	struct v4l2_subdev *subdev;
 	unsigned int i;
+	unsigned int num_pads = num_sink_pads + num_source_pads;
 	int ret;
 
 	for (i = 0; i < ARRAY_SIZE(vsp1_routes); ++i) {
@@ -501,18 +503,17 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
 	if (entity->pads == NULL)
 		return -ENOMEM;
 
-	for (i = 0; i < num_pads - 1; ++i)
+	for (i = 0; i < num_sink_pads; ++i)
 		entity->pads[i].flags = MEDIA_PAD_FL_SINK;
 
-	entity->sources = devm_kcalloc(vsp1->dev, max(num_pads - 1, 1U),
+	for (; i < num_pads; ++i)
+		entity->pads[i].flags = MEDIA_PAD_FL_SOURCE;
+
+	entity->sources = devm_kcalloc(vsp1->dev, num_source_pads,
 				       sizeof(*entity->sources), GFP_KERNEL);
 	if (entity->sources == NULL)
 		return -ENOMEM;
 
-	/* Single-pad entities only have a sink. */
-	entity->pads[num_pads - 1].flags = num_pads > 1 ? MEDIA_PAD_FL_SOURCE
-					 : MEDIA_PAD_FL_SINK;
-
 	/* Initialize the media entity. */
 	ret = media_entity_pads_init(&entity->subdev.entity, num_pads,
 				     entity->pads);
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
index c169a060b6d2..c709c29eb994 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.h
+++ b/drivers/media/platform/vsp1/vsp1_entity.h
@@ -120,7 +120,8 @@ static inline struct vsp1_entity *to_vsp1_entity(struct v4l2_subdev *subdev)
 }
 
 int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
-		     const char *name, unsigned int num_pads,
+		     const char *name, unsigned int num_sink_pads,
+		     unsigned int num_source_pads,
 		     const struct v4l2_subdev_ops *ops, u32 function);
 void vsp1_entity_destroy(struct vsp1_entity *entity);
 
diff --git a/drivers/media/platform/vsp1/vsp1_histo.c b/drivers/media/platform/vsp1/vsp1_histo.c
index e1d0d7236907..8d809afb3b09 100644
--- a/drivers/media/platform/vsp1/vsp1_histo.c
+++ b/drivers/media/platform/vsp1/vsp1_histo.c
@@ -589,7 +589,7 @@ int vsp1_histogram_init(struct vsp1_device *vsp1, struct vsp1_histogram *histo,
 	histo->entity.ops = ops;
 	histo->entity.type = type;
 
-	ret = vsp1_entity_init(vsp1, &histo->entity, name, 2, &histo_ops,
+	ret = vsp1_entity_init(vsp1, &histo->entity, name, 1, 1, &histo_ops,
 			       MEDIA_ENT_F_PROC_VIDEO_STATISTICS);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c
index 94316afc54ff..6c54f2483248 100644
--- a/drivers/media/platform/vsp1/vsp1_hsit.c
+++ b/drivers/media/platform/vsp1/vsp1_hsit.c
@@ -173,7 +173,7 @@ struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device *vsp1, bool inverse)
 		hsit->entity.type = VSP1_ENTITY_HST;
 
 	ret = vsp1_entity_init(vsp1, &hsit->entity, inverse ? "hsi" : "hst",
-			       2, &hsit_ops,
+			       1, 1, &hsit_ops,
 			       MEDIA_ENT_F_PROC_VIDEO_PIXEL_ENC_CONV);
 	if (ret < 0)
 		return ERR_PTR(ret);
diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c
index e32acae1fc6e..c3f87879e0bf 100644
--- a/drivers/media/platform/vsp1/vsp1_lif.c
+++ b/drivers/media/platform/vsp1/vsp1_lif.c
@@ -180,7 +180,7 @@ struct vsp1_lif *vsp1_lif_create(struct vsp1_device *vsp1)
 	 * requires a function to be set. Use PROC_VIDEO_PIXEL_FORMATTER just to
 	 * avoid triggering a WARN_ON(), the value won't be seen anywhere.
 	 */
-	ret = vsp1_entity_init(vsp1, &lif->entity, "lif", 2, &lif_ops,
+	ret = vsp1_entity_init(vsp1, &lif->entity, "lif", 1, 1, &lif_ops,
 			       MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER);
 	if (ret < 0)
 		return ERR_PTR(ret);
diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c
index c67cc60db0db..595f036f6476 100644
--- a/drivers/media/platform/vsp1/vsp1_lut.c
+++ b/drivers/media/platform/vsp1/vsp1_lut.c
@@ -239,7 +239,7 @@ struct vsp1_lut *vsp1_lut_create(struct vsp1_device *vsp1)
 	lut->entity.ops = &lut_entity_ops;
 	lut->entity.type = VSP1_ENTITY_LUT;
 
-	ret = vsp1_entity_init(vsp1, &lut->entity, "lut", 2, &lut_ops,
+	ret = vsp1_entity_init(vsp1, &lut->entity, "lut", 1, 1, &lut_ops,
 			       MEDIA_ENT_F_PROC_VIDEO_LUT);
 	if (ret < 0)
 		return ERR_PTR(ret);
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index 03d71601bab6..427cbabf5c6a 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -274,7 +274,7 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
 	rpf->entity.index = index;
 
 	sprintf(name, "rpf.%u", index);
-	ret = vsp1_entity_init(vsp1, &rpf->entity, name, 2, &rpf_ops,
+	ret = vsp1_entity_init(vsp1, &rpf->entity, name, 1, 1, &rpf_ops,
 			       MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER);
 	if (ret < 0)
 		return ERR_PTR(ret);
diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c
index b4e568a3b4ed..404f9d484a2a 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.c
+++ b/drivers/media/platform/vsp1/vsp1_sru.c
@@ -345,7 +345,7 @@ struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1)
 	sru->entity.ops = &sru_entity_ops;
 	sru->entity.type = VSP1_ENTITY_SRU;
 
-	ret = vsp1_entity_init(vsp1, &sru->entity, "sru", 2, &sru_ops,
+	ret = vsp1_entity_init(vsp1, &sru->entity, "sru", 1, 1, &sru_ops,
 			       MEDIA_ENT_F_PROC_VIDEO_SCALER);
 	if (ret < 0)
 		return ERR_PTR(ret);
diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c
index da8f89a31ea4..777d68dfe1f8 100644
--- a/drivers/media/platform/vsp1/vsp1_uds.c
+++ b/drivers/media/platform/vsp1/vsp1_uds.c
@@ -366,7 +366,7 @@ struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index)
 	uds->entity.index = index;
 
 	sprintf(name, "uds.%u", index);
-	ret = vsp1_entity_init(vsp1, &uds->entity, name, 2, &uds_ops,
+	ret = vsp1_entity_init(vsp1, &uds->entity, name, 1, 1, &uds_ops,
 			       MEDIA_ENT_F_PROC_VIDEO_SCALER);
 	if (ret < 0)
 		return ERR_PTR(ret);
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index 958e7f215a2b..b5f44d6839c6 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -494,7 +494,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
 	wpf->entity.index = index;
 
 	sprintf(name, "wpf.%u", index);
-	ret = vsp1_entity_init(vsp1, &wpf->entity, name, 2, &wpf_ops,
+	ret = vsp1_entity_init(vsp1, &wpf->entity, name, 1, 1, &wpf_ops,
 			       MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER);
 	if (ret < 0)
 		return ERR_PTR(ret);
-- 
2.7.4


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

* [RFC 3/3] v4l: vsp1: Provide a writeback video device
  2016-10-27 14:01 [RFC 0/3] vsp1 writeback prototype Kieran Bingham
  2016-10-27 14:01 ` [RFC 1/3] Revert "[media] v4l: vsp1: Supply frames to the DU continuously" Kieran Bingham
  2016-10-27 14:01 ` [RFC 2/3] v4l: vsp1: allow entities to have multiple source pads Kieran Bingham
@ 2016-10-27 14:01 ` Kieran Bingham
  2016-11-01 12:19   ` Kieran Bingham
  2 siblings, 1 reply; 8+ messages in thread
From: Kieran Bingham @ 2016-10-27 14:01 UTC (permalink / raw)
  To: Laurent Pinchart, Kieran Bingham
  Cc: linux-media, linux-renesas-soc, Kieran Bingham

When the VSP1 is used in an active display pipeline, the output of the
WPF can supply the LIF entity directly and simultaneously write to
memory.

Support this functionality in the VSP1 driver, by extending the WPF
source pads, and establishing a V4L2 video device node connected to the
new source.

The source will be able to perform pixel format conversion, but not
rescaling, and as such the output from the memory node will always be
of the same dimensions as the display output.

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1.h       |   1 +
 drivers/media/platform/vsp1/vsp1_drm.c   |  20 ++++
 drivers/media/platform/vsp1/vsp1_drv.c   |   5 +-
 drivers/media/platform/vsp1/vsp1_rwpf.c  |  15 ++-
 drivers/media/platform/vsp1/vsp1_rwpf.h  |   2 +
 drivers/media/platform/vsp1/vsp1_video.c | 161 ++++++++++++++++++++++++++++++-
 drivers/media/platform/vsp1/vsp1_video.h |   5 +
 drivers/media/platform/vsp1/vsp1_wpf.c   |  23 ++++-
 8 files changed, 219 insertions(+), 13 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 85387a64179a..a2d462264312 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -54,6 +54,7 @@ struct vsp1_uds;
 #define VSP1_HAS_WPF_HFLIP	(1 << 6)
 #define VSP1_HAS_HGO		(1 << 7)
 #define VSP1_HAS_HGT		(1 << 8)
+#define VSP1_HAS_WPF_WRITEBACK	(1 << 9)
 
 struct vsp1_device_info {
 	u32 version;
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 0daf5f2c06e2..446188a06a92 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -27,6 +27,7 @@
 #include "vsp1_lif.h"
 #include "vsp1_pipe.h"
 #include "vsp1_rwpf.h"
+#include "vsp1_video.h"
 
 
 /* -----------------------------------------------------------------------------
@@ -479,6 +480,13 @@ void vsp1_du_atomic_flush(struct device *dev)
 				__func__, rpf->entity.index);
 	}
 
+	/*
+	 * If we have a writeback node attached, we use this opportunity to
+	 * update the video buffers.
+	 */
+	if (pipe->output->video && pipe->output->video->frame_end)
+		pipe->output->video->frame_end(pipe);
+
 	/* Configure all entities in the pipeline. */
 	list_for_each_entry(entity, &pipe->entities, list_pipe) {
 		/* Disconnect unused RPFs from the pipeline. */
@@ -590,6 +598,17 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
 	if (ret < 0)
 		return ret;
 
+	if (!(vsp1->info->features & VSP1_HAS_WPF_WRITEBACK))
+		return 0;
+
+	/* Connect the video device to the WPF for Writeback support */
+	ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
+				    RWPF_PAD_SOURCE_WB,
+				    &vsp1->wpf[0]->video->video.entity,
+				    0, flags);
+	if (ret < 0)
+		return ret;
+
 	return 0;
 }
 
@@ -620,6 +639,7 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
 	pipe->bru = &vsp1->bru->entity;
 	pipe->lif = &vsp1->lif->entity;
 	pipe->output = vsp1->wpf[0];
+	pipe->output->pipe = pipe;
 
 	return 0;
 }
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 3b084976094b..42fa822b38d3 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -408,7 +408,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 		vsp1->wpf[i] = wpf;
 		list_add_tail(&wpf->entity.list_dev, &vsp1->entities);
 
-		if (vsp1->info->uapi) {
+		if (vsp1->info->uapi || wpf->has_writeback) {
 			struct vsp1_video *video = vsp1_video_create(vsp1, wpf);
 
 			if (IS_ERR(video)) {
@@ -705,7 +705,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
 		.version = VI6_IP_VERSION_MODEL_VSPD_GEN3,
 		.model = "VSP2-D",
 		.gen = 3,
-		.features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_WPF_VFLIP,
+		.features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_WPF_VFLIP
+			  | VSP1_HAS_WPF_WRITEBACK,
 		.rpf_count = 5,
 		.wpf_count = 2,
 		.num_bru_inputs = 5,
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c
index 7deb6b9acf0b..7ad3ed097d50 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.c
@@ -83,9 +83,10 @@ static int vsp1_rwpf_set_format(struct v4l2_subdev *subdev,
 
 	format = vsp1_entity_get_pad_format(&rwpf->entity, config, fmt->pad);
 
-	if (fmt->pad == RWPF_PAD_SOURCE) {
+	if (fmt->pad == RWPF_PAD_SOURCE ||
+	    fmt->pad == RWPF_PAD_SOURCE_WB) {
 		/* The RWPF performs format conversion but can't scale, only the
-		 * format code can be changed on the source pad.
+		 * format code can be changed on the source pads.
 		 */
 		format->code = fmt->format.code;
 		fmt->format = *format;
@@ -113,11 +114,19 @@ static int vsp1_rwpf_set_format(struct v4l2_subdev *subdev,
 		crop->height = fmt->format.height;
 	}
 
-	/* Propagate the format to the source pad. */
+	/* Propagate the format to the source pads. */
 	format = vsp1_entity_get_pad_format(&rwpf->entity, config,
 					    RWPF_PAD_SOURCE);
 	*format = fmt->format;
 
+	if (rwpf->has_writeback) {
+		/* Propogate the format to the Writeback pad */
+		format = vsp1_entity_get_pad_format(&rwpf->entity, config,
+				RWPF_PAD_SOURCE_WB);
+
+		*format = fmt->format;
+	}
+
 	if (rwpf->flip.rotate) {
 		format->width = fmt->format.height;
 		format->height = fmt->format.width;
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index b4ffc38f48af..739088a009e8 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -24,6 +24,7 @@
 
 #define RWPF_PAD_SINK				0
 #define RWPF_PAD_SOURCE				1
+#define RWPF_PAD_SOURCE_WB			2
 
 struct v4l2_ctrl;
 struct vsp1_dl_manager;
@@ -53,6 +54,7 @@ struct vsp1_rwpf {
 
 	u32 mult_alpha;
 	u32 outfmt;
+	bool has_writeback;
 
 	struct {
 		spinlock_t lock;
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index f10401065cd3..68cef93117f9 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -81,11 +81,16 @@ static int vsp1_video_verify_format(struct vsp1_video *video)
 	if (ret < 0)
 		return ret == -ENOIOCTLCMD ? -EINVAL : ret;
 
-	if (video->rwpf->fmtinfo->mbus != fmt.format.code ||
-	    video->rwpf->format.height != fmt.format.height ||
+	/* WPF entities can not perform any scaling action */
+	if (video->rwpf->format.height != fmt.format.height ||
 	    video->rwpf->format.width != fmt.format.width)
 		return -EINVAL;
 
+	/* Unless we are in writeback mode, we must match the format as well */
+	if (!video->is_writeback &&
+	    video->rwpf->fmtinfo->mbus != fmt.format.code)
+		return -EINVAL;
+
 	return 0;
 }
 
@@ -860,6 +865,7 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq)
 	list_for_each_entry(buffer, &video->irqqueue, queue)
 		vb2_buffer_done(&buffer->buf.vb2_buf, VB2_BUF_STATE_ERROR);
 	INIT_LIST_HEAD(&video->irqqueue);
+	INIT_LIST_HEAD(&video->wbqueue);
 	spin_unlock_irqrestore(&video->irqlock, flags);
 }
 
@@ -873,6 +879,149 @@ static const struct vb2_ops vsp1_video_queue_qops = {
 	.stop_streaming = vsp1_video_stop_streaming,
 };
 
+
+/* -----------------------------------------------------------------------------
+ * videobuf2 queue operations for writeback nodes
+ */
+
+static void vsp1_video_wb_process_buffer(struct vsp1_video *video)
+{
+	struct vsp1_vb2_buffer *buf;
+	unsigned long flags;
+
+	/*
+	 * Writeback uses a running stream, unlike the M2M interface which
+	 * controls a pipeline process manually though the use of
+	 * vsp1_pipeline_run().
+	 *
+	 * Instead writeback will commence at the next frame interval, and can
+	 * be marked complete at the interval following that. To handle this we
+	 * store the configured buffer as pending until the next callback.
+	 *
+	 * |    |    |    |    |
+	 *  A   |<-->|
+	 *       B   |<-->|
+	 *            C   |<-->| : Only at interrupt C can A be marked done
+	 */
+
+	spin_lock_irqsave(&video->irqlock, flags);
+
+	/* Move the pending image to the active hw queue */
+	if (video->pending) {
+		list_add_tail(&video->pending->queue, &video->irqqueue);
+		video->pending = NULL;
+	}
+
+	buf = list_first_entry_or_null(&video->wbqueue, struct vsp1_vb2_buffer,
+					queue);
+
+	if (buf) {
+		video->rwpf->mem = buf->mem;
+
+		/* Store this buffer as pending. It will commence at the next
+		 * frame start interrupt */
+		video->pending = buf;
+		list_del(&buf->queue);
+	} else {
+		/* Disable writeback with no buffer */
+		video->rwpf->mem = (struct vsp1_rwpf_memory) { 0 };
+	}
+
+	spin_unlock_irqrestore(&video->irqlock, flags);
+}
+
+static void vsp1_video_wb_frame_end(struct vsp1_pipeline *pipe)
+{
+	struct vsp1_video *video = pipe->output->video;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pipe->irqlock, flags);
+
+	/* Complete any buffer on the IRQ queue */
+	vsp1_video_complete_buffer(video);
+
+	/* Queue up any buffer from our wb queue, and place on the IRQ queue */
+	vsp1_video_wb_process_buffer(video);
+
+	spin_unlock_irqrestore(&pipe->irqlock, flags);
+}
+
+static void vsp1_video_wb_buffer_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue);
+	struct vsp1_vb2_buffer *buf = to_vsp1_vb2_buffer(vbuf);
+	unsigned long flags;
+
+	spin_lock_irqsave(&video->irqlock, flags);
+	list_add_tail(&buf->queue, &video->wbqueue);
+	spin_unlock_irqrestore(&video->irqlock, flags);
+
+	return;
+}
+
+static int vsp1_video_wb_start_streaming(struct vb2_queue *vq,
+		unsigned int count)
+{
+	struct vsp1_video *video = vb2_get_drv_priv(vq);
+	unsigned long flags;
+
+	/* Enable the completion interrupts */
+	spin_lock_irqsave(&video->irqlock, flags);
+	video->frame_end = vsp1_video_wb_frame_end;
+	spin_unlock_irqrestore(&video->irqlock, flags);
+
+	return 0;
+}
+
+static void vsp1_video_wb_stop_streaming(struct vb2_queue *vq)
+{
+	struct vsp1_video *video = vb2_get_drv_priv(vq);
+	struct vsp1_rwpf *rwpf = video->rwpf;
+	struct vsp1_pipeline *pipe = rwpf->pipe;
+	struct vsp1_vb2_buffer *buffer;
+	unsigned long flags;
+
+	/*
+	 * Disable the completion interrupts, and clear the WPF memory to
+	 * prevent writing out frames
+	 */
+	spin_lock_irqsave(&video->irqlock, flags);
+	video->frame_end = NULL;
+	rwpf->mem = (struct vsp1_rwpf_memory) { 0 };
+
+	/* Return all queued buffers to userspace */
+	list_for_each_entry(buffer, &video->wbqueue, queue)
+		vb2_buffer_done(&buffer->buf.vb2_buf, VB2_BUF_STATE_ERROR);
+	list_for_each_entry(buffer, &video->irqqueue, queue)
+		vb2_buffer_done(&buffer->buf.vb2_buf, VB2_BUF_STATE_ERROR);
+	if (video->pending) {
+		vb2_buffer_done(&video->pending->buf.vb2_buf,
+				VB2_BUF_STATE_ERROR);
+		video->pending = NULL;
+	}
+
+	INIT_LIST_HEAD(&video->wbqueue);
+	INIT_LIST_HEAD(&video->irqqueue);
+	spin_unlock_irqrestore(&video->irqlock, flags);
+
+	/* Return the reference obtained by vsp1_video_streamon() */
+	vsp1_video_pipeline_put(pipe);
+
+	return;
+}
+
+static const struct vb2_ops vsp1_video_wb_queue_qops = {
+	.queue_setup = vsp1_video_queue_setup,
+	.buf_prepare = vsp1_video_buffer_prepare,
+	.buf_queue = vsp1_video_wb_buffer_queue,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+	.start_streaming = vsp1_video_wb_start_streaming,
+	.stop_streaming = vsp1_video_wb_stop_streaming,
+};
+
+
 /* -----------------------------------------------------------------------------
  * V4L2 ioctls
  */
@@ -1109,6 +1258,8 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1,
 	video->vsp1 = vsp1;
 	video->rwpf = rwpf;
 
+	video->is_writeback = rwpf->has_writeback;
+
 	if (rwpf->entity.type == VSP1_ENTITY_RPF) {
 		direction = "input";
 		video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
@@ -1124,6 +1275,7 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1,
 	mutex_init(&video->lock);
 	spin_lock_init(&video->irqlock);
 	INIT_LIST_HEAD(&video->irqqueue);
+	INIT_LIST_HEAD(&video->wbqueue);
 
 	/* Initialize the media entity... */
 	ret = media_entity_pads_init(&video->video.entity, 1, &video->pad);
@@ -1147,12 +1299,15 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1,
 
 	video_set_drvdata(&video->video, video);
 
+	if (video->is_writeback)
+		video->queue.ops = &vsp1_video_wb_queue_qops;
+	else
+		video->queue.ops = &vsp1_video_queue_qops;
 	video->queue.type = video->type;
 	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_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;
 	video->queue.dev = video->vsp1->dev;
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index 50ea7f02205f..b63e14bbaef0 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -48,6 +48,11 @@ struct vsp1_video {
 	struct vb2_queue queue;
 	spinlock_t irqlock;
 	struct list_head irqqueue;
+
+	bool is_writeback;
+	struct list_head wbqueue;
+	struct vsp1_vb2_buffer *pending;
+	void (*frame_end)(struct vsp1_pipeline *pipe);
 };
 
 static inline struct vsp1_video *to_vsp1_video(struct video_device *vdev)
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index b5f44d6839c6..fea0fd3e662e 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -248,6 +248,8 @@ static void wpf_configure(struct vsp1_entity *entity,
 	u32 outfmt = 0;
 	u32 srcrpf = 0;
 
+	bool writeback = pipe->lif && wpf->mem.addr[0];
+
 	if (params == VSP1_ENTITY_PARAMS_RUNTIME) {
 		const unsigned int mask = BIT(WPF_CTRL_VFLIP)
 					| BIT(WPF_CTRL_HFLIP);
@@ -299,7 +301,14 @@ static void wpf_configure(struct vsp1_entity *entity,
 			       (0 << VI6_WPF_SZCLIP_OFST_SHIFT) |
 			       (height << VI6_WPF_SZCLIP_SIZE_SHIFT));
 
-		if (pipe->lif)
+		vsp1_dl_list_write(dl, VI6_WPF_WRBCK_CTRL, writeback ?
+						VI6_WPF_WRBCK_CTRL_WBMD : 0);
+
+		/*
+		 * Display pipelines with no writeback memory do not configure
+		 * the write out address
+		 */
+		if (pipe->lif && !writeback)
 			return;
 
 		/*
@@ -384,7 +393,7 @@ static void wpf_configure(struct vsp1_entity *entity,
 	}
 
 	/* Format */
-	if (!pipe->lif) {
+	if (!pipe->lif || writeback) {
 		const struct v4l2_pix_format_mplane *format = &wpf->format;
 		const struct vsp1_format_info *fmtinfo = wpf->fmtinfo;
 
@@ -424,8 +433,6 @@ static void wpf_configure(struct vsp1_entity *entity,
 	vsp1_dl_list_write(dl, VI6_DPR_WPF_FPORCH(wpf->entity.index),
 			   VI6_DPR_WPF_FPORCH_FP_WPFN);
 
-	vsp1_dl_list_write(dl, VI6_WPF_WRBCK_CTRL, 0);
-
 	/* Sources. If the pipeline has a single input and BRU is not used,
 	 * configure it as the master layer. Otherwise configure all
 	 * inputs as sub-layers and select the virtual RPF as the master
@@ -475,6 +482,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
 {
 	struct vsp1_rwpf *wpf;
 	char name[6];
+	int sink_pads;
 	int ret;
 
 	wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL);
@@ -493,8 +501,13 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
 	wpf->entity.type = VSP1_ENTITY_WPF;
 	wpf->entity.index = index;
 
+	/* WPF's with Write back support can output to the LIF and Memory */
+	wpf->has_writeback = (vsp1->info->features & VSP1_HAS_WPF_WRITEBACK)
+			   && index == 0;
+	sink_pads = wpf->has_writeback ? 2 : 1;
+
 	sprintf(name, "wpf.%u", index);
-	ret = vsp1_entity_init(vsp1, &wpf->entity, name, 1, 1, &wpf_ops,
+	ret = vsp1_entity_init(vsp1, &wpf->entity, name, 1, sink_pads, &wpf_ops,
 			       MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER);
 	if (ret < 0)
 		return ERR_PTR(ret);
-- 
2.7.4


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

* Re: [RFC 3/3] v4l: vsp1: Provide a writeback video device
  2016-10-27 14:01 ` [RFC 3/3] v4l: vsp1: Provide a writeback video device Kieran Bingham
@ 2016-11-01 12:19   ` Kieran Bingham
  0 siblings, 0 replies; 8+ messages in thread
From: Kieran Bingham @ 2016-11-01 12:19 UTC (permalink / raw)
  To: Kieran Bingham, Laurent Pinchart, Kieran Bingham
  Cc: linux-media, linux-renesas-soc

Looks like I forgot to run checkpatch here, and it picked up a few things.

Please disregard them in your review, and they will be fixed for next
version.


On 27/10/16 15:01, Kieran Bingham wrote:
> When the VSP1 is used in an active display pipeline, the output of the
> WPF can supply the LIF entity directly and simultaneously write to
> memory.
> 
> Support this functionality in the VSP1 driver, by extending the WPF
> source pads, and establishing a V4L2 video device node connected to the
> new source.
> 
> The source will be able to perform pixel format conversion, but not
> rescaling, and as such the output from the memory node will always be
> of the same dimensions as the display output.
> 
> Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> ---
>  drivers/media/platform/vsp1/vsp1.h       |   1 +
>  drivers/media/platform/vsp1/vsp1_drm.c   |  20 ++++
>  drivers/media/platform/vsp1/vsp1_drv.c   |   5 +-
>  drivers/media/platform/vsp1/vsp1_rwpf.c  |  15 ++-
>  drivers/media/platform/vsp1/vsp1_rwpf.h  |   2 +
>  drivers/media/platform/vsp1/vsp1_video.c | 161 ++++++++++++++++++++++++++++++-
>  drivers/media/platform/vsp1/vsp1_video.h |   5 +
>  drivers/media/platform/vsp1/vsp1_wpf.c   |  23 ++++-
>  8 files changed, 219 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
> index 85387a64179a..a2d462264312 100644
> --- a/drivers/media/platform/vsp1/vsp1.h
> +++ b/drivers/media/platform/vsp1/vsp1.h
> @@ -54,6 +54,7 @@ struct vsp1_uds;
>  #define VSP1_HAS_WPF_HFLIP	(1 << 6)
>  #define VSP1_HAS_HGO		(1 << 7)
>  #define VSP1_HAS_HGT		(1 << 8)
> +#define VSP1_HAS_WPF_WRITEBACK	(1 << 9)
>  
>  struct vsp1_device_info {
>  	u32 version;
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 0daf5f2c06e2..446188a06a92 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -27,6 +27,7 @@
>  #include "vsp1_lif.h"
>  #include "vsp1_pipe.h"
>  #include "vsp1_rwpf.h"
> +#include "vsp1_video.h"
>  
>  
>  /* -----------------------------------------------------------------------------
> @@ -479,6 +480,13 @@ void vsp1_du_atomic_flush(struct device *dev)
>  				__func__, rpf->entity.index);
>  	}
>  
> +	/*
> +	 * If we have a writeback node attached, we use this opportunity to
> +	 * update the video buffers.
> +	 */
> +	if (pipe->output->video && pipe->output->video->frame_end)
> +		pipe->output->video->frame_end(pipe);
> +
>  	/* Configure all entities in the pipeline. */
>  	list_for_each_entry(entity, &pipe->entities, list_pipe) {
>  		/* Disconnect unused RPFs from the pipeline. */
> @@ -590,6 +598,17 @@ int vsp1_drm_create_links(struct vsp1_device *vsp1)
>  	if (ret < 0)
>  		return ret;
>  
> +	if (!(vsp1->info->features & VSP1_HAS_WPF_WRITEBACK))
> +		return 0;
> +
> +	/* Connect the video device to the WPF for Writeback support */
> +	ret = media_create_pad_link(&vsp1->wpf[0]->entity.subdev.entity,
> +				    RWPF_PAD_SOURCE_WB,
> +				    &vsp1->wpf[0]->video->video.entity,
> +				    0, flags);
> +	if (ret < 0)
> +		return ret;
> +
>  	return 0;
>  }
>  
> @@ -620,6 +639,7 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
>  	pipe->bru = &vsp1->bru->entity;
>  	pipe->lif = &vsp1->lif->entity;
>  	pipe->output = vsp1->wpf[0];
> +	pipe->output->pipe = pipe;
>  
>  	return 0;
>  }
> diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
> index 3b084976094b..42fa822b38d3 100644
> --- a/drivers/media/platform/vsp1/vsp1_drv.c
> +++ b/drivers/media/platform/vsp1/vsp1_drv.c
> @@ -408,7 +408,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
>  		vsp1->wpf[i] = wpf;
>  		list_add_tail(&wpf->entity.list_dev, &vsp1->entities);
>  
> -		if (vsp1->info->uapi) {
> +		if (vsp1->info->uapi || wpf->has_writeback) {
>  			struct vsp1_video *video = vsp1_video_create(vsp1, wpf);
>  
>  			if (IS_ERR(video)) {
> @@ -705,7 +705,8 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
>  		.version = VI6_IP_VERSION_MODEL_VSPD_GEN3,
>  		.model = "VSP2-D",
>  		.gen = 3,
> -		.features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_WPF_VFLIP,
> +		.features = VSP1_HAS_BRU | VSP1_HAS_LIF | VSP1_HAS_WPF_VFLIP
> +			  | VSP1_HAS_WPF_WRITEBACK,
>  		.rpf_count = 5,
>  		.wpf_count = 2,
>  		.num_bru_inputs = 5,
> diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c
> index 7deb6b9acf0b..7ad3ed097d50 100644
> --- a/drivers/media/platform/vsp1/vsp1_rwpf.c
> +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c
> @@ -83,9 +83,10 @@ static int vsp1_rwpf_set_format(struct v4l2_subdev *subdev,
>  
>  	format = vsp1_entity_get_pad_format(&rwpf->entity, config, fmt->pad);
>  
> -	if (fmt->pad == RWPF_PAD_SOURCE) {
> +	if (fmt->pad == RWPF_PAD_SOURCE ||
> +	    fmt->pad == RWPF_PAD_SOURCE_WB) {
>  		/* The RWPF performs format conversion but can't scale, only the
> -		 * format code can be changed on the source pad.
> +		 * format code can be changed on the source pads.
>  		 */
>  		format->code = fmt->format.code;
>  		fmt->format = *format;
> @@ -113,11 +114,19 @@ static int vsp1_rwpf_set_format(struct v4l2_subdev *subdev,
>  		crop->height = fmt->format.height;
>  	}
>  
> -	/* Propagate the format to the source pad. */
> +	/* Propagate the format to the source pads. */

s/Propagate/Propogate/ will be fixed in next version.

>  	format = vsp1_entity_get_pad_format(&rwpf->entity, config,
>  					    RWPF_PAD_SOURCE);
>  	*format = fmt->format;
>  
> +	if (rwpf->has_writeback) {
> +		/* Propogate the format to the Writeback pad */

Likewise:
s/Propagate/Propogate/ will be fixed in next version.

> +		format = vsp1_entity_get_pad_format(&rwpf->entity, config,
> +				RWPF_PAD_SOURCE_WB);
> +
> +		*format = fmt->format;
> +	}
> +
>  	if (rwpf->flip.rotate) {
>  		format->width = fmt->format.height;
>  		format->height = fmt->format.width;
> diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
> index b4ffc38f48af..739088a009e8 100644
> --- a/drivers/media/platform/vsp1/vsp1_rwpf.h
> +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
> @@ -24,6 +24,7 @@
>  
>  #define RWPF_PAD_SINK				0
>  #define RWPF_PAD_SOURCE				1
> +#define RWPF_PAD_SOURCE_WB			2
>  
>  struct v4l2_ctrl;
>  struct vsp1_dl_manager;
> @@ -53,6 +54,7 @@ struct vsp1_rwpf {
>  
>  	u32 mult_alpha;
>  	u32 outfmt;
> +	bool has_writeback;
>  
>  	struct {
>  		spinlock_t lock;
> diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
> index f10401065cd3..68cef93117f9 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.c
> +++ b/drivers/media/platform/vsp1/vsp1_video.c
> @@ -81,11 +81,16 @@ static int vsp1_video_verify_format(struct vsp1_video *video)
>  	if (ret < 0)
>  		return ret == -ENOIOCTLCMD ? -EINVAL : ret;
>  
> -	if (video->rwpf->fmtinfo->mbus != fmt.format.code ||
> -	    video->rwpf->format.height != fmt.format.height ||
> +	/* WPF entities can not perform any scaling action */
> +	if (video->rwpf->format.height != fmt.format.height ||
>  	    video->rwpf->format.width != fmt.format.width)
>  		return -EINVAL;
>  
> +	/* Unless we are in writeback mode, we must match the format as well */
> +	if (!video->is_writeback &&
> +	    video->rwpf->fmtinfo->mbus != fmt.format.code)
> +		return -EINVAL;
> +
>  	return 0;
>  }
>  
> @@ -860,6 +865,7 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq)
>  	list_for_each_entry(buffer, &video->irqqueue, queue)
>  		vb2_buffer_done(&buffer->buf.vb2_buf, VB2_BUF_STATE_ERROR);
>  	INIT_LIST_HEAD(&video->irqqueue);
> +	INIT_LIST_HEAD(&video->wbqueue);
>  	spin_unlock_irqrestore(&video->irqlock, flags);
>  }
>  
> @@ -873,6 +879,149 @@ static const struct vb2_ops vsp1_video_queue_qops = {
>  	.stop_streaming = vsp1_video_stop_streaming,
>  };
>  
> +
> +/* -----------------------------------------------------------------------------
> + * videobuf2 queue operations for writeback nodes
> + */
> +
> +static void vsp1_video_wb_process_buffer(struct vsp1_video *video)
> +{
> +	struct vsp1_vb2_buffer *buf;
> +	unsigned long flags;
> +
> +	/*
> +	 * Writeback uses a running stream, unlike the M2M interface which
> +	 * controls a pipeline process manually though the use of
> +	 * vsp1_pipeline_run().
> +	 *
> +	 * Instead writeback will commence at the next frame interval, and can
> +	 * be marked complete at the interval following that. To handle this we
> +	 * store the configured buffer as pending until the next callback.
> +	 *
> +	 * |    |    |    |    |
> +	 *  A   |<-->|
> +	 *       B   |<-->|
> +	 *            C   |<-->| : Only at interrupt C can A be marked done
> +	 */
> +
> +	spin_lock_irqsave(&video->irqlock, flags);
> +
> +	/* Move the pending image to the active hw queue */
> +	if (video->pending) {
> +		list_add_tail(&video->pending->queue, &video->irqqueue);
> +		video->pending = NULL;
> +	}
> +
> +	buf = list_first_entry_or_null(&video->wbqueue, struct vsp1_vb2_buffer,
> +					queue);
> +
> +	if (buf) {
> +		video->rwpf->mem = buf->mem;
> +
> +		/* Store this buffer as pending. It will commence at the next
> +		 * frame start interrupt */
> +		video->pending = buf;
> +		list_del(&buf->queue);
> +	} else {
> +		/* Disable writeback with no buffer */
> +		video->rwpf->mem = (struct vsp1_rwpf_memory) { 0 };
> +	}
> +
> +	spin_unlock_irqrestore(&video->irqlock, flags);
> +}
> +
> +static void vsp1_video_wb_frame_end(struct vsp1_pipeline *pipe)
> +{
> +	struct vsp1_video *video = pipe->output->video;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&pipe->irqlock, flags);
> +
> +	/* Complete any buffer on the IRQ queue */
> +	vsp1_video_complete_buffer(video);
> +
> +	/* Queue up any buffer from our wb queue, and place on the IRQ queue */
> +	vsp1_video_wb_process_buffer(video);
> +
> +	spin_unlock_irqrestore(&pipe->irqlock, flags);
> +}
> +
> +static void vsp1_video_wb_buffer_queue(struct vb2_buffer *vb)
> +{
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +	struct vsp1_video *video = vb2_get_drv_priv(vb->vb2_queue);
> +	struct vsp1_vb2_buffer *buf = to_vsp1_vb2_buffer(vbuf);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&video->irqlock, flags);
> +	list_add_tail(&buf->queue, &video->wbqueue);
> +	spin_unlock_irqrestore(&video->irqlock, flags);
> +
> +	return;

return statement not needed - will be removed.

> +}
> +
> +static int vsp1_video_wb_start_streaming(struct vb2_queue *vq,
> +		unsigned int count)
> +{
> +	struct vsp1_video *video = vb2_get_drv_priv(vq);
> +	unsigned long flags;
> +
> +	/* Enable the completion interrupts */
> +	spin_lock_irqsave(&video->irqlock, flags);
> +	video->frame_end = vsp1_video_wb_frame_end;
> +	spin_unlock_irqrestore(&video->irqlock, flags);
> +
> +	return 0;
> +}
> +
> +static void vsp1_video_wb_stop_streaming(struct vb2_queue *vq)
> +{
> +	struct vsp1_video *video = vb2_get_drv_priv(vq);
> +	struct vsp1_rwpf *rwpf = video->rwpf;
> +	struct vsp1_pipeline *pipe = rwpf->pipe;
> +	struct vsp1_vb2_buffer *buffer;
> +	unsigned long flags;
> +
> +	/*
> +	 * Disable the completion interrupts, and clear the WPF memory to
> +	 * prevent writing out frames
> +	 */
> +	spin_lock_irqsave(&video->irqlock, flags);
> +	video->frame_end = NULL;
> +	rwpf->mem = (struct vsp1_rwpf_memory) { 0 };
> +
> +	/* Return all queued buffers to userspace */
> +	list_for_each_entry(buffer, &video->wbqueue, queue)
> +		vb2_buffer_done(&buffer->buf.vb2_buf, VB2_BUF_STATE_ERROR);
> +	list_for_each_entry(buffer, &video->irqqueue, queue)
> +		vb2_buffer_done(&buffer->buf.vb2_buf, VB2_BUF_STATE_ERROR);
> +	if (video->pending) {
> +		vb2_buffer_done(&video->pending->buf.vb2_buf,
> +				VB2_BUF_STATE_ERROR);
> +		video->pending = NULL;
> +	}
> +
> +	INIT_LIST_HEAD(&video->wbqueue);
> +	INIT_LIST_HEAD(&video->irqqueue);
> +	spin_unlock_irqrestore(&video->irqlock, flags);
> +
> +	/* Return the reference obtained by vsp1_video_streamon() */
> +	vsp1_video_pipeline_put(pipe);
> +
> +	return;

return statement not needed - will be removed.

> +}
> +
> +static const struct vb2_ops vsp1_video_wb_queue_qops = {
> +	.queue_setup = vsp1_video_queue_setup,
> +	.buf_prepare = vsp1_video_buffer_prepare,
> +	.buf_queue = vsp1_video_wb_buffer_queue,
> +	.wait_prepare = vb2_ops_wait_prepare,
> +	.wait_finish = vb2_ops_wait_finish,
> +	.start_streaming = vsp1_video_wb_start_streaming,
> +	.stop_streaming = vsp1_video_wb_stop_streaming,
> +};
> +
> +
>  /* -----------------------------------------------------------------------------
>   * V4L2 ioctls
>   */
> @@ -1109,6 +1258,8 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1,
>  	video->vsp1 = vsp1;
>  	video->rwpf = rwpf;
>  
> +	video->is_writeback = rwpf->has_writeback;
> +
>  	if (rwpf->entity.type == VSP1_ENTITY_RPF) {
>  		direction = "input";
>  		video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
> @@ -1124,6 +1275,7 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1,
>  	mutex_init(&video->lock);
>  	spin_lock_init(&video->irqlock);
>  	INIT_LIST_HEAD(&video->irqqueue);
> +	INIT_LIST_HEAD(&video->wbqueue);
>  
>  	/* Initialize the media entity... */
>  	ret = media_entity_pads_init(&video->video.entity, 1, &video->pad);
> @@ -1147,12 +1299,15 @@ struct vsp1_video *vsp1_video_create(struct vsp1_device *vsp1,
>  
>  	video_set_drvdata(&video->video, video);
>  
> +	if (video->is_writeback)
> +		video->queue.ops = &vsp1_video_wb_queue_qops;
> +	else
> +		video->queue.ops = &vsp1_video_queue_qops;
>  	video->queue.type = video->type;
>  	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_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;
>  	video->queue.dev = video->vsp1->dev;
> diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
> index 50ea7f02205f..b63e14bbaef0 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.h
> +++ b/drivers/media/platform/vsp1/vsp1_video.h
> @@ -48,6 +48,11 @@ struct vsp1_video {
>  	struct vb2_queue queue;
>  	spinlock_t irqlock;
>  	struct list_head irqqueue;
> +
> +	bool is_writeback;
> +	struct list_head wbqueue;
> +	struct vsp1_vb2_buffer *pending;
> +	void (*frame_end)(struct vsp1_pipeline *pipe);
>  };
>  
>  static inline struct vsp1_video *to_vsp1_video(struct video_device *vdev)
> diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
> index b5f44d6839c6..fea0fd3e662e 100644
> --- a/drivers/media/platform/vsp1/vsp1_wpf.c
> +++ b/drivers/media/platform/vsp1/vsp1_wpf.c
> @@ -248,6 +248,8 @@ static void wpf_configure(struct vsp1_entity *entity,
>  	u32 outfmt = 0;
>  	u32 srcrpf = 0;
>  
> +	bool writeback = pipe->lif && wpf->mem.addr[0];
> +
>  	if (params == VSP1_ENTITY_PARAMS_RUNTIME) {
>  		const unsigned int mask = BIT(WPF_CTRL_VFLIP)
>  					| BIT(WPF_CTRL_HFLIP);
> @@ -299,7 +301,14 @@ static void wpf_configure(struct vsp1_entity *entity,
>  			       (0 << VI6_WPF_SZCLIP_OFST_SHIFT) |
>  			       (height << VI6_WPF_SZCLIP_SIZE_SHIFT));
>  
> -		if (pipe->lif)
> +		vsp1_dl_list_write(dl, VI6_WPF_WRBCK_CTRL, writeback ?
> +						VI6_WPF_WRBCK_CTRL_WBMD : 0);
> +
> +		/*
> +		 * Display pipelines with no writeback memory do not configure
> +		 * the write out address
> +		 */
> +		if (pipe->lif && !writeback)
>  			return;
>  
>  		/*
> @@ -384,7 +393,7 @@ static void wpf_configure(struct vsp1_entity *entity,
>  	}
>  
>  	/* Format */
> -	if (!pipe->lif) {
> +	if (!pipe->lif || writeback) {
>  		const struct v4l2_pix_format_mplane *format = &wpf->format;
>  		const struct vsp1_format_info *fmtinfo = wpf->fmtinfo;
>  
> @@ -424,8 +433,6 @@ static void wpf_configure(struct vsp1_entity *entity,
>  	vsp1_dl_list_write(dl, VI6_DPR_WPF_FPORCH(wpf->entity.index),
>  			   VI6_DPR_WPF_FPORCH_FP_WPFN);
>  
> -	vsp1_dl_list_write(dl, VI6_WPF_WRBCK_CTRL, 0);
> -
>  	/* Sources. If the pipeline has a single input and BRU is not used,
>  	 * configure it as the master layer. Otherwise configure all
>  	 * inputs as sub-layers and select the virtual RPF as the master
> @@ -475,6 +482,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
>  {
>  	struct vsp1_rwpf *wpf;
>  	char name[6];
> +	int sink_pads;
>  	int ret;
>  
>  	wpf = devm_kzalloc(vsp1->dev, sizeof(*wpf), GFP_KERNEL);
> @@ -493,8 +501,13 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
>  	wpf->entity.type = VSP1_ENTITY_WPF;
>  	wpf->entity.index = index;
>  
> +	/* WPF's with Write back support can output to the LIF and Memory */
> +	wpf->has_writeback = (vsp1->info->features & VSP1_HAS_WPF_WRITEBACK)
> +			   && index == 0;
> +	sink_pads = wpf->has_writeback ? 2 : 1;
> +
>  	sprintf(name, "wpf.%u", index);
> -	ret = vsp1_entity_init(vsp1, &wpf->entity, name, 1, 1, &wpf_ops,
> +	ret = vsp1_entity_init(vsp1, &wpf->entity, name, 1, sink_pads, &wpf_ops,
>  			       MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER);
>  	if (ret < 0)
>  		return ERR_PTR(ret);
> 

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

* Re: [RFC 1/3] Revert "[media] v4l: vsp1: Supply frames to the DU continuously"
  2016-10-27 14:01 ` [RFC 1/3] Revert "[media] v4l: vsp1: Supply frames to the DU continuously" Kieran Bingham
@ 2016-11-02 23:57   ` Laurent Pinchart
  0 siblings, 0 replies; 8+ messages in thread
From: Laurent Pinchart @ 2016-11-02 23:57 UTC (permalink / raw)
  To: Kieran Bingham; +Cc: Kieran Bingham, linux-media, linux-renesas-soc

Hi Kieran,

Thank you for the patch.

On Thursday 27 Oct 2016 15:01:23 Kieran Bingham wrote:
> This reverts commit 3299ba5c0b213be5d911752d40251c1abc1004f7.
> 
> The DU output mode does not rely on frames being supplied on the WPF as
> its pipeline is supplied from DRM. For the upcoming WPF writeback
> functionality, we will choose to enable writeback mode if there is an
> output buffer, or disable it (leaving the existing display pipeline
> unharmed) otherwise.
> 
> Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

and applied to my tree.

> ---
>  drivers/media/platform/vsp1/vsp1_video.c | 11 -----------
>  1 file changed, 11 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_video.c
> b/drivers/media/platform/vsp1/vsp1_video.c index 94b428596c4f..f10401065cd3
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.c
> +++ b/drivers/media/platform/vsp1/vsp1_video.c
> @@ -296,11 +296,6 @@ static struct v4l2_rect vsp1_video_partition(struct
> vsp1_pipeline *pipe, * This function completes the current buffer by
> filling its sequence number, * time stamp and payload size, and hands it
> back to the videobuf core. *
> - * When operating in DU output mode (deep pipeline to the DU through the
> LIF), - * the VSP1 needs to constantly supply frames to the display. In
> that case, if - * no other buffer is queued, reuse the one that has just
> been processed instead - * of handing it back to the videobuf core.
> - *
>   * Return the next queued buffer or NULL if the queue is empty.
>   */
>  static struct vsp1_vb2_buffer *
> @@ -322,12 +317,6 @@ vsp1_video_complete_buffer(struct vsp1_video *video)
>  	done = list_first_entry(&video->irqqueue,
>  				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)) {
> -		spin_unlock_irqrestore(&video->irqlock, flags);
> -		return done;
> -	}
> -
>  	list_del(&done->queue);
> 
>  	if (!list_empty(&video->irqqueue))

-- 
Regards,

Laurent Pinchart


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

* Re: [RFC 2/3] v4l: vsp1: allow entities to have multiple source pads
  2016-10-27 14:01 ` [RFC 2/3] v4l: vsp1: allow entities to have multiple source pads Kieran Bingham
@ 2016-11-02 23:59   ` Laurent Pinchart
  2016-11-03 10:51     ` Kieran Bingham
  0 siblings, 1 reply; 8+ messages in thread
From: Laurent Pinchart @ 2016-11-02 23:59 UTC (permalink / raw)
  To: Kieran Bingham; +Cc: Kieran Bingham, linux-media, linux-renesas-soc

Hi Kieran,

Thank you for the patch.

On Thursday 27 Oct 2016 15:01:24 Kieran Bingham wrote:
> The upcoming writeback feature of the VSP1 WPF, allows the active output
> of the DU to be written back to memory. On Generation 3 hardware, the DU
> is fed by the LIF, which is in turn fed by the WPF.
> 
> It is the WPF which will perform memory writeback functionality, and
> this brings in a second output of the entity. Configured in this mode,
> the WPF will output to both the LIF, and to a memory (V4L2 video)
> device.
> 
> Support this feature by extending vsp1_entity_init() to specify the
> number of source and sink pads.

Do we need this, can't we just connect the single WPF source pad to both the 
LIF and WPF output (video node) entities ?

> Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> ---
>  drivers/media/platform/vsp1/vsp1_bru.c    |  2 +-
>  drivers/media/platform/vsp1/vsp1_clu.c    |  2 +-
>  drivers/media/platform/vsp1/vsp1_entity.c | 15 ++++++++-------
>  drivers/media/platform/vsp1/vsp1_entity.h |  3 ++-
>  drivers/media/platform/vsp1/vsp1_histo.c  |  2 +-
>  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, 20 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_bru.c
> b/drivers/media/platform/vsp1/vsp1_bru.c index ee8355c28f94..796bcc77eb44
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_bru.c
> +++ b/drivers/media/platform/vsp1/vsp1_bru.c
> @@ -411,7 +411,7 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device
> *vsp1) bru->entity.type = VSP1_ENTITY_BRU;
> 
>  	ret = vsp1_entity_init(vsp1, &bru->entity, "bru",
> -			       vsp1->info->num_bru_inputs + 1, &bru_ops,
> +			       vsp1->info->num_bru_inputs, 1, &bru_ops,
>  			       MEDIA_ENT_F_PROC_VIDEO_COMPOSER);
>  	if (ret < 0)
>  		return ERR_PTR(ret);
> diff --git a/drivers/media/platform/vsp1/vsp1_clu.c
> b/drivers/media/platform/vsp1/vsp1_clu.c index f2fb26e5ab4e..b38692b1f0dd
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_clu.c
> +++ b/drivers/media/platform/vsp1/vsp1_clu.c
> @@ -283,7 +283,7 @@ struct vsp1_clu *vsp1_clu_create(struct vsp1_device
> *vsp1) clu->entity.ops = &clu_entity_ops;
>  	clu->entity.type = VSP1_ENTITY_CLU;
> 
> -	ret = vsp1_entity_init(vsp1, &clu->entity, "clu", 2, &clu_ops,
> +	ret = vsp1_entity_init(vsp1, &clu->entity, "clu", 1, 1, &clu_ops,
>  			       MEDIA_ENT_F_PROC_VIDEO_LUT);
>  	if (ret < 0)
>  		return ERR_PTR(ret);
> diff --git a/drivers/media/platform/vsp1/vsp1_entity.c
> b/drivers/media/platform/vsp1/vsp1_entity.c index
> 5263387f7ec7..72c99de6e3a4 100644
> --- a/drivers/media/platform/vsp1/vsp1_entity.c
> +++ b/drivers/media/platform/vsp1/vsp1_entity.c
> @@ -472,11 +472,13 @@ static const struct vsp1_route vsp1_routes[] = {
>  };
> 
>  int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
> -		     const char *name, unsigned int num_pads,
> +		     const char *name, unsigned int num_sink_pads,
> +		     unsigned int num_source_pads,
>  		     const struct v4l2_subdev_ops *ops, u32 function)
>  {
>  	struct v4l2_subdev *subdev;
>  	unsigned int i;
> +	unsigned int num_pads = num_sink_pads + num_source_pads;
>  	int ret;
> 
>  	for (i = 0; i < ARRAY_SIZE(vsp1_routes); ++i) {
> @@ -501,18 +503,17 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct
> vsp1_entity *entity, if (entity->pads == NULL)
>  		return -ENOMEM;
> 
> -	for (i = 0; i < num_pads - 1; ++i)
> +	for (i = 0; i < num_sink_pads; ++i)
>  		entity->pads[i].flags = MEDIA_PAD_FL_SINK;
> 
> -	entity->sources = devm_kcalloc(vsp1->dev, max(num_pads - 1, 1U),
> +	for (; i < num_pads; ++i)
> +		entity->pads[i].flags = MEDIA_PAD_FL_SOURCE;
> +
> +	entity->sources = devm_kcalloc(vsp1->dev, num_source_pads,
>  				       sizeof(*entity->sources), GFP_KERNEL);
>  	if (entity->sources == NULL)
>  		return -ENOMEM;
> 
> -	/* Single-pad entities only have a sink. */
> -	entity->pads[num_pads - 1].flags = num_pads > 1 ? MEDIA_PAD_FL_SOURCE
> -					 : MEDIA_PAD_FL_SINK;
> -
>  	/* Initialize the media entity. */
>  	ret = media_entity_pads_init(&entity->subdev.entity, num_pads,
>  				     entity->pads);
> diff --git a/drivers/media/platform/vsp1/vsp1_entity.h
> b/drivers/media/platform/vsp1/vsp1_entity.h index
> c169a060b6d2..c709c29eb994 100644
> --- a/drivers/media/platform/vsp1/vsp1_entity.h
> +++ b/drivers/media/platform/vsp1/vsp1_entity.h
> @@ -120,7 +120,8 @@ static inline struct vsp1_entity *to_vsp1_entity(struct
> v4l2_subdev *subdev) }
> 
>  int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
> -		     const char *name, unsigned int num_pads,
> +		     const char *name, unsigned int num_sink_pads,
> +		     unsigned int num_source_pads,
>  		     const struct v4l2_subdev_ops *ops, u32 function);
>  void vsp1_entity_destroy(struct vsp1_entity *entity);
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_histo.c
> b/drivers/media/platform/vsp1/vsp1_histo.c index e1d0d7236907..8d809afb3b09
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_histo.c
> +++ b/drivers/media/platform/vsp1/vsp1_histo.c
> @@ -589,7 +589,7 @@ int vsp1_histogram_init(struct vsp1_device *vsp1, struct
> vsp1_histogram *histo, histo->entity.ops = ops;
>  	histo->entity.type = type;
> 
> -	ret = vsp1_entity_init(vsp1, &histo->entity, name, 2, &histo_ops,
> +	ret = vsp1_entity_init(vsp1, &histo->entity, name, 1, 1, &histo_ops,
>  			       MEDIA_ENT_F_PROC_VIDEO_STATISTICS);
>  	if (ret < 0)
>  		return ret;
> diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c
> b/drivers/media/platform/vsp1/vsp1_hsit.c index 94316afc54ff..6c54f2483248
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_hsit.c
> +++ b/drivers/media/platform/vsp1/vsp1_hsit.c
> @@ -173,7 +173,7 @@ struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device
> *vsp1, bool inverse) hsit->entity.type = VSP1_ENTITY_HST;
> 
>  	ret = vsp1_entity_init(vsp1, &hsit->entity, inverse ? "hsi" : "hst",
> -			       2, &hsit_ops,
> +			       1, 1, &hsit_ops,
>  			       MEDIA_ENT_F_PROC_VIDEO_PIXEL_ENC_CONV);
>  	if (ret < 0)
>  		return ERR_PTR(ret);
> diff --git a/drivers/media/platform/vsp1/vsp1_lif.c
> b/drivers/media/platform/vsp1/vsp1_lif.c index e32acae1fc6e..c3f87879e0bf
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_lif.c
> +++ b/drivers/media/platform/vsp1/vsp1_lif.c
> @@ -180,7 +180,7 @@ struct vsp1_lif *vsp1_lif_create(struct vsp1_device
> *vsp1) * requires a function to be set. Use PROC_VIDEO_PIXEL_FORMATTER just
> to * avoid triggering a WARN_ON(), the value won't be seen anywhere. */
> -	ret = vsp1_entity_init(vsp1, &lif->entity, "lif", 2, &lif_ops,
> +	ret = vsp1_entity_init(vsp1, &lif->entity, "lif", 1, 1, &lif_ops,
>  			       MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER);
>  	if (ret < 0)
>  		return ERR_PTR(ret);
> diff --git a/drivers/media/platform/vsp1/vsp1_lut.c
> b/drivers/media/platform/vsp1/vsp1_lut.c index c67cc60db0db..595f036f6476
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_lut.c
> +++ b/drivers/media/platform/vsp1/vsp1_lut.c
> @@ -239,7 +239,7 @@ struct vsp1_lut *vsp1_lut_create(struct vsp1_device
> *vsp1) lut->entity.ops = &lut_entity_ops;
>  	lut->entity.type = VSP1_ENTITY_LUT;
> 
> -	ret = vsp1_entity_init(vsp1, &lut->entity, "lut", 2, &lut_ops,
> +	ret = vsp1_entity_init(vsp1, &lut->entity, "lut", 1, 1, &lut_ops,
>  			       MEDIA_ENT_F_PROC_VIDEO_LUT);
>  	if (ret < 0)
>  		return ERR_PTR(ret);
> diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c
> b/drivers/media/platform/vsp1/vsp1_rpf.c index 03d71601bab6..427cbabf5c6a
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_rpf.c
> +++ b/drivers/media/platform/vsp1/vsp1_rpf.c
> @@ -274,7 +274,7 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device
> *vsp1, unsigned int index) rpf->entity.index = index;
> 
>  	sprintf(name, "rpf.%u", index);
> -	ret = vsp1_entity_init(vsp1, &rpf->entity, name, 2, &rpf_ops,
> +	ret = vsp1_entity_init(vsp1, &rpf->entity, name, 1, 1, &rpf_ops,
>  			       MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER);
>  	if (ret < 0)
>  		return ERR_PTR(ret);
> diff --git a/drivers/media/platform/vsp1/vsp1_sru.c
> b/drivers/media/platform/vsp1/vsp1_sru.c index b4e568a3b4ed..404f9d484a2a
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_sru.c
> +++ b/drivers/media/platform/vsp1/vsp1_sru.c
> @@ -345,7 +345,7 @@ struct vsp1_sru *vsp1_sru_create(struct vsp1_device
> *vsp1) sru->entity.ops = &sru_entity_ops;
>  	sru->entity.type = VSP1_ENTITY_SRU;
> 
> -	ret = vsp1_entity_init(vsp1, &sru->entity, "sru", 2, &sru_ops,
> +	ret = vsp1_entity_init(vsp1, &sru->entity, "sru", 1, 1, &sru_ops,
>  			       MEDIA_ENT_F_PROC_VIDEO_SCALER);
>  	if (ret < 0)
>  		return ERR_PTR(ret);
> diff --git a/drivers/media/platform/vsp1/vsp1_uds.c
> b/drivers/media/platform/vsp1/vsp1_uds.c index da8f89a31ea4..777d68dfe1f8
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_uds.c
> +++ b/drivers/media/platform/vsp1/vsp1_uds.c
> @@ -366,7 +366,7 @@ struct vsp1_uds *vsp1_uds_create(struct vsp1_device
> *vsp1, unsigned int index) uds->entity.index = index;
> 
>  	sprintf(name, "uds.%u", index);
> -	ret = vsp1_entity_init(vsp1, &uds->entity, name, 2, &uds_ops,
> +	ret = vsp1_entity_init(vsp1, &uds->entity, name, 1, 1, &uds_ops,
>  			       MEDIA_ENT_F_PROC_VIDEO_SCALER);
>  	if (ret < 0)
>  		return ERR_PTR(ret);
> diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c
> b/drivers/media/platform/vsp1/vsp1_wpf.c index 958e7f215a2b..b5f44d6839c6
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_wpf.c
> +++ b/drivers/media/platform/vsp1/vsp1_wpf.c
> @@ -494,7 +494,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device
> *vsp1, unsigned int index) wpf->entity.index = index;
> 
>  	sprintf(name, "wpf.%u", index);
> -	ret = vsp1_entity_init(vsp1, &wpf->entity, name, 2, &wpf_ops,
> +	ret = vsp1_entity_init(vsp1, &wpf->entity, name, 1, 1, &wpf_ops,
>  			       MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER);
>  	if (ret < 0)
>  		return ERR_PTR(ret);

-- 
Regards,

Laurent Pinchart


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

* Re: [RFC 2/3] v4l: vsp1: allow entities to have multiple source pads
  2016-11-02 23:59   ` Laurent Pinchart
@ 2016-11-03 10:51     ` Kieran Bingham
  0 siblings, 0 replies; 8+ messages in thread
From: Kieran Bingham @ 2016-11-03 10:51 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-media, linux-renesas-soc

Hi Laurent,

On 02/11/16 23:59, Laurent Pinchart wrote:
> Hi Kieran,
> 
> Thank you for the patch.
> 
> On Thursday 27 Oct 2016 15:01:24 Kieran Bingham wrote:
>> The upcoming writeback feature of the VSP1 WPF, allows the active output
>> of the DU to be written back to memory. On Generation 3 hardware, the DU
>> is fed by the LIF, which is in turn fed by the WPF.
>>
>> It is the WPF which will perform memory writeback functionality, and
>> this brings in a second output of the entity. Configured in this mode,
>> the WPF will output to both the LIF, and to a memory (V4L2 video)
>> device.
>>
>> Support this feature by extending vsp1_entity_init() to specify the
>> number of source and sink pads.
> 
> Do we need this, can't we just connect the single WPF source pad to both the 
> LIF and WPF output (video node) entities ?

Yes, we can.

Looks like I was over-engineering this - for not any particular/good
reason - so I've dropped this patch and reworked the writeback to
connect to the existing source pad.

--
Regards

Kieran

> 
>> Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
>> ---
>>  drivers/media/platform/vsp1/vsp1_bru.c    |  2 +-
>>  drivers/media/platform/vsp1/vsp1_clu.c    |  2 +-
>>  drivers/media/platform/vsp1/vsp1_entity.c | 15 ++++++++-------
>>  drivers/media/platform/vsp1/vsp1_entity.h |  3 ++-
>>  drivers/media/platform/vsp1/vsp1_histo.c  |  2 +-
>>  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, 20 insertions(+), 18 deletions(-)
>>
>> diff --git a/drivers/media/platform/vsp1/vsp1_bru.c
>> b/drivers/media/platform/vsp1/vsp1_bru.c index ee8355c28f94..796bcc77eb44
>> 100644
>> --- a/drivers/media/platform/vsp1/vsp1_bru.c
>> +++ b/drivers/media/platform/vsp1/vsp1_bru.c
>> @@ -411,7 +411,7 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device
>> *vsp1) bru->entity.type = VSP1_ENTITY_BRU;
>>
>>  	ret = vsp1_entity_init(vsp1, &bru->entity, "bru",
>> -			       vsp1->info->num_bru_inputs + 1, &bru_ops,
>> +			       vsp1->info->num_bru_inputs, 1, &bru_ops,
>>  			       MEDIA_ENT_F_PROC_VIDEO_COMPOSER);
>>  	if (ret < 0)
>>  		return ERR_PTR(ret);
>> diff --git a/drivers/media/platform/vsp1/vsp1_clu.c
>> b/drivers/media/platform/vsp1/vsp1_clu.c index f2fb26e5ab4e..b38692b1f0dd
>> 100644
>> --- a/drivers/media/platform/vsp1/vsp1_clu.c
>> +++ b/drivers/media/platform/vsp1/vsp1_clu.c
>> @@ -283,7 +283,7 @@ struct vsp1_clu *vsp1_clu_create(struct vsp1_device
>> *vsp1) clu->entity.ops = &clu_entity_ops;
>>  	clu->entity.type = VSP1_ENTITY_CLU;
>>
>> -	ret = vsp1_entity_init(vsp1, &clu->entity, "clu", 2, &clu_ops,
>> +	ret = vsp1_entity_init(vsp1, &clu->entity, "clu", 1, 1, &clu_ops,
>>  			       MEDIA_ENT_F_PROC_VIDEO_LUT);
>>  	if (ret < 0)
>>  		return ERR_PTR(ret);
>> diff --git a/drivers/media/platform/vsp1/vsp1_entity.c
>> b/drivers/media/platform/vsp1/vsp1_entity.c index
>> 5263387f7ec7..72c99de6e3a4 100644
>> --- a/drivers/media/platform/vsp1/vsp1_entity.c
>> +++ b/drivers/media/platform/vsp1/vsp1_entity.c
>> @@ -472,11 +472,13 @@ static const struct vsp1_route vsp1_routes[] = {
>>  };
>>
>>  int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
>> -		     const char *name, unsigned int num_pads,
>> +		     const char *name, unsigned int num_sink_pads,
>> +		     unsigned int num_source_pads,
>>  		     const struct v4l2_subdev_ops *ops, u32 function)
>>  {
>>  	struct v4l2_subdev *subdev;
>>  	unsigned int i;
>> +	unsigned int num_pads = num_sink_pads + num_source_pads;
>>  	int ret;
>>
>>  	for (i = 0; i < ARRAY_SIZE(vsp1_routes); ++i) {
>> @@ -501,18 +503,17 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct
>> vsp1_entity *entity, if (entity->pads == NULL)
>>  		return -ENOMEM;
>>
>> -	for (i = 0; i < num_pads - 1; ++i)
>> +	for (i = 0; i < num_sink_pads; ++i)
>>  		entity->pads[i].flags = MEDIA_PAD_FL_SINK;
>>
>> -	entity->sources = devm_kcalloc(vsp1->dev, max(num_pads - 1, 1U),
>> +	for (; i < num_pads; ++i)
>> +		entity->pads[i].flags = MEDIA_PAD_FL_SOURCE;
>> +
>> +	entity->sources = devm_kcalloc(vsp1->dev, num_source_pads,
>>  				       sizeof(*entity->sources), GFP_KERNEL);
>>  	if (entity->sources == NULL)
>>  		return -ENOMEM;
>>
>> -	/* Single-pad entities only have a sink. */
>> -	entity->pads[num_pads - 1].flags = num_pads > 1 ? MEDIA_PAD_FL_SOURCE
>> -					 : MEDIA_PAD_FL_SINK;
>> -
>>  	/* Initialize the media entity. */
>>  	ret = media_entity_pads_init(&entity->subdev.entity, num_pads,
>>  				     entity->pads);
>> diff --git a/drivers/media/platform/vsp1/vsp1_entity.h
>> b/drivers/media/platform/vsp1/vsp1_entity.h index
>> c169a060b6d2..c709c29eb994 100644
>> --- a/drivers/media/platform/vsp1/vsp1_entity.h
>> +++ b/drivers/media/platform/vsp1/vsp1_entity.h
>> @@ -120,7 +120,8 @@ static inline struct vsp1_entity *to_vsp1_entity(struct
>> v4l2_subdev *subdev) }
>>
>>  int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
>> -		     const char *name, unsigned int num_pads,
>> +		     const char *name, unsigned int num_sink_pads,
>> +		     unsigned int num_source_pads,
>>  		     const struct v4l2_subdev_ops *ops, u32 function);
>>  void vsp1_entity_destroy(struct vsp1_entity *entity);
>>
>> diff --git a/drivers/media/platform/vsp1/vsp1_histo.c
>> b/drivers/media/platform/vsp1/vsp1_histo.c index e1d0d7236907..8d809afb3b09
>> 100644
>> --- a/drivers/media/platform/vsp1/vsp1_histo.c
>> +++ b/drivers/media/platform/vsp1/vsp1_histo.c
>> @@ -589,7 +589,7 @@ int vsp1_histogram_init(struct vsp1_device *vsp1, struct
>> vsp1_histogram *histo, histo->entity.ops = ops;
>>  	histo->entity.type = type;
>>
>> -	ret = vsp1_entity_init(vsp1, &histo->entity, name, 2, &histo_ops,
>> +	ret = vsp1_entity_init(vsp1, &histo->entity, name, 1, 1, &histo_ops,
>>  			       MEDIA_ENT_F_PROC_VIDEO_STATISTICS);
>>  	if (ret < 0)
>>  		return ret;
>> diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c
>> b/drivers/media/platform/vsp1/vsp1_hsit.c index 94316afc54ff..6c54f2483248
>> 100644
>> --- a/drivers/media/platform/vsp1/vsp1_hsit.c
>> +++ b/drivers/media/platform/vsp1/vsp1_hsit.c
>> @@ -173,7 +173,7 @@ struct vsp1_hsit *vsp1_hsit_create(struct vsp1_device
>> *vsp1, bool inverse) hsit->entity.type = VSP1_ENTITY_HST;
>>
>>  	ret = vsp1_entity_init(vsp1, &hsit->entity, inverse ? "hsi" : "hst",
>> -			       2, &hsit_ops,
>> +			       1, 1, &hsit_ops,
>>  			       MEDIA_ENT_F_PROC_VIDEO_PIXEL_ENC_CONV);
>>  	if (ret < 0)
>>  		return ERR_PTR(ret);
>> diff --git a/drivers/media/platform/vsp1/vsp1_lif.c
>> b/drivers/media/platform/vsp1/vsp1_lif.c index e32acae1fc6e..c3f87879e0bf
>> 100644
>> --- a/drivers/media/platform/vsp1/vsp1_lif.c
>> +++ b/drivers/media/platform/vsp1/vsp1_lif.c
>> @@ -180,7 +180,7 @@ struct vsp1_lif *vsp1_lif_create(struct vsp1_device
>> *vsp1) * requires a function to be set. Use PROC_VIDEO_PIXEL_FORMATTER just
>> to * avoid triggering a WARN_ON(), the value won't be seen anywhere. */
>> -	ret = vsp1_entity_init(vsp1, &lif->entity, "lif", 2, &lif_ops,
>> +	ret = vsp1_entity_init(vsp1, &lif->entity, "lif", 1, 1, &lif_ops,
>>  			       MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER);
>>  	if (ret < 0)
>>  		return ERR_PTR(ret);
>> diff --git a/drivers/media/platform/vsp1/vsp1_lut.c
>> b/drivers/media/platform/vsp1/vsp1_lut.c index c67cc60db0db..595f036f6476
>> 100644
>> --- a/drivers/media/platform/vsp1/vsp1_lut.c
>> +++ b/drivers/media/platform/vsp1/vsp1_lut.c
>> @@ -239,7 +239,7 @@ struct vsp1_lut *vsp1_lut_create(struct vsp1_device
>> *vsp1) lut->entity.ops = &lut_entity_ops;
>>  	lut->entity.type = VSP1_ENTITY_LUT;
>>
>> -	ret = vsp1_entity_init(vsp1, &lut->entity, "lut", 2, &lut_ops,
>> +	ret = vsp1_entity_init(vsp1, &lut->entity, "lut", 1, 1, &lut_ops,
>>  			       MEDIA_ENT_F_PROC_VIDEO_LUT);
>>  	if (ret < 0)
>>  		return ERR_PTR(ret);
>> diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c
>> b/drivers/media/platform/vsp1/vsp1_rpf.c index 03d71601bab6..427cbabf5c6a
>> 100644
>> --- a/drivers/media/platform/vsp1/vsp1_rpf.c
>> +++ b/drivers/media/platform/vsp1/vsp1_rpf.c
>> @@ -274,7 +274,7 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device
>> *vsp1, unsigned int index) rpf->entity.index = index;
>>
>>  	sprintf(name, "rpf.%u", index);
>> -	ret = vsp1_entity_init(vsp1, &rpf->entity, name, 2, &rpf_ops,
>> +	ret = vsp1_entity_init(vsp1, &rpf->entity, name, 1, 1, &rpf_ops,
>>  			       MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER);
>>  	if (ret < 0)
>>  		return ERR_PTR(ret);
>> diff --git a/drivers/media/platform/vsp1/vsp1_sru.c
>> b/drivers/media/platform/vsp1/vsp1_sru.c index b4e568a3b4ed..404f9d484a2a
>> 100644
>> --- a/drivers/media/platform/vsp1/vsp1_sru.c
>> +++ b/drivers/media/platform/vsp1/vsp1_sru.c
>> @@ -345,7 +345,7 @@ struct vsp1_sru *vsp1_sru_create(struct vsp1_device
>> *vsp1) sru->entity.ops = &sru_entity_ops;
>>  	sru->entity.type = VSP1_ENTITY_SRU;
>>
>> -	ret = vsp1_entity_init(vsp1, &sru->entity, "sru", 2, &sru_ops,
>> +	ret = vsp1_entity_init(vsp1, &sru->entity, "sru", 1, 1, &sru_ops,
>>  			       MEDIA_ENT_F_PROC_VIDEO_SCALER);
>>  	if (ret < 0)
>>  		return ERR_PTR(ret);
>> diff --git a/drivers/media/platform/vsp1/vsp1_uds.c
>> b/drivers/media/platform/vsp1/vsp1_uds.c index da8f89a31ea4..777d68dfe1f8
>> 100644
>> --- a/drivers/media/platform/vsp1/vsp1_uds.c
>> +++ b/drivers/media/platform/vsp1/vsp1_uds.c
>> @@ -366,7 +366,7 @@ struct vsp1_uds *vsp1_uds_create(struct vsp1_device
>> *vsp1, unsigned int index) uds->entity.index = index;
>>
>>  	sprintf(name, "uds.%u", index);
>> -	ret = vsp1_entity_init(vsp1, &uds->entity, name, 2, &uds_ops,
>> +	ret = vsp1_entity_init(vsp1, &uds->entity, name, 1, 1, &uds_ops,
>>  			       MEDIA_ENT_F_PROC_VIDEO_SCALER);
>>  	if (ret < 0)
>>  		return ERR_PTR(ret);
>> diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c
>> b/drivers/media/platform/vsp1/vsp1_wpf.c index 958e7f215a2b..b5f44d6839c6
>> 100644
>> --- a/drivers/media/platform/vsp1/vsp1_wpf.c
>> +++ b/drivers/media/platform/vsp1/vsp1_wpf.c
>> @@ -494,7 +494,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device
>> *vsp1, unsigned int index) wpf->entity.index = index;
>>
>>  	sprintf(name, "wpf.%u", index);
>> -	ret = vsp1_entity_init(vsp1, &wpf->entity, name, 2, &wpf_ops,
>> +	ret = vsp1_entity_init(vsp1, &wpf->entity, name, 1, 1, &wpf_ops,
>>  			       MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER);
>>  	if (ret < 0)
>>  		return ERR_PTR(ret);
> 

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

end of thread, other threads:[~2016-11-03 10:51 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-27 14:01 [RFC 0/3] vsp1 writeback prototype Kieran Bingham
2016-10-27 14:01 ` [RFC 1/3] Revert "[media] v4l: vsp1: Supply frames to the DU continuously" Kieran Bingham
2016-11-02 23:57   ` Laurent Pinchart
2016-10-27 14:01 ` [RFC 2/3] v4l: vsp1: allow entities to have multiple source pads Kieran Bingham
2016-11-02 23:59   ` Laurent Pinchart
2016-11-03 10:51     ` Kieran Bingham
2016-10-27 14:01 ` [RFC 3/3] v4l: vsp1: Provide a writeback video device Kieran Bingham
2016-11-01 12:19   ` Kieran Bingham

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).