All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/15] R-Car VSP1: Dynamically assign blend units to display pipelines
@ 2018-02-26 21:45 ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: dri-devel, linux-renesas-soc, Kieran Bingham

Hello,

On R-Car H3 ES2.0+ and M3-N SoCs, two display pipelines are served by the same
VSP instance (named VSPDL). The VSPDL includes two blending units named BRU
and BRS, unlike the other display-related VSPD that serves a single display
channel with a single blending unit.

The VSPDL has five inputs and can freely assign them at runtime to two display
pipelines, using the BRU and BRS to blend multiple inputs. The BRU supports
blending up to five inputs, while the BRS is limited to two inputs.

Each display pipeline requires a blending unit, and the BRU and BRS are
currently assigned statically to the first and second pipeline respectively.
This artificially limits the number of inputs for the second pipeline to two.
To overcome that limitation, the BRU and BRS need to be dynamically assigned
to the display pipelines, which is what this patch series does.

Patches 01/15 to 10/15 perform small cleanups and refactoring to prepare for
the rest of the series. Patches 11/15 and 12/15 implement new internal
features for the same purpose, and patch 13/15 performs the bulk of the work
by implementing dynamic BRU and BRS assignment to pipelines.

Reassigning the BRU and BRS when two pipelines are running results in flicker
as one pipeline has to first release its blending unit. Synchronization
between the two pipelines also require locking that effectively serializes
page flips for the two pipelines, even when not interacting with each other.
This is currently believed to be unavoidable due to the hardware design, but
please feel free to prove me wrong (ideally with a patch - one can always
dream).

Patch 14/15 then adds messages useful for debugging this new feature. I have
kept it separate from 13/15 to make it easier to remove those messages once
dynamic assignment of blending units will be deemed perfectly stable, but I
won't oppose squashing it with 13/15 if that is preferred.

Patch 15/15 finally rename BRU to BRx to avoid confusion between the BRU terms
that refer to the BRU in particular, and the ones that refer to any of the BRU
or BRS. As this might be a bit controversial I've put the patch last in the
series in case it needs to be dropped.

I have decided to CC the dri-devel mailing list even though the code doesn't
touch the R-Car DU driver and will be merged through the Linux media tree as
the display is involved and the series could benefit from the expertise of the
DRM/KMS community from that point of view.

The patches are based on top of the latest Linux media master branch. For
convenience their are available from

	git://linuxtv.org/pinchartl/media.git v4l2/vsp1/bru-brs

The series passes the DU test suite with the new BRx dynamic assignment
test available from

	git://git.ideasonboard.com/renesas/kms-tests.git bru-brs

The VSP test suite also runs without any noticed regression.

Laurent Pinchart (15):
  v4l: vsp1: Don't start/stop media pipeline for DRM
  v4l: vsp1: Remove outdated comment
  v4l: vsp1: Remove unused field from vsp1_drm_pipeline structure
  v4l: vsp1: Store pipeline pointer in vsp1_entity
  v4l: vsp1: Use vsp1_entity.pipe to check if entity belongs to a
    pipeline
  v4l: vsp1: Share duplicated DRM pipeline configuration code
  v4l: vsp1: Move DRM atomic commit pipeline setup to separate function
  v4l: vsp1: Setup BRU at atomic commit time
  v4l: vsp1: Replace manual DRM pipeline input setup in
    vsp1_du_setup_lif
  v4l: vsp1: Move DRM pipeline output setup code to a function
  v4l: vsp1: Add per-display list completion notification support
  v4l: vsp1: Generalize detection of entity removal from DRM pipeline
  v4l: vsp1: Assign BRU and BRS to pipelines dynamically
  v4l: vsp1: Add BRx dynamic assignment debugging messages
  v4l: vsp1: Rename BRU to BRx

 drivers/media/platform/vsp1/Makefile               |   2 +-
 drivers/media/platform/vsp1/vsp1.h                 |   6 +-
 .../media/platform/vsp1/{vsp1_bru.c => vsp1_brx.c} | 202 ++---
 .../media/platform/vsp1/{vsp1_bru.h => vsp1_brx.h} |  18 +-
 drivers/media/platform/vsp1/vsp1_dl.c              |  27 +-
 drivers/media/platform/vsp1/vsp1_dl.h              |   4 +-
 drivers/media/platform/vsp1/vsp1_drm.c             | 829 ++++++++++++---------
 drivers/media/platform/vsp1/vsp1_drm.h             |  16 +-
 drivers/media/platform/vsp1/vsp1_drv.c             |   8 +-
 drivers/media/platform/vsp1/vsp1_entity.h          |   2 +
 drivers/media/platform/vsp1/vsp1_histo.c           |   2 +-
 drivers/media/platform/vsp1/vsp1_histo.h           |   3 -
 drivers/media/platform/vsp1/vsp1_pipe.c            |  50 +-
 drivers/media/platform/vsp1/vsp1_pipe.h            |   7 +-
 drivers/media/platform/vsp1/vsp1_rpf.c             |  12 +-
 drivers/media/platform/vsp1/vsp1_rwpf.h            |   4 +-
 drivers/media/platform/vsp1/vsp1_video.c           |  37 +-
 drivers/media/platform/vsp1/vsp1_wpf.c             |   8 +-
 18 files changed, 705 insertions(+), 532 deletions(-)
 rename drivers/media/platform/vsp1/{vsp1_bru.c => vsp1_brx.c} (63%)
 rename drivers/media/platform/vsp1/{vsp1_bru.h => vsp1_brx.h} (66%)

-- 
Regards,

Laurent Pinchart

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

* [PATCH 00/15] R-Car VSP1: Dynamically assign blend units to display pipelines
@ 2018-02-26 21:45 ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: linux-renesas-soc, Kieran Bingham, dri-devel

Hello,

On R-Car H3 ES2.0+ and M3-N SoCs, two display pipelines are served by the same
VSP instance (named VSPDL). The VSPDL includes two blending units named BRU
and BRS, unlike the other display-related VSPD that serves a single display
channel with a single blending unit.

The VSPDL has five inputs and can freely assign them at runtime to two display
pipelines, using the BRU and BRS to blend multiple inputs. The BRU supports
blending up to five inputs, while the BRS is limited to two inputs.

Each display pipeline requires a blending unit, and the BRU and BRS are
currently assigned statically to the first and second pipeline respectively.
This artificially limits the number of inputs for the second pipeline to two.
To overcome that limitation, the BRU and BRS need to be dynamically assigned
to the display pipelines, which is what this patch series does.

Patches 01/15 to 10/15 perform small cleanups and refactoring to prepare for
the rest of the series. Patches 11/15 and 12/15 implement new internal
features for the same purpose, and patch 13/15 performs the bulk of the work
by implementing dynamic BRU and BRS assignment to pipelines.

Reassigning the BRU and BRS when two pipelines are running results in flicker
as one pipeline has to first release its blending unit. Synchronization
between the two pipelines also require locking that effectively serializes
page flips for the two pipelines, even when not interacting with each other.
This is currently believed to be unavoidable due to the hardware design, but
please feel free to prove me wrong (ideally with a patch - one can always
dream).

Patch 14/15 then adds messages useful for debugging this new feature. I have
kept it separate from 13/15 to make it easier to remove those messages once
dynamic assignment of blending units will be deemed perfectly stable, but I
won't oppose squashing it with 13/15 if that is preferred.

Patch 15/15 finally rename BRU to BRx to avoid confusion between the BRU terms
that refer to the BRU in particular, and the ones that refer to any of the BRU
or BRS. As this might be a bit controversial I've put the patch last in the
series in case it needs to be dropped.

I have decided to CC the dri-devel mailing list even though the code doesn't
touch the R-Car DU driver and will be merged through the Linux media tree as
the display is involved and the series could benefit from the expertise of the
DRM/KMS community from that point of view.

The patches are based on top of the latest Linux media master branch. For
convenience their are available from

	git://linuxtv.org/pinchartl/media.git v4l2/vsp1/bru-brs

The series passes the DU test suite with the new BRx dynamic assignment
test available from

	git://git.ideasonboard.com/renesas/kms-tests.git bru-brs

The VSP test suite also runs without any noticed regression.

Laurent Pinchart (15):
  v4l: vsp1: Don't start/stop media pipeline for DRM
  v4l: vsp1: Remove outdated comment
  v4l: vsp1: Remove unused field from vsp1_drm_pipeline structure
  v4l: vsp1: Store pipeline pointer in vsp1_entity
  v4l: vsp1: Use vsp1_entity.pipe to check if entity belongs to a
    pipeline
  v4l: vsp1: Share duplicated DRM pipeline configuration code
  v4l: vsp1: Move DRM atomic commit pipeline setup to separate function
  v4l: vsp1: Setup BRU at atomic commit time
  v4l: vsp1: Replace manual DRM pipeline input setup in
    vsp1_du_setup_lif
  v4l: vsp1: Move DRM pipeline output setup code to a function
  v4l: vsp1: Add per-display list completion notification support
  v4l: vsp1: Generalize detection of entity removal from DRM pipeline
  v4l: vsp1: Assign BRU and BRS to pipelines dynamically
  v4l: vsp1: Add BRx dynamic assignment debugging messages
  v4l: vsp1: Rename BRU to BRx

 drivers/media/platform/vsp1/Makefile               |   2 +-
 drivers/media/platform/vsp1/vsp1.h                 |   6 +-
 .../media/platform/vsp1/{vsp1_bru.c => vsp1_brx.c} | 202 ++---
 .../media/platform/vsp1/{vsp1_bru.h => vsp1_brx.h} |  18 +-
 drivers/media/platform/vsp1/vsp1_dl.c              |  27 +-
 drivers/media/platform/vsp1/vsp1_dl.h              |   4 +-
 drivers/media/platform/vsp1/vsp1_drm.c             | 829 ++++++++++++---------
 drivers/media/platform/vsp1/vsp1_drm.h             |  16 +-
 drivers/media/platform/vsp1/vsp1_drv.c             |   8 +-
 drivers/media/platform/vsp1/vsp1_entity.h          |   2 +
 drivers/media/platform/vsp1/vsp1_histo.c           |   2 +-
 drivers/media/platform/vsp1/vsp1_histo.h           |   3 -
 drivers/media/platform/vsp1/vsp1_pipe.c            |  50 +-
 drivers/media/platform/vsp1/vsp1_pipe.h            |   7 +-
 drivers/media/platform/vsp1/vsp1_rpf.c             |  12 +-
 drivers/media/platform/vsp1/vsp1_rwpf.h            |   4 +-
 drivers/media/platform/vsp1/vsp1_video.c           |  37 +-
 drivers/media/platform/vsp1/vsp1_wpf.c             |   8 +-
 18 files changed, 705 insertions(+), 532 deletions(-)
 rename drivers/media/platform/vsp1/{vsp1_bru.c => vsp1_brx.c} (63%)
 rename drivers/media/platform/vsp1/{vsp1_bru.h => vsp1_brx.h} (66%)

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 01/15] v4l: vsp1: Don't start/stop media pipeline for DRM
  2018-02-26 21:45 ` Laurent Pinchart
@ 2018-02-26 21:45   ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: dri-devel, linux-renesas-soc, Kieran Bingham

The DRM support code manages a pipeline of VSP entities, each backed by
a media entity. When starting or stopping the pipeline, it starts and
stops the media pipeline through the media API in order to store the
pipeline pointer in every entity.

The driver doesn't use the pipe pointer in media entities, neither does
it rely on the other effects of the media_pipeline_start() and
media_pipeline_stop() functions. Furthermore, as the media links for the
DRM pipeline are never set up correctly, and as the pipeline can be
modified dynamically when enabling or disabling planes, the current
implementation is not correct. Remove the incorrect and unneeded code.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index b8fee1834253..e31fb371eaf9 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -109,8 +109,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 		if (ret == -ETIMEDOUT)
 			dev_err(vsp1->dev, "DRM pipeline stop timeout\n");
 
-		media_pipeline_stop(&pipe->output->entity.subdev.entity);
-
 		for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i) {
 			struct vsp1_rwpf *rpf = pipe->inputs[i];
 
@@ -224,11 +222,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	}
 
 	/*
-	 * 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.
+	 * Enable the VSP1. 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)
@@ -241,14 +237,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	drm_pipe->du_complete = cfg->callback;
 	drm_pipe->du_private = cfg->callback_data;
 
-	ret = media_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;
-	}
-
 	/* Disable the display interrupts. */
 	vsp1_write(vsp1, VI6_DISP_IRQ_STA, 0);
 	vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0);
-- 
Regards,

Laurent Pinchart

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

* [PATCH 01/15] v4l: vsp1: Don't start/stop media pipeline for DRM
@ 2018-02-26 21:45   ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: linux-renesas-soc, Kieran Bingham, dri-devel

The DRM support code manages a pipeline of VSP entities, each backed by
a media entity. When starting or stopping the pipeline, it starts and
stops the media pipeline through the media API in order to store the
pipeline pointer in every entity.

The driver doesn't use the pipe pointer in media entities, neither does
it rely on the other effects of the media_pipeline_start() and
media_pipeline_stop() functions. Furthermore, as the media links for the
DRM pipeline are never set up correctly, and as the pipeline can be
modified dynamically when enabling or disabling planes, the current
implementation is not correct. Remove the incorrect and unneeded code.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index b8fee1834253..e31fb371eaf9 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -109,8 +109,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 		if (ret == -ETIMEDOUT)
 			dev_err(vsp1->dev, "DRM pipeline stop timeout\n");
 
-		media_pipeline_stop(&pipe->output->entity.subdev.entity);
-
 		for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i) {
 			struct vsp1_rwpf *rpf = pipe->inputs[i];
 
@@ -224,11 +222,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	}
 
 	/*
-	 * 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.
+	 * Enable the VSP1. 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)
@@ -241,14 +237,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	drm_pipe->du_complete = cfg->callback;
 	drm_pipe->du_private = cfg->callback_data;
 
-	ret = media_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;
-	}
-
 	/* Disable the display interrupts. */
 	vsp1_write(vsp1, VI6_DISP_IRQ_STA, 0);
 	vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0);
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 02/15] v4l: vsp1: Remove outdated comment
  2018-02-26 21:45 ` Laurent Pinchart
@ 2018-02-26 21:45   ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: dri-devel, linux-renesas-soc, Kieran Bingham

The entities in the pipeline are all started when the LIF is setup.
Remove the outdated comment that state otherwise.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index e31fb371eaf9..a1f2ba044092 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -221,11 +221,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 		return -EPIPE;
 	}
 
-	/*
-	 * Enable the VSP1. 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.
-	 */
+	/* Enable the VSP1. */
 	ret = vsp1_device_get(vsp1);
 	if (ret < 0)
 		return ret;
-- 
Regards,

Laurent Pinchart

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

* [PATCH 02/15] v4l: vsp1: Remove outdated comment
@ 2018-02-26 21:45   ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: linux-renesas-soc, Kieran Bingham, dri-devel

The entities in the pipeline are all started when the LIF is setup.
Remove the outdated comment that state otherwise.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index e31fb371eaf9..a1f2ba044092 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -221,11 +221,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 		return -EPIPE;
 	}
 
-	/*
-	 * Enable the VSP1. 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.
-	 */
+	/* Enable the VSP1. */
 	ret = vsp1_device_get(vsp1);
 	if (ret < 0)
 		return ret;
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 03/15] v4l: vsp1: Remove unused field from vsp1_drm_pipeline structure
  2018-02-26 21:45 ` Laurent Pinchart
@ 2018-02-26 21:45   ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: dri-devel, linux-renesas-soc, Kieran Bingham

The vsp1_drm_pipeline enabled field is set but never used. Remove it.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index a1f2ba044092..a267f12f0cc8 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -273,10 +273,6 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
  */
 void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index)
 {
-	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
-	struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index];
-
-	drm_pipe->enabled = drm_pipe->pipe.num_inputs != 0;
 }
 EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
 
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
index 1cd9db785bf7..9aa19325cbe9 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.h
+++ b/drivers/media/platform/vsp1/vsp1_drm.h
@@ -20,13 +20,11 @@
 /**
  * vsp1_drm_pipeline - State for the API exposed to the DRM driver
  * @pipe: the VSP1 pipeline used for display
- * @enabled: pipeline state at the beginning of an update
  * @du_complete: frame completion callback for the DU driver (optional)
  * @du_private: data to be passed to the du_complete callback
  */
 struct vsp1_drm_pipeline {
 	struct vsp1_pipeline pipe;
-	bool enabled;
 
 	/* Frame synchronisation */
 	void (*du_complete)(void *, bool);
-- 
Regards,

Laurent Pinchart

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

* [PATCH 03/15] v4l: vsp1: Remove unused field from vsp1_drm_pipeline structure
@ 2018-02-26 21:45   ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: linux-renesas-soc, Kieran Bingham, dri-devel

The vsp1_drm_pipeline enabled field is set but never used. Remove it.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index a1f2ba044092..a267f12f0cc8 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -273,10 +273,6 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
  */
 void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index)
 {
-	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
-	struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index];
-
-	drm_pipe->enabled = drm_pipe->pipe.num_inputs != 0;
 }
 EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
 
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
index 1cd9db785bf7..9aa19325cbe9 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.h
+++ b/drivers/media/platform/vsp1/vsp1_drm.h
@@ -20,13 +20,11 @@
 /**
  * vsp1_drm_pipeline - State for the API exposed to the DRM driver
  * @pipe: the VSP1 pipeline used for display
- * @enabled: pipeline state at the beginning of an update
  * @du_complete: frame completion callback for the DU driver (optional)
  * @du_private: data to be passed to the du_complete callback
  */
 struct vsp1_drm_pipeline {
 	struct vsp1_pipeline pipe;
-	bool enabled;
 
 	/* Frame synchronisation */
 	void (*du_complete)(void *, bool);
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 04/15] v4l: vsp1: Store pipeline pointer in vsp1_entity
  2018-02-26 21:45 ` Laurent Pinchart
@ 2018-02-26 21:45   ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: dri-devel, linux-renesas-soc, Kieran Bingham

Various types of objects subclassing vsp1_entity currently store a
pointer to the pipeline. Move the pointer to vsp1_entity to simplify the
code and avoid storing the pipeline in more entity subclasses later.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_drm.c    | 20 +++++++++++++------
 drivers/media/platform/vsp1/vsp1_drv.c    |  2 +-
 drivers/media/platform/vsp1/vsp1_entity.h |  2 ++
 drivers/media/platform/vsp1/vsp1_histo.c  |  2 +-
 drivers/media/platform/vsp1/vsp1_histo.h  |  3 ---
 drivers/media/platform/vsp1/vsp1_pipe.c   | 33 +++++++++----------------------
 drivers/media/platform/vsp1/vsp1_rwpf.h   |  2 --
 drivers/media/platform/vsp1/vsp1_video.c  | 17 +++++++---------
 8 files changed, 34 insertions(+), 47 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index a267f12f0cc8..a7ad85ab0b08 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -120,6 +120,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 			 * inputs.
 			 */
 			WARN_ON(list_empty(&rpf->entity.list_pipe));
+			rpf->entity.pipe = NULL;
 			list_del_init(&rpf->entity.list_pipe);
 			pipe->inputs[i] = NULL;
 
@@ -536,8 +537,10 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 			continue;
 		}
 
-		if (list_empty(&rpf->entity.list_pipe))
+		if (list_empty(&rpf->entity.list_pipe)) {
+			rpf->entity.pipe = pipe;
 			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
+		}
 
 		bru->inputs[i].rpf = rpf;
 		rpf->bru_input = i;
@@ -562,6 +565,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 			vsp1_dl_list_write(dl, entity->route->reg,
 					   VI6_DPR_NODE_UNUSED);
 
+			entity->pipe = NULL;
 			list_del_init(&entity->list_pipe);
 
 			continue;
@@ -625,24 +629,28 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
 
 		vsp1_pipeline_init(pipe);
 
+		pipe->frame_end = vsp1_du_pipeline_frame_end;
+
 		/*
 		 * The DRM pipeline is static, add entities manually. The first
 		 * pipeline uses the BRU and the second pipeline the BRS.
 		 */
 		pipe->bru = i == 0 ? &vsp1->bru->entity : &vsp1->brs->entity;
-		pipe->lif = &vsp1->lif[i]->entity;
 		pipe->output = vsp1->wpf[i];
-		pipe->output->pipe = pipe;
-		pipe->frame_end = vsp1_du_pipeline_frame_end;
+		pipe->lif = &vsp1->lif[i]->entity;
 
+		pipe->bru->pipe = pipe;
 		pipe->bru->sink = &pipe->output->entity;
 		pipe->bru->sink_pad = 0;
+		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
+
+		pipe->output->entity.pipe = pipe;
 		pipe->output->entity.sink = pipe->lif;
 		pipe->output->entity.sink_pad = 0;
+		list_add_tail(&pipe->output->entity.list_pipe, &pipe->entities);
 
-		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
+		pipe->lif->pipe = pipe;
 		list_add_tail(&pipe->lif->list_pipe, &pipe->entities);
-		list_add_tail(&pipe->output->entity.list_pipe, &pipe->entities);
 	}
 
 	/* Disable all RPFs initially. */
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index eed9516e25e1..58a7993f2306 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -63,7 +63,7 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data)
 		vsp1_write(vsp1, VI6_WPF_IRQ_STA(i), ~status & mask);
 
 		if (status & VI6_WFP_IRQ_STA_DFE) {
-			vsp1_pipeline_frame_end(wpf->pipe);
+			vsp1_pipeline_frame_end(wpf->entity.pipe);
 			ret = IRQ_HANDLED;
 		}
 	}
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
index 408602ebeb97..c26523c56c05 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.h
+++ b/drivers/media/platform/vsp1/vsp1_entity.h
@@ -106,6 +106,8 @@ struct vsp1_entity {
 	unsigned int index;
 	const struct vsp1_route *route;
 
+	struct vsp1_pipeline *pipe;
+
 	struct list_head list_dev;
 	struct list_head list_pipe;
 
diff --git a/drivers/media/platform/vsp1/vsp1_histo.c b/drivers/media/platform/vsp1/vsp1_histo.c
index afab77cf4fa5..8638ebc514b4 100644
--- a/drivers/media/platform/vsp1/vsp1_histo.c
+++ b/drivers/media/platform/vsp1/vsp1_histo.c
@@ -61,7 +61,7 @@ void vsp1_histogram_buffer_complete(struct vsp1_histogram *histo,
 				    struct vsp1_histogram_buffer *buf,
 				    size_t size)
 {
-	struct vsp1_pipeline *pipe = histo->pipe;
+	struct vsp1_pipeline *pipe = histo->entity.pipe;
 	unsigned long flags;
 
 	/*
diff --git a/drivers/media/platform/vsp1/vsp1_histo.h b/drivers/media/platform/vsp1/vsp1_histo.h
index af2874f6031d..e774adbf251f 100644
--- a/drivers/media/platform/vsp1/vsp1_histo.h
+++ b/drivers/media/platform/vsp1/vsp1_histo.h
@@ -25,7 +25,6 @@
 #include "vsp1_entity.h"
 
 struct vsp1_device;
-struct vsp1_pipeline;
 
 #define HISTO_PAD_SINK				0
 #define HISTO_PAD_SOURCE			1
@@ -37,8 +36,6 @@ struct vsp1_histogram_buffer {
 };
 
 struct vsp1_histogram {
-	struct vsp1_pipeline *pipe;
-
 	struct vsp1_entity entity;
 	struct video_device video;
 	struct media_pad pad;
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
index 44944ac86d9b..99ccbac3256a 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.c
+++ b/drivers/media/platform/vsp1/vsp1_pipe.c
@@ -185,6 +185,7 @@ const struct vsp1_format_info *vsp1_get_format_info(struct vsp1_device *vsp1,
 
 void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
 {
+	struct vsp1_entity *entity;
 	unsigned int i;
 
 	if (pipe->bru) {
@@ -194,29 +195,13 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
 			bru->inputs[i].rpf = NULL;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i) {
-		if (pipe->inputs[i]) {
-			pipe->inputs[i]->pipe = NULL;
-			pipe->inputs[i] = NULL;
-		}
-	}
-
-	if (pipe->output) {
-		pipe->output->pipe = NULL;
-		pipe->output = NULL;
-	}
+	for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i)
+		pipe->inputs[i] = NULL;
 
-	if (pipe->hgo) {
-		struct vsp1_hgo *hgo = to_hgo(&pipe->hgo->subdev);
+	pipe->output = NULL;
 
-		hgo->histo.pipe = NULL;
-	}
-
-	if (pipe->hgt) {
-		struct vsp1_hgt *hgt = to_hgt(&pipe->hgt->subdev);
-
-		hgt->histo.pipe = NULL;
-	}
+	list_for_each_entry(entity, &pipe->entities, list_pipe)
+		entity->pipe = NULL;
 
 	INIT_LIST_HEAD(&pipe->entities);
 	pipe->state = VSP1_PIPELINE_STOPPED;
@@ -423,7 +408,7 @@ void vsp1_pipelines_suspend(struct vsp1_device *vsp1)
 		if (wpf == NULL)
 			continue;
 
-		pipe = wpf->pipe;
+		pipe = wpf->entity.pipe;
 		if (pipe == NULL)
 			continue;
 
@@ -440,7 +425,7 @@ void vsp1_pipelines_suspend(struct vsp1_device *vsp1)
 		if (wpf == NULL)
 			continue;
 
-		pipe = wpf->pipe;
+		pipe = wpf->entity.pipe;
 		if (pipe == NULL)
 			continue;
 
@@ -465,7 +450,7 @@ void vsp1_pipelines_resume(struct vsp1_device *vsp1)
 		if (wpf == NULL)
 			continue;
 
-		pipe = wpf->pipe;
+		pipe = wpf->entity.pipe;
 		if (pipe == NULL)
 			continue;
 
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index 58215a7ab631..c94ac89abfa7 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -27,7 +27,6 @@
 
 struct v4l2_ctrl;
 struct vsp1_dl_manager;
-struct vsp1_pipeline;
 struct vsp1_rwpf;
 struct vsp1_video;
 
@@ -39,7 +38,6 @@ struct vsp1_rwpf {
 	struct vsp1_entity entity;
 	struct v4l2_ctrl_handler ctrls;
 
-	struct vsp1_pipeline *pipe;
 	struct vsp1_video *video;
 
 	unsigned int max_width;
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index c2d3b8f0f487..cdd53d6cc408 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -324,7 +324,7 @@ static int vsp1_video_pipeline_setup_partitions(struct vsp1_pipeline *pipe)
 static struct vsp1_vb2_buffer *
 vsp1_video_complete_buffer(struct vsp1_video *video)
 {
-	struct vsp1_pipeline *pipe = video->rwpf->pipe;
+	struct vsp1_pipeline *pipe = video->rwpf->entity.pipe;
 	struct vsp1_vb2_buffer *next = NULL;
 	struct vsp1_vb2_buffer *done;
 	unsigned long flags;
@@ -598,20 +598,19 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe,
 		subdev = media_entity_to_v4l2_subdev(entity);
 		e = to_vsp1_entity(subdev);
 		list_add_tail(&e->list_pipe, &pipe->entities);
+		e->pipe = pipe;
 
 		switch (e->type) {
 		case VSP1_ENTITY_RPF:
 			rwpf = to_rwpf(subdev);
 			pipe->inputs[rwpf->entity.index] = rwpf;
 			rwpf->video->pipe_index = ++pipe->num_inputs;
-			rwpf->pipe = pipe;
 			break;
 
 		case VSP1_ENTITY_WPF:
 			rwpf = to_rwpf(subdev);
 			pipe->output = rwpf;
 			rwpf->video->pipe_index = 0;
-			rwpf->pipe = pipe;
 			break;
 
 		case VSP1_ENTITY_LIF:
@@ -625,12 +624,10 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe,
 
 		case VSP1_ENTITY_HGO:
 			pipe->hgo = e;
-			to_hgo(subdev)->histo.pipe = pipe;
 			break;
 
 		case VSP1_ENTITY_HGT:
 			pipe->hgt = e;
-			to_hgt(subdev)->histo.pipe = pipe;
 			break;
 
 		default:
@@ -682,7 +679,7 @@ static struct vsp1_pipeline *vsp1_video_pipeline_get(struct vsp1_video *video)
 	 * Otherwise allocate a new pipeline and initialize it, it will be freed
 	 * when the last reference is released.
 	 */
-	if (!video->rwpf->pipe) {
+	if (!video->rwpf->entity.pipe) {
 		pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);
 		if (!pipe)
 			return ERR_PTR(-ENOMEM);
@@ -694,7 +691,7 @@ static struct vsp1_pipeline *vsp1_video_pipeline_get(struct vsp1_video *video)
 			return ERR_PTR(ret);
 		}
 	} else {
-		pipe = video->rwpf->pipe;
+		pipe = video->rwpf->entity.pipe;
 		kref_get(&pipe->kref);
 	}
 
@@ -777,7 +774,7 @@ static void vsp1_video_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_pipeline *pipe = video->rwpf->pipe;
+	struct vsp1_pipeline *pipe = video->rwpf->entity.pipe;
 	struct vsp1_vb2_buffer *buf = to_vsp1_vb2_buffer(vbuf);
 	unsigned long flags;
 	bool empty;
@@ -872,7 +869,7 @@ static void vsp1_video_cleanup_pipeline(struct vsp1_pipeline *pipe)
 static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct vsp1_video *video = vb2_get_drv_priv(vq);
-	struct vsp1_pipeline *pipe = video->rwpf->pipe;
+	struct vsp1_pipeline *pipe = video->rwpf->entity.pipe;
 	bool start_pipeline = false;
 	unsigned long flags;
 	int ret;
@@ -913,7 +910,7 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
 static void vsp1_video_stop_streaming(struct vb2_queue *vq)
 {
 	struct vsp1_video *video = vb2_get_drv_priv(vq);
-	struct vsp1_pipeline *pipe = video->rwpf->pipe;
+	struct vsp1_pipeline *pipe = video->rwpf->entity.pipe;
 	unsigned long flags;
 	int ret;
 
-- 
Regards,

Laurent Pinchart

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

* [PATCH 04/15] v4l: vsp1: Store pipeline pointer in vsp1_entity
@ 2018-02-26 21:45   ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: linux-renesas-soc, Kieran Bingham, dri-devel

Various types of objects subclassing vsp1_entity currently store a
pointer to the pipeline. Move the pointer to vsp1_entity to simplify the
code and avoid storing the pipeline in more entity subclasses later.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_drm.c    | 20 +++++++++++++------
 drivers/media/platform/vsp1/vsp1_drv.c    |  2 +-
 drivers/media/platform/vsp1/vsp1_entity.h |  2 ++
 drivers/media/platform/vsp1/vsp1_histo.c  |  2 +-
 drivers/media/platform/vsp1/vsp1_histo.h  |  3 ---
 drivers/media/platform/vsp1/vsp1_pipe.c   | 33 +++++++++----------------------
 drivers/media/platform/vsp1/vsp1_rwpf.h   |  2 --
 drivers/media/platform/vsp1/vsp1_video.c  | 17 +++++++---------
 8 files changed, 34 insertions(+), 47 deletions(-)

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index a267f12f0cc8..a7ad85ab0b08 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -120,6 +120,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 			 * inputs.
 			 */
 			WARN_ON(list_empty(&rpf->entity.list_pipe));
+			rpf->entity.pipe = NULL;
 			list_del_init(&rpf->entity.list_pipe);
 			pipe->inputs[i] = NULL;
 
@@ -536,8 +537,10 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 			continue;
 		}
 
-		if (list_empty(&rpf->entity.list_pipe))
+		if (list_empty(&rpf->entity.list_pipe)) {
+			rpf->entity.pipe = pipe;
 			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
+		}
 
 		bru->inputs[i].rpf = rpf;
 		rpf->bru_input = i;
@@ -562,6 +565,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 			vsp1_dl_list_write(dl, entity->route->reg,
 					   VI6_DPR_NODE_UNUSED);
 
+			entity->pipe = NULL;
 			list_del_init(&entity->list_pipe);
 
 			continue;
@@ -625,24 +629,28 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
 
 		vsp1_pipeline_init(pipe);
 
+		pipe->frame_end = vsp1_du_pipeline_frame_end;
+
 		/*
 		 * The DRM pipeline is static, add entities manually. The first
 		 * pipeline uses the BRU and the second pipeline the BRS.
 		 */
 		pipe->bru = i == 0 ? &vsp1->bru->entity : &vsp1->brs->entity;
-		pipe->lif = &vsp1->lif[i]->entity;
 		pipe->output = vsp1->wpf[i];
-		pipe->output->pipe = pipe;
-		pipe->frame_end = vsp1_du_pipeline_frame_end;
+		pipe->lif = &vsp1->lif[i]->entity;
 
+		pipe->bru->pipe = pipe;
 		pipe->bru->sink = &pipe->output->entity;
 		pipe->bru->sink_pad = 0;
+		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
+
+		pipe->output->entity.pipe = pipe;
 		pipe->output->entity.sink = pipe->lif;
 		pipe->output->entity.sink_pad = 0;
+		list_add_tail(&pipe->output->entity.list_pipe, &pipe->entities);
 
-		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
+		pipe->lif->pipe = pipe;
 		list_add_tail(&pipe->lif->list_pipe, &pipe->entities);
-		list_add_tail(&pipe->output->entity.list_pipe, &pipe->entities);
 	}
 
 	/* Disable all RPFs initially. */
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index eed9516e25e1..58a7993f2306 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -63,7 +63,7 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data)
 		vsp1_write(vsp1, VI6_WPF_IRQ_STA(i), ~status & mask);
 
 		if (status & VI6_WFP_IRQ_STA_DFE) {
-			vsp1_pipeline_frame_end(wpf->pipe);
+			vsp1_pipeline_frame_end(wpf->entity.pipe);
 			ret = IRQ_HANDLED;
 		}
 	}
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
index 408602ebeb97..c26523c56c05 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.h
+++ b/drivers/media/platform/vsp1/vsp1_entity.h
@@ -106,6 +106,8 @@ struct vsp1_entity {
 	unsigned int index;
 	const struct vsp1_route *route;
 
+	struct vsp1_pipeline *pipe;
+
 	struct list_head list_dev;
 	struct list_head list_pipe;
 
diff --git a/drivers/media/platform/vsp1/vsp1_histo.c b/drivers/media/platform/vsp1/vsp1_histo.c
index afab77cf4fa5..8638ebc514b4 100644
--- a/drivers/media/platform/vsp1/vsp1_histo.c
+++ b/drivers/media/platform/vsp1/vsp1_histo.c
@@ -61,7 +61,7 @@ void vsp1_histogram_buffer_complete(struct vsp1_histogram *histo,
 				    struct vsp1_histogram_buffer *buf,
 				    size_t size)
 {
-	struct vsp1_pipeline *pipe = histo->pipe;
+	struct vsp1_pipeline *pipe = histo->entity.pipe;
 	unsigned long flags;
 
 	/*
diff --git a/drivers/media/platform/vsp1/vsp1_histo.h b/drivers/media/platform/vsp1/vsp1_histo.h
index af2874f6031d..e774adbf251f 100644
--- a/drivers/media/platform/vsp1/vsp1_histo.h
+++ b/drivers/media/platform/vsp1/vsp1_histo.h
@@ -25,7 +25,6 @@
 #include "vsp1_entity.h"
 
 struct vsp1_device;
-struct vsp1_pipeline;
 
 #define HISTO_PAD_SINK				0
 #define HISTO_PAD_SOURCE			1
@@ -37,8 +36,6 @@ struct vsp1_histogram_buffer {
 };
 
 struct vsp1_histogram {
-	struct vsp1_pipeline *pipe;
-
 	struct vsp1_entity entity;
 	struct video_device video;
 	struct media_pad pad;
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
index 44944ac86d9b..99ccbac3256a 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.c
+++ b/drivers/media/platform/vsp1/vsp1_pipe.c
@@ -185,6 +185,7 @@ const struct vsp1_format_info *vsp1_get_format_info(struct vsp1_device *vsp1,
 
 void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
 {
+	struct vsp1_entity *entity;
 	unsigned int i;
 
 	if (pipe->bru) {
@@ -194,29 +195,13 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
 			bru->inputs[i].rpf = NULL;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i) {
-		if (pipe->inputs[i]) {
-			pipe->inputs[i]->pipe = NULL;
-			pipe->inputs[i] = NULL;
-		}
-	}
-
-	if (pipe->output) {
-		pipe->output->pipe = NULL;
-		pipe->output = NULL;
-	}
+	for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i)
+		pipe->inputs[i] = NULL;
 
-	if (pipe->hgo) {
-		struct vsp1_hgo *hgo = to_hgo(&pipe->hgo->subdev);
+	pipe->output = NULL;
 
-		hgo->histo.pipe = NULL;
-	}
-
-	if (pipe->hgt) {
-		struct vsp1_hgt *hgt = to_hgt(&pipe->hgt->subdev);
-
-		hgt->histo.pipe = NULL;
-	}
+	list_for_each_entry(entity, &pipe->entities, list_pipe)
+		entity->pipe = NULL;
 
 	INIT_LIST_HEAD(&pipe->entities);
 	pipe->state = VSP1_PIPELINE_STOPPED;
@@ -423,7 +408,7 @@ void vsp1_pipelines_suspend(struct vsp1_device *vsp1)
 		if (wpf == NULL)
 			continue;
 
-		pipe = wpf->pipe;
+		pipe = wpf->entity.pipe;
 		if (pipe == NULL)
 			continue;
 
@@ -440,7 +425,7 @@ void vsp1_pipelines_suspend(struct vsp1_device *vsp1)
 		if (wpf == NULL)
 			continue;
 
-		pipe = wpf->pipe;
+		pipe = wpf->entity.pipe;
 		if (pipe == NULL)
 			continue;
 
@@ -465,7 +450,7 @@ void vsp1_pipelines_resume(struct vsp1_device *vsp1)
 		if (wpf == NULL)
 			continue;
 
-		pipe = wpf->pipe;
+		pipe = wpf->entity.pipe;
 		if (pipe == NULL)
 			continue;
 
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index 58215a7ab631..c94ac89abfa7 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -27,7 +27,6 @@
 
 struct v4l2_ctrl;
 struct vsp1_dl_manager;
-struct vsp1_pipeline;
 struct vsp1_rwpf;
 struct vsp1_video;
 
@@ -39,7 +38,6 @@ struct vsp1_rwpf {
 	struct vsp1_entity entity;
 	struct v4l2_ctrl_handler ctrls;
 
-	struct vsp1_pipeline *pipe;
 	struct vsp1_video *video;
 
 	unsigned int max_width;
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index c2d3b8f0f487..cdd53d6cc408 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -324,7 +324,7 @@ static int vsp1_video_pipeline_setup_partitions(struct vsp1_pipeline *pipe)
 static struct vsp1_vb2_buffer *
 vsp1_video_complete_buffer(struct vsp1_video *video)
 {
-	struct vsp1_pipeline *pipe = video->rwpf->pipe;
+	struct vsp1_pipeline *pipe = video->rwpf->entity.pipe;
 	struct vsp1_vb2_buffer *next = NULL;
 	struct vsp1_vb2_buffer *done;
 	unsigned long flags;
@@ -598,20 +598,19 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe,
 		subdev = media_entity_to_v4l2_subdev(entity);
 		e = to_vsp1_entity(subdev);
 		list_add_tail(&e->list_pipe, &pipe->entities);
+		e->pipe = pipe;
 
 		switch (e->type) {
 		case VSP1_ENTITY_RPF:
 			rwpf = to_rwpf(subdev);
 			pipe->inputs[rwpf->entity.index] = rwpf;
 			rwpf->video->pipe_index = ++pipe->num_inputs;
-			rwpf->pipe = pipe;
 			break;
 
 		case VSP1_ENTITY_WPF:
 			rwpf = to_rwpf(subdev);
 			pipe->output = rwpf;
 			rwpf->video->pipe_index = 0;
-			rwpf->pipe = pipe;
 			break;
 
 		case VSP1_ENTITY_LIF:
@@ -625,12 +624,10 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe,
 
 		case VSP1_ENTITY_HGO:
 			pipe->hgo = e;
-			to_hgo(subdev)->histo.pipe = pipe;
 			break;
 
 		case VSP1_ENTITY_HGT:
 			pipe->hgt = e;
-			to_hgt(subdev)->histo.pipe = pipe;
 			break;
 
 		default:
@@ -682,7 +679,7 @@ static struct vsp1_pipeline *vsp1_video_pipeline_get(struct vsp1_video *video)
 	 * Otherwise allocate a new pipeline and initialize it, it will be freed
 	 * when the last reference is released.
 	 */
-	if (!video->rwpf->pipe) {
+	if (!video->rwpf->entity.pipe) {
 		pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);
 		if (!pipe)
 			return ERR_PTR(-ENOMEM);
@@ -694,7 +691,7 @@ static struct vsp1_pipeline *vsp1_video_pipeline_get(struct vsp1_video *video)
 			return ERR_PTR(ret);
 		}
 	} else {
-		pipe = video->rwpf->pipe;
+		pipe = video->rwpf->entity.pipe;
 		kref_get(&pipe->kref);
 	}
 
@@ -777,7 +774,7 @@ static void vsp1_video_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_pipeline *pipe = video->rwpf->pipe;
+	struct vsp1_pipeline *pipe = video->rwpf->entity.pipe;
 	struct vsp1_vb2_buffer *buf = to_vsp1_vb2_buffer(vbuf);
 	unsigned long flags;
 	bool empty;
@@ -872,7 +869,7 @@ static void vsp1_video_cleanup_pipeline(struct vsp1_pipeline *pipe)
 static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
 	struct vsp1_video *video = vb2_get_drv_priv(vq);
-	struct vsp1_pipeline *pipe = video->rwpf->pipe;
+	struct vsp1_pipeline *pipe = video->rwpf->entity.pipe;
 	bool start_pipeline = false;
 	unsigned long flags;
 	int ret;
@@ -913,7 +910,7 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
 static void vsp1_video_stop_streaming(struct vb2_queue *vq)
 {
 	struct vsp1_video *video = vb2_get_drv_priv(vq);
-	struct vsp1_pipeline *pipe = video->rwpf->pipe;
+	struct vsp1_pipeline *pipe = video->rwpf->entity.pipe;
 	unsigned long flags;
 	int ret;
 
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 05/15] v4l: vsp1: Use vsp1_entity.pipe to check if entity belongs to a pipeline
  2018-02-26 21:45 ` Laurent Pinchart
@ 2018-02-26 21:45   ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: dri-devel, linux-renesas-soc, Kieran Bingham

The DRM pipeline handling code uses the entity's pipe list head to check
whether the entity is already included in a pipeline. This method is a
bit fragile in the sense that it uses list_empty() on a list_head that
is a list member. Replace it by a simpler check for the entity pipe
pointer.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index a7ad85ab0b08..e210917fdc3f 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -119,9 +119,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 			 * Remove the RPF from the pipe and the list of BRU
 			 * inputs.
 			 */
-			WARN_ON(list_empty(&rpf->entity.list_pipe));
+			WARN_ON(!rpf->entity.pipe);
 			rpf->entity.pipe = NULL;
-			list_del_init(&rpf->entity.list_pipe);
+			list_del(&rpf->entity.list_pipe);
 			pipe->inputs[i] = NULL;
 
 			bru->inputs[rpf->bru_input].rpf = NULL;
@@ -537,7 +537,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 			continue;
 		}
 
-		if (list_empty(&rpf->entity.list_pipe)) {
+		if (!rpf->entity.pipe) {
 			rpf->entity.pipe = pipe;
 			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
 		}
@@ -566,7 +566,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 					   VI6_DPR_NODE_UNUSED);
 
 			entity->pipe = NULL;
-			list_del_init(&entity->list_pipe);
+			list_del(&entity->list_pipe);
 
 			continue;
 		}
-- 
Regards,

Laurent Pinchart

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

* [PATCH 05/15] v4l: vsp1: Use vsp1_entity.pipe to check if entity belongs to a pipeline
@ 2018-02-26 21:45   ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: linux-renesas-soc, Kieran Bingham, dri-devel

The DRM pipeline handling code uses the entity's pipe list head to check
whether the entity is already included in a pipeline. This method is a
bit fragile in the sense that it uses list_empty() on a list_head that
is a list member. Replace it by a simpler check for the entity pipe
pointer.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index a7ad85ab0b08..e210917fdc3f 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -119,9 +119,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 			 * Remove the RPF from the pipe and the list of BRU
 			 * inputs.
 			 */
-			WARN_ON(list_empty(&rpf->entity.list_pipe));
+			WARN_ON(!rpf->entity.pipe);
 			rpf->entity.pipe = NULL;
-			list_del_init(&rpf->entity.list_pipe);
+			list_del(&rpf->entity.list_pipe);
 			pipe->inputs[i] = NULL;
 
 			bru->inputs[rpf->bru_input].rpf = NULL;
@@ -537,7 +537,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 			continue;
 		}
 
-		if (list_empty(&rpf->entity.list_pipe)) {
+		if (!rpf->entity.pipe) {
 			rpf->entity.pipe = pipe;
 			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
 		}
@@ -566,7 +566,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 					   VI6_DPR_NODE_UNUSED);
 
 			entity->pipe = NULL;
-			list_del_init(&entity->list_pipe);
+			list_del(&entity->list_pipe);
 
 			continue;
 		}
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 06/15] v4l: vsp1: Share duplicated DRM pipeline configuration code
  2018-02-26 21:45 ` Laurent Pinchart
@ 2018-02-26 21:45   ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: dri-devel, linux-renesas-soc, Kieran Bingham

Move the duplicated DRM pipeline configuration code to a function and
call it from vsp1_du_setup_lif() and vsp1_du_atomic_flush().

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index e210917fdc3f..9a043a915c0b 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -42,6 +42,47 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
 		drm_pipe->du_complete(drm_pipe->du_private, completed);
 }
 
+/* -----------------------------------------------------------------------------
+ * Pipeline Configuration
+ */
+
+/* Configure all entities in the pipeline. */
+static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
+{
+	struct vsp1_entity *entity;
+	struct vsp1_entity *next;
+	struct vsp1_dl_list *dl;
+
+	dl = vsp1_dl_list_get(pipe->output->dlm);
+
+	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
+		/* Disconnect unused RPFs from the pipeline. */
+		if (entity->type == VSP1_ENTITY_RPF &&
+		    !pipe->inputs[entity->index]) {
+			vsp1_dl_list_write(dl, entity->route->reg,
+					   VI6_DPR_NODE_UNUSED);
+
+			entity->pipe = NULL;
+			list_del(&entity->list_pipe);
+
+			continue;
+		}
+
+		vsp1_entity_route_setup(entity, pipe, dl);
+
+		if (entity->ops->configure) {
+			entity->ops->configure(entity, pipe, dl,
+					       VSP1_ENTITY_PARAMS_INIT);
+			entity->ops->configure(entity, pipe, dl,
+					       VSP1_ENTITY_PARAMS_RUNTIME);
+			entity->ops->configure(entity, pipe, dl,
+					       VSP1_ENTITY_PARAMS_PARTITION);
+		}
+	}
+
+	vsp1_dl_list_commit(dl);
+}
+
 /* -----------------------------------------------------------------------------
  * DU Driver API
  */
@@ -85,9 +126,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	struct vsp1_drm_pipeline *drm_pipe;
 	struct vsp1_pipeline *pipe;
 	struct vsp1_bru *bru;
-	struct vsp1_entity *entity;
-	struct vsp1_entity *next;
-	struct vsp1_dl_list *dl;
 	struct v4l2_subdev_format format;
 	unsigned long flags;
 	unsigned int i;
@@ -239,22 +277,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0);
 
 	/* Configure all entities in the pipeline. */
-	dl = vsp1_dl_list_get(pipe->output->dlm);
-
-	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
-		vsp1_entity_route_setup(entity, pipe, dl);
-
-		if (entity->ops->configure) {
-			entity->ops->configure(entity, pipe, dl,
-					       VSP1_ENTITY_PARAMS_INIT);
-			entity->ops->configure(entity, pipe, dl,
-					       VSP1_ENTITY_PARAMS_RUNTIME);
-			entity->ops->configure(entity, pipe, dl,
-					       VSP1_ENTITY_PARAMS_PARTITION);
-		}
-	}
-
-	vsp1_dl_list_commit(dl);
+	vsp1_du_pipeline_configure(pipe);
 
 	/* Start the pipeline. */
 	spin_lock_irqsave(&pipe->irqlock, flags);
@@ -490,15 +513,9 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 	struct vsp1_pipeline *pipe = &drm_pipe->pipe;
 	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
 	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
-	struct vsp1_entity *entity;
-	struct vsp1_entity *next;
-	struct vsp1_dl_list *dl;
 	unsigned int i;
 	int ret;
 
-	/* Prepare the display list. */
-	dl = vsp1_dl_list_get(pipe->output->dlm);
-
 	/* Count the number of enabled inputs and sort them by Z-order. */
 	pipe->num_inputs = 0;
 
@@ -557,33 +574,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 				__func__, rpf->entity.index);
 	}
 
-	/* Configure all entities in the pipeline. */
-	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
-		/* Disconnect unused RPFs from the pipeline. */
-		if (entity->type == VSP1_ENTITY_RPF &&
-		    !pipe->inputs[entity->index]) {
-			vsp1_dl_list_write(dl, entity->route->reg,
-					   VI6_DPR_NODE_UNUSED);
-
-			entity->pipe = NULL;
-			list_del(&entity->list_pipe);
-
-			continue;
-		}
-
-		vsp1_entity_route_setup(entity, pipe, dl);
-
-		if (entity->ops->configure) {
-			entity->ops->configure(entity, pipe, dl,
-					       VSP1_ENTITY_PARAMS_INIT);
-			entity->ops->configure(entity, pipe, dl,
-					       VSP1_ENTITY_PARAMS_RUNTIME);
-			entity->ops->configure(entity, pipe, dl,
-					       VSP1_ENTITY_PARAMS_PARTITION);
-		}
-	}
-
-	vsp1_dl_list_commit(dl);
+	vsp1_du_pipeline_configure(pipe);
 }
 EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
 
-- 
Regards,

Laurent Pinchart

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

* [PATCH 06/15] v4l: vsp1: Share duplicated DRM pipeline configuration code
@ 2018-02-26 21:45   ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: linux-renesas-soc, Kieran Bingham, dri-devel

Move the duplicated DRM pipeline configuration code to a function and
call it from vsp1_du_setup_lif() and vsp1_du_atomic_flush().

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index e210917fdc3f..9a043a915c0b 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -42,6 +42,47 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
 		drm_pipe->du_complete(drm_pipe->du_private, completed);
 }
 
+/* -----------------------------------------------------------------------------
+ * Pipeline Configuration
+ */
+
+/* Configure all entities in the pipeline. */
+static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
+{
+	struct vsp1_entity *entity;
+	struct vsp1_entity *next;
+	struct vsp1_dl_list *dl;
+
+	dl = vsp1_dl_list_get(pipe->output->dlm);
+
+	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
+		/* Disconnect unused RPFs from the pipeline. */
+		if (entity->type == VSP1_ENTITY_RPF &&
+		    !pipe->inputs[entity->index]) {
+			vsp1_dl_list_write(dl, entity->route->reg,
+					   VI6_DPR_NODE_UNUSED);
+
+			entity->pipe = NULL;
+			list_del(&entity->list_pipe);
+
+			continue;
+		}
+
+		vsp1_entity_route_setup(entity, pipe, dl);
+
+		if (entity->ops->configure) {
+			entity->ops->configure(entity, pipe, dl,
+					       VSP1_ENTITY_PARAMS_INIT);
+			entity->ops->configure(entity, pipe, dl,
+					       VSP1_ENTITY_PARAMS_RUNTIME);
+			entity->ops->configure(entity, pipe, dl,
+					       VSP1_ENTITY_PARAMS_PARTITION);
+		}
+	}
+
+	vsp1_dl_list_commit(dl);
+}
+
 /* -----------------------------------------------------------------------------
  * DU Driver API
  */
@@ -85,9 +126,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	struct vsp1_drm_pipeline *drm_pipe;
 	struct vsp1_pipeline *pipe;
 	struct vsp1_bru *bru;
-	struct vsp1_entity *entity;
-	struct vsp1_entity *next;
-	struct vsp1_dl_list *dl;
 	struct v4l2_subdev_format format;
 	unsigned long flags;
 	unsigned int i;
@@ -239,22 +277,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0);
 
 	/* Configure all entities in the pipeline. */
-	dl = vsp1_dl_list_get(pipe->output->dlm);
-
-	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
-		vsp1_entity_route_setup(entity, pipe, dl);
-
-		if (entity->ops->configure) {
-			entity->ops->configure(entity, pipe, dl,
-					       VSP1_ENTITY_PARAMS_INIT);
-			entity->ops->configure(entity, pipe, dl,
-					       VSP1_ENTITY_PARAMS_RUNTIME);
-			entity->ops->configure(entity, pipe, dl,
-					       VSP1_ENTITY_PARAMS_PARTITION);
-		}
-	}
-
-	vsp1_dl_list_commit(dl);
+	vsp1_du_pipeline_configure(pipe);
 
 	/* Start the pipeline. */
 	spin_lock_irqsave(&pipe->irqlock, flags);
@@ -490,15 +513,9 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 	struct vsp1_pipeline *pipe = &drm_pipe->pipe;
 	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
 	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
-	struct vsp1_entity *entity;
-	struct vsp1_entity *next;
-	struct vsp1_dl_list *dl;
 	unsigned int i;
 	int ret;
 
-	/* Prepare the display list. */
-	dl = vsp1_dl_list_get(pipe->output->dlm);
-
 	/* Count the number of enabled inputs and sort them by Z-order. */
 	pipe->num_inputs = 0;
 
@@ -557,33 +574,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 				__func__, rpf->entity.index);
 	}
 
-	/* Configure all entities in the pipeline. */
-	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
-		/* Disconnect unused RPFs from the pipeline. */
-		if (entity->type == VSP1_ENTITY_RPF &&
-		    !pipe->inputs[entity->index]) {
-			vsp1_dl_list_write(dl, entity->route->reg,
-					   VI6_DPR_NODE_UNUSED);
-
-			entity->pipe = NULL;
-			list_del(&entity->list_pipe);
-
-			continue;
-		}
-
-		vsp1_entity_route_setup(entity, pipe, dl);
-
-		if (entity->ops->configure) {
-			entity->ops->configure(entity, pipe, dl,
-					       VSP1_ENTITY_PARAMS_INIT);
-			entity->ops->configure(entity, pipe, dl,
-					       VSP1_ENTITY_PARAMS_RUNTIME);
-			entity->ops->configure(entity, pipe, dl,
-					       VSP1_ENTITY_PARAMS_PARTITION);
-		}
-	}
-
-	vsp1_dl_list_commit(dl);
+	vsp1_du_pipeline_configure(pipe);
 }
 EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
 
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 07/15] v4l: vsp1: Move DRM atomic commit pipeline setup to separate function
  2018-02-26 21:45 ` Laurent Pinchart
@ 2018-02-26 21:45   ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: dri-devel, linux-renesas-soc, Kieran Bingham

The DRM pipeline setup code used at atomic commit time is similar to the
setup code used when enabling the pipeline. Move it to a separate
function in order to share it.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 9a043a915c0b..7bf697ba7969 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -46,6 +46,185 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
  * Pipeline Configuration
  */
 
+/* Setup one RPF and the connected BRU sink pad. */
+static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
+				      struct vsp1_pipeline *pipe,
+				      struct vsp1_rwpf *rpf,
+				      unsigned int bru_input)
+{
+	struct v4l2_subdev_selection sel;
+	struct v4l2_subdev_format format;
+	const struct v4l2_rect *crop;
+	int ret;
+
+	/*
+	 * Configure the format on the RPF sink pad and propagate it up to the
+	 * BRU sink pad.
+	 */
+	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
+
+	memset(&format, 0, sizeof(format));
+	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	format.pad = RWPF_PAD_SINK;
+	format.format.width = crop->width + crop->left;
+	format.format.height = crop->height + crop->top;
+	format.format.code = rpf->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 = *crop;
+
+	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 = bru_input;
+
+	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code, BRU_NAME(pipe->bru), format.pad);
+
+	sel.pad = bru_input;
+	sel.target = V4L2_SEL_TGT_COMPOSE;
+	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
+
+	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL,
+			       &sel);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
+		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
+		BRU_NAME(pipe->bru), sel.pad);
+
+	return 0;
+}
+
+static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
+{
+	return vsp1->drm->inputs[rpf->entity.index].zpos;
+}
+
+/* Setup the input side of the pipeline (RPFs and BRU sink pads). */
+static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
+					struct vsp1_pipeline *pipe)
+{
+	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
+	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
+	unsigned int i;
+	int ret;
+
+	/* Count the number of enabled inputs and sort them by Z-order. */
+	pipe->num_inputs = 0;
+
+	for (i = 0; i < vsp1->info->rpf_count; ++i) {
+		struct vsp1_rwpf *rpf = vsp1->rpf[i];
+		unsigned int j;
+
+		/*
+		 * Make sure we don't accept more inputs than the hardware can
+		 * handle. This is a temporary fix to avoid display stall, we
+		 * need to instead allocate the BRU or BRS to display pipelines
+		 * dynamically based on the number of planes they each use.
+		 */
+		if (pipe->num_inputs >= pipe->bru->source_pad)
+			pipe->inputs[i] = NULL;
+
+		if (!pipe->inputs[i])
+			continue;
+
+		/* Insert the RPF in the sorted RPFs array. */
+		for (j = pipe->num_inputs++; j > 0; --j) {
+			if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf))
+				break;
+			inputs[j] = inputs[j-1];
+		}
+
+		inputs[j] = rpf;
+	}
+
+	/* Setup the RPF input pipeline for every enabled input. */
+	for (i = 0; i < pipe->bru->source_pad; ++i) {
+		struct vsp1_rwpf *rpf = inputs[i];
+
+		if (!rpf) {
+			bru->inputs[i].rpf = NULL;
+			continue;
+		}
+
+		if (!rpf->entity.pipe) {
+			rpf->entity.pipe = pipe;
+			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
+		}
+
+		bru->inputs[i].rpf = rpf;
+		rpf->bru_input = i;
+		rpf->entity.sink = pipe->bru;
+		rpf->entity.sink_pad = i;
+
+		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
+			__func__, rpf->entity.index, BRU_NAME(pipe->bru), i);
+
+		ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, i);
+		if (ret < 0) {
+			dev_err(vsp1->dev,
+				"%s: failed to setup RPF.%u\n",
+				__func__, rpf->entity.index);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 /* Configure all entities in the pipeline. */
 static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
 {
@@ -396,111 +575,6 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index,
 }
 EXPORT_SYMBOL_GPL(vsp1_du_atomic_update);
 
-static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1,
-				  struct vsp1_pipeline *pipe,
-				  struct vsp1_rwpf *rpf, unsigned int bru_input)
-{
-	struct v4l2_subdev_selection sel;
-	struct v4l2_subdev_format format;
-	const struct v4l2_rect *crop;
-	int ret;
-
-	/*
-	 * Configure the format on the RPF sink pad and propagate it up to the
-	 * BRU sink pad.
-	 */
-	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
-
-	memset(&format, 0, sizeof(format));
-	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-	format.pad = RWPF_PAD_SINK;
-	format.format.width = crop->width + crop->left;
-	format.format.height = crop->height + crop->top;
-	format.format.code = rpf->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 = *crop;
-
-	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 = bru_input;
-
-	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
-			       &format);
-	if (ret < 0)
-		return ret;
-
-	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
-		__func__, format.format.width, format.format.height,
-		format.format.code, BRU_NAME(pipe->bru), format.pad);
-
-	sel.pad = bru_input;
-	sel.target = V4L2_SEL_TGT_COMPOSE;
-	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
-
-	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL,
-			       &sel);
-	if (ret < 0)
-		return ret;
-
-	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
-		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
-		BRU_NAME(pipe->bru), sel.pad);
-
-	return 0;
-}
-
-static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
-{
-	return vsp1->drm->inputs[rpf->entity.index].zpos;
-}
-
 /**
  * vsp1_du_atomic_flush - Commit an atomic update
  * @dev: the VSP device
@@ -511,69 +585,8 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
 	struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index];
 	struct vsp1_pipeline *pipe = &drm_pipe->pipe;
-	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
-	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
-	unsigned int i;
-	int ret;
-
-	/* Count the number of enabled inputs and sort them by Z-order. */
-	pipe->num_inputs = 0;
-
-	for (i = 0; i < vsp1->info->rpf_count; ++i) {
-		struct vsp1_rwpf *rpf = vsp1->rpf[i];
-		unsigned int j;
-
-		/*
-		 * Make sure we don't accept more inputs than the hardware can
-		 * handle. This is a temporary fix to avoid display stall, we
-		 * need to instead allocate the BRU or BRS to display pipelines
-		 * dynamically based on the number of planes they each use.
-		 */
-		if (pipe->num_inputs >= pipe->bru->source_pad)
-			pipe->inputs[i] = NULL;
-
-		if (!pipe->inputs[i])
-			continue;
-
-		/* Insert the RPF in the sorted RPFs array. */
-		for (j = pipe->num_inputs++; j > 0; --j) {
-			if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf))
-				break;
-			inputs[j] = inputs[j-1];
-		}
-
-		inputs[j] = rpf;
-	}
-
-	/* Setup the RPF input pipeline for every enabled input. */
-	for (i = 0; i < pipe->bru->source_pad; ++i) {
-		struct vsp1_rwpf *rpf = inputs[i];
-
-		if (!rpf) {
-			bru->inputs[i].rpf = NULL;
-			continue;
-		}
-
-		if (!rpf->entity.pipe) {
-			rpf->entity.pipe = pipe;
-			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
-		}
-
-		bru->inputs[i].rpf = rpf;
-		rpf->bru_input = i;
-		rpf->entity.sink = pipe->bru;
-		rpf->entity.sink_pad = i;
-
-		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
-			__func__, rpf->entity.index, BRU_NAME(pipe->bru), i);
-
-		ret = vsp1_du_setup_rpf_pipe(vsp1, pipe, rpf, i);
-		if (ret < 0)
-			dev_err(vsp1->dev,
-				"%s: failed to setup RPF.%u\n",
-				__func__, rpf->entity.index);
-	}
 
+	vsp1_du_pipeline_setup_input(vsp1, pipe);
 	vsp1_du_pipeline_configure(pipe);
 }
 EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
-- 
Regards,

Laurent Pinchart

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

* [PATCH 07/15] v4l: vsp1: Move DRM atomic commit pipeline setup to separate function
@ 2018-02-26 21:45   ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: linux-renesas-soc, Kieran Bingham, dri-devel

The DRM pipeline setup code used at atomic commit time is similar to the
setup code used when enabling the pipeline. Move it to a separate
function in order to share it.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 9a043a915c0b..7bf697ba7969 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -46,6 +46,185 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
  * Pipeline Configuration
  */
 
+/* Setup one RPF and the connected BRU sink pad. */
+static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
+				      struct vsp1_pipeline *pipe,
+				      struct vsp1_rwpf *rpf,
+				      unsigned int bru_input)
+{
+	struct v4l2_subdev_selection sel;
+	struct v4l2_subdev_format format;
+	const struct v4l2_rect *crop;
+	int ret;
+
+	/*
+	 * Configure the format on the RPF sink pad and propagate it up to the
+	 * BRU sink pad.
+	 */
+	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
+
+	memset(&format, 0, sizeof(format));
+	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	format.pad = RWPF_PAD_SINK;
+	format.format.width = crop->width + crop->left;
+	format.format.height = crop->height + crop->top;
+	format.format.code = rpf->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 = *crop;
+
+	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 = bru_input;
+
+	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code, BRU_NAME(pipe->bru), format.pad);
+
+	sel.pad = bru_input;
+	sel.target = V4L2_SEL_TGT_COMPOSE;
+	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
+
+	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL,
+			       &sel);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
+		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
+		BRU_NAME(pipe->bru), sel.pad);
+
+	return 0;
+}
+
+static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
+{
+	return vsp1->drm->inputs[rpf->entity.index].zpos;
+}
+
+/* Setup the input side of the pipeline (RPFs and BRU sink pads). */
+static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
+					struct vsp1_pipeline *pipe)
+{
+	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
+	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
+	unsigned int i;
+	int ret;
+
+	/* Count the number of enabled inputs and sort them by Z-order. */
+	pipe->num_inputs = 0;
+
+	for (i = 0; i < vsp1->info->rpf_count; ++i) {
+		struct vsp1_rwpf *rpf = vsp1->rpf[i];
+		unsigned int j;
+
+		/*
+		 * Make sure we don't accept more inputs than the hardware can
+		 * handle. This is a temporary fix to avoid display stall, we
+		 * need to instead allocate the BRU or BRS to display pipelines
+		 * dynamically based on the number of planes they each use.
+		 */
+		if (pipe->num_inputs >= pipe->bru->source_pad)
+			pipe->inputs[i] = NULL;
+
+		if (!pipe->inputs[i])
+			continue;
+
+		/* Insert the RPF in the sorted RPFs array. */
+		for (j = pipe->num_inputs++; j > 0; --j) {
+			if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf))
+				break;
+			inputs[j] = inputs[j-1];
+		}
+
+		inputs[j] = rpf;
+	}
+
+	/* Setup the RPF input pipeline for every enabled input. */
+	for (i = 0; i < pipe->bru->source_pad; ++i) {
+		struct vsp1_rwpf *rpf = inputs[i];
+
+		if (!rpf) {
+			bru->inputs[i].rpf = NULL;
+			continue;
+		}
+
+		if (!rpf->entity.pipe) {
+			rpf->entity.pipe = pipe;
+			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
+		}
+
+		bru->inputs[i].rpf = rpf;
+		rpf->bru_input = i;
+		rpf->entity.sink = pipe->bru;
+		rpf->entity.sink_pad = i;
+
+		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
+			__func__, rpf->entity.index, BRU_NAME(pipe->bru), i);
+
+		ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, i);
+		if (ret < 0) {
+			dev_err(vsp1->dev,
+				"%s: failed to setup RPF.%u\n",
+				__func__, rpf->entity.index);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 /* Configure all entities in the pipeline. */
 static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
 {
@@ -396,111 +575,6 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index,
 }
 EXPORT_SYMBOL_GPL(vsp1_du_atomic_update);
 
-static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1,
-				  struct vsp1_pipeline *pipe,
-				  struct vsp1_rwpf *rpf, unsigned int bru_input)
-{
-	struct v4l2_subdev_selection sel;
-	struct v4l2_subdev_format format;
-	const struct v4l2_rect *crop;
-	int ret;
-
-	/*
-	 * Configure the format on the RPF sink pad and propagate it up to the
-	 * BRU sink pad.
-	 */
-	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
-
-	memset(&format, 0, sizeof(format));
-	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-	format.pad = RWPF_PAD_SINK;
-	format.format.width = crop->width + crop->left;
-	format.format.height = crop->height + crop->top;
-	format.format.code = rpf->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 = *crop;
-
-	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 = bru_input;
-
-	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
-			       &format);
-	if (ret < 0)
-		return ret;
-
-	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
-		__func__, format.format.width, format.format.height,
-		format.format.code, BRU_NAME(pipe->bru), format.pad);
-
-	sel.pad = bru_input;
-	sel.target = V4L2_SEL_TGT_COMPOSE;
-	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
-
-	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL,
-			       &sel);
-	if (ret < 0)
-		return ret;
-
-	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
-		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
-		BRU_NAME(pipe->bru), sel.pad);
-
-	return 0;
-}
-
-static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
-{
-	return vsp1->drm->inputs[rpf->entity.index].zpos;
-}
-
 /**
  * vsp1_du_atomic_flush - Commit an atomic update
  * @dev: the VSP device
@@ -511,69 +585,8 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
 	struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index];
 	struct vsp1_pipeline *pipe = &drm_pipe->pipe;
-	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
-	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
-	unsigned int i;
-	int ret;
-
-	/* Count the number of enabled inputs and sort them by Z-order. */
-	pipe->num_inputs = 0;
-
-	for (i = 0; i < vsp1->info->rpf_count; ++i) {
-		struct vsp1_rwpf *rpf = vsp1->rpf[i];
-		unsigned int j;
-
-		/*
-		 * Make sure we don't accept more inputs than the hardware can
-		 * handle. This is a temporary fix to avoid display stall, we
-		 * need to instead allocate the BRU or BRS to display pipelines
-		 * dynamically based on the number of planes they each use.
-		 */
-		if (pipe->num_inputs >= pipe->bru->source_pad)
-			pipe->inputs[i] = NULL;
-
-		if (!pipe->inputs[i])
-			continue;
-
-		/* Insert the RPF in the sorted RPFs array. */
-		for (j = pipe->num_inputs++; j > 0; --j) {
-			if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf))
-				break;
-			inputs[j] = inputs[j-1];
-		}
-
-		inputs[j] = rpf;
-	}
-
-	/* Setup the RPF input pipeline for every enabled input. */
-	for (i = 0; i < pipe->bru->source_pad; ++i) {
-		struct vsp1_rwpf *rpf = inputs[i];
-
-		if (!rpf) {
-			bru->inputs[i].rpf = NULL;
-			continue;
-		}
-
-		if (!rpf->entity.pipe) {
-			rpf->entity.pipe = pipe;
-			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
-		}
-
-		bru->inputs[i].rpf = rpf;
-		rpf->bru_input = i;
-		rpf->entity.sink = pipe->bru;
-		rpf->entity.sink_pad = i;
-
-		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
-			__func__, rpf->entity.index, BRU_NAME(pipe->bru), i);
-
-		ret = vsp1_du_setup_rpf_pipe(vsp1, pipe, rpf, i);
-		if (ret < 0)
-			dev_err(vsp1->dev,
-				"%s: failed to setup RPF.%u\n",
-				__func__, rpf->entity.index);
-	}
 
+	vsp1_du_pipeline_setup_input(vsp1, pipe);
 	vsp1_du_pipeline_configure(pipe);
 }
 EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 08/15] v4l: vsp1: Setup BRU at atomic commit time
  2018-02-26 21:45 ` Laurent Pinchart
@ 2018-02-26 21:45   ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: dri-devel, linux-renesas-soc, Kieran Bingham

To implement fully dynamic plane assignment to pipelines, we need to
reassign the BRU and BRS to the DRM pipelines in the atomic commit
handler. In preparation for this setup factor out the BRU source pad
code and call it both at LIF setup and atomic commit time.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_drm.c | 56 +++++++++++++++++++++++++++++++++-
 drivers/media/platform/vsp1/vsp1_drm.h |  5 +++
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 7bf697ba7969..6ad8aa6c8138 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -148,12 +148,51 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
 	return 0;
 }
 
+/* Setup the BRU source pad. */
+static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
+				      struct vsp1_pipeline *pipe)
+{
+	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
+	struct v4l2_subdev_format format = {
+		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+	};
+	int ret;
+
+	/*
+	 * Configure the format on the BRU source and verify that it matches the
+	 * requested format. We don't set the media bus code as it is configured
+	 * on the BRU sink pad 0 and propagated inside the entity, not on the
+	 * source pad.
+	 */
+	format.pad = pipe->bru->source_pad;
+	format.format.width = drm_pipe->width;
+	format.format.height = drm_pipe->height;
+	format.format.field = V4L2_FIELD_NONE;
+
+	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code, BRU_NAME(pipe->bru), pipe->bru->source_pad);
+
+	if (format.format.width != drm_pipe->width ||
+	    format.format.height != drm_pipe->height) {
+		dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__);
+		return -EPIPE;
+	}
+
+	return 0;
+}
+
 static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
 {
 	return vsp1->drm->inputs[rpf->entity.index].zpos;
 }
 
-/* Setup the input side of the pipeline (RPFs and BRU sink pads). */
+/* Setup the input side of the pipeline (RPFs and BRU). */
 static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 					struct vsp1_pipeline *pipe)
 {
@@ -191,6 +230,18 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 		inputs[j] = rpf;
 	}
 
+	/*
+	 * Setup the BRU. This must be done before setting up the RPF input
+	 * pipelines as the BRU sink compose rectangles depend on the BRU source
+	 * format.
+	 */
+	ret = vsp1_du_pipeline_setup_bru(vsp1, pipe);
+	if (ret < 0) {
+		dev_err(vsp1->dev, "%s: failed to setup %s source\n", __func__,
+			BRU_NAME(pipe->bru));
+		return ret;
+	}
+
 	/* Setup the RPF input pipeline for every enabled input. */
 	for (i = 0; i < pipe->bru->source_pad; ++i) {
 		struct vsp1_rwpf *rpf = inputs[i];
@@ -355,6 +406,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 		return 0;
 	}
 
+	drm_pipe->width = cfg->width;
+	drm_pipe->height = cfg->height;
+
 	dev_dbg(vsp1->dev, "%s: configuring LIF%u with format %ux%u\n",
 		__func__, pipe_index, cfg->width, cfg->height);
 
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
index 9aa19325cbe9..c8dd75ba01f6 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.h
+++ b/drivers/media/platform/vsp1/vsp1_drm.h
@@ -20,12 +20,17 @@
 /**
  * vsp1_drm_pipeline - State for the API exposed to the DRM driver
  * @pipe: the VSP1 pipeline used for display
+ * @width: output display width
+ * @height: output display height
  * @du_complete: frame completion callback for the DU driver (optional)
  * @du_private: data to be passed to the du_complete callback
  */
 struct vsp1_drm_pipeline {
 	struct vsp1_pipeline pipe;
 
+	unsigned int width;
+	unsigned int height;
+
 	/* Frame synchronisation */
 	void (*du_complete)(void *, bool);
 	void *du_private;
-- 
Regards,

Laurent Pinchart

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

* [PATCH 08/15] v4l: vsp1: Setup BRU at atomic commit time
@ 2018-02-26 21:45   ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: linux-renesas-soc, Kieran Bingham, dri-devel

To implement fully dynamic plane assignment to pipelines, we need to
reassign the BRU and BRS to the DRM pipelines in the atomic commit
handler. In preparation for this setup factor out the BRU source pad
code and call it both at LIF setup and atomic commit time.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/vsp1_drm.c | 56 +++++++++++++++++++++++++++++++++-
 drivers/media/platform/vsp1/vsp1_drm.h |  5 +++
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 7bf697ba7969..6ad8aa6c8138 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -148,12 +148,51 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
 	return 0;
 }
 
+/* Setup the BRU source pad. */
+static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
+				      struct vsp1_pipeline *pipe)
+{
+	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
+	struct v4l2_subdev_format format = {
+		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+	};
+	int ret;
+
+	/*
+	 * Configure the format on the BRU source and verify that it matches the
+	 * requested format. We don't set the media bus code as it is configured
+	 * on the BRU sink pad 0 and propagated inside the entity, not on the
+	 * source pad.
+	 */
+	format.pad = pipe->bru->source_pad;
+	format.format.width = drm_pipe->width;
+	format.format.height = drm_pipe->height;
+	format.format.field = V4L2_FIELD_NONE;
+
+	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code, BRU_NAME(pipe->bru), pipe->bru->source_pad);
+
+	if (format.format.width != drm_pipe->width ||
+	    format.format.height != drm_pipe->height) {
+		dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__);
+		return -EPIPE;
+	}
+
+	return 0;
+}
+
 static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
 {
 	return vsp1->drm->inputs[rpf->entity.index].zpos;
 }
 
-/* Setup the input side of the pipeline (RPFs and BRU sink pads). */
+/* Setup the input side of the pipeline (RPFs and BRU). */
 static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 					struct vsp1_pipeline *pipe)
 {
@@ -191,6 +230,18 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 		inputs[j] = rpf;
 	}
 
+	/*
+	 * Setup the BRU. This must be done before setting up the RPF input
+	 * pipelines as the BRU sink compose rectangles depend on the BRU source
+	 * format.
+	 */
+	ret = vsp1_du_pipeline_setup_bru(vsp1, pipe);
+	if (ret < 0) {
+		dev_err(vsp1->dev, "%s: failed to setup %s source\n", __func__,
+			BRU_NAME(pipe->bru));
+		return ret;
+	}
+
 	/* Setup the RPF input pipeline for every enabled input. */
 	for (i = 0; i < pipe->bru->source_pad; ++i) {
 		struct vsp1_rwpf *rpf = inputs[i];
@@ -355,6 +406,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 		return 0;
 	}
 
+	drm_pipe->width = cfg->width;
+	drm_pipe->height = cfg->height;
+
 	dev_dbg(vsp1->dev, "%s: configuring LIF%u with format %ux%u\n",
 		__func__, pipe_index, cfg->width, cfg->height);
 
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
index 9aa19325cbe9..c8dd75ba01f6 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.h
+++ b/drivers/media/platform/vsp1/vsp1_drm.h
@@ -20,12 +20,17 @@
 /**
  * vsp1_drm_pipeline - State for the API exposed to the DRM driver
  * @pipe: the VSP1 pipeline used for display
+ * @width: output display width
+ * @height: output display height
  * @du_complete: frame completion callback for the DU driver (optional)
  * @du_private: data to be passed to the du_complete callback
  */
 struct vsp1_drm_pipeline {
 	struct vsp1_pipeline pipe;
 
+	unsigned int width;
+	unsigned int height;
+
 	/* Frame synchronisation */
 	void (*du_complete)(void *, bool);
 	void *du_private;
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 09/15] v4l: vsp1: Replace manual DRM pipeline input setup in vsp1_du_setup_lif
  2018-02-26 21:45 ` Laurent Pinchart
@ 2018-02-26 21:45   ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: dri-devel, linux-renesas-soc, Kieran Bingham

The vsp1_du_setup_lif() function setups the DRM pipeline input manually.
This duplicates the code from the vsp1_du_pipeline_setup_input()
function. Replace the manual implementation by a call to the function.

As the pipeline has no enabled input in vsp1_du_setup_lif(), the
vsp1_du_pipeline_setup_input() function will not setup any RPF, and will
thus not setup formats on the BRU sink pads. This isn't a problem as all
inputs are disabled, and the BRU sink pads will be reconfigured from the
atomic commit handler when inputs will be enabled.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 6ad8aa6c8138..00ce99bd1605 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -412,47 +412,19 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	dev_dbg(vsp1->dev, "%s: configuring LIF%u with format %ux%u\n",
 		__func__, pipe_index, cfg->width, cfg->height);
 
-	/*
-	 * Configure the format at the BRU sinks and propagate it through the
-	 * pipeline.
-	 */
+	/* Setup formats through the pipeline. */
+	ret = vsp1_du_pipeline_setup_input(vsp1, pipe);
+	if (ret < 0)
+		return ret;
+
 	memset(&format, 0, sizeof(format));
 	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-
-	for (i = 0; i < pipe->bru->source_pad; ++i) {
-		format.pad = i;
-
-		format.format.width = cfg->width;
-		format.format.height = cfg->height;
-		format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
-		format.format.field = V4L2_FIELD_NONE;
-
-		ret = v4l2_subdev_call(&pipe->bru->subdev, pad,
-				       set_fmt, NULL, &format);
-		if (ret < 0)
-			return ret;
-
-		dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
-			__func__, format.format.width, format.format.height,
-			format.format.code, BRU_NAME(pipe->bru), i);
-	}
-
-	format.pad = pipe->bru->source_pad;
+	format.pad = RWPF_PAD_SINK;
 	format.format.width = cfg->width;
 	format.format.height = cfg->height;
 	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
 	format.format.field = V4L2_FIELD_NONE;
 
-	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
-			       &format);
-	if (ret < 0)
-		return ret;
-
-	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
-		__func__, format.format.width, format.format.height,
-		format.format.code, BRU_NAME(pipe->bru), i);
-
-	format.pad = RWPF_PAD_SINK;
 	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL,
 			       &format);
 	if (ret < 0)
-- 
Regards,

Laurent Pinchart

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

* [PATCH 09/15] v4l: vsp1: Replace manual DRM pipeline input setup in vsp1_du_setup_lif
@ 2018-02-26 21:45   ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: linux-renesas-soc, Kieran Bingham, dri-devel

The vsp1_du_setup_lif() function setups the DRM pipeline input manually.
This duplicates the code from the vsp1_du_pipeline_setup_input()
function. Replace the manual implementation by a call to the function.

As the pipeline has no enabled input in vsp1_du_setup_lif(), the
vsp1_du_pipeline_setup_input() function will not setup any RPF, and will
thus not setup formats on the BRU sink pads. This isn't a problem as all
inputs are disabled, and the BRU sink pads will be reconfigured from the
atomic commit handler when inputs will be enabled.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 6ad8aa6c8138..00ce99bd1605 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -412,47 +412,19 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	dev_dbg(vsp1->dev, "%s: configuring LIF%u with format %ux%u\n",
 		__func__, pipe_index, cfg->width, cfg->height);
 
-	/*
-	 * Configure the format at the BRU sinks and propagate it through the
-	 * pipeline.
-	 */
+	/* Setup formats through the pipeline. */
+	ret = vsp1_du_pipeline_setup_input(vsp1, pipe);
+	if (ret < 0)
+		return ret;
+
 	memset(&format, 0, sizeof(format));
 	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-
-	for (i = 0; i < pipe->bru->source_pad; ++i) {
-		format.pad = i;
-
-		format.format.width = cfg->width;
-		format.format.height = cfg->height;
-		format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
-		format.format.field = V4L2_FIELD_NONE;
-
-		ret = v4l2_subdev_call(&pipe->bru->subdev, pad,
-				       set_fmt, NULL, &format);
-		if (ret < 0)
-			return ret;
-
-		dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
-			__func__, format.format.width, format.format.height,
-			format.format.code, BRU_NAME(pipe->bru), i);
-	}
-
-	format.pad = pipe->bru->source_pad;
+	format.pad = RWPF_PAD_SINK;
 	format.format.width = cfg->width;
 	format.format.height = cfg->height;
 	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
 	format.format.field = V4L2_FIELD_NONE;
 
-	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
-			       &format);
-	if (ret < 0)
-		return ret;
-
-	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
-		__func__, format.format.width, format.format.height,
-		format.format.code, BRU_NAME(pipe->bru), i);
-
-	format.pad = RWPF_PAD_SINK;
 	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL,
 			       &format);
 	if (ret < 0)
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 10/15] v4l: vsp1: Move DRM pipeline output setup code to a function
  2018-02-26 21:45 ` Laurent Pinchart
@ 2018-02-26 21:45   ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: dri-devel, linux-renesas-soc, Kieran Bingham

In order to make the vsp1_du_setup_lif() easier to read, and for
symmetry with the DRM pipeline input setup, move the pipeline output
setup code to a separate function.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 00ce99bd1605..1c8adda47440 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -276,6 +276,66 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 	return 0;
 }
 
+/* Setup the output side of the pipeline (WPF and LIF). */
+static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
+					 struct vsp1_pipeline *pipe)
+{
+	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
+	struct v4l2_subdev_format format = {
+		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+	};
+	int ret;
+
+	format.pad = RWPF_PAD_SINK;
+	format.format.width = drm_pipe->width;
+	format.format.height = drm_pipe->height;
+	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
+	format.format.field = V4L2_FIELD_NONE;
+
+	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF%u sink\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code, pipe->output->entity.index);
+
+	format.pad = RWPF_PAD_SOURCE;
+	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, get_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF%u source\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code, pipe->output->entity.index);
+
+	format.pad = LIF_PAD_SINK;
+	ret = v4l2_subdev_call(&pipe->lif->subdev, pad, set_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF%u sink\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code, pipe->lif->index);
+
+	/*
+	 * Verify that the format at the output of the pipeline matches the
+	 * requested frame size and media bus code.
+	 */
+	if (format.format.width != drm_pipe->width ||
+	    format.format.height != drm_pipe->height ||
+	    format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) {
+		dev_dbg(vsp1->dev, "%s: format mismatch on LIF%u\n", __func__,
+			pipe->lif->index);
+		return -EPIPE;
+	}
+
+	return 0;
+}
+
 /* Configure all entities in the pipeline. */
 static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
 {
@@ -356,7 +416,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	struct vsp1_drm_pipeline *drm_pipe;
 	struct vsp1_pipeline *pipe;
 	struct vsp1_bru *bru;
-	struct v4l2_subdev_format format;
 	unsigned long flags;
 	unsigned int i;
 	int ret;
@@ -417,54 +476,10 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	if (ret < 0)
 		return ret;
 
-	memset(&format, 0, sizeof(format));
-	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-	format.pad = RWPF_PAD_SINK;
-	format.format.width = cfg->width;
-	format.format.height = cfg->height;
-	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
-	format.format.field = V4L2_FIELD_NONE;
-
-	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL,
-			       &format);
+	ret = vsp1_du_pipeline_setup_output(vsp1, pipe);
 	if (ret < 0)
 		return ret;
 
-	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF%u sink\n",
-		__func__, format.format.width, format.format.height,
-		format.format.code, pipe->output->entity.index);
-
-	format.pad = RWPF_PAD_SOURCE;
-	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, get_fmt, NULL,
-			       &format);
-	if (ret < 0)
-		return ret;
-
-	dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF%u source\n",
-		__func__, format.format.width, format.format.height,
-		format.format.code, pipe->output->entity.index);
-
-	format.pad = LIF_PAD_SINK;
-	ret = v4l2_subdev_call(&pipe->lif->subdev, pad, set_fmt, NULL,
-			       &format);
-	if (ret < 0)
-		return ret;
-
-	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF%u sink\n",
-		__func__, format.format.width, format.format.height,
-		format.format.code, pipe_index);
-
-	/*
-	 * Verify that the format at the output of the pipeline matches the
-	 * requested frame size and media bus code.
-	 */
-	if (format.format.width != cfg->width ||
-	    format.format.height != cfg->height ||
-	    format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) {
-		dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__);
-		return -EPIPE;
-	}
-
 	/* Enable the VSP1. */
 	ret = vsp1_device_get(vsp1);
 	if (ret < 0)
-- 
Regards,

Laurent Pinchart

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

* [PATCH 10/15] v4l: vsp1: Move DRM pipeline output setup code to a function
@ 2018-02-26 21:45   ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: linux-renesas-soc, Kieran Bingham, dri-devel

In order to make the vsp1_du_setup_lif() easier to read, and for
symmetry with the DRM pipeline input setup, move the pipeline output
setup code to a separate function.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 00ce99bd1605..1c8adda47440 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -276,6 +276,66 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 	return 0;
 }
 
+/* Setup the output side of the pipeline (WPF and LIF). */
+static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
+					 struct vsp1_pipeline *pipe)
+{
+	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
+	struct v4l2_subdev_format format = {
+		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+	};
+	int ret;
+
+	format.pad = RWPF_PAD_SINK;
+	format.format.width = drm_pipe->width;
+	format.format.height = drm_pipe->height;
+	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
+	format.format.field = V4L2_FIELD_NONE;
+
+	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF%u sink\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code, pipe->output->entity.index);
+
+	format.pad = RWPF_PAD_SOURCE;
+	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, get_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF%u source\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code, pipe->output->entity.index);
+
+	format.pad = LIF_PAD_SINK;
+	ret = v4l2_subdev_call(&pipe->lif->subdev, pad, set_fmt, NULL,
+			       &format);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF%u sink\n",
+		__func__, format.format.width, format.format.height,
+		format.format.code, pipe->lif->index);
+
+	/*
+	 * Verify that the format at the output of the pipeline matches the
+	 * requested frame size and media bus code.
+	 */
+	if (format.format.width != drm_pipe->width ||
+	    format.format.height != drm_pipe->height ||
+	    format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) {
+		dev_dbg(vsp1->dev, "%s: format mismatch on LIF%u\n", __func__,
+			pipe->lif->index);
+		return -EPIPE;
+	}
+
+	return 0;
+}
+
 /* Configure all entities in the pipeline. */
 static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
 {
@@ -356,7 +416,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	struct vsp1_drm_pipeline *drm_pipe;
 	struct vsp1_pipeline *pipe;
 	struct vsp1_bru *bru;
-	struct v4l2_subdev_format format;
 	unsigned long flags;
 	unsigned int i;
 	int ret;
@@ -417,54 +476,10 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	if (ret < 0)
 		return ret;
 
-	memset(&format, 0, sizeof(format));
-	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-	format.pad = RWPF_PAD_SINK;
-	format.format.width = cfg->width;
-	format.format.height = cfg->height;
-	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
-	format.format.field = V4L2_FIELD_NONE;
-
-	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL,
-			       &format);
+	ret = vsp1_du_pipeline_setup_output(vsp1, pipe);
 	if (ret < 0)
 		return ret;
 
-	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF%u sink\n",
-		__func__, format.format.width, format.format.height,
-		format.format.code, pipe->output->entity.index);
-
-	format.pad = RWPF_PAD_SOURCE;
-	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, get_fmt, NULL,
-			       &format);
-	if (ret < 0)
-		return ret;
-
-	dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF%u source\n",
-		__func__, format.format.width, format.format.height,
-		format.format.code, pipe->output->entity.index);
-
-	format.pad = LIF_PAD_SINK;
-	ret = v4l2_subdev_call(&pipe->lif->subdev, pad, set_fmt, NULL,
-			       &format);
-	if (ret < 0)
-		return ret;
-
-	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF%u sink\n",
-		__func__, format.format.width, format.format.height,
-		format.format.code, pipe_index);
-
-	/*
-	 * Verify that the format at the output of the pipeline matches the
-	 * requested frame size and media bus code.
-	 */
-	if (format.format.width != cfg->width ||
-	    format.format.height != cfg->height ||
-	    format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) {
-		dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__);
-		return -EPIPE;
-	}
-
 	/* Enable the VSP1. */
 	ret = vsp1_device_get(vsp1);
 	if (ret < 0)
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 11/15] v4l: vsp1: Add per-display list completion notification support
  2018-02-26 21:45 ` Laurent Pinchart
@ 2018-02-26 21:45   ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: dri-devel, linux-renesas-soc, Kieran Bingham

Display list completion is already reported to the frame end handler,
but that mechanism is global to all display lists. In order to implement
BRU and BRS reassignment in DRM pipelines we will need to wait for
completion of a particular display list. Extend the display list and
frame end handler APIs to support such a notification.

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

diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c
index 0b86ed01e85d..eb2971218e28 100644
--- a/drivers/media/platform/vsp1/vsp1_dl.c
+++ b/drivers/media/platform/vsp1/vsp1_dl.c
@@ -72,6 +72,7 @@ struct vsp1_dl_body {
  * @fragments: list of extra display list bodies
  * @has_chain: if true, indicates that there's a partition chain
  * @chain: entry in the display list partition chain
+ * @notify: whether the display list completion should be notified
  */
 struct vsp1_dl_list {
 	struct list_head list;
@@ -85,6 +86,8 @@ struct vsp1_dl_list {
 
 	bool has_chain;
 	struct list_head chain;
+
+	bool notify;
 };
 
 enum vsp1_dl_mode {
@@ -550,8 +553,16 @@ static void vsp1_dl_list_commit_continuous(struct vsp1_dl_list *dl)
 	 * case we can't replace the queued list by the new one, as we could
 	 * race with the hardware. We thus mark the update as pending, it will
 	 * be queued up to the hardware by the frame end interrupt handler.
+	 *
+	 * If a display list is already pending we simply drop it as the new
+	 * display list is assumed to contain a more recent configuration. It is
+	 * an error if the already pending list has the notify flag set, as
+	 * there is then a process waiting for that list to complete. This
+	 * shouldn't happen as the waiting process should perform proper
+	 * locking, but warn just in case.
 	 */
 	if (vsp1_dl_list_hw_update_pending(dlm)) {
+		WARN_ON(dlm->pending && dlm->pending->notify);
 		__vsp1_dl_list_put(dlm->pending);
 		dlm->pending = dl;
 		return;
@@ -581,7 +592,7 @@ static void vsp1_dl_list_commit_singleshot(struct vsp1_dl_list *dl)
 	dlm->active = dl;
 }
 
-void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
+void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool notify)
 {
 	struct vsp1_dl_manager *dlm = dl->dlm;
 	struct vsp1_dl_list *dl_child;
@@ -598,6 +609,8 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
 		}
 	}
 
+	dl->notify = notify;
+
 	spin_lock_irqsave(&dlm->lock, flags);
 
 	if (dlm->singleshot)
@@ -615,16 +628,23 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
 /**
  * vsp1_dlm_irq_frame_end - Display list handler for the frame end interrupt
  * @dlm: the display list manager
+ * @notify: whether the display list that completed has notification enabled
  *
  * Return true if the previous display list has completed at frame end, or false
  * if it has been delayed by one frame because the display list commit raced
  * with the frame end interrupt. The function always returns true in header mode
  * as display list processing is then not continuous and races never occur.
+ *
+ * Upon return, the @notify parameter is set to true if the previous display
+ * list has completed and had been queued with the notify flag, or to false
+ * otherwise. Notification is only supported for continuous mode.
  */
-bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
+bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm, bool *notify)
 {
 	bool completed = false;
 
+	*notify = false;
+
 	spin_lock(&dlm->lock);
 
 	/*
@@ -652,6 +672,9 @@ bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
 	 * frame end interrupt. The display list thus becomes active.
 	 */
 	if (dlm->queued) {
+		*notify = dlm->queued->notify;
+		dlm->queued->notify = false;
+
 		__vsp1_dl_list_put(dlm->active);
 		dlm->active = dlm->queued;
 		dlm->queued = NULL;
diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h
index ee3508172f0a..480c6b0dd2e4 100644
--- a/drivers/media/platform/vsp1/vsp1_dl.h
+++ b/drivers/media/platform/vsp1/vsp1_dl.h
@@ -27,12 +27,12 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
 					unsigned int prealloc);
 void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm);
 void vsp1_dlm_reset(struct vsp1_dl_manager *dlm);
-bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm);
+bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm, bool *notify);
 
 struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm);
 void vsp1_dl_list_put(struct vsp1_dl_list *dl);
 void vsp1_dl_list_write(struct vsp1_dl_list *dl, u32 reg, u32 data);
-void vsp1_dl_list_commit(struct vsp1_dl_list *dl);
+void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool notify);
 
 struct vsp1_dl_body *vsp1_dl_fragment_alloc(struct vsp1_device *vsp1,
 					    unsigned int num_entries);
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 1c8adda47440..d705a6e9fa1d 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -34,7 +34,7 @@
  */
 
 static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
-				       bool completed)
+				       bool completed, bool notify)
 {
 	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
 
@@ -370,7 +370,7 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
 		}
 	}
 
-	vsp1_dl_list_commit(dl);
+	vsp1_dl_list_commit(dl, false);
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
index 99ccbac3256a..4d819c9019f4 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.c
+++ b/drivers/media/platform/vsp1/vsp1_pipe.c
@@ -316,6 +316,7 @@ bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe)
 void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
 {
 	bool completed;
+	bool notify;
 
 	if (pipe == NULL)
 		return;
@@ -325,7 +326,7 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
 	 * up being postponed by one frame. @completed represents whether the
 	 * active frame was finished or postponed.
 	 */
-	completed = vsp1_dlm_irq_frame_end(pipe->output->dlm);
+	completed = vsp1_dlm_irq_frame_end(pipe->output->dlm, &notify);
 
 	if (pipe->hgo)
 		vsp1_hgo_frame_end(pipe->hgo);
@@ -338,7 +339,7 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
 	 * frame_end to account for vblank events.
 	 */
 	if (pipe->frame_end)
-		pipe->frame_end(pipe, completed);
+		pipe->frame_end(pipe, completed, notify);
 
 	pipe->sequence++;
 }
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
index dfff9b5685fe..482711024fa2 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.h
+++ b/drivers/media/platform/vsp1/vsp1_pipe.h
@@ -118,7 +118,8 @@ struct vsp1_pipeline {
 	enum vsp1_pipeline_state state;
 	wait_queue_head_t wq;
 
-	void (*frame_end)(struct vsp1_pipeline *pipe, bool completed);
+	void (*frame_end)(struct vsp1_pipeline *pipe, bool completed,
+			  bool notify);
 
 	struct mutex lock;
 	struct kref kref;
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index cdd53d6cc408..483b4259e1b4 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -437,14 +437,14 @@ static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe)
 	}
 
 	/* Complete, and commit the head display list. */
-	vsp1_dl_list_commit(pipe->dl);
+	vsp1_dl_list_commit(pipe->dl, false);
 	pipe->dl = NULL;
 
 	vsp1_pipeline_run(pipe);
 }
 
 static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe,
-					  bool completed)
+					  bool completed, bool notify)
 {
 	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
 	enum vsp1_pipeline_state state;
-- 
Regards,

Laurent Pinchart

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

* [PATCH 11/15] v4l: vsp1: Add per-display list completion notification support
@ 2018-02-26 21:45   ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: linux-renesas-soc, Kieran Bingham, dri-devel

Display list completion is already reported to the frame end handler,
but that mechanism is global to all display lists. In order to implement
BRU and BRS reassignment in DRM pipelines we will need to wait for
completion of a particular display list. Extend the display list and
frame end handler APIs to support such a notification.

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

diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c
index 0b86ed01e85d..eb2971218e28 100644
--- a/drivers/media/platform/vsp1/vsp1_dl.c
+++ b/drivers/media/platform/vsp1/vsp1_dl.c
@@ -72,6 +72,7 @@ struct vsp1_dl_body {
  * @fragments: list of extra display list bodies
  * @has_chain: if true, indicates that there's a partition chain
  * @chain: entry in the display list partition chain
+ * @notify: whether the display list completion should be notified
  */
 struct vsp1_dl_list {
 	struct list_head list;
@@ -85,6 +86,8 @@ struct vsp1_dl_list {
 
 	bool has_chain;
 	struct list_head chain;
+
+	bool notify;
 };
 
 enum vsp1_dl_mode {
@@ -550,8 +553,16 @@ static void vsp1_dl_list_commit_continuous(struct vsp1_dl_list *dl)
 	 * case we can't replace the queued list by the new one, as we could
 	 * race with the hardware. We thus mark the update as pending, it will
 	 * be queued up to the hardware by the frame end interrupt handler.
+	 *
+	 * If a display list is already pending we simply drop it as the new
+	 * display list is assumed to contain a more recent configuration. It is
+	 * an error if the already pending list has the notify flag set, as
+	 * there is then a process waiting for that list to complete. This
+	 * shouldn't happen as the waiting process should perform proper
+	 * locking, but warn just in case.
 	 */
 	if (vsp1_dl_list_hw_update_pending(dlm)) {
+		WARN_ON(dlm->pending && dlm->pending->notify);
 		__vsp1_dl_list_put(dlm->pending);
 		dlm->pending = dl;
 		return;
@@ -581,7 +592,7 @@ static void vsp1_dl_list_commit_singleshot(struct vsp1_dl_list *dl)
 	dlm->active = dl;
 }
 
-void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
+void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool notify)
 {
 	struct vsp1_dl_manager *dlm = dl->dlm;
 	struct vsp1_dl_list *dl_child;
@@ -598,6 +609,8 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
 		}
 	}
 
+	dl->notify = notify;
+
 	spin_lock_irqsave(&dlm->lock, flags);
 
 	if (dlm->singleshot)
@@ -615,16 +628,23 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
 /**
  * vsp1_dlm_irq_frame_end - Display list handler for the frame end interrupt
  * @dlm: the display list manager
+ * @notify: whether the display list that completed has notification enabled
  *
  * Return true if the previous display list has completed at frame end, or false
  * if it has been delayed by one frame because the display list commit raced
  * with the frame end interrupt. The function always returns true in header mode
  * as display list processing is then not continuous and races never occur.
+ *
+ * Upon return, the @notify parameter is set to true if the previous display
+ * list has completed and had been queued with the notify flag, or to false
+ * otherwise. Notification is only supported for continuous mode.
  */
-bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
+bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm, bool *notify)
 {
 	bool completed = false;
 
+	*notify = false;
+
 	spin_lock(&dlm->lock);
 
 	/*
@@ -652,6 +672,9 @@ bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
 	 * frame end interrupt. The display list thus becomes active.
 	 */
 	if (dlm->queued) {
+		*notify = dlm->queued->notify;
+		dlm->queued->notify = false;
+
 		__vsp1_dl_list_put(dlm->active);
 		dlm->active = dlm->queued;
 		dlm->queued = NULL;
diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h
index ee3508172f0a..480c6b0dd2e4 100644
--- a/drivers/media/platform/vsp1/vsp1_dl.h
+++ b/drivers/media/platform/vsp1/vsp1_dl.h
@@ -27,12 +27,12 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
 					unsigned int prealloc);
 void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm);
 void vsp1_dlm_reset(struct vsp1_dl_manager *dlm);
-bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm);
+bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm, bool *notify);
 
 struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm);
 void vsp1_dl_list_put(struct vsp1_dl_list *dl);
 void vsp1_dl_list_write(struct vsp1_dl_list *dl, u32 reg, u32 data);
-void vsp1_dl_list_commit(struct vsp1_dl_list *dl);
+void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool notify);
 
 struct vsp1_dl_body *vsp1_dl_fragment_alloc(struct vsp1_device *vsp1,
 					    unsigned int num_entries);
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 1c8adda47440..d705a6e9fa1d 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -34,7 +34,7 @@
  */
 
 static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
-				       bool completed)
+				       bool completed, bool notify)
 {
 	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
 
@@ -370,7 +370,7 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
 		}
 	}
 
-	vsp1_dl_list_commit(dl);
+	vsp1_dl_list_commit(dl, false);
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
index 99ccbac3256a..4d819c9019f4 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.c
+++ b/drivers/media/platform/vsp1/vsp1_pipe.c
@@ -316,6 +316,7 @@ bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe)
 void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
 {
 	bool completed;
+	bool notify;
 
 	if (pipe == NULL)
 		return;
@@ -325,7 +326,7 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
 	 * up being postponed by one frame. @completed represents whether the
 	 * active frame was finished or postponed.
 	 */
-	completed = vsp1_dlm_irq_frame_end(pipe->output->dlm);
+	completed = vsp1_dlm_irq_frame_end(pipe->output->dlm, &notify);
 
 	if (pipe->hgo)
 		vsp1_hgo_frame_end(pipe->hgo);
@@ -338,7 +339,7 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
 	 * frame_end to account for vblank events.
 	 */
 	if (pipe->frame_end)
-		pipe->frame_end(pipe, completed);
+		pipe->frame_end(pipe, completed, notify);
 
 	pipe->sequence++;
 }
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
index dfff9b5685fe..482711024fa2 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.h
+++ b/drivers/media/platform/vsp1/vsp1_pipe.h
@@ -118,7 +118,8 @@ struct vsp1_pipeline {
 	enum vsp1_pipeline_state state;
 	wait_queue_head_t wq;
 
-	void (*frame_end)(struct vsp1_pipeline *pipe, bool completed);
+	void (*frame_end)(struct vsp1_pipeline *pipe, bool completed,
+			  bool notify);
 
 	struct mutex lock;
 	struct kref kref;
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index cdd53d6cc408..483b4259e1b4 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -437,14 +437,14 @@ static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe)
 	}
 
 	/* Complete, and commit the head display list. */
-	vsp1_dl_list_commit(pipe->dl);
+	vsp1_dl_list_commit(pipe->dl, false);
 	pipe->dl = NULL;
 
 	vsp1_pipeline_run(pipe);
 }
 
 static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe,
-					  bool completed)
+					  bool completed, bool notify)
 {
 	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
 	enum vsp1_pipeline_state state;
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 12/15] v4l: vsp1: Generalize detection of entity removal from DRM pipeline
  2018-02-26 21:45 ` Laurent Pinchart
@ 2018-02-26 21:45   ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: dri-devel, linux-renesas-soc, Kieran Bingham

When disabling a DRM plane, the corresponding RPF is only marked as
removed from the pipeline in the atomic update handler, with the actual
removal happening when configuring the pipeline at atomic commit time.
This is required as the RPF has to be disabled in the hardware, which
can't be done from the atomic update handler.

The current implementation is RPF-specific. Make it independent of the
entity type by using the entity's pipe pointer to mark removal from the
pipeline. This will allow using the mechanism to remove BRU instances.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index d705a6e9fa1d..6c60b72b6f50 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -346,13 +346,12 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
 	dl = vsp1_dl_list_get(pipe->output->dlm);
 
 	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
-		/* Disconnect unused RPFs from the pipeline. */
-		if (entity->type == VSP1_ENTITY_RPF &&
-		    !pipe->inputs[entity->index]) {
+		/* Disconnect unused entities from the pipeline. */
+		if (!entity->pipe) {
 			vsp1_dl_list_write(dl, entity->route->reg,
 					   VI6_DPR_NODE_UNUSED);
 
-			entity->pipe = NULL;
+			entity->sink = NULL;
 			list_del(&entity->list_pipe);
 
 			continue;
@@ -569,10 +568,11 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index,
 			rpf_index);
 
 		/*
-		 * Remove the RPF from the pipe's inputs. The atomic flush
-		 * handler will disable the input and remove the entity from the
-		 * pipe's entities list.
+		 * Remove the RPF from the pipeline's inputs. Keep it in the
+		 * pipeline's entity list to let vsp1_du_pipeline_configure()
+		 * remove it from the hardware pipeline.
 		 */
+		rpf->entity.pipe = NULL;
 		drm_pipe->pipe.inputs[rpf_index] = NULL;
 		return 0;
 	}
-- 
Regards,

Laurent Pinchart

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

* [PATCH 12/15] v4l: vsp1: Generalize detection of entity removal from DRM pipeline
@ 2018-02-26 21:45   ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: linux-renesas-soc, Kieran Bingham, dri-devel

When disabling a DRM plane, the corresponding RPF is only marked as
removed from the pipeline in the atomic update handler, with the actual
removal happening when configuring the pipeline at atomic commit time.
This is required as the RPF has to be disabled in the hardware, which
can't be done from the atomic update handler.

The current implementation is RPF-specific. Make it independent of the
entity type by using the entity's pipe pointer to mark removal from the
pipeline. This will allow using the mechanism to remove BRU instances.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index d705a6e9fa1d..6c60b72b6f50 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -346,13 +346,12 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
 	dl = vsp1_dl_list_get(pipe->output->dlm);
 
 	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
-		/* Disconnect unused RPFs from the pipeline. */
-		if (entity->type == VSP1_ENTITY_RPF &&
-		    !pipe->inputs[entity->index]) {
+		/* Disconnect unused entities from the pipeline. */
+		if (!entity->pipe) {
 			vsp1_dl_list_write(dl, entity->route->reg,
 					   VI6_DPR_NODE_UNUSED);
 
-			entity->pipe = NULL;
+			entity->sink = NULL;
 			list_del(&entity->list_pipe);
 
 			continue;
@@ -569,10 +568,11 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index,
 			rpf_index);
 
 		/*
-		 * Remove the RPF from the pipe's inputs. The atomic flush
-		 * handler will disable the input and remove the entity from the
-		 * pipe's entities list.
+		 * Remove the RPF from the pipeline's inputs. Keep it in the
+		 * pipeline's entity list to let vsp1_du_pipeline_configure()
+		 * remove it from the hardware pipeline.
 		 */
+		rpf->entity.pipe = NULL;
 		drm_pipe->pipe.inputs[rpf_index] = NULL;
 		return 0;
 	}
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 13/15] v4l: vsp1: Assign BRU and BRS to pipelines dynamically
  2018-02-26 21:45 ` Laurent Pinchart
@ 2018-02-26 21:45   ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: dri-devel, linux-renesas-soc, Kieran Bingham

The VSPDL variant drives two DU channels through two LIF and two
blenders, BRU and BRS. The DU channels thus share the five available
VSPDL inputs and expose them as five KMS planes.

The current implementation assigns the BRS to the second LIF and thus
artificially limits the number of planes for the second display channel
to two at most.

Lift this artificial limitation by assigning the BRU and BRS to the
display pipelines on demand based on the number of planes used by each
pipeline. When a display pipeline needs more than two inputs and the BRU
is already in use by the other pipeline, this requires reconfiguring the
other pipeline to free the BRU before processing, which can result in
frame drop on both pipelines.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 6c60b72b6f50..87e31ba0ddf5 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -39,7 +39,13 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
 	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
 
 	if (drm_pipe->du_complete)
-		drm_pipe->du_complete(drm_pipe->du_private, completed);
+		drm_pipe->du_complete(drm_pipe->du_private,
+				      completed && !notify);
+
+	if (notify) {
+		drm_pipe->force_bru_release = false;
+		wake_up(&drm_pipe->wait_queue);
+	}
 }
 
 /* -----------------------------------------------------------------------------
@@ -149,6 +155,10 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
 }
 
 /* Setup the BRU source pad. */
+static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
+					struct vsp1_pipeline *pipe);
+static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe);
+
 static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
 				      struct vsp1_pipeline *pipe)
 {
@@ -156,8 +166,93 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
 	struct v4l2_subdev_format format = {
 		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
 	};
+	struct vsp1_entity *bru;
 	int ret;
 
+	/*
+	 * Pick a BRU:
+	 * - If we need more than two inputs, use the main BRU.
+	 * - Otherwise, if we are not forced to release our BRU, keep it.
+	 * - Else, use any free BRU (randomly starting with the main BRU).
+	 */
+	if (pipe->num_inputs > 2)
+		bru = &vsp1->bru->entity;
+	else if (pipe->bru && !drm_pipe->force_bru_release)
+		bru = pipe->bru;
+	else if (!vsp1->bru->entity.pipe)
+		bru = &vsp1->bru->entity;
+	else
+		bru = &vsp1->brs->entity;
+
+	/* Switch BRU if needed. */
+	if (bru != pipe->bru) {
+		struct vsp1_entity *released_bru = NULL;
+
+		/* Release our BRU if we have one. */
+		if (pipe->bru) {
+			/*
+			 * The BRU might be acquired by the other pipeline in
+			 * the next step. We must thus remove it from the list
+			 * of entities for this pipeline. The other pipeline's
+			 * hardware configuration will reconfigure the BRU
+			 * routing.
+			 *
+			 * However, if the other pipeline doesn't acquire our
+			 * BRU, we need to keep it in the list, otherwise the
+			 * hardware configuration step won't disconnect it from
+			 * the pipeline. To solve this, store the released BRU
+			 * pointer to add it back to the list of entities later
+			 * if it isn't acquired by the other pipeline.
+			 */
+			released_bru = pipe->bru;
+
+			list_del(&pipe->bru->list_pipe);
+			pipe->bru->sink = NULL;
+			pipe->bru->pipe = NULL;
+			pipe->bru = NULL;
+		}
+
+		/*
+		 * If the BRU we need is in use, force the owner pipeline to
+		 * switch to the other BRU and wait until the switch completes.
+		 */
+		if (bru->pipe) {
+			struct vsp1_drm_pipeline *owner_pipe;
+
+			owner_pipe = to_vsp1_drm_pipeline(bru->pipe);
+			owner_pipe->force_bru_release = true;
+
+			vsp1_du_pipeline_setup_input(vsp1, &owner_pipe->pipe);
+			vsp1_du_pipeline_configure(&owner_pipe->pipe);
+
+			ret = wait_event_timeout(owner_pipe->wait_queue,
+						 !owner_pipe->force_bru_release,
+						 msecs_to_jiffies(500));
+			if (ret == 0)
+				dev_warn(vsp1->dev,
+					 "DRM pipeline %u reconfiguration timeout\n",
+					 owner_pipe->pipe.lif->index);
+		}
+
+		/*
+		 * If the BRU we have released previously hasn't been acquired
+		 * by the other pipeline, add it back to the entities list (with
+		 * the pipe pointer NULL) to let vsp1_du_pipeline_configure()
+		 * disconnect it from the hardware pipeline.
+		 */
+		if (released_bru && !released_bru->pipe)
+			list_add_tail(&released_bru->list_pipe,
+				      &pipe->entities);
+
+		/* Add the BRU to the pipeline. */
+		pipe->bru = bru;
+		pipe->bru->pipe = pipe;
+		pipe->bru->sink = &pipe->output->entity;
+		pipe->bru->sink_pad = 0;
+
+		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
+	}
+
 	/*
 	 * Configure the format on the BRU source and verify that it matches the
 	 * requested format. We don't set the media bus code as it is configured
@@ -197,7 +292,7 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 					struct vsp1_pipeline *pipe)
 {
 	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
-	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
+	struct vsp1_bru *bru;
 	unsigned int i;
 	int ret;
 
@@ -208,15 +303,6 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 		struct vsp1_rwpf *rpf = vsp1->rpf[i];
 		unsigned int j;
 
-		/*
-		 * Make sure we don't accept more inputs than the hardware can
-		 * handle. This is a temporary fix to avoid display stall, we
-		 * need to instead allocate the BRU or BRS to display pipelines
-		 * dynamically based on the number of planes they each use.
-		 */
-		if (pipe->num_inputs >= pipe->bru->source_pad)
-			pipe->inputs[i] = NULL;
-
 		if (!pipe->inputs[i])
 			continue;
 
@@ -242,6 +328,8 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 		return ret;
 	}
 
+	bru = to_bru(&pipe->bru->subdev);
+
 	/* Setup the RPF input pipeline for every enabled input. */
 	for (i = 0; i < pipe->bru->source_pad; ++i) {
 		struct vsp1_rwpf *rpf = inputs[i];
@@ -339,6 +427,7 @@ static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
 /* Configure all entities in the pipeline. */
 static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
 {
+	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
 	struct vsp1_entity *entity;
 	struct vsp1_entity *next;
 	struct vsp1_dl_list *dl;
@@ -369,7 +458,7 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
 		}
 	}
 
-	vsp1_dl_list_commit(dl, false);
+	vsp1_dl_list_commit(dl, drm_pipe->force_bru_release);
 }
 
 /* -----------------------------------------------------------------------------
@@ -414,7 +503,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
 	struct vsp1_drm_pipeline *drm_pipe;
 	struct vsp1_pipeline *pipe;
-	struct vsp1_bru *bru;
 	unsigned long flags;
 	unsigned int i;
 	int ret;
@@ -424,9 +512,14 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 
 	drm_pipe = &vsp1->drm->pipe[pipe_index];
 	pipe = &drm_pipe->pipe;
-	bru = to_bru(&pipe->bru->subdev);
 
 	if (!cfg) {
+		struct vsp1_bru *bru;
+
+		mutex_lock(&vsp1->drm->lock);
+
+		bru = to_bru(&pipe->bru->subdev);
+
 		/*
 		 * NULL configuration means the CRTC is being disabled, stop
 		 * the pipeline and turn the light off.
@@ -456,6 +549,12 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 		drm_pipe->du_complete = NULL;
 		pipe->num_inputs = 0;
 
+		list_del(&pipe->bru->list_pipe);
+		pipe->bru->pipe = NULL;
+		pipe->bru = NULL;
+
+		mutex_unlock(&vsp1->drm->lock);
+
 		vsp1_dlm_reset(pipe->output->dlm);
 		vsp1_device_put(vsp1);
 
@@ -470,19 +569,21 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	dev_dbg(vsp1->dev, "%s: configuring LIF%u with format %ux%u\n",
 		__func__, pipe_index, cfg->width, cfg->height);
 
+	mutex_lock(&vsp1->drm->lock);
+
 	/* Setup formats through the pipeline. */
 	ret = vsp1_du_pipeline_setup_input(vsp1, pipe);
 	if (ret < 0)
-		return ret;
+		goto unlock;
 
 	ret = vsp1_du_pipeline_setup_output(vsp1, pipe);
 	if (ret < 0)
-		return ret;
+		goto unlock;
 
 	/* Enable the VSP1. */
 	ret = vsp1_device_get(vsp1);
 	if (ret < 0)
-		return ret;
+		goto unlock;
 
 	/*
 	 * Register a callback to allow us to notify the DRM driver of frame
@@ -498,6 +599,12 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	/* Configure all entities in the pipeline. */
 	vsp1_du_pipeline_configure(pipe);
 
+unlock:
+	mutex_unlock(&vsp1->drm->lock);
+
+	if (ret < 0)
+		return ret;
+
 	/* Start the pipeline. */
 	spin_lock_irqsave(&pipe->irqlock, flags);
 	vsp1_pipeline_run(pipe);
@@ -516,6 +623,9 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
  */
 void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index)
 {
+	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
+
+	mutex_lock(&vsp1->drm->lock);
 }
 EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
 
@@ -629,6 +739,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 
 	vsp1_du_pipeline_setup_input(vsp1, pipe);
 	vsp1_du_pipeline_configure(pipe);
+	mutex_unlock(&vsp1->drm->lock);
 }
 EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
 
@@ -667,28 +778,26 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
 	if (!vsp1->drm)
 		return -ENOMEM;
 
+	mutex_init(&vsp1->drm->lock);
+
 	/* Create one DRM pipeline per LIF. */
 	for (i = 0; i < vsp1->info->lif_count; ++i) {
 		struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[i];
 		struct vsp1_pipeline *pipe = &drm_pipe->pipe;
 
+		init_waitqueue_head(&drm_pipe->wait_queue);
+
 		vsp1_pipeline_init(pipe);
 
 		pipe->frame_end = vsp1_du_pipeline_frame_end;
 
 		/*
-		 * The DRM pipeline is static, add entities manually. The first
-		 * pipeline uses the BRU and the second pipeline the BRS.
+		 * The output side of the DRM pipeline is static, add the
+		 * corresponding entities manually.
 		 */
-		pipe->bru = i == 0 ? &vsp1->bru->entity : &vsp1->brs->entity;
 		pipe->output = vsp1->wpf[i];
 		pipe->lif = &vsp1->lif[i]->entity;
 
-		pipe->bru->pipe = pipe;
-		pipe->bru->sink = &pipe->output->entity;
-		pipe->bru->sink_pad = 0;
-		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
-
 		pipe->output->entity.pipe = pipe;
 		pipe->output->entity.sink = pipe->lif;
 		pipe->output->entity.sink_pad = 0;
@@ -710,4 +819,5 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
 
 void vsp1_drm_cleanup(struct vsp1_device *vsp1)
 {
+	mutex_destroy(&vsp1->drm->lock);
 }
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
index c8dd75ba01f6..c84bc1c456c0 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.h
+++ b/drivers/media/platform/vsp1/vsp1_drm.h
@@ -13,7 +13,9 @@
 #ifndef __VSP1_DRM_H__
 #define __VSP1_DRM_H__
 
+#include <linux/mutex.h>
 #include <linux/videodev2.h>
+#include <linux/wait.h>
 
 #include "vsp1_pipe.h"
 
@@ -22,6 +24,8 @@
  * @pipe: the VSP1 pipeline used for display
  * @width: output display width
  * @height: output display height
+ * @force_bru_release: when set, release the BRU during the next reconfiguration
+ * @wait_queue: wait queue to wait for BRU release completion
  * @du_complete: frame completion callback for the DU driver (optional)
  * @du_private: data to be passed to the du_complete callback
  */
@@ -31,6 +35,9 @@ struct vsp1_drm_pipeline {
 	unsigned int width;
 	unsigned int height;
 
+	bool force_bru_release;
+	wait_queue_head_t wait_queue;
+
 	/* Frame synchronisation */
 	void (*du_complete)(void *, bool);
 	void *du_private;
@@ -39,11 +46,13 @@ struct vsp1_drm_pipeline {
 /**
  * vsp1_drm - State for the API exposed to the DRM driver
  * @pipe: the VSP1 DRM pipeline used for display
+ * @lock: protects the BRU and BRS allocation
  * @inputs: source crop rectangle, destination compose rectangle and z-order
  *	position for every input (indexed by RPF index)
  */
 struct vsp1_drm {
 	struct vsp1_drm_pipeline pipe[VSP1_MAX_LIF];
+	struct mutex lock;
 
 	struct {
 		struct v4l2_rect crop;
-- 
Regards,

Laurent Pinchart

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

* [PATCH 13/15] v4l: vsp1: Assign BRU and BRS to pipelines dynamically
@ 2018-02-26 21:45   ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: linux-renesas-soc, Kieran Bingham, dri-devel

The VSPDL variant drives two DU channels through two LIF and two
blenders, BRU and BRS. The DU channels thus share the five available
VSPDL inputs and expose them as five KMS planes.

The current implementation assigns the BRS to the second LIF and thus
artificially limits the number of planes for the second display channel
to two at most.

Lift this artificial limitation by assigning the BRU and BRS to the
display pipelines on demand based on the number of planes used by each
pipeline. When a display pipeline needs more than two inputs and the BRU
is already in use by the other pipeline, this requires reconfiguring the
other pipeline to free the BRU before processing, which can result in
frame drop on both pipelines.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 6c60b72b6f50..87e31ba0ddf5 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -39,7 +39,13 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
 	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
 
 	if (drm_pipe->du_complete)
-		drm_pipe->du_complete(drm_pipe->du_private, completed);
+		drm_pipe->du_complete(drm_pipe->du_private,
+				      completed && !notify);
+
+	if (notify) {
+		drm_pipe->force_bru_release = false;
+		wake_up(&drm_pipe->wait_queue);
+	}
 }
 
 /* -----------------------------------------------------------------------------
@@ -149,6 +155,10 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
 }
 
 /* Setup the BRU source pad. */
+static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
+					struct vsp1_pipeline *pipe);
+static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe);
+
 static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
 				      struct vsp1_pipeline *pipe)
 {
@@ -156,8 +166,93 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
 	struct v4l2_subdev_format format = {
 		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
 	};
+	struct vsp1_entity *bru;
 	int ret;
 
+	/*
+	 * Pick a BRU:
+	 * - If we need more than two inputs, use the main BRU.
+	 * - Otherwise, if we are not forced to release our BRU, keep it.
+	 * - Else, use any free BRU (randomly starting with the main BRU).
+	 */
+	if (pipe->num_inputs > 2)
+		bru = &vsp1->bru->entity;
+	else if (pipe->bru && !drm_pipe->force_bru_release)
+		bru = pipe->bru;
+	else if (!vsp1->bru->entity.pipe)
+		bru = &vsp1->bru->entity;
+	else
+		bru = &vsp1->brs->entity;
+
+	/* Switch BRU if needed. */
+	if (bru != pipe->bru) {
+		struct vsp1_entity *released_bru = NULL;
+
+		/* Release our BRU if we have one. */
+		if (pipe->bru) {
+			/*
+			 * The BRU might be acquired by the other pipeline in
+			 * the next step. We must thus remove it from the list
+			 * of entities for this pipeline. The other pipeline's
+			 * hardware configuration will reconfigure the BRU
+			 * routing.
+			 *
+			 * However, if the other pipeline doesn't acquire our
+			 * BRU, we need to keep it in the list, otherwise the
+			 * hardware configuration step won't disconnect it from
+			 * the pipeline. To solve this, store the released BRU
+			 * pointer to add it back to the list of entities later
+			 * if it isn't acquired by the other pipeline.
+			 */
+			released_bru = pipe->bru;
+
+			list_del(&pipe->bru->list_pipe);
+			pipe->bru->sink = NULL;
+			pipe->bru->pipe = NULL;
+			pipe->bru = NULL;
+		}
+
+		/*
+		 * If the BRU we need is in use, force the owner pipeline to
+		 * switch to the other BRU and wait until the switch completes.
+		 */
+		if (bru->pipe) {
+			struct vsp1_drm_pipeline *owner_pipe;
+
+			owner_pipe = to_vsp1_drm_pipeline(bru->pipe);
+			owner_pipe->force_bru_release = true;
+
+			vsp1_du_pipeline_setup_input(vsp1, &owner_pipe->pipe);
+			vsp1_du_pipeline_configure(&owner_pipe->pipe);
+
+			ret = wait_event_timeout(owner_pipe->wait_queue,
+						 !owner_pipe->force_bru_release,
+						 msecs_to_jiffies(500));
+			if (ret == 0)
+				dev_warn(vsp1->dev,
+					 "DRM pipeline %u reconfiguration timeout\n",
+					 owner_pipe->pipe.lif->index);
+		}
+
+		/*
+		 * If the BRU we have released previously hasn't been acquired
+		 * by the other pipeline, add it back to the entities list (with
+		 * the pipe pointer NULL) to let vsp1_du_pipeline_configure()
+		 * disconnect it from the hardware pipeline.
+		 */
+		if (released_bru && !released_bru->pipe)
+			list_add_tail(&released_bru->list_pipe,
+				      &pipe->entities);
+
+		/* Add the BRU to the pipeline. */
+		pipe->bru = bru;
+		pipe->bru->pipe = pipe;
+		pipe->bru->sink = &pipe->output->entity;
+		pipe->bru->sink_pad = 0;
+
+		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
+	}
+
 	/*
 	 * Configure the format on the BRU source and verify that it matches the
 	 * requested format. We don't set the media bus code as it is configured
@@ -197,7 +292,7 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 					struct vsp1_pipeline *pipe)
 {
 	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
-	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
+	struct vsp1_bru *bru;
 	unsigned int i;
 	int ret;
 
@@ -208,15 +303,6 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 		struct vsp1_rwpf *rpf = vsp1->rpf[i];
 		unsigned int j;
 
-		/*
-		 * Make sure we don't accept more inputs than the hardware can
-		 * handle. This is a temporary fix to avoid display stall, we
-		 * need to instead allocate the BRU or BRS to display pipelines
-		 * dynamically based on the number of planes they each use.
-		 */
-		if (pipe->num_inputs >= pipe->bru->source_pad)
-			pipe->inputs[i] = NULL;
-
 		if (!pipe->inputs[i])
 			continue;
 
@@ -242,6 +328,8 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 		return ret;
 	}
 
+	bru = to_bru(&pipe->bru->subdev);
+
 	/* Setup the RPF input pipeline for every enabled input. */
 	for (i = 0; i < pipe->bru->source_pad; ++i) {
 		struct vsp1_rwpf *rpf = inputs[i];
@@ -339,6 +427,7 @@ static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
 /* Configure all entities in the pipeline. */
 static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
 {
+	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
 	struct vsp1_entity *entity;
 	struct vsp1_entity *next;
 	struct vsp1_dl_list *dl;
@@ -369,7 +458,7 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
 		}
 	}
 
-	vsp1_dl_list_commit(dl, false);
+	vsp1_dl_list_commit(dl, drm_pipe->force_bru_release);
 }
 
 /* -----------------------------------------------------------------------------
@@ -414,7 +503,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
 	struct vsp1_drm_pipeline *drm_pipe;
 	struct vsp1_pipeline *pipe;
-	struct vsp1_bru *bru;
 	unsigned long flags;
 	unsigned int i;
 	int ret;
@@ -424,9 +512,14 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 
 	drm_pipe = &vsp1->drm->pipe[pipe_index];
 	pipe = &drm_pipe->pipe;
-	bru = to_bru(&pipe->bru->subdev);
 
 	if (!cfg) {
+		struct vsp1_bru *bru;
+
+		mutex_lock(&vsp1->drm->lock);
+
+		bru = to_bru(&pipe->bru->subdev);
+
 		/*
 		 * NULL configuration means the CRTC is being disabled, stop
 		 * the pipeline and turn the light off.
@@ -456,6 +549,12 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 		drm_pipe->du_complete = NULL;
 		pipe->num_inputs = 0;
 
+		list_del(&pipe->bru->list_pipe);
+		pipe->bru->pipe = NULL;
+		pipe->bru = NULL;
+
+		mutex_unlock(&vsp1->drm->lock);
+
 		vsp1_dlm_reset(pipe->output->dlm);
 		vsp1_device_put(vsp1);
 
@@ -470,19 +569,21 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	dev_dbg(vsp1->dev, "%s: configuring LIF%u with format %ux%u\n",
 		__func__, pipe_index, cfg->width, cfg->height);
 
+	mutex_lock(&vsp1->drm->lock);
+
 	/* Setup formats through the pipeline. */
 	ret = vsp1_du_pipeline_setup_input(vsp1, pipe);
 	if (ret < 0)
-		return ret;
+		goto unlock;
 
 	ret = vsp1_du_pipeline_setup_output(vsp1, pipe);
 	if (ret < 0)
-		return ret;
+		goto unlock;
 
 	/* Enable the VSP1. */
 	ret = vsp1_device_get(vsp1);
 	if (ret < 0)
-		return ret;
+		goto unlock;
 
 	/*
 	 * Register a callback to allow us to notify the DRM driver of frame
@@ -498,6 +599,12 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	/* Configure all entities in the pipeline. */
 	vsp1_du_pipeline_configure(pipe);
 
+unlock:
+	mutex_unlock(&vsp1->drm->lock);
+
+	if (ret < 0)
+		return ret;
+
 	/* Start the pipeline. */
 	spin_lock_irqsave(&pipe->irqlock, flags);
 	vsp1_pipeline_run(pipe);
@@ -516,6 +623,9 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
  */
 void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index)
 {
+	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
+
+	mutex_lock(&vsp1->drm->lock);
 }
 EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
 
@@ -629,6 +739,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
 
 	vsp1_du_pipeline_setup_input(vsp1, pipe);
 	vsp1_du_pipeline_configure(pipe);
+	mutex_unlock(&vsp1->drm->lock);
 }
 EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
 
@@ -667,28 +778,26 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
 	if (!vsp1->drm)
 		return -ENOMEM;
 
+	mutex_init(&vsp1->drm->lock);
+
 	/* Create one DRM pipeline per LIF. */
 	for (i = 0; i < vsp1->info->lif_count; ++i) {
 		struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[i];
 		struct vsp1_pipeline *pipe = &drm_pipe->pipe;
 
+		init_waitqueue_head(&drm_pipe->wait_queue);
+
 		vsp1_pipeline_init(pipe);
 
 		pipe->frame_end = vsp1_du_pipeline_frame_end;
 
 		/*
-		 * The DRM pipeline is static, add entities manually. The first
-		 * pipeline uses the BRU and the second pipeline the BRS.
+		 * The output side of the DRM pipeline is static, add the
+		 * corresponding entities manually.
 		 */
-		pipe->bru = i == 0 ? &vsp1->bru->entity : &vsp1->brs->entity;
 		pipe->output = vsp1->wpf[i];
 		pipe->lif = &vsp1->lif[i]->entity;
 
-		pipe->bru->pipe = pipe;
-		pipe->bru->sink = &pipe->output->entity;
-		pipe->bru->sink_pad = 0;
-		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
-
 		pipe->output->entity.pipe = pipe;
 		pipe->output->entity.sink = pipe->lif;
 		pipe->output->entity.sink_pad = 0;
@@ -710,4 +819,5 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
 
 void vsp1_drm_cleanup(struct vsp1_device *vsp1)
 {
+	mutex_destroy(&vsp1->drm->lock);
 }
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
index c8dd75ba01f6..c84bc1c456c0 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.h
+++ b/drivers/media/platform/vsp1/vsp1_drm.h
@@ -13,7 +13,9 @@
 #ifndef __VSP1_DRM_H__
 #define __VSP1_DRM_H__
 
+#include <linux/mutex.h>
 #include <linux/videodev2.h>
+#include <linux/wait.h>
 
 #include "vsp1_pipe.h"
 
@@ -22,6 +24,8 @@
  * @pipe: the VSP1 pipeline used for display
  * @width: output display width
  * @height: output display height
+ * @force_bru_release: when set, release the BRU during the next reconfiguration
+ * @wait_queue: wait queue to wait for BRU release completion
  * @du_complete: frame completion callback for the DU driver (optional)
  * @du_private: data to be passed to the du_complete callback
  */
@@ -31,6 +35,9 @@ struct vsp1_drm_pipeline {
 	unsigned int width;
 	unsigned int height;
 
+	bool force_bru_release;
+	wait_queue_head_t wait_queue;
+
 	/* Frame synchronisation */
 	void (*du_complete)(void *, bool);
 	void *du_private;
@@ -39,11 +46,13 @@ struct vsp1_drm_pipeline {
 /**
  * vsp1_drm - State for the API exposed to the DRM driver
  * @pipe: the VSP1 DRM pipeline used for display
+ * @lock: protects the BRU and BRS allocation
  * @inputs: source crop rectangle, destination compose rectangle and z-order
  *	position for every input (indexed by RPF index)
  */
 struct vsp1_drm {
 	struct vsp1_drm_pipeline pipe[VSP1_MAX_LIF];
+	struct mutex lock;
 
 	struct {
 		struct v4l2_rect crop;
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 14/15] v4l: vsp1: Add BRx dynamic assignment debugging messages
  2018-02-26 21:45 ` Laurent Pinchart
@ 2018-02-26 21:45   ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: dri-devel, linux-renesas-soc, Kieran Bingham

Dynamic assignment of the BRU and BRS to pipelines is prone to
regressions, add messages to make debugging easier. Keep it as a
separate commit to ease removal of those messages once the code will
deem to be completely stable.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 87e31ba0ddf5..521bbc227110 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -190,6 +190,10 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
 
 		/* Release our BRU if we have one. */
 		if (pipe->bru) {
+			dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
+				__func__, pipe->lif->index,
+				BRU_NAME(pipe->bru));
+
 			/*
 			 * The BRU might be acquired by the other pipeline in
 			 * the next step. We must thus remove it from the list
@@ -219,6 +223,9 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
 		if (bru->pipe) {
 			struct vsp1_drm_pipeline *owner_pipe;
 
+			dev_dbg(vsp1->dev, "%s: pipe %u: waiting for %s\n",
+				__func__, pipe->lif->index, BRU_NAME(bru));
+
 			owner_pipe = to_vsp1_drm_pipeline(bru->pipe);
 			owner_pipe->force_bru_release = true;
 
@@ -245,6 +252,9 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
 				      &pipe->entities);
 
 		/* Add the BRU to the pipeline. */
+		dev_dbg(vsp1->dev, "%s: pipe %u: acquired %s\n",
+			__func__, pipe->lif->index, BRU_NAME(bru));
+
 		pipe->bru = bru;
 		pipe->bru->pipe = pipe;
 		pipe->bru->sink = &pipe->output->entity;
@@ -549,6 +559,10 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 		drm_pipe->du_complete = NULL;
 		pipe->num_inputs = 0;
 
+		dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
+			__func__, pipe->lif->index,
+			BRU_NAME(pipe->bru));
+
 		list_del(&pipe->bru->list_pipe);
 		pipe->bru->pipe = NULL;
 		pipe->bru = NULL;
-- 
Regards,

Laurent Pinchart

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

* [PATCH 14/15] v4l: vsp1: Add BRx dynamic assignment debugging messages
@ 2018-02-26 21:45   ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: linux-renesas-soc, Kieran Bingham, dri-devel

Dynamic assignment of the BRU and BRS to pipelines is prone to
regressions, add messages to make debugging easier. Keep it as a
separate commit to ease removal of those messages once the code will
deem to be completely stable.

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

diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 87e31ba0ddf5..521bbc227110 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -190,6 +190,10 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
 
 		/* Release our BRU if we have one. */
 		if (pipe->bru) {
+			dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
+				__func__, pipe->lif->index,
+				BRU_NAME(pipe->bru));
+
 			/*
 			 * The BRU might be acquired by the other pipeline in
 			 * the next step. We must thus remove it from the list
@@ -219,6 +223,9 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
 		if (bru->pipe) {
 			struct vsp1_drm_pipeline *owner_pipe;
 
+			dev_dbg(vsp1->dev, "%s: pipe %u: waiting for %s\n",
+				__func__, pipe->lif->index, BRU_NAME(bru));
+
 			owner_pipe = to_vsp1_drm_pipeline(bru->pipe);
 			owner_pipe->force_bru_release = true;
 
@@ -245,6 +252,9 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
 				      &pipe->entities);
 
 		/* Add the BRU to the pipeline. */
+		dev_dbg(vsp1->dev, "%s: pipe %u: acquired %s\n",
+			__func__, pipe->lif->index, BRU_NAME(bru));
+
 		pipe->bru = bru;
 		pipe->bru->pipe = pipe;
 		pipe->bru->sink = &pipe->output->entity;
@@ -549,6 +559,10 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 		drm_pipe->du_complete = NULL;
 		pipe->num_inputs = 0;
 
+		dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
+			__func__, pipe->lif->index,
+			BRU_NAME(pipe->bru));
+
 		list_del(&pipe->bru->list_pipe);
 		pipe->bru->pipe = NULL;
 		pipe->bru = NULL;
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 15/15] v4l: vsp1: Rename BRU to BRx
  2018-02-26 21:45 ` Laurent Pinchart
@ 2018-02-26 21:45   ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: dri-devel, linux-renesas-soc, Kieran Bingham

Some VSP instances have two blending units named BRU (Blend/ROP Unit)
and BRS (Blend/ROP Sub unit). The BRS is a smaller version of the BRU
with only two inputs, but otherwise offers similar features and offers
the same register interface. The BRU and BRS can be used exchangeably in
VSP pipelines (provided no more than two inputs are needed).

Due to historical reasons, the VSP1 driver implements support for both
the BRU and BRS through objects named vsp1_bru. The code uses the name
BRU to refer to either the BRU or the BRS, except in a few places where
noted explicitly. This creates confusion.

In an effort to avoid confusion, rename the vsp1_bru object and the
corresponding API to vsp1_brx, and use BRx to refer to blend unit
instances regardless of their type. The names BRU and BRS are retained
where reference to a particular blend unit type is needed, as well as in
hardware registers to stay close to the datasheet.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/Makefile               |   2 +-
 drivers/media/platform/vsp1/vsp1.h                 |   6 +-
 .../media/platform/vsp1/{vsp1_bru.c => vsp1_brx.c} | 202 ++++++++++-----------
 .../media/platform/vsp1/{vsp1_bru.h => vsp1_brx.h} |  18 +-
 drivers/media/platform/vsp1/vsp1_drm.c             | 172 +++++++++---------
 drivers/media/platform/vsp1/vsp1_drm.h             |   6 +-
 drivers/media/platform/vsp1/vsp1_drv.c             |   6 +-
 drivers/media/platform/vsp1/vsp1_pipe.c            |  12 +-
 drivers/media/platform/vsp1/vsp1_pipe.h            |   4 +-
 drivers/media/platform/vsp1/vsp1_rpf.c             |  12 +-
 drivers/media/platform/vsp1/vsp1_rwpf.h            |   2 +-
 drivers/media/platform/vsp1/vsp1_video.c           |  16 +-
 drivers/media/platform/vsp1/vsp1_wpf.c             |   8 +-
 13 files changed, 233 insertions(+), 233 deletions(-)
 rename drivers/media/platform/vsp1/{vsp1_bru.c => vsp1_brx.c} (63%)
 rename drivers/media/platform/vsp1/{vsp1_bru.h => vsp1_brx.h} (66%)

diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile
index f5cd6f0491cb..596775f932c0 100644
--- a/drivers/media/platform/vsp1/Makefile
+++ b/drivers/media/platform/vsp1/Makefile
@@ -3,7 +3,7 @@ vsp1-y					:= vsp1_drv.o vsp1_entity.o vsp1_pipe.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_clu.o vsp1_hsit.o vsp1_lut.o
-vsp1-y					+= vsp1_bru.o vsp1_sru.o vsp1_uds.o
+vsp1-y					+= vsp1_brx.o vsp1_sru.o vsp1_uds.o
 vsp1-y					+= vsp1_hgo.o vsp1_hgt.o vsp1_histo.o
 vsp1-y					+= vsp1_lif.o
 
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 78ef838416b3..894cc725c2d4 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -30,7 +30,7 @@ struct rcar_fcp_device;
 struct vsp1_drm;
 struct vsp1_entity;
 struct vsp1_platform_data;
-struct vsp1_bru;
+struct vsp1_brx;
 struct vsp1_clu;
 struct vsp1_hgo;
 struct vsp1_hgt;
@@ -78,8 +78,8 @@ struct vsp1_device {
 	struct rcar_fcp_device *fcp;
 	struct device *bus_master;
 
-	struct vsp1_bru *brs;
-	struct vsp1_bru *bru;
+	struct vsp1_brx *brs;
+	struct vsp1_brx *bru;
 	struct vsp1_clu *clu;
 	struct vsp1_hgo *hgo;
 	struct vsp1_hgt *hgt;
diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_brx.c
similarity index 63%
rename from drivers/media/platform/vsp1/vsp1_bru.c
rename to drivers/media/platform/vsp1/vsp1_brx.c
index e8fd2ae3b3eb..b4af1d546022 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.c
+++ b/drivers/media/platform/vsp1/vsp1_brx.c
@@ -1,5 +1,5 @@
 /*
- * vsp1_bru.c  --  R-Car VSP1 Blend ROP Unit
+ * vsp1_brx.c  --  R-Car VSP1 Blend ROP Unit (BRU and BRS)
  *
  * Copyright (C) 2013 Renesas Corporation
  *
@@ -17,45 +17,45 @@
 #include <media/v4l2-subdev.h>
 
 #include "vsp1.h"
-#include "vsp1_bru.h"
+#include "vsp1_brx.h"
 #include "vsp1_dl.h"
 #include "vsp1_pipe.h"
 #include "vsp1_rwpf.h"
 #include "vsp1_video.h"
 
-#define BRU_MIN_SIZE				1U
-#define BRU_MAX_SIZE				8190U
+#define BRX_MIN_SIZE				1U
+#define BRX_MAX_SIZE				8190U
 
 /* -----------------------------------------------------------------------------
  * Device Access
  */
 
-static inline void vsp1_bru_write(struct vsp1_bru *bru, struct vsp1_dl_list *dl,
+static inline void vsp1_brx_write(struct vsp1_brx *brx, struct vsp1_dl_list *dl,
 				  u32 reg, u32 data)
 {
-	vsp1_dl_list_write(dl, bru->base + reg, data);
+	vsp1_dl_list_write(dl, brx->base + reg, data);
 }
 
 /* -----------------------------------------------------------------------------
  * Controls
  */
 
-static int bru_s_ctrl(struct v4l2_ctrl *ctrl)
+static int brx_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct vsp1_bru *bru =
-		container_of(ctrl->handler, struct vsp1_bru, ctrls);
+	struct vsp1_brx *brx =
+		container_of(ctrl->handler, struct vsp1_brx, ctrls);
 
 	switch (ctrl->id) {
 	case V4L2_CID_BG_COLOR:
-		bru->bgcolor = ctrl->val;
+		brx->bgcolor = ctrl->val;
 		break;
 	}
 
 	return 0;
 }
 
-static const struct v4l2_ctrl_ops bru_ctrl_ops = {
-	.s_ctrl = bru_s_ctrl,
+static const struct v4l2_ctrl_ops brx_ctrl_ops = {
+	.s_ctrl = brx_s_ctrl,
 };
 
 /* -----------------------------------------------------------------------------
@@ -63,12 +63,12 @@ static const struct v4l2_ctrl_ops bru_ctrl_ops = {
  */
 
 /*
- * The BRU can't perform format conversion, all sink and source formats must be
+ * The BRx can't perform format conversion, all sink and source formats must be
  * identical. We pick the format on the first sink pad (pad 0) and propagate it
  * to all other pads.
  */
 
-static int bru_enum_mbus_code(struct v4l2_subdev *subdev,
+static int brx_enum_mbus_code(struct v4l2_subdev *subdev,
 			      struct v4l2_subdev_pad_config *cfg,
 			      struct v4l2_subdev_mbus_code_enum *code)
 {
@@ -81,7 +81,7 @@ static int bru_enum_mbus_code(struct v4l2_subdev *subdev,
 					  ARRAY_SIZE(codes));
 }
 
-static int bru_enum_frame_size(struct v4l2_subdev *subdev,
+static int brx_enum_frame_size(struct v4l2_subdev *subdev,
 			       struct v4l2_subdev_pad_config *cfg,
 			       struct v4l2_subdev_frame_size_enum *fse)
 {
@@ -92,29 +92,29 @@ static int bru_enum_frame_size(struct v4l2_subdev *subdev,
 	    fse->code != MEDIA_BUS_FMT_AYUV8_1X32)
 		return -EINVAL;
 
-	fse->min_width = BRU_MIN_SIZE;
-	fse->max_width = BRU_MAX_SIZE;
-	fse->min_height = BRU_MIN_SIZE;
-	fse->max_height = BRU_MAX_SIZE;
+	fse->min_width = BRX_MIN_SIZE;
+	fse->max_width = BRX_MAX_SIZE;
+	fse->min_height = BRX_MIN_SIZE;
+	fse->max_height = BRX_MAX_SIZE;
 
 	return 0;
 }
 
-static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru,
+static struct v4l2_rect *brx_get_compose(struct vsp1_brx *brx,
 					 struct v4l2_subdev_pad_config *cfg,
 					 unsigned int pad)
 {
-	return v4l2_subdev_get_try_compose(&bru->entity.subdev, cfg, pad);
+	return v4l2_subdev_get_try_compose(&brx->entity.subdev, cfg, pad);
 }
 
-static void bru_try_format(struct vsp1_bru *bru,
+static void brx_try_format(struct vsp1_brx *brx,
 			   struct v4l2_subdev_pad_config *config,
 			   unsigned int pad, struct v4l2_mbus_framefmt *fmt)
 {
 	struct v4l2_mbus_framefmt *format;
 
 	switch (pad) {
-	case BRU_PAD_SINK(0):
+	case BRX_PAD_SINK(0):
 		/* Default to YUV if the requested format is not supported. */
 		if (fmt->code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
 		    fmt->code != MEDIA_BUS_FMT_AYUV8_1X32)
@@ -122,46 +122,46 @@ static void bru_try_format(struct vsp1_bru *bru,
 		break;
 
 	default:
-		/* The BRU can't perform format conversion. */
-		format = vsp1_entity_get_pad_format(&bru->entity, config,
-						    BRU_PAD_SINK(0));
+		/* The BRx can't perform format conversion. */
+		format = vsp1_entity_get_pad_format(&brx->entity, config,
+						    BRX_PAD_SINK(0));
 		fmt->code = format->code;
 		break;
 	}
 
-	fmt->width = clamp(fmt->width, BRU_MIN_SIZE, BRU_MAX_SIZE);
-	fmt->height = clamp(fmt->height, BRU_MIN_SIZE, BRU_MAX_SIZE);
+	fmt->width = clamp(fmt->width, BRX_MIN_SIZE, BRX_MAX_SIZE);
+	fmt->height = clamp(fmt->height, BRX_MIN_SIZE, BRX_MAX_SIZE);
 	fmt->field = V4L2_FIELD_NONE;
 	fmt->colorspace = V4L2_COLORSPACE_SRGB;
 }
 
-static int bru_set_format(struct v4l2_subdev *subdev,
+static int brx_set_format(struct v4l2_subdev *subdev,
 			  struct v4l2_subdev_pad_config *cfg,
 			  struct v4l2_subdev_format *fmt)
 {
-	struct vsp1_bru *bru = to_bru(subdev);
+	struct vsp1_brx *brx = to_brx(subdev);
 	struct v4l2_subdev_pad_config *config;
 	struct v4l2_mbus_framefmt *format;
 	int ret = 0;
 
-	mutex_lock(&bru->entity.lock);
+	mutex_lock(&brx->entity.lock);
 
-	config = vsp1_entity_get_pad_config(&bru->entity, cfg, fmt->which);
+	config = vsp1_entity_get_pad_config(&brx->entity, cfg, fmt->which);
 	if (!config) {
 		ret = -EINVAL;
 		goto done;
 	}
 
-	bru_try_format(bru, config, fmt->pad, &fmt->format);
+	brx_try_format(brx, config, fmt->pad, &fmt->format);
 
-	format = vsp1_entity_get_pad_format(&bru->entity, config, fmt->pad);
+	format = vsp1_entity_get_pad_format(&brx->entity, config, fmt->pad);
 	*format = fmt->format;
 
 	/* Reset the compose rectangle */
-	if (fmt->pad != bru->entity.source_pad) {
+	if (fmt->pad != brx->entity.source_pad) {
 		struct v4l2_rect *compose;
 
-		compose = bru_get_compose(bru, config, fmt->pad);
+		compose = brx_get_compose(brx, config, fmt->pad);
 		compose->left = 0;
 		compose->top = 0;
 		compose->width = format->width;
@@ -169,48 +169,48 @@ static int bru_set_format(struct v4l2_subdev *subdev,
 	}
 
 	/* Propagate the format code to all pads */
-	if (fmt->pad == BRU_PAD_SINK(0)) {
+	if (fmt->pad == BRX_PAD_SINK(0)) {
 		unsigned int i;
 
-		for (i = 0; i <= bru->entity.source_pad; ++i) {
-			format = vsp1_entity_get_pad_format(&bru->entity,
+		for (i = 0; i <= brx->entity.source_pad; ++i) {
+			format = vsp1_entity_get_pad_format(&brx->entity,
 							    config, i);
 			format->code = fmt->format.code;
 		}
 	}
 
 done:
-	mutex_unlock(&bru->entity.lock);
+	mutex_unlock(&brx->entity.lock);
 	return ret;
 }
 
-static int bru_get_selection(struct v4l2_subdev *subdev,
+static int brx_get_selection(struct v4l2_subdev *subdev,
 			     struct v4l2_subdev_pad_config *cfg,
 			     struct v4l2_subdev_selection *sel)
 {
-	struct vsp1_bru *bru = to_bru(subdev);
+	struct vsp1_brx *brx = to_brx(subdev);
 	struct v4l2_subdev_pad_config *config;
 
-	if (sel->pad == bru->entity.source_pad)
+	if (sel->pad == brx->entity.source_pad)
 		return -EINVAL;
 
 	switch (sel->target) {
 	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
 		sel->r.left = 0;
 		sel->r.top = 0;
-		sel->r.width = BRU_MAX_SIZE;
-		sel->r.height = BRU_MAX_SIZE;
+		sel->r.width = BRX_MAX_SIZE;
+		sel->r.height = BRX_MAX_SIZE;
 		return 0;
 
 	case V4L2_SEL_TGT_COMPOSE:
-		config = vsp1_entity_get_pad_config(&bru->entity, cfg,
+		config = vsp1_entity_get_pad_config(&brx->entity, cfg,
 						    sel->which);
 		if (!config)
 			return -EINVAL;
 
-		mutex_lock(&bru->entity.lock);
-		sel->r = *bru_get_compose(bru, config, sel->pad);
-		mutex_unlock(&bru->entity.lock);
+		mutex_lock(&brx->entity.lock);
+		sel->r = *brx_get_compose(brx, config, sel->pad);
+		mutex_unlock(&brx->entity.lock);
 		return 0;
 
 	default:
@@ -218,25 +218,25 @@ static int bru_get_selection(struct v4l2_subdev *subdev,
 	}
 }
 
-static int bru_set_selection(struct v4l2_subdev *subdev,
+static int brx_set_selection(struct v4l2_subdev *subdev,
 			     struct v4l2_subdev_pad_config *cfg,
 			     struct v4l2_subdev_selection *sel)
 {
-	struct vsp1_bru *bru = to_bru(subdev);
+	struct vsp1_brx *brx = to_brx(subdev);
 	struct v4l2_subdev_pad_config *config;
 	struct v4l2_mbus_framefmt *format;
 	struct v4l2_rect *compose;
 	int ret = 0;
 
-	if (sel->pad == bru->entity.source_pad)
+	if (sel->pad == brx->entity.source_pad)
 		return -EINVAL;
 
 	if (sel->target != V4L2_SEL_TGT_COMPOSE)
 		return -EINVAL;
 
-	mutex_lock(&bru->entity.lock);
+	mutex_lock(&brx->entity.lock);
 
-	config = vsp1_entity_get_pad_config(&bru->entity, cfg, sel->which);
+	config = vsp1_entity_get_pad_config(&brx->entity, cfg, sel->which);
 	if (!config) {
 		ret = -EINVAL;
 		goto done;
@@ -246,8 +246,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, config,
-					    bru->entity.source_pad);
+	format = vsp1_entity_get_pad_format(&brx->entity, config,
+					    brx->entity.source_pad);
 	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);
 
@@ -255,42 +255,42 @@ static int bru_set_selection(struct v4l2_subdev *subdev,
 	 * Scaling isn't supported, the compose rectangle size must be identical
 	 * to the sink format size.
 	 */
-	format = vsp1_entity_get_pad_format(&bru->entity, config, sel->pad);
+	format = vsp1_entity_get_pad_format(&brx->entity, config, sel->pad);
 	sel->r.width = format->width;
 	sel->r.height = format->height;
 
-	compose = bru_get_compose(bru, config, sel->pad);
+	compose = brx_get_compose(brx, config, sel->pad);
 	*compose = sel->r;
 
 done:
-	mutex_unlock(&bru->entity.lock);
+	mutex_unlock(&brx->entity.lock);
 	return ret;
 }
 
-static const struct v4l2_subdev_pad_ops bru_pad_ops = {
+static const struct v4l2_subdev_pad_ops brx_pad_ops = {
 	.init_cfg = vsp1_entity_init_cfg,
-	.enum_mbus_code = bru_enum_mbus_code,
-	.enum_frame_size = bru_enum_frame_size,
+	.enum_mbus_code = brx_enum_mbus_code,
+	.enum_frame_size = brx_enum_frame_size,
 	.get_fmt = vsp1_subdev_get_pad_format,
-	.set_fmt = bru_set_format,
-	.get_selection = bru_get_selection,
-	.set_selection = bru_set_selection,
+	.set_fmt = brx_set_format,
+	.get_selection = brx_get_selection,
+	.set_selection = brx_set_selection,
 };
 
-static const struct v4l2_subdev_ops bru_ops = {
-	.pad    = &bru_pad_ops,
+static const struct v4l2_subdev_ops brx_ops = {
+	.pad    = &brx_pad_ops,
 };
 
 /* -----------------------------------------------------------------------------
  * VSP1 Entity Operations
  */
 
-static void bru_configure(struct vsp1_entity *entity,
+static void brx_configure(struct vsp1_entity *entity,
 			  struct vsp1_pipeline *pipe,
 			  struct vsp1_dl_list *dl,
 			  enum vsp1_entity_params params)
 {
-	struct vsp1_bru *bru = to_bru(&entity->subdev);
+	struct vsp1_brx *brx = to_brx(&entity->subdev);
 	struct v4l2_mbus_framefmt *format;
 	unsigned int flags;
 	unsigned int i;
@@ -298,8 +298,8 @@ static void bru_configure(struct vsp1_entity *entity,
 	if (params != VSP1_ENTITY_PARAMS_INIT)
 		return;
 
-	format = vsp1_entity_get_pad_format(&bru->entity, bru->entity.config,
-					    bru->entity.source_pad);
+	format = vsp1_entity_get_pad_format(&brx->entity, brx->entity.config,
+					    brx->entity.source_pad);
 
 	/*
 	 * The hardware is extremely flexible but we have no userspace API to
@@ -313,7 +313,7 @@ static void bru_configure(struct vsp1_entity *entity,
 	 * format at the pipeline output is premultiplied.
 	 */
 	flags = pipe->output ? pipe->output->format.flags : 0;
-	vsp1_bru_write(bru, dl, VI6_BRU_INCTRL,
+	vsp1_brx_write(brx, dl, VI6_BRU_INCTRL,
 		       flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ?
 		       0 : VI6_BRU_INCTRL_NRM);
 
@@ -321,12 +321,12 @@ static void bru_configure(struct vsp1_entity *entity,
 	 * Set the background position to cover the whole output image and
 	 * configure its color.
 	 */
-	vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_SIZE,
+	vsp1_brx_write(brx, dl, VI6_BRU_VIRRPF_SIZE,
 		       (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) |
 		       (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT));
-	vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_LOC, 0);
+	vsp1_brx_write(brx, dl, VI6_BRU_VIRRPF_LOC, 0);
 
-	vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_COL, bru->bgcolor |
+	vsp1_brx_write(brx, dl, VI6_BRU_VIRRPF_COL, brx->bgcolor |
 		       (0xff << VI6_BRU_VIRRPF_COL_A_SHIFT));
 
 	/*
@@ -336,25 +336,25 @@ static void bru_configure(struct vsp1_entity *entity,
 	 * unit.
 	 */
 	if (entity->type == VSP1_ENTITY_BRU)
-		vsp1_bru_write(bru, dl, VI6_BRU_ROP,
+		vsp1_brx_write(brx, dl, VI6_BRU_ROP,
 			       VI6_BRU_ROP_DSTSEL_BRUIN(1) |
 			       VI6_BRU_ROP_CROP(VI6_ROP_NOP) |
 			       VI6_BRU_ROP_AROP(VI6_ROP_NOP));
 
-	for (i = 0; i < bru->entity.source_pad; ++i) {
+	for (i = 0; i < brx->entity.source_pad; ++i) {
 		bool premultiplied = false;
 		u32 ctrl = 0;
 
 		/*
-		 * Configure all Blend/ROP units corresponding to an enabled BRU
+		 * Configure all Blend/ROP units corresponding to an enabled BRx
 		 * input for alpha blending. Blend/ROP units corresponding to
-		 * disabled BRU inputs are used in ROP NOP mode to ignore the
+		 * disabled BRx inputs are used in ROP NOP mode to ignore the
 		 * SRC input.
 		 */
-		if (bru->inputs[i].rpf) {
+		if (brx->inputs[i].rpf) {
 			ctrl |= VI6_BRU_CTRL_RBC;
 
-			premultiplied = bru->inputs[i].rpf->format.flags
+			premultiplied = brx->inputs[i].rpf->format.flags
 				      & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA;
 		} else {
 			ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP)
@@ -378,7 +378,7 @@ static void bru_configure(struct vsp1_entity *entity,
 		if (!(entity->type == VSP1_ENTITY_BRU && i == 1))
 			ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i);
 
-		vsp1_bru_write(bru, dl, VI6_BRU_CTRL(i), ctrl);
+		vsp1_brx_write(brx, dl, VI6_BRU_CTRL(i), ctrl);
 
 		/*
 		 * Harcode the blending formula to
@@ -393,7 +393,7 @@ static void bru_configure(struct vsp1_entity *entity,
 		 *
 		 * otherwise.
 		 */
-		vsp1_bru_write(bru, dl, VI6_BRU_BLD(i),
+		vsp1_brx_write(brx, dl, VI6_BRU_BLD(i),
 			       VI6_BRU_BLD_CCMDX_255_SRC_A |
 			       (premultiplied ? VI6_BRU_BLD_CCMDY_COEFY :
 						VI6_BRU_BLD_CCMDY_SRC_A) |
@@ -403,29 +403,29 @@ static void bru_configure(struct vsp1_entity *entity,
 	}
 }
 
-static const struct vsp1_entity_operations bru_entity_ops = {
-	.configure = bru_configure,
+static const struct vsp1_entity_operations brx_entity_ops = {
+	.configure = brx_configure,
 };
 
 /* -----------------------------------------------------------------------------
  * Initialization and Cleanup
  */
 
-struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1,
+struct vsp1_brx *vsp1_brx_create(struct vsp1_device *vsp1,
 				 enum vsp1_entity_type type)
 {
-	struct vsp1_bru *bru;
+	struct vsp1_brx *brx;
 	unsigned int num_pads;
 	const char *name;
 	int ret;
 
-	bru = devm_kzalloc(vsp1->dev, sizeof(*bru), GFP_KERNEL);
-	if (bru == NULL)
+	brx = devm_kzalloc(vsp1->dev, sizeof(*brx), GFP_KERNEL);
+	if (brx == NULL)
 		return ERR_PTR(-ENOMEM);
 
-	bru->base = type == VSP1_ENTITY_BRU ? VI6_BRU_BASE : VI6_BRS_BASE;
-	bru->entity.ops = &bru_entity_ops;
-	bru->entity.type = type;
+	brx->base = type == VSP1_ENTITY_BRU ? VI6_BRU_BASE : VI6_BRS_BASE;
+	brx->entity.ops = &brx_entity_ops;
+	brx->entity.type = type;
 
 	if (type == VSP1_ENTITY_BRU) {
 		num_pads = vsp1->info->num_bru_inputs + 1;
@@ -435,26 +435,26 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1,
 		name = "brs";
 	}
 
-	ret = vsp1_entity_init(vsp1, &bru->entity, name, num_pads, &bru_ops,
+	ret = vsp1_entity_init(vsp1, &brx->entity, name, num_pads, &brx_ops,
 			       MEDIA_ENT_F_PROC_VIDEO_COMPOSER);
 	if (ret < 0)
 		return ERR_PTR(ret);
 
 	/* Initialize the control handler. */
-	v4l2_ctrl_handler_init(&bru->ctrls, 1);
-	v4l2_ctrl_new_std(&bru->ctrls, &bru_ctrl_ops, V4L2_CID_BG_COLOR,
+	v4l2_ctrl_handler_init(&brx->ctrls, 1);
+	v4l2_ctrl_new_std(&brx->ctrls, &brx_ctrl_ops, V4L2_CID_BG_COLOR,
 			  0, 0xffffff, 1, 0);
 
-	bru->bgcolor = 0;
+	brx->bgcolor = 0;
 
-	bru->entity.subdev.ctrl_handler = &bru->ctrls;
+	brx->entity.subdev.ctrl_handler = &brx->ctrls;
 
-	if (bru->ctrls.error) {
+	if (brx->ctrls.error) {
 		dev_err(vsp1->dev, "%s: failed to initialize controls\n", name);
-		ret = bru->ctrls.error;
-		vsp1_entity_destroy(&bru->entity);
+		ret = brx->ctrls.error;
+		vsp1_entity_destroy(&brx->entity);
 		return ERR_PTR(ret);
 	}
 
-	return bru;
+	return brx;
 }
diff --git a/drivers/media/platform/vsp1/vsp1_bru.h b/drivers/media/platform/vsp1/vsp1_brx.h
similarity index 66%
rename from drivers/media/platform/vsp1/vsp1_bru.h
rename to drivers/media/platform/vsp1/vsp1_brx.h
index c98ed96d8de6..927aa4254c0f 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.h
+++ b/drivers/media/platform/vsp1/vsp1_brx.h
@@ -1,5 +1,5 @@
 /*
- * vsp1_bru.h  --  R-Car VSP1 Blend ROP Unit
+ * vsp1_brx.h  --  R-Car VSP1 Blend ROP Unit (BRU and BRS)
  *
  * Copyright (C) 2013 Renesas Corporation
  *
@@ -10,8 +10,8 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-#ifndef __VSP1_BRU_H__
-#define __VSP1_BRU_H__
+#ifndef __VSP1_BRX_H__
+#define __VSP1_BRX_H__
 
 #include <media/media-entity.h>
 #include <media/v4l2-ctrls.h>
@@ -22,9 +22,9 @@
 struct vsp1_device;
 struct vsp1_rwpf;
 
-#define BRU_PAD_SINK(n)				(n)
+#define BRX_PAD_SINK(n)				(n)
 
-struct vsp1_bru {
+struct vsp1_brx {
 	struct vsp1_entity entity;
 	unsigned int base;
 
@@ -37,12 +37,12 @@ struct vsp1_bru {
 	u32 bgcolor;
 };
 
-static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev)
+static inline struct vsp1_brx *to_brx(struct v4l2_subdev *subdev)
 {
-	return container_of(subdev, struct vsp1_bru, entity.subdev);
+	return container_of(subdev, struct vsp1_brx, entity.subdev);
 }
 
-struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1,
+struct vsp1_brx *vsp1_brx_create(struct vsp1_device *vsp1,
 				 enum vsp1_entity_type type);
 
-#endif /* __VSP1_BRU_H__ */
+#endif /* __VSP1_BRX_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 521bbc227110..50496343bbdb 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -20,14 +20,14 @@
 #include <media/vsp1.h>
 
 #include "vsp1.h"
-#include "vsp1_bru.h"
+#include "vsp1_brx.h"
 #include "vsp1_dl.h"
 #include "vsp1_drm.h"
 #include "vsp1_lif.h"
 #include "vsp1_pipe.h"
 #include "vsp1_rwpf.h"
 
-#define BRU_NAME(e)	(e)->type == VSP1_ENTITY_BRU ? "BRU" : "BRS"
+#define BRX_NAME(e)	(e)->type == VSP1_ENTITY_BRU ? "BRU" : "BRS"
 
 /* -----------------------------------------------------------------------------
  * Interrupt Handling
@@ -43,7 +43,7 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
 				      completed && !notify);
 
 	if (notify) {
-		drm_pipe->force_bru_release = false;
+		drm_pipe->force_brx_release = false;
 		wake_up(&drm_pipe->wait_queue);
 	}
 }
@@ -52,11 +52,11 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
  * Pipeline Configuration
  */
 
-/* Setup one RPF and the connected BRU sink pad. */
+/* Setup one RPF and the connected BRx sink pad. */
 static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
 				      struct vsp1_pipeline *pipe,
 				      struct vsp1_rwpf *rpf,
-				      unsigned int bru_input)
+				      unsigned int brx_input)
 {
 	struct v4l2_subdev_selection sel;
 	struct v4l2_subdev_format format;
@@ -65,7 +65,7 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
 
 	/*
 	 * Configure the format on the RPF sink pad and propagate it up to the
-	 * BRU sink pad.
+	 * BRx sink pad.
 	 */
 	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
 
@@ -126,114 +126,114 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
 	if (ret < 0)
 		return ret;
 
-	/* BRU sink, propagate the format from the RPF source. */
-	format.pad = bru_input;
+	/* BRx sink, propagate the format from the RPF source. */
+	format.pad = brx_input;
 
-	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
+	ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_fmt, NULL,
 			       &format);
 	if (ret < 0)
 		return ret;
 
 	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
 		__func__, format.format.width, format.format.height,
-		format.format.code, BRU_NAME(pipe->bru), format.pad);
+		format.format.code, BRX_NAME(pipe->brx), format.pad);
 
-	sel.pad = bru_input;
+	sel.pad = brx_input;
 	sel.target = V4L2_SEL_TGT_COMPOSE;
 	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
 
-	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL,
+	ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_selection, NULL,
 			       &sel);
 	if (ret < 0)
 		return ret;
 
 	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
 		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
-		BRU_NAME(pipe->bru), sel.pad);
+		BRX_NAME(pipe->brx), sel.pad);
 
 	return 0;
 }
 
-/* Setup the BRU source pad. */
+/* Setup the BRx source pad. */
 static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 					struct vsp1_pipeline *pipe);
 static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe);
 
-static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
+static int vsp1_du_pipeline_setup_brx(struct vsp1_device *vsp1,
 				      struct vsp1_pipeline *pipe)
 {
 	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
 	struct v4l2_subdev_format format = {
 		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
 	};
-	struct vsp1_entity *bru;
+	struct vsp1_entity *brx;
 	int ret;
 
 	/*
-	 * Pick a BRU:
-	 * - If we need more than two inputs, use the main BRU.
-	 * - Otherwise, if we are not forced to release our BRU, keep it.
-	 * - Else, use any free BRU (randomly starting with the main BRU).
+	 * Pick a BRx:
+	 * - If we need more than two inputs, use the BRU.
+	 * - Otherwise, if we are not forced to release our BRx, keep it.
+	 * - Else, use any free BRx (randomly starting with the BRU).
 	 */
 	if (pipe->num_inputs > 2)
-		bru = &vsp1->bru->entity;
-	else if (pipe->bru && !drm_pipe->force_bru_release)
-		bru = pipe->bru;
+		brx = &vsp1->bru->entity;
+	else if (pipe->brx && !drm_pipe->force_brx_release)
+		brx = pipe->brx;
 	else if (!vsp1->bru->entity.pipe)
-		bru = &vsp1->bru->entity;
+		brx = &vsp1->bru->entity;
 	else
-		bru = &vsp1->brs->entity;
+		brx = &vsp1->brs->entity;
 
-	/* Switch BRU if needed. */
-	if (bru != pipe->bru) {
-		struct vsp1_entity *released_bru = NULL;
+	/* Switch BRx if needed. */
+	if (brx != pipe->brx) {
+		struct vsp1_entity *released_brx = NULL;
 
-		/* Release our BRU if we have one. */
-		if (pipe->bru) {
+		/* Release our BRx if we have one. */
+		if (pipe->brx) {
 			dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
 				__func__, pipe->lif->index,
-				BRU_NAME(pipe->bru));
+				BRX_NAME(pipe->brx));
 
 			/*
-			 * The BRU might be acquired by the other pipeline in
+			 * The BRx might be acquired by the other pipeline in
 			 * the next step. We must thus remove it from the list
 			 * of entities for this pipeline. The other pipeline's
-			 * hardware configuration will reconfigure the BRU
+			 * hardware configuration will reconfigure the BRx
 			 * routing.
 			 *
 			 * However, if the other pipeline doesn't acquire our
-			 * BRU, we need to keep it in the list, otherwise the
+			 * BRx, we need to keep it in the list, otherwise the
 			 * hardware configuration step won't disconnect it from
-			 * the pipeline. To solve this, store the released BRU
+			 * the pipeline. To solve this, store the released BRx
 			 * pointer to add it back to the list of entities later
 			 * if it isn't acquired by the other pipeline.
 			 */
-			released_bru = pipe->bru;
+			released_brx = pipe->brx;
 
-			list_del(&pipe->bru->list_pipe);
-			pipe->bru->sink = NULL;
-			pipe->bru->pipe = NULL;
-			pipe->bru = NULL;
+			list_del(&pipe->brx->list_pipe);
+			pipe->brx->sink = NULL;
+			pipe->brx->pipe = NULL;
+			pipe->brx = NULL;
 		}
 
 		/*
-		 * If the BRU we need is in use, force the owner pipeline to
-		 * switch to the other BRU and wait until the switch completes.
+		 * If the BRx we need is in use, force the owner pipeline to
+		 * switch to the other BRx and wait until the switch completes.
 		 */
-		if (bru->pipe) {
+		if (brx->pipe) {
 			struct vsp1_drm_pipeline *owner_pipe;
 
 			dev_dbg(vsp1->dev, "%s: pipe %u: waiting for %s\n",
-				__func__, pipe->lif->index, BRU_NAME(bru));
+				__func__, pipe->lif->index, BRX_NAME(brx));
 
-			owner_pipe = to_vsp1_drm_pipeline(bru->pipe);
-			owner_pipe->force_bru_release = true;
+			owner_pipe = to_vsp1_drm_pipeline(brx->pipe);
+			owner_pipe->force_brx_release = true;
 
 			vsp1_du_pipeline_setup_input(vsp1, &owner_pipe->pipe);
 			vsp1_du_pipeline_configure(&owner_pipe->pipe);
 
 			ret = wait_event_timeout(owner_pipe->wait_queue,
-						 !owner_pipe->force_bru_release,
+						 !owner_pipe->force_brx_release,
 						 msecs_to_jiffies(500));
 			if (ret == 0)
 				dev_warn(vsp1->dev,
@@ -242,46 +242,46 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
 		}
 
 		/*
-		 * If the BRU we have released previously hasn't been acquired
+		 * If the BRx we have released previously hasn't been acquired
 		 * by the other pipeline, add it back to the entities list (with
 		 * the pipe pointer NULL) to let vsp1_du_pipeline_configure()
 		 * disconnect it from the hardware pipeline.
 		 */
-		if (released_bru && !released_bru->pipe)
-			list_add_tail(&released_bru->list_pipe,
+		if (released_brx && !released_brx->pipe)
+			list_add_tail(&released_brx->list_pipe,
 				      &pipe->entities);
 
-		/* Add the BRU to the pipeline. */
+		/* Add the BRx to the pipeline. */
 		dev_dbg(vsp1->dev, "%s: pipe %u: acquired %s\n",
-			__func__, pipe->lif->index, BRU_NAME(bru));
+			__func__, pipe->lif->index, BRX_NAME(brx));
 
-		pipe->bru = bru;
-		pipe->bru->pipe = pipe;
-		pipe->bru->sink = &pipe->output->entity;
-		pipe->bru->sink_pad = 0;
+		pipe->brx = brx;
+		pipe->brx->pipe = pipe;
+		pipe->brx->sink = &pipe->output->entity;
+		pipe->brx->sink_pad = 0;
 
-		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
+		list_add_tail(&pipe->brx->list_pipe, &pipe->entities);
 	}
 
 	/*
-	 * Configure the format on the BRU source and verify that it matches the
+	 * Configure the format on the BRx source and verify that it matches the
 	 * requested format. We don't set the media bus code as it is configured
-	 * on the BRU sink pad 0 and propagated inside the entity, not on the
+	 * on the BRx sink pad 0 and propagated inside the entity, not on the
 	 * source pad.
 	 */
-	format.pad = pipe->bru->source_pad;
+	format.pad = pipe->brx->source_pad;
 	format.format.width = drm_pipe->width;
 	format.format.height = drm_pipe->height;
 	format.format.field = V4L2_FIELD_NONE;
 
-	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
+	ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_fmt, NULL,
 			       &format);
 	if (ret < 0)
 		return ret;
 
 	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
 		__func__, format.format.width, format.format.height,
-		format.format.code, BRU_NAME(pipe->bru), pipe->bru->source_pad);
+		format.format.code, BRX_NAME(pipe->brx), pipe->brx->source_pad);
 
 	if (format.format.width != drm_pipe->width ||
 	    format.format.height != drm_pipe->height) {
@@ -297,12 +297,12 @@ static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
 	return vsp1->drm->inputs[rpf->entity.index].zpos;
 }
 
-/* Setup the input side of the pipeline (RPFs and BRU). */
+/* Setup the input side of the pipeline (RPFs and BRx). */
 static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 					struct vsp1_pipeline *pipe)
 {
 	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
-	struct vsp1_bru *bru;
+	struct vsp1_brx *brx;
 	unsigned int i;
 	int ret;
 
@@ -327,25 +327,25 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 	}
 
 	/*
-	 * Setup the BRU. This must be done before setting up the RPF input
-	 * pipelines as the BRU sink compose rectangles depend on the BRU source
+	 * Setup the BRx. This must be done before setting up the RPF input
+	 * pipelines as the BRx sink compose rectangles depend on the BRx source
 	 * format.
 	 */
-	ret = vsp1_du_pipeline_setup_bru(vsp1, pipe);
+	ret = vsp1_du_pipeline_setup_brx(vsp1, pipe);
 	if (ret < 0) {
 		dev_err(vsp1->dev, "%s: failed to setup %s source\n", __func__,
-			BRU_NAME(pipe->bru));
+			BRX_NAME(pipe->brx));
 		return ret;
 	}
 
-	bru = to_bru(&pipe->bru->subdev);
+	brx = to_brx(&pipe->brx->subdev);
 
 	/* Setup the RPF input pipeline for every enabled input. */
-	for (i = 0; i < pipe->bru->source_pad; ++i) {
+	for (i = 0; i < pipe->brx->source_pad; ++i) {
 		struct vsp1_rwpf *rpf = inputs[i];
 
 		if (!rpf) {
-			bru->inputs[i].rpf = NULL;
+			brx->inputs[i].rpf = NULL;
 			continue;
 		}
 
@@ -354,13 +354,13 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
 		}
 
-		bru->inputs[i].rpf = rpf;
-		rpf->bru_input = i;
-		rpf->entity.sink = pipe->bru;
+		brx->inputs[i].rpf = rpf;
+		rpf->brx_input = i;
+		rpf->entity.sink = pipe->brx;
 		rpf->entity.sink_pad = i;
 
 		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
-			__func__, rpf->entity.index, BRU_NAME(pipe->bru), i);
+			__func__, rpf->entity.index, BRX_NAME(pipe->brx), i);
 
 		ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, i);
 		if (ret < 0) {
@@ -468,7 +468,7 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
 		}
 	}
 
-	vsp1_dl_list_commit(dl, drm_pipe->force_bru_release);
+	vsp1_dl_list_commit(dl, drm_pipe->force_brx_release);
 }
 
 /* -----------------------------------------------------------------------------
@@ -493,8 +493,8 @@ EXPORT_SYMBOL_GPL(vsp1_du_init);
  * @cfg: the LIF configuration
  *
  * Configure the output part of VSP DRM pipeline for the given frame @cfg.width
- * and @cfg.height. This sets up formats on the blend unit (BRU or BRS) source
- * pad, the WPF sink and source pads, and the LIF sink pad.
+ * and @cfg.height. This sets up formats on the BRx source pad, the WPF sink and
+ * source pads, and the LIF sink pad.
  *
  * The @pipe_index argument selects which DRM pipeline to setup. The number of
  * available pipelines depend on the VSP instance.
@@ -524,11 +524,11 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	pipe = &drm_pipe->pipe;
 
 	if (!cfg) {
-		struct vsp1_bru *bru;
+		struct vsp1_brx *brx;
 
 		mutex_lock(&vsp1->drm->lock);
 
-		bru = to_bru(&pipe->bru->subdev);
+		brx = to_brx(&pipe->brx->subdev);
 
 		/*
 		 * NULL configuration means the CRTC is being disabled, stop
@@ -545,7 +545,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 				continue;
 
 			/*
-			 * Remove the RPF from the pipe and the list of BRU
+			 * Remove the RPF from the pipe and the list of BRx
 			 * inputs.
 			 */
 			WARN_ON(!rpf->entity.pipe);
@@ -553,7 +553,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 			list_del(&rpf->entity.list_pipe);
 			pipe->inputs[i] = NULL;
 
-			bru->inputs[rpf->bru_input].rpf = NULL;
+			brx->inputs[rpf->brx_input].rpf = NULL;
 		}
 
 		drm_pipe->du_complete = NULL;
@@ -561,11 +561,11 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 
 		dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
 			__func__, pipe->lif->index,
-			BRU_NAME(pipe->bru));
+			BRX_NAME(pipe->brx));
 
-		list_del(&pipe->bru->list_pipe);
-		pipe->bru->pipe = NULL;
-		pipe->bru = NULL;
+		list_del(&pipe->brx->list_pipe);
+		pipe->brx->pipe = NULL;
+		pipe->brx = NULL;
 
 		mutex_unlock(&vsp1->drm->lock);
 
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
index c84bc1c456c0..d738cc57f0e3 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.h
+++ b/drivers/media/platform/vsp1/vsp1_drm.h
@@ -24,8 +24,8 @@
  * @pipe: the VSP1 pipeline used for display
  * @width: output display width
  * @height: output display height
- * @force_bru_release: when set, release the BRU during the next reconfiguration
- * @wait_queue: wait queue to wait for BRU release completion
+ * @force_brx_release: when set, release the BRx during the next reconfiguration
+ * @wait_queue: wait queue to wait for BRx release completion
  * @du_complete: frame completion callback for the DU driver (optional)
  * @du_private: data to be passed to the du_complete callback
  */
@@ -35,7 +35,7 @@ struct vsp1_drm_pipeline {
 	unsigned int width;
 	unsigned int height;
 
-	bool force_bru_release;
+	bool force_brx_release;
 	wait_queue_head_t wait_queue;
 
 	/* Frame synchronisation */
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 58a7993f2306..f41cd70409db 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -26,7 +26,7 @@
 #include <media/v4l2-subdev.h>
 
 #include "vsp1.h"
-#include "vsp1_bru.h"
+#include "vsp1_brx.h"
 #include "vsp1_clu.h"
 #include "vsp1_dl.h"
 #include "vsp1_drm.h"
@@ -269,7 +269,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 
 	/* Instantiate all the entities. */
 	if (vsp1->info->features & VSP1_HAS_BRS) {
-		vsp1->brs = vsp1_bru_create(vsp1, VSP1_ENTITY_BRS);
+		vsp1->brs = vsp1_brx_create(vsp1, VSP1_ENTITY_BRS);
 		if (IS_ERR(vsp1->brs)) {
 			ret = PTR_ERR(vsp1->brs);
 			goto done;
@@ -279,7 +279,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 	}
 
 	if (vsp1->info->features & VSP1_HAS_BRU) {
-		vsp1->bru = vsp1_bru_create(vsp1, VSP1_ENTITY_BRU);
+		vsp1->bru = vsp1_brx_create(vsp1, VSP1_ENTITY_BRU);
 		if (IS_ERR(vsp1->bru)) {
 			ret = PTR_ERR(vsp1->bru);
 			goto done;
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
index 4d819c9019f4..45da3ff10955 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.c
+++ b/drivers/media/platform/vsp1/vsp1_pipe.c
@@ -20,7 +20,7 @@
 #include <media/v4l2-subdev.h>
 
 #include "vsp1.h"
-#include "vsp1_bru.h"
+#include "vsp1_brx.h"
 #include "vsp1_dl.h"
 #include "vsp1_entity.h"
 #include "vsp1_hgo.h"
@@ -188,11 +188,11 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
 	struct vsp1_entity *entity;
 	unsigned int i;
 
-	if (pipe->bru) {
-		struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
+	if (pipe->brx) {
+		struct vsp1_brx *brx = to_brx(&pipe->brx->subdev);
 
-		for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i)
-			bru->inputs[i].rpf = NULL;
+		for (i = 0; i < ARRAY_SIZE(brx->inputs); ++i)
+			brx->inputs[i].rpf = NULL;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i)
@@ -207,7 +207,7 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
 	pipe->state = VSP1_PIPELINE_STOPPED;
 	pipe->buffers_ready = 0;
 	pipe->num_inputs = 0;
-	pipe->bru = NULL;
+	pipe->brx = NULL;
 	pipe->hgo = NULL;
 	pipe->hgt = NULL;
 	pipe->lif = NULL;
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
index 482711024fa2..9eca9fe16724 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.h
+++ b/drivers/media/platform/vsp1/vsp1_pipe.h
@@ -99,7 +99,7 @@ struct vsp1_partition {
  * @num_inputs: number of RPFs
  * @inputs: array of RPFs in the pipeline (indexed by RPF index)
  * @output: WPF at the output of the pipeline
- * @bru: BRU entity, if present
+ * @brx: BRx entity, if present
  * @hgo: HGO entity, if present
  * @hgt: HGT entity, if present
  * @lif: LIF entity, if present
@@ -130,7 +130,7 @@ struct vsp1_pipeline {
 	unsigned int num_inputs;
 	struct vsp1_rwpf *inputs[VSP1_MAX_RPF];
 	struct vsp1_rwpf *output;
-	struct vsp1_entity *bru;
+	struct vsp1_entity *brx;
 	struct vsp1_entity *hgo;
 	struct vsp1_entity *hgt;
 	struct vsp1_entity *lif;
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index fe0633da5a5f..7e74c2015070 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -167,12 +167,12 @@ static void rpf_configure(struct vsp1_entity *entity,
 	vsp1_rpf_write(rpf, dl, VI6_RPF_DSWAP, fmtinfo->swap);
 
 	/* Output location */
-	if (pipe->bru) {
+	if (pipe->brx) {
 		const struct v4l2_rect *compose;
 
-		compose = vsp1_entity_get_pad_selection(pipe->bru,
-							pipe->bru->config,
-							rpf->bru_input,
+		compose = vsp1_entity_get_pad_selection(pipe->brx,
+							pipe->brx->config,
+							rpf->brx_input,
 							V4L2_SEL_TGT_COMPOSE);
 		left = compose->left;
 		top = compose->top;
@@ -191,10 +191,10 @@ static void rpf_configure(struct vsp1_entity *entity,
 	 * alpha channel by a fixed global alpha value, and multiply the pixel
 	 * components to convert the input to premultiplied alpha.
 	 *
-	 * As alpha premultiplication is available in the BRU for both Gen2 and
+	 * As alpha premultiplication is available in the BRx for both Gen2 and
 	 * Gen3 we handle it there and use the Gen3 alpha multiplier for global
 	 * alpha multiplication only. This however prevents conversion to
-	 * premultiplied alpha if no BRU is present in the pipeline. If that use
+	 * premultiplied alpha if no BRx is present in the pipeline. If that use
 	 * case turns out to be useful we will revisit the implementation (for
 	 * Gen3 only).
 	 *
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index c94ac89abfa7..915aeadb21dd 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -45,7 +45,7 @@ struct vsp1_rwpf {
 
 	struct v4l2_pix_format_mplane format;
 	const struct vsp1_format_info *fmtinfo;
-	unsigned int bru_input;
+	unsigned int brx_input;
 
 	unsigned int alpha;
 
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 483b4259e1b4..1958d241d19b 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -28,7 +28,7 @@
 #include <media/videobuf2-dma-contig.h>
 
 #include "vsp1.h"
-#include "vsp1_bru.h"
+#include "vsp1_brx.h"
 #include "vsp1_dl.h"
 #include "vsp1_entity.h"
 #include "vsp1_hgo.h"
@@ -488,7 +488,7 @@ static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
 	struct media_entity_enum ent_enum;
 	struct vsp1_entity *entity;
 	struct media_pad *pad;
-	struct vsp1_bru *bru = NULL;
+	struct vsp1_brx *brx = NULL;
 	int ret;
 
 	ret = media_entity_enum_init(&ent_enum, &input->entity.vsp1->media_dev);
@@ -524,14 +524,14 @@ static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
 		if (entity->type == VSP1_ENTITY_BRU ||
 		    entity->type == VSP1_ENTITY_BRS) {
 			/* BRU and BRS can't be chained. */
-			if (bru) {
+			if (brx) {
 				ret = -EPIPE;
 				goto out;
 			}
 
-			bru = to_bru(&entity->subdev);
-			bru->inputs[pad->index].rpf = input;
-			input->bru_input = pad->index;
+			brx = to_brx(&entity->subdev);
+			brx->inputs[pad->index].rpf = input;
+			input->brx_input = pad->index;
 		}
 
 		/* We've reached the WPF, we're done. */
@@ -553,7 +553,7 @@ static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
 			}
 
 			pipe->uds = entity;
-			pipe->uds_input = bru ? &bru->entity : &input->entity;
+			pipe->uds_input = brx ? &brx->entity : &input->entity;
 		}
 
 		/* Follow the source link, ignoring any HGO or HGT. */
@@ -619,7 +619,7 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe,
 
 		case VSP1_ENTITY_BRU:
 		case VSP1_ENTITY_BRS:
-			pipe->bru = e;
+			pipe->brx = e;
 			break;
 
 		case VSP1_ENTITY_HGO:
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index f7f3b4b2c2de..76f2686e292f 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -436,7 +436,7 @@ static void wpf_configure(struct vsp1_entity *entity,
 	vsp1_dl_list_write(dl, VI6_WPF_WRBCK_CTRL, 0);
 
 	/*
-	 * Sources. If the pipeline has a single input and BRU is not used,
+	 * Sources. If the pipeline has a single input and BRx is not used,
 	 * configure it as the master layer. Otherwise configure all
 	 * inputs as sub-layers and select the virtual RPF as the master
 	 * layer.
@@ -447,13 +447,13 @@ static void wpf_configure(struct vsp1_entity *entity,
 		if (!input)
 			continue;
 
-		srcrpf |= (!pipe->bru && pipe->num_inputs == 1)
+		srcrpf |= (!pipe->brx && pipe->num_inputs == 1)
 			? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index)
 			: VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index);
 	}
 
-	if (pipe->bru || pipe->num_inputs > 1)
-		srcrpf |= pipe->bru->type == VSP1_ENTITY_BRU
+	if (pipe->brx || pipe->num_inputs > 1)
+		srcrpf |= pipe->brx->type == VSP1_ENTITY_BRU
 			? VI6_WPF_SRCRPF_VIRACT_MST
 			: VI6_WPF_SRCRPF_VIRACT2_MST;
 
-- 
Regards,

Laurent Pinchart

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

* [PATCH 15/15] v4l: vsp1: Rename BRU to BRx
@ 2018-02-26 21:45   ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-26 21:45 UTC (permalink / raw)
  To: linux-media; +Cc: linux-renesas-soc, Kieran Bingham, dri-devel

Some VSP instances have two blending units named BRU (Blend/ROP Unit)
and BRS (Blend/ROP Sub unit). The BRS is a smaller version of the BRU
with only two inputs, but otherwise offers similar features and offers
the same register interface. The BRU and BRS can be used exchangeably in
VSP pipelines (provided no more than two inputs are needed).

Due to historical reasons, the VSP1 driver implements support for both
the BRU and BRS through objects named vsp1_bru. The code uses the name
BRU to refer to either the BRU or the BRS, except in a few places where
noted explicitly. This creates confusion.

In an effort to avoid confusion, rename the vsp1_bru object and the
corresponding API to vsp1_brx, and use BRx to refer to blend unit
instances regardless of their type. The names BRU and BRS are retained
where reference to a particular blend unit type is needed, as well as in
hardware registers to stay close to the datasheet.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/media/platform/vsp1/Makefile               |   2 +-
 drivers/media/platform/vsp1/vsp1.h                 |   6 +-
 .../media/platform/vsp1/{vsp1_bru.c => vsp1_brx.c} | 202 ++++++++++-----------
 .../media/platform/vsp1/{vsp1_bru.h => vsp1_brx.h} |  18 +-
 drivers/media/platform/vsp1/vsp1_drm.c             | 172 +++++++++---------
 drivers/media/platform/vsp1/vsp1_drm.h             |   6 +-
 drivers/media/platform/vsp1/vsp1_drv.c             |   6 +-
 drivers/media/platform/vsp1/vsp1_pipe.c            |  12 +-
 drivers/media/platform/vsp1/vsp1_pipe.h            |   4 +-
 drivers/media/platform/vsp1/vsp1_rpf.c             |  12 +-
 drivers/media/platform/vsp1/vsp1_rwpf.h            |   2 +-
 drivers/media/platform/vsp1/vsp1_video.c           |  16 +-
 drivers/media/platform/vsp1/vsp1_wpf.c             |   8 +-
 13 files changed, 233 insertions(+), 233 deletions(-)
 rename drivers/media/platform/vsp1/{vsp1_bru.c => vsp1_brx.c} (63%)
 rename drivers/media/platform/vsp1/{vsp1_bru.h => vsp1_brx.h} (66%)

diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile
index f5cd6f0491cb..596775f932c0 100644
--- a/drivers/media/platform/vsp1/Makefile
+++ b/drivers/media/platform/vsp1/Makefile
@@ -3,7 +3,7 @@ vsp1-y					:= vsp1_drv.o vsp1_entity.o vsp1_pipe.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_clu.o vsp1_hsit.o vsp1_lut.o
-vsp1-y					+= vsp1_bru.o vsp1_sru.o vsp1_uds.o
+vsp1-y					+= vsp1_brx.o vsp1_sru.o vsp1_uds.o
 vsp1-y					+= vsp1_hgo.o vsp1_hgt.o vsp1_histo.o
 vsp1-y					+= vsp1_lif.o
 
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 78ef838416b3..894cc725c2d4 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -30,7 +30,7 @@ struct rcar_fcp_device;
 struct vsp1_drm;
 struct vsp1_entity;
 struct vsp1_platform_data;
-struct vsp1_bru;
+struct vsp1_brx;
 struct vsp1_clu;
 struct vsp1_hgo;
 struct vsp1_hgt;
@@ -78,8 +78,8 @@ struct vsp1_device {
 	struct rcar_fcp_device *fcp;
 	struct device *bus_master;
 
-	struct vsp1_bru *brs;
-	struct vsp1_bru *bru;
+	struct vsp1_brx *brs;
+	struct vsp1_brx *bru;
 	struct vsp1_clu *clu;
 	struct vsp1_hgo *hgo;
 	struct vsp1_hgt *hgt;
diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_brx.c
similarity index 63%
rename from drivers/media/platform/vsp1/vsp1_bru.c
rename to drivers/media/platform/vsp1/vsp1_brx.c
index e8fd2ae3b3eb..b4af1d546022 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.c
+++ b/drivers/media/platform/vsp1/vsp1_brx.c
@@ -1,5 +1,5 @@
 /*
- * vsp1_bru.c  --  R-Car VSP1 Blend ROP Unit
+ * vsp1_brx.c  --  R-Car VSP1 Blend ROP Unit (BRU and BRS)
  *
  * Copyright (C) 2013 Renesas Corporation
  *
@@ -17,45 +17,45 @@
 #include <media/v4l2-subdev.h>
 
 #include "vsp1.h"
-#include "vsp1_bru.h"
+#include "vsp1_brx.h"
 #include "vsp1_dl.h"
 #include "vsp1_pipe.h"
 #include "vsp1_rwpf.h"
 #include "vsp1_video.h"
 
-#define BRU_MIN_SIZE				1U
-#define BRU_MAX_SIZE				8190U
+#define BRX_MIN_SIZE				1U
+#define BRX_MAX_SIZE				8190U
 
 /* -----------------------------------------------------------------------------
  * Device Access
  */
 
-static inline void vsp1_bru_write(struct vsp1_bru *bru, struct vsp1_dl_list *dl,
+static inline void vsp1_brx_write(struct vsp1_brx *brx, struct vsp1_dl_list *dl,
 				  u32 reg, u32 data)
 {
-	vsp1_dl_list_write(dl, bru->base + reg, data);
+	vsp1_dl_list_write(dl, brx->base + reg, data);
 }
 
 /* -----------------------------------------------------------------------------
  * Controls
  */
 
-static int bru_s_ctrl(struct v4l2_ctrl *ctrl)
+static int brx_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct vsp1_bru *bru =
-		container_of(ctrl->handler, struct vsp1_bru, ctrls);
+	struct vsp1_brx *brx =
+		container_of(ctrl->handler, struct vsp1_brx, ctrls);
 
 	switch (ctrl->id) {
 	case V4L2_CID_BG_COLOR:
-		bru->bgcolor = ctrl->val;
+		brx->bgcolor = ctrl->val;
 		break;
 	}
 
 	return 0;
 }
 
-static const struct v4l2_ctrl_ops bru_ctrl_ops = {
-	.s_ctrl = bru_s_ctrl,
+static const struct v4l2_ctrl_ops brx_ctrl_ops = {
+	.s_ctrl = brx_s_ctrl,
 };
 
 /* -----------------------------------------------------------------------------
@@ -63,12 +63,12 @@ static const struct v4l2_ctrl_ops bru_ctrl_ops = {
  */
 
 /*
- * The BRU can't perform format conversion, all sink and source formats must be
+ * The BRx can't perform format conversion, all sink and source formats must be
  * identical. We pick the format on the first sink pad (pad 0) and propagate it
  * to all other pads.
  */
 
-static int bru_enum_mbus_code(struct v4l2_subdev *subdev,
+static int brx_enum_mbus_code(struct v4l2_subdev *subdev,
 			      struct v4l2_subdev_pad_config *cfg,
 			      struct v4l2_subdev_mbus_code_enum *code)
 {
@@ -81,7 +81,7 @@ static int bru_enum_mbus_code(struct v4l2_subdev *subdev,
 					  ARRAY_SIZE(codes));
 }
 
-static int bru_enum_frame_size(struct v4l2_subdev *subdev,
+static int brx_enum_frame_size(struct v4l2_subdev *subdev,
 			       struct v4l2_subdev_pad_config *cfg,
 			       struct v4l2_subdev_frame_size_enum *fse)
 {
@@ -92,29 +92,29 @@ static int bru_enum_frame_size(struct v4l2_subdev *subdev,
 	    fse->code != MEDIA_BUS_FMT_AYUV8_1X32)
 		return -EINVAL;
 
-	fse->min_width = BRU_MIN_SIZE;
-	fse->max_width = BRU_MAX_SIZE;
-	fse->min_height = BRU_MIN_SIZE;
-	fse->max_height = BRU_MAX_SIZE;
+	fse->min_width = BRX_MIN_SIZE;
+	fse->max_width = BRX_MAX_SIZE;
+	fse->min_height = BRX_MIN_SIZE;
+	fse->max_height = BRX_MAX_SIZE;
 
 	return 0;
 }
 
-static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru,
+static struct v4l2_rect *brx_get_compose(struct vsp1_brx *brx,
 					 struct v4l2_subdev_pad_config *cfg,
 					 unsigned int pad)
 {
-	return v4l2_subdev_get_try_compose(&bru->entity.subdev, cfg, pad);
+	return v4l2_subdev_get_try_compose(&brx->entity.subdev, cfg, pad);
 }
 
-static void bru_try_format(struct vsp1_bru *bru,
+static void brx_try_format(struct vsp1_brx *brx,
 			   struct v4l2_subdev_pad_config *config,
 			   unsigned int pad, struct v4l2_mbus_framefmt *fmt)
 {
 	struct v4l2_mbus_framefmt *format;
 
 	switch (pad) {
-	case BRU_PAD_SINK(0):
+	case BRX_PAD_SINK(0):
 		/* Default to YUV if the requested format is not supported. */
 		if (fmt->code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
 		    fmt->code != MEDIA_BUS_FMT_AYUV8_1X32)
@@ -122,46 +122,46 @@ static void bru_try_format(struct vsp1_bru *bru,
 		break;
 
 	default:
-		/* The BRU can't perform format conversion. */
-		format = vsp1_entity_get_pad_format(&bru->entity, config,
-						    BRU_PAD_SINK(0));
+		/* The BRx can't perform format conversion. */
+		format = vsp1_entity_get_pad_format(&brx->entity, config,
+						    BRX_PAD_SINK(0));
 		fmt->code = format->code;
 		break;
 	}
 
-	fmt->width = clamp(fmt->width, BRU_MIN_SIZE, BRU_MAX_SIZE);
-	fmt->height = clamp(fmt->height, BRU_MIN_SIZE, BRU_MAX_SIZE);
+	fmt->width = clamp(fmt->width, BRX_MIN_SIZE, BRX_MAX_SIZE);
+	fmt->height = clamp(fmt->height, BRX_MIN_SIZE, BRX_MAX_SIZE);
 	fmt->field = V4L2_FIELD_NONE;
 	fmt->colorspace = V4L2_COLORSPACE_SRGB;
 }
 
-static int bru_set_format(struct v4l2_subdev *subdev,
+static int brx_set_format(struct v4l2_subdev *subdev,
 			  struct v4l2_subdev_pad_config *cfg,
 			  struct v4l2_subdev_format *fmt)
 {
-	struct vsp1_bru *bru = to_bru(subdev);
+	struct vsp1_brx *brx = to_brx(subdev);
 	struct v4l2_subdev_pad_config *config;
 	struct v4l2_mbus_framefmt *format;
 	int ret = 0;
 
-	mutex_lock(&bru->entity.lock);
+	mutex_lock(&brx->entity.lock);
 
-	config = vsp1_entity_get_pad_config(&bru->entity, cfg, fmt->which);
+	config = vsp1_entity_get_pad_config(&brx->entity, cfg, fmt->which);
 	if (!config) {
 		ret = -EINVAL;
 		goto done;
 	}
 
-	bru_try_format(bru, config, fmt->pad, &fmt->format);
+	brx_try_format(brx, config, fmt->pad, &fmt->format);
 
-	format = vsp1_entity_get_pad_format(&bru->entity, config, fmt->pad);
+	format = vsp1_entity_get_pad_format(&brx->entity, config, fmt->pad);
 	*format = fmt->format;
 
 	/* Reset the compose rectangle */
-	if (fmt->pad != bru->entity.source_pad) {
+	if (fmt->pad != brx->entity.source_pad) {
 		struct v4l2_rect *compose;
 
-		compose = bru_get_compose(bru, config, fmt->pad);
+		compose = brx_get_compose(brx, config, fmt->pad);
 		compose->left = 0;
 		compose->top = 0;
 		compose->width = format->width;
@@ -169,48 +169,48 @@ static int bru_set_format(struct v4l2_subdev *subdev,
 	}
 
 	/* Propagate the format code to all pads */
-	if (fmt->pad == BRU_PAD_SINK(0)) {
+	if (fmt->pad == BRX_PAD_SINK(0)) {
 		unsigned int i;
 
-		for (i = 0; i <= bru->entity.source_pad; ++i) {
-			format = vsp1_entity_get_pad_format(&bru->entity,
+		for (i = 0; i <= brx->entity.source_pad; ++i) {
+			format = vsp1_entity_get_pad_format(&brx->entity,
 							    config, i);
 			format->code = fmt->format.code;
 		}
 	}
 
 done:
-	mutex_unlock(&bru->entity.lock);
+	mutex_unlock(&brx->entity.lock);
 	return ret;
 }
 
-static int bru_get_selection(struct v4l2_subdev *subdev,
+static int brx_get_selection(struct v4l2_subdev *subdev,
 			     struct v4l2_subdev_pad_config *cfg,
 			     struct v4l2_subdev_selection *sel)
 {
-	struct vsp1_bru *bru = to_bru(subdev);
+	struct vsp1_brx *brx = to_brx(subdev);
 	struct v4l2_subdev_pad_config *config;
 
-	if (sel->pad == bru->entity.source_pad)
+	if (sel->pad == brx->entity.source_pad)
 		return -EINVAL;
 
 	switch (sel->target) {
 	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
 		sel->r.left = 0;
 		sel->r.top = 0;
-		sel->r.width = BRU_MAX_SIZE;
-		sel->r.height = BRU_MAX_SIZE;
+		sel->r.width = BRX_MAX_SIZE;
+		sel->r.height = BRX_MAX_SIZE;
 		return 0;
 
 	case V4L2_SEL_TGT_COMPOSE:
-		config = vsp1_entity_get_pad_config(&bru->entity, cfg,
+		config = vsp1_entity_get_pad_config(&brx->entity, cfg,
 						    sel->which);
 		if (!config)
 			return -EINVAL;
 
-		mutex_lock(&bru->entity.lock);
-		sel->r = *bru_get_compose(bru, config, sel->pad);
-		mutex_unlock(&bru->entity.lock);
+		mutex_lock(&brx->entity.lock);
+		sel->r = *brx_get_compose(brx, config, sel->pad);
+		mutex_unlock(&brx->entity.lock);
 		return 0;
 
 	default:
@@ -218,25 +218,25 @@ static int bru_get_selection(struct v4l2_subdev *subdev,
 	}
 }
 
-static int bru_set_selection(struct v4l2_subdev *subdev,
+static int brx_set_selection(struct v4l2_subdev *subdev,
 			     struct v4l2_subdev_pad_config *cfg,
 			     struct v4l2_subdev_selection *sel)
 {
-	struct vsp1_bru *bru = to_bru(subdev);
+	struct vsp1_brx *brx = to_brx(subdev);
 	struct v4l2_subdev_pad_config *config;
 	struct v4l2_mbus_framefmt *format;
 	struct v4l2_rect *compose;
 	int ret = 0;
 
-	if (sel->pad == bru->entity.source_pad)
+	if (sel->pad == brx->entity.source_pad)
 		return -EINVAL;
 
 	if (sel->target != V4L2_SEL_TGT_COMPOSE)
 		return -EINVAL;
 
-	mutex_lock(&bru->entity.lock);
+	mutex_lock(&brx->entity.lock);
 
-	config = vsp1_entity_get_pad_config(&bru->entity, cfg, sel->which);
+	config = vsp1_entity_get_pad_config(&brx->entity, cfg, sel->which);
 	if (!config) {
 		ret = -EINVAL;
 		goto done;
@@ -246,8 +246,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, config,
-					    bru->entity.source_pad);
+	format = vsp1_entity_get_pad_format(&brx->entity, config,
+					    brx->entity.source_pad);
 	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);
 
@@ -255,42 +255,42 @@ static int bru_set_selection(struct v4l2_subdev *subdev,
 	 * Scaling isn't supported, the compose rectangle size must be identical
 	 * to the sink format size.
 	 */
-	format = vsp1_entity_get_pad_format(&bru->entity, config, sel->pad);
+	format = vsp1_entity_get_pad_format(&brx->entity, config, sel->pad);
 	sel->r.width = format->width;
 	sel->r.height = format->height;
 
-	compose = bru_get_compose(bru, config, sel->pad);
+	compose = brx_get_compose(brx, config, sel->pad);
 	*compose = sel->r;
 
 done:
-	mutex_unlock(&bru->entity.lock);
+	mutex_unlock(&brx->entity.lock);
 	return ret;
 }
 
-static const struct v4l2_subdev_pad_ops bru_pad_ops = {
+static const struct v4l2_subdev_pad_ops brx_pad_ops = {
 	.init_cfg = vsp1_entity_init_cfg,
-	.enum_mbus_code = bru_enum_mbus_code,
-	.enum_frame_size = bru_enum_frame_size,
+	.enum_mbus_code = brx_enum_mbus_code,
+	.enum_frame_size = brx_enum_frame_size,
 	.get_fmt = vsp1_subdev_get_pad_format,
-	.set_fmt = bru_set_format,
-	.get_selection = bru_get_selection,
-	.set_selection = bru_set_selection,
+	.set_fmt = brx_set_format,
+	.get_selection = brx_get_selection,
+	.set_selection = brx_set_selection,
 };
 
-static const struct v4l2_subdev_ops bru_ops = {
-	.pad    = &bru_pad_ops,
+static const struct v4l2_subdev_ops brx_ops = {
+	.pad    = &brx_pad_ops,
 };
 
 /* -----------------------------------------------------------------------------
  * VSP1 Entity Operations
  */
 
-static void bru_configure(struct vsp1_entity *entity,
+static void brx_configure(struct vsp1_entity *entity,
 			  struct vsp1_pipeline *pipe,
 			  struct vsp1_dl_list *dl,
 			  enum vsp1_entity_params params)
 {
-	struct vsp1_bru *bru = to_bru(&entity->subdev);
+	struct vsp1_brx *brx = to_brx(&entity->subdev);
 	struct v4l2_mbus_framefmt *format;
 	unsigned int flags;
 	unsigned int i;
@@ -298,8 +298,8 @@ static void bru_configure(struct vsp1_entity *entity,
 	if (params != VSP1_ENTITY_PARAMS_INIT)
 		return;
 
-	format = vsp1_entity_get_pad_format(&bru->entity, bru->entity.config,
-					    bru->entity.source_pad);
+	format = vsp1_entity_get_pad_format(&brx->entity, brx->entity.config,
+					    brx->entity.source_pad);
 
 	/*
 	 * The hardware is extremely flexible but we have no userspace API to
@@ -313,7 +313,7 @@ static void bru_configure(struct vsp1_entity *entity,
 	 * format at the pipeline output is premultiplied.
 	 */
 	flags = pipe->output ? pipe->output->format.flags : 0;
-	vsp1_bru_write(bru, dl, VI6_BRU_INCTRL,
+	vsp1_brx_write(brx, dl, VI6_BRU_INCTRL,
 		       flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ?
 		       0 : VI6_BRU_INCTRL_NRM);
 
@@ -321,12 +321,12 @@ static void bru_configure(struct vsp1_entity *entity,
 	 * Set the background position to cover the whole output image and
 	 * configure its color.
 	 */
-	vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_SIZE,
+	vsp1_brx_write(brx, dl, VI6_BRU_VIRRPF_SIZE,
 		       (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) |
 		       (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT));
-	vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_LOC, 0);
+	vsp1_brx_write(brx, dl, VI6_BRU_VIRRPF_LOC, 0);
 
-	vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_COL, bru->bgcolor |
+	vsp1_brx_write(brx, dl, VI6_BRU_VIRRPF_COL, brx->bgcolor |
 		       (0xff << VI6_BRU_VIRRPF_COL_A_SHIFT));
 
 	/*
@@ -336,25 +336,25 @@ static void bru_configure(struct vsp1_entity *entity,
 	 * unit.
 	 */
 	if (entity->type == VSP1_ENTITY_BRU)
-		vsp1_bru_write(bru, dl, VI6_BRU_ROP,
+		vsp1_brx_write(brx, dl, VI6_BRU_ROP,
 			       VI6_BRU_ROP_DSTSEL_BRUIN(1) |
 			       VI6_BRU_ROP_CROP(VI6_ROP_NOP) |
 			       VI6_BRU_ROP_AROP(VI6_ROP_NOP));
 
-	for (i = 0; i < bru->entity.source_pad; ++i) {
+	for (i = 0; i < brx->entity.source_pad; ++i) {
 		bool premultiplied = false;
 		u32 ctrl = 0;
 
 		/*
-		 * Configure all Blend/ROP units corresponding to an enabled BRU
+		 * Configure all Blend/ROP units corresponding to an enabled BRx
 		 * input for alpha blending. Blend/ROP units corresponding to
-		 * disabled BRU inputs are used in ROP NOP mode to ignore the
+		 * disabled BRx inputs are used in ROP NOP mode to ignore the
 		 * SRC input.
 		 */
-		if (bru->inputs[i].rpf) {
+		if (brx->inputs[i].rpf) {
 			ctrl |= VI6_BRU_CTRL_RBC;
 
-			premultiplied = bru->inputs[i].rpf->format.flags
+			premultiplied = brx->inputs[i].rpf->format.flags
 				      & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA;
 		} else {
 			ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP)
@@ -378,7 +378,7 @@ static void bru_configure(struct vsp1_entity *entity,
 		if (!(entity->type == VSP1_ENTITY_BRU && i == 1))
 			ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i);
 
-		vsp1_bru_write(bru, dl, VI6_BRU_CTRL(i), ctrl);
+		vsp1_brx_write(brx, dl, VI6_BRU_CTRL(i), ctrl);
 
 		/*
 		 * Harcode the blending formula to
@@ -393,7 +393,7 @@ static void bru_configure(struct vsp1_entity *entity,
 		 *
 		 * otherwise.
 		 */
-		vsp1_bru_write(bru, dl, VI6_BRU_BLD(i),
+		vsp1_brx_write(brx, dl, VI6_BRU_BLD(i),
 			       VI6_BRU_BLD_CCMDX_255_SRC_A |
 			       (premultiplied ? VI6_BRU_BLD_CCMDY_COEFY :
 						VI6_BRU_BLD_CCMDY_SRC_A) |
@@ -403,29 +403,29 @@ static void bru_configure(struct vsp1_entity *entity,
 	}
 }
 
-static const struct vsp1_entity_operations bru_entity_ops = {
-	.configure = bru_configure,
+static const struct vsp1_entity_operations brx_entity_ops = {
+	.configure = brx_configure,
 };
 
 /* -----------------------------------------------------------------------------
  * Initialization and Cleanup
  */
 
-struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1,
+struct vsp1_brx *vsp1_brx_create(struct vsp1_device *vsp1,
 				 enum vsp1_entity_type type)
 {
-	struct vsp1_bru *bru;
+	struct vsp1_brx *brx;
 	unsigned int num_pads;
 	const char *name;
 	int ret;
 
-	bru = devm_kzalloc(vsp1->dev, sizeof(*bru), GFP_KERNEL);
-	if (bru == NULL)
+	brx = devm_kzalloc(vsp1->dev, sizeof(*brx), GFP_KERNEL);
+	if (brx == NULL)
 		return ERR_PTR(-ENOMEM);
 
-	bru->base = type == VSP1_ENTITY_BRU ? VI6_BRU_BASE : VI6_BRS_BASE;
-	bru->entity.ops = &bru_entity_ops;
-	bru->entity.type = type;
+	brx->base = type == VSP1_ENTITY_BRU ? VI6_BRU_BASE : VI6_BRS_BASE;
+	brx->entity.ops = &brx_entity_ops;
+	brx->entity.type = type;
 
 	if (type == VSP1_ENTITY_BRU) {
 		num_pads = vsp1->info->num_bru_inputs + 1;
@@ -435,26 +435,26 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1,
 		name = "brs";
 	}
 
-	ret = vsp1_entity_init(vsp1, &bru->entity, name, num_pads, &bru_ops,
+	ret = vsp1_entity_init(vsp1, &brx->entity, name, num_pads, &brx_ops,
 			       MEDIA_ENT_F_PROC_VIDEO_COMPOSER);
 	if (ret < 0)
 		return ERR_PTR(ret);
 
 	/* Initialize the control handler. */
-	v4l2_ctrl_handler_init(&bru->ctrls, 1);
-	v4l2_ctrl_new_std(&bru->ctrls, &bru_ctrl_ops, V4L2_CID_BG_COLOR,
+	v4l2_ctrl_handler_init(&brx->ctrls, 1);
+	v4l2_ctrl_new_std(&brx->ctrls, &brx_ctrl_ops, V4L2_CID_BG_COLOR,
 			  0, 0xffffff, 1, 0);
 
-	bru->bgcolor = 0;
+	brx->bgcolor = 0;
 
-	bru->entity.subdev.ctrl_handler = &bru->ctrls;
+	brx->entity.subdev.ctrl_handler = &brx->ctrls;
 
-	if (bru->ctrls.error) {
+	if (brx->ctrls.error) {
 		dev_err(vsp1->dev, "%s: failed to initialize controls\n", name);
-		ret = bru->ctrls.error;
-		vsp1_entity_destroy(&bru->entity);
+		ret = brx->ctrls.error;
+		vsp1_entity_destroy(&brx->entity);
 		return ERR_PTR(ret);
 	}
 
-	return bru;
+	return brx;
 }
diff --git a/drivers/media/platform/vsp1/vsp1_bru.h b/drivers/media/platform/vsp1/vsp1_brx.h
similarity index 66%
rename from drivers/media/platform/vsp1/vsp1_bru.h
rename to drivers/media/platform/vsp1/vsp1_brx.h
index c98ed96d8de6..927aa4254c0f 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.h
+++ b/drivers/media/platform/vsp1/vsp1_brx.h
@@ -1,5 +1,5 @@
 /*
- * vsp1_bru.h  --  R-Car VSP1 Blend ROP Unit
+ * vsp1_brx.h  --  R-Car VSP1 Blend ROP Unit (BRU and BRS)
  *
  * Copyright (C) 2013 Renesas Corporation
  *
@@ -10,8 +10,8 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-#ifndef __VSP1_BRU_H__
-#define __VSP1_BRU_H__
+#ifndef __VSP1_BRX_H__
+#define __VSP1_BRX_H__
 
 #include <media/media-entity.h>
 #include <media/v4l2-ctrls.h>
@@ -22,9 +22,9 @@
 struct vsp1_device;
 struct vsp1_rwpf;
 
-#define BRU_PAD_SINK(n)				(n)
+#define BRX_PAD_SINK(n)				(n)
 
-struct vsp1_bru {
+struct vsp1_brx {
 	struct vsp1_entity entity;
 	unsigned int base;
 
@@ -37,12 +37,12 @@ struct vsp1_bru {
 	u32 bgcolor;
 };
 
-static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev)
+static inline struct vsp1_brx *to_brx(struct v4l2_subdev *subdev)
 {
-	return container_of(subdev, struct vsp1_bru, entity.subdev);
+	return container_of(subdev, struct vsp1_brx, entity.subdev);
 }
 
-struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1,
+struct vsp1_brx *vsp1_brx_create(struct vsp1_device *vsp1,
 				 enum vsp1_entity_type type);
 
-#endif /* __VSP1_BRU_H__ */
+#endif /* __VSP1_BRX_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
index 521bbc227110..50496343bbdb 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.c
+++ b/drivers/media/platform/vsp1/vsp1_drm.c
@@ -20,14 +20,14 @@
 #include <media/vsp1.h>
 
 #include "vsp1.h"
-#include "vsp1_bru.h"
+#include "vsp1_brx.h"
 #include "vsp1_dl.h"
 #include "vsp1_drm.h"
 #include "vsp1_lif.h"
 #include "vsp1_pipe.h"
 #include "vsp1_rwpf.h"
 
-#define BRU_NAME(e)	(e)->type == VSP1_ENTITY_BRU ? "BRU" : "BRS"
+#define BRX_NAME(e)	(e)->type == VSP1_ENTITY_BRU ? "BRU" : "BRS"
 
 /* -----------------------------------------------------------------------------
  * Interrupt Handling
@@ -43,7 +43,7 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
 				      completed && !notify);
 
 	if (notify) {
-		drm_pipe->force_bru_release = false;
+		drm_pipe->force_brx_release = false;
 		wake_up(&drm_pipe->wait_queue);
 	}
 }
@@ -52,11 +52,11 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
  * Pipeline Configuration
  */
 
-/* Setup one RPF and the connected BRU sink pad. */
+/* Setup one RPF and the connected BRx sink pad. */
 static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
 				      struct vsp1_pipeline *pipe,
 				      struct vsp1_rwpf *rpf,
-				      unsigned int bru_input)
+				      unsigned int brx_input)
 {
 	struct v4l2_subdev_selection sel;
 	struct v4l2_subdev_format format;
@@ -65,7 +65,7 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
 
 	/*
 	 * Configure the format on the RPF sink pad and propagate it up to the
-	 * BRU sink pad.
+	 * BRx sink pad.
 	 */
 	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
 
@@ -126,114 +126,114 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
 	if (ret < 0)
 		return ret;
 
-	/* BRU sink, propagate the format from the RPF source. */
-	format.pad = bru_input;
+	/* BRx sink, propagate the format from the RPF source. */
+	format.pad = brx_input;
 
-	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
+	ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_fmt, NULL,
 			       &format);
 	if (ret < 0)
 		return ret;
 
 	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
 		__func__, format.format.width, format.format.height,
-		format.format.code, BRU_NAME(pipe->bru), format.pad);
+		format.format.code, BRX_NAME(pipe->brx), format.pad);
 
-	sel.pad = bru_input;
+	sel.pad = brx_input;
 	sel.target = V4L2_SEL_TGT_COMPOSE;
 	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
 
-	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL,
+	ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_selection, NULL,
 			       &sel);
 	if (ret < 0)
 		return ret;
 
 	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
 		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
-		BRU_NAME(pipe->bru), sel.pad);
+		BRX_NAME(pipe->brx), sel.pad);
 
 	return 0;
 }
 
-/* Setup the BRU source pad. */
+/* Setup the BRx source pad. */
 static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 					struct vsp1_pipeline *pipe);
 static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe);
 
-static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
+static int vsp1_du_pipeline_setup_brx(struct vsp1_device *vsp1,
 				      struct vsp1_pipeline *pipe)
 {
 	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
 	struct v4l2_subdev_format format = {
 		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
 	};
-	struct vsp1_entity *bru;
+	struct vsp1_entity *brx;
 	int ret;
 
 	/*
-	 * Pick a BRU:
-	 * - If we need more than two inputs, use the main BRU.
-	 * - Otherwise, if we are not forced to release our BRU, keep it.
-	 * - Else, use any free BRU (randomly starting with the main BRU).
+	 * Pick a BRx:
+	 * - If we need more than two inputs, use the BRU.
+	 * - Otherwise, if we are not forced to release our BRx, keep it.
+	 * - Else, use any free BRx (randomly starting with the BRU).
 	 */
 	if (pipe->num_inputs > 2)
-		bru = &vsp1->bru->entity;
-	else if (pipe->bru && !drm_pipe->force_bru_release)
-		bru = pipe->bru;
+		brx = &vsp1->bru->entity;
+	else if (pipe->brx && !drm_pipe->force_brx_release)
+		brx = pipe->brx;
 	else if (!vsp1->bru->entity.pipe)
-		bru = &vsp1->bru->entity;
+		brx = &vsp1->bru->entity;
 	else
-		bru = &vsp1->brs->entity;
+		brx = &vsp1->brs->entity;
 
-	/* Switch BRU if needed. */
-	if (bru != pipe->bru) {
-		struct vsp1_entity *released_bru = NULL;
+	/* Switch BRx if needed. */
+	if (brx != pipe->brx) {
+		struct vsp1_entity *released_brx = NULL;
 
-		/* Release our BRU if we have one. */
-		if (pipe->bru) {
+		/* Release our BRx if we have one. */
+		if (pipe->brx) {
 			dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
 				__func__, pipe->lif->index,
-				BRU_NAME(pipe->bru));
+				BRX_NAME(pipe->brx));
 
 			/*
-			 * The BRU might be acquired by the other pipeline in
+			 * The BRx might be acquired by the other pipeline in
 			 * the next step. We must thus remove it from the list
 			 * of entities for this pipeline. The other pipeline's
-			 * hardware configuration will reconfigure the BRU
+			 * hardware configuration will reconfigure the BRx
 			 * routing.
 			 *
 			 * However, if the other pipeline doesn't acquire our
-			 * BRU, we need to keep it in the list, otherwise the
+			 * BRx, we need to keep it in the list, otherwise the
 			 * hardware configuration step won't disconnect it from
-			 * the pipeline. To solve this, store the released BRU
+			 * the pipeline. To solve this, store the released BRx
 			 * pointer to add it back to the list of entities later
 			 * if it isn't acquired by the other pipeline.
 			 */
-			released_bru = pipe->bru;
+			released_brx = pipe->brx;
 
-			list_del(&pipe->bru->list_pipe);
-			pipe->bru->sink = NULL;
-			pipe->bru->pipe = NULL;
-			pipe->bru = NULL;
+			list_del(&pipe->brx->list_pipe);
+			pipe->brx->sink = NULL;
+			pipe->brx->pipe = NULL;
+			pipe->brx = NULL;
 		}
 
 		/*
-		 * If the BRU we need is in use, force the owner pipeline to
-		 * switch to the other BRU and wait until the switch completes.
+		 * If the BRx we need is in use, force the owner pipeline to
+		 * switch to the other BRx and wait until the switch completes.
 		 */
-		if (bru->pipe) {
+		if (brx->pipe) {
 			struct vsp1_drm_pipeline *owner_pipe;
 
 			dev_dbg(vsp1->dev, "%s: pipe %u: waiting for %s\n",
-				__func__, pipe->lif->index, BRU_NAME(bru));
+				__func__, pipe->lif->index, BRX_NAME(brx));
 
-			owner_pipe = to_vsp1_drm_pipeline(bru->pipe);
-			owner_pipe->force_bru_release = true;
+			owner_pipe = to_vsp1_drm_pipeline(brx->pipe);
+			owner_pipe->force_brx_release = true;
 
 			vsp1_du_pipeline_setup_input(vsp1, &owner_pipe->pipe);
 			vsp1_du_pipeline_configure(&owner_pipe->pipe);
 
 			ret = wait_event_timeout(owner_pipe->wait_queue,
-						 !owner_pipe->force_bru_release,
+						 !owner_pipe->force_brx_release,
 						 msecs_to_jiffies(500));
 			if (ret == 0)
 				dev_warn(vsp1->dev,
@@ -242,46 +242,46 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
 		}
 
 		/*
-		 * If the BRU we have released previously hasn't been acquired
+		 * If the BRx we have released previously hasn't been acquired
 		 * by the other pipeline, add it back to the entities list (with
 		 * the pipe pointer NULL) to let vsp1_du_pipeline_configure()
 		 * disconnect it from the hardware pipeline.
 		 */
-		if (released_bru && !released_bru->pipe)
-			list_add_tail(&released_bru->list_pipe,
+		if (released_brx && !released_brx->pipe)
+			list_add_tail(&released_brx->list_pipe,
 				      &pipe->entities);
 
-		/* Add the BRU to the pipeline. */
+		/* Add the BRx to the pipeline. */
 		dev_dbg(vsp1->dev, "%s: pipe %u: acquired %s\n",
-			__func__, pipe->lif->index, BRU_NAME(bru));
+			__func__, pipe->lif->index, BRX_NAME(brx));
 
-		pipe->bru = bru;
-		pipe->bru->pipe = pipe;
-		pipe->bru->sink = &pipe->output->entity;
-		pipe->bru->sink_pad = 0;
+		pipe->brx = brx;
+		pipe->brx->pipe = pipe;
+		pipe->brx->sink = &pipe->output->entity;
+		pipe->brx->sink_pad = 0;
 
-		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
+		list_add_tail(&pipe->brx->list_pipe, &pipe->entities);
 	}
 
 	/*
-	 * Configure the format on the BRU source and verify that it matches the
+	 * Configure the format on the BRx source and verify that it matches the
 	 * requested format. We don't set the media bus code as it is configured
-	 * on the BRU sink pad 0 and propagated inside the entity, not on the
+	 * on the BRx sink pad 0 and propagated inside the entity, not on the
 	 * source pad.
 	 */
-	format.pad = pipe->bru->source_pad;
+	format.pad = pipe->brx->source_pad;
 	format.format.width = drm_pipe->width;
 	format.format.height = drm_pipe->height;
 	format.format.field = V4L2_FIELD_NONE;
 
-	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
+	ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_fmt, NULL,
 			       &format);
 	if (ret < 0)
 		return ret;
 
 	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
 		__func__, format.format.width, format.format.height,
-		format.format.code, BRU_NAME(pipe->bru), pipe->bru->source_pad);
+		format.format.code, BRX_NAME(pipe->brx), pipe->brx->source_pad);
 
 	if (format.format.width != drm_pipe->width ||
 	    format.format.height != drm_pipe->height) {
@@ -297,12 +297,12 @@ static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
 	return vsp1->drm->inputs[rpf->entity.index].zpos;
 }
 
-/* Setup the input side of the pipeline (RPFs and BRU). */
+/* Setup the input side of the pipeline (RPFs and BRx). */
 static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 					struct vsp1_pipeline *pipe)
 {
 	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
-	struct vsp1_bru *bru;
+	struct vsp1_brx *brx;
 	unsigned int i;
 	int ret;
 
@@ -327,25 +327,25 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 	}
 
 	/*
-	 * Setup the BRU. This must be done before setting up the RPF input
-	 * pipelines as the BRU sink compose rectangles depend on the BRU source
+	 * Setup the BRx. This must be done before setting up the RPF input
+	 * pipelines as the BRx sink compose rectangles depend on the BRx source
 	 * format.
 	 */
-	ret = vsp1_du_pipeline_setup_bru(vsp1, pipe);
+	ret = vsp1_du_pipeline_setup_brx(vsp1, pipe);
 	if (ret < 0) {
 		dev_err(vsp1->dev, "%s: failed to setup %s source\n", __func__,
-			BRU_NAME(pipe->bru));
+			BRX_NAME(pipe->brx));
 		return ret;
 	}
 
-	bru = to_bru(&pipe->bru->subdev);
+	brx = to_brx(&pipe->brx->subdev);
 
 	/* Setup the RPF input pipeline for every enabled input. */
-	for (i = 0; i < pipe->bru->source_pad; ++i) {
+	for (i = 0; i < pipe->brx->source_pad; ++i) {
 		struct vsp1_rwpf *rpf = inputs[i];
 
 		if (!rpf) {
-			bru->inputs[i].rpf = NULL;
+			brx->inputs[i].rpf = NULL;
 			continue;
 		}
 
@@ -354,13 +354,13 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
 			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
 		}
 
-		bru->inputs[i].rpf = rpf;
-		rpf->bru_input = i;
-		rpf->entity.sink = pipe->bru;
+		brx->inputs[i].rpf = rpf;
+		rpf->brx_input = i;
+		rpf->entity.sink = pipe->brx;
 		rpf->entity.sink_pad = i;
 
 		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
-			__func__, rpf->entity.index, BRU_NAME(pipe->bru), i);
+			__func__, rpf->entity.index, BRX_NAME(pipe->brx), i);
 
 		ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, i);
 		if (ret < 0) {
@@ -468,7 +468,7 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
 		}
 	}
 
-	vsp1_dl_list_commit(dl, drm_pipe->force_bru_release);
+	vsp1_dl_list_commit(dl, drm_pipe->force_brx_release);
 }
 
 /* -----------------------------------------------------------------------------
@@ -493,8 +493,8 @@ EXPORT_SYMBOL_GPL(vsp1_du_init);
  * @cfg: the LIF configuration
  *
  * Configure the output part of VSP DRM pipeline for the given frame @cfg.width
- * and @cfg.height. This sets up formats on the blend unit (BRU or BRS) source
- * pad, the WPF sink and source pads, and the LIF sink pad.
+ * and @cfg.height. This sets up formats on the BRx source pad, the WPF sink and
+ * source pads, and the LIF sink pad.
  *
  * The @pipe_index argument selects which DRM pipeline to setup. The number of
  * available pipelines depend on the VSP instance.
@@ -524,11 +524,11 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 	pipe = &drm_pipe->pipe;
 
 	if (!cfg) {
-		struct vsp1_bru *bru;
+		struct vsp1_brx *brx;
 
 		mutex_lock(&vsp1->drm->lock);
 
-		bru = to_bru(&pipe->bru->subdev);
+		brx = to_brx(&pipe->brx->subdev);
 
 		/*
 		 * NULL configuration means the CRTC is being disabled, stop
@@ -545,7 +545,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 				continue;
 
 			/*
-			 * Remove the RPF from the pipe and the list of BRU
+			 * Remove the RPF from the pipe and the list of BRx
 			 * inputs.
 			 */
 			WARN_ON(!rpf->entity.pipe);
@@ -553,7 +553,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 			list_del(&rpf->entity.list_pipe);
 			pipe->inputs[i] = NULL;
 
-			bru->inputs[rpf->bru_input].rpf = NULL;
+			brx->inputs[rpf->brx_input].rpf = NULL;
 		}
 
 		drm_pipe->du_complete = NULL;
@@ -561,11 +561,11 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
 
 		dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
 			__func__, pipe->lif->index,
-			BRU_NAME(pipe->bru));
+			BRX_NAME(pipe->brx));
 
-		list_del(&pipe->bru->list_pipe);
-		pipe->bru->pipe = NULL;
-		pipe->bru = NULL;
+		list_del(&pipe->brx->list_pipe);
+		pipe->brx->pipe = NULL;
+		pipe->brx = NULL;
 
 		mutex_unlock(&vsp1->drm->lock);
 
diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
index c84bc1c456c0..d738cc57f0e3 100644
--- a/drivers/media/platform/vsp1/vsp1_drm.h
+++ b/drivers/media/platform/vsp1/vsp1_drm.h
@@ -24,8 +24,8 @@
  * @pipe: the VSP1 pipeline used for display
  * @width: output display width
  * @height: output display height
- * @force_bru_release: when set, release the BRU during the next reconfiguration
- * @wait_queue: wait queue to wait for BRU release completion
+ * @force_brx_release: when set, release the BRx during the next reconfiguration
+ * @wait_queue: wait queue to wait for BRx release completion
  * @du_complete: frame completion callback for the DU driver (optional)
  * @du_private: data to be passed to the du_complete callback
  */
@@ -35,7 +35,7 @@ struct vsp1_drm_pipeline {
 	unsigned int width;
 	unsigned int height;
 
-	bool force_bru_release;
+	bool force_brx_release;
 	wait_queue_head_t wait_queue;
 
 	/* Frame synchronisation */
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 58a7993f2306..f41cd70409db 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -26,7 +26,7 @@
 #include <media/v4l2-subdev.h>
 
 #include "vsp1.h"
-#include "vsp1_bru.h"
+#include "vsp1_brx.h"
 #include "vsp1_clu.h"
 #include "vsp1_dl.h"
 #include "vsp1_drm.h"
@@ -269,7 +269,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 
 	/* Instantiate all the entities. */
 	if (vsp1->info->features & VSP1_HAS_BRS) {
-		vsp1->brs = vsp1_bru_create(vsp1, VSP1_ENTITY_BRS);
+		vsp1->brs = vsp1_brx_create(vsp1, VSP1_ENTITY_BRS);
 		if (IS_ERR(vsp1->brs)) {
 			ret = PTR_ERR(vsp1->brs);
 			goto done;
@@ -279,7 +279,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
 	}
 
 	if (vsp1->info->features & VSP1_HAS_BRU) {
-		vsp1->bru = vsp1_bru_create(vsp1, VSP1_ENTITY_BRU);
+		vsp1->bru = vsp1_brx_create(vsp1, VSP1_ENTITY_BRU);
 		if (IS_ERR(vsp1->bru)) {
 			ret = PTR_ERR(vsp1->bru);
 			goto done;
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
index 4d819c9019f4..45da3ff10955 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.c
+++ b/drivers/media/platform/vsp1/vsp1_pipe.c
@@ -20,7 +20,7 @@
 #include <media/v4l2-subdev.h>
 
 #include "vsp1.h"
-#include "vsp1_bru.h"
+#include "vsp1_brx.h"
 #include "vsp1_dl.h"
 #include "vsp1_entity.h"
 #include "vsp1_hgo.h"
@@ -188,11 +188,11 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
 	struct vsp1_entity *entity;
 	unsigned int i;
 
-	if (pipe->bru) {
-		struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
+	if (pipe->brx) {
+		struct vsp1_brx *brx = to_brx(&pipe->brx->subdev);
 
-		for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i)
-			bru->inputs[i].rpf = NULL;
+		for (i = 0; i < ARRAY_SIZE(brx->inputs); ++i)
+			brx->inputs[i].rpf = NULL;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i)
@@ -207,7 +207,7 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
 	pipe->state = VSP1_PIPELINE_STOPPED;
 	pipe->buffers_ready = 0;
 	pipe->num_inputs = 0;
-	pipe->bru = NULL;
+	pipe->brx = NULL;
 	pipe->hgo = NULL;
 	pipe->hgt = NULL;
 	pipe->lif = NULL;
diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
index 482711024fa2..9eca9fe16724 100644
--- a/drivers/media/platform/vsp1/vsp1_pipe.h
+++ b/drivers/media/platform/vsp1/vsp1_pipe.h
@@ -99,7 +99,7 @@ struct vsp1_partition {
  * @num_inputs: number of RPFs
  * @inputs: array of RPFs in the pipeline (indexed by RPF index)
  * @output: WPF at the output of the pipeline
- * @bru: BRU entity, if present
+ * @brx: BRx entity, if present
  * @hgo: HGO entity, if present
  * @hgt: HGT entity, if present
  * @lif: LIF entity, if present
@@ -130,7 +130,7 @@ struct vsp1_pipeline {
 	unsigned int num_inputs;
 	struct vsp1_rwpf *inputs[VSP1_MAX_RPF];
 	struct vsp1_rwpf *output;
-	struct vsp1_entity *bru;
+	struct vsp1_entity *brx;
 	struct vsp1_entity *hgo;
 	struct vsp1_entity *hgt;
 	struct vsp1_entity *lif;
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index fe0633da5a5f..7e74c2015070 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -167,12 +167,12 @@ static void rpf_configure(struct vsp1_entity *entity,
 	vsp1_rpf_write(rpf, dl, VI6_RPF_DSWAP, fmtinfo->swap);
 
 	/* Output location */
-	if (pipe->bru) {
+	if (pipe->brx) {
 		const struct v4l2_rect *compose;
 
-		compose = vsp1_entity_get_pad_selection(pipe->bru,
-							pipe->bru->config,
-							rpf->bru_input,
+		compose = vsp1_entity_get_pad_selection(pipe->brx,
+							pipe->brx->config,
+							rpf->brx_input,
 							V4L2_SEL_TGT_COMPOSE);
 		left = compose->left;
 		top = compose->top;
@@ -191,10 +191,10 @@ static void rpf_configure(struct vsp1_entity *entity,
 	 * alpha channel by a fixed global alpha value, and multiply the pixel
 	 * components to convert the input to premultiplied alpha.
 	 *
-	 * As alpha premultiplication is available in the BRU for both Gen2 and
+	 * As alpha premultiplication is available in the BRx for both Gen2 and
 	 * Gen3 we handle it there and use the Gen3 alpha multiplier for global
 	 * alpha multiplication only. This however prevents conversion to
-	 * premultiplied alpha if no BRU is present in the pipeline. If that use
+	 * premultiplied alpha if no BRx is present in the pipeline. If that use
 	 * case turns out to be useful we will revisit the implementation (for
 	 * Gen3 only).
 	 *
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index c94ac89abfa7..915aeadb21dd 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -45,7 +45,7 @@ struct vsp1_rwpf {
 
 	struct v4l2_pix_format_mplane format;
 	const struct vsp1_format_info *fmtinfo;
-	unsigned int bru_input;
+	unsigned int brx_input;
 
 	unsigned int alpha;
 
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 483b4259e1b4..1958d241d19b 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -28,7 +28,7 @@
 #include <media/videobuf2-dma-contig.h>
 
 #include "vsp1.h"
-#include "vsp1_bru.h"
+#include "vsp1_brx.h"
 #include "vsp1_dl.h"
 #include "vsp1_entity.h"
 #include "vsp1_hgo.h"
@@ -488,7 +488,7 @@ static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
 	struct media_entity_enum ent_enum;
 	struct vsp1_entity *entity;
 	struct media_pad *pad;
-	struct vsp1_bru *bru = NULL;
+	struct vsp1_brx *brx = NULL;
 	int ret;
 
 	ret = media_entity_enum_init(&ent_enum, &input->entity.vsp1->media_dev);
@@ -524,14 +524,14 @@ static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
 		if (entity->type == VSP1_ENTITY_BRU ||
 		    entity->type == VSP1_ENTITY_BRS) {
 			/* BRU and BRS can't be chained. */
-			if (bru) {
+			if (brx) {
 				ret = -EPIPE;
 				goto out;
 			}
 
-			bru = to_bru(&entity->subdev);
-			bru->inputs[pad->index].rpf = input;
-			input->bru_input = pad->index;
+			brx = to_brx(&entity->subdev);
+			brx->inputs[pad->index].rpf = input;
+			input->brx_input = pad->index;
 		}
 
 		/* We've reached the WPF, we're done. */
@@ -553,7 +553,7 @@ static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
 			}
 
 			pipe->uds = entity;
-			pipe->uds_input = bru ? &bru->entity : &input->entity;
+			pipe->uds_input = brx ? &brx->entity : &input->entity;
 		}
 
 		/* Follow the source link, ignoring any HGO or HGT. */
@@ -619,7 +619,7 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe,
 
 		case VSP1_ENTITY_BRU:
 		case VSP1_ENTITY_BRS:
-			pipe->bru = e;
+			pipe->brx = e;
 			break;
 
 		case VSP1_ENTITY_HGO:
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index f7f3b4b2c2de..76f2686e292f 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -436,7 +436,7 @@ static void wpf_configure(struct vsp1_entity *entity,
 	vsp1_dl_list_write(dl, VI6_WPF_WRBCK_CTRL, 0);
 
 	/*
-	 * Sources. If the pipeline has a single input and BRU is not used,
+	 * Sources. If the pipeline has a single input and BRx is not used,
 	 * configure it as the master layer. Otherwise configure all
 	 * inputs as sub-layers and select the virtual RPF as the master
 	 * layer.
@@ -447,13 +447,13 @@ static void wpf_configure(struct vsp1_entity *entity,
 		if (!input)
 			continue;
 
-		srcrpf |= (!pipe->bru && pipe->num_inputs == 1)
+		srcrpf |= (!pipe->brx && pipe->num_inputs == 1)
 			? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index)
 			: VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index);
 	}
 
-	if (pipe->bru || pipe->num_inputs > 1)
-		srcrpf |= pipe->bru->type == VSP1_ENTITY_BRU
+	if (pipe->brx || pipe->num_inputs > 1)
+		srcrpf |= pipe->brx->type == VSP1_ENTITY_BRU
 			? VI6_WPF_SRCRPF_VIRACT_MST
 			: VI6_WPF_SRCRPF_VIRACT2_MST;
 
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 02/15] v4l: vsp1: Remove outdated comment
  2018-02-26 21:45   ` Laurent Pinchart
@ 2018-02-27  8:22     ` Sergei Shtylyov
  -1 siblings, 0 replies; 88+ messages in thread
From: Sergei Shtylyov @ 2018-02-27  8:22 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media
  Cc: dri-devel, linux-renesas-soc, Kieran Bingham

Hello!

On 2/27/2018 12:45 AM, Laurent Pinchart wrote:

> The entities in the pipeline are all started when the LIF is setup.
> Remove the outdated comment that state otherwise.

    States?

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

MBR, Sergei

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

* Re: [PATCH 02/15] v4l: vsp1: Remove outdated comment
@ 2018-02-27  8:22     ` Sergei Shtylyov
  0 siblings, 0 replies; 88+ messages in thread
From: Sergei Shtylyov @ 2018-02-27  8:22 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media
  Cc: linux-renesas-soc, Kieran Bingham, dri-devel

Hello!

On 2/27/2018 12:45 AM, Laurent Pinchart wrote:

> The entities in the pipeline are all started when the LIF is setup.
> Remove the outdated comment that state otherwise.

    States?

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

MBR, Sergei
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 02/15] v4l: vsp1: Remove outdated comment
  2018-02-27  8:22     ` Sergei Shtylyov
@ 2018-02-27  9:14       ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-27  9:14 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: Laurent Pinchart, linux-media, dri-devel, linux-renesas-soc,
	Kieran Bingham

Hi Sergei,

On Tuesday, 27 February 2018 10:22:25 EET Sergei Shtylyov wrote:
> On 2/27/2018 12:45 AM, Laurent Pinchart wrote:
> > The entities in the pipeline are all started when the LIF is setup.
> > Remove the outdated comment that state otherwise.
> 
> States?

You're right, will fix in v2.

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

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 02/15] v4l: vsp1: Remove outdated comment
@ 2018-02-27  9:14       ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-02-27  9:14 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: linux-renesas-soc, Laurent Pinchart, Kieran Bingham, dri-devel,
	linux-media

Hi Sergei,

On Tuesday, 27 February 2018 10:22:25 EET Sergei Shtylyov wrote:
> On 2/27/2018 12:45 AM, Laurent Pinchart wrote:
> > The entities in the pipeline are all started when the LIF is setup.
> > Remove the outdated comment that state otherwise.
> 
> States?

You're right, will fix in v2.

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

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 02/15] v4l: vsp1: Remove outdated comment
  2018-02-26 21:45   ` Laurent Pinchart
@ 2018-03-28 12:27     ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 12:27 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media
  Cc: dri-devel, linux-renesas-soc, Kieran Bingham

Hi Laurent,

Thank you for the patch.

On 26/02/18 21:45, Laurent Pinchart wrote:
> The entities in the pipeline are all started when the LIF is setup.
> Remove the outdated comment that state otherwise.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

I'll start with the easy ones :-)

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 6 +-----
>  1 file changed, 1 insertion(+), 5 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index e31fb371eaf9..a1f2ba044092 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -221,11 +221,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  		return -EPIPE;
>  	}
>  
> -	/*
> -	 * Enable the VSP1. 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.
> -	 */
> +	/* Enable the VSP1. */
>  	ret = vsp1_device_get(vsp1);
>  	if (ret < 0)
>  		return ret;
> 

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

* Re: [PATCH 02/15] v4l: vsp1: Remove outdated comment
@ 2018-03-28 12:27     ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 12:27 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media
  Cc: linux-renesas-soc, Kieran Bingham, dri-devel

Hi Laurent,

Thank you for the patch.

On 26/02/18 21:45, Laurent Pinchart wrote:
> The entities in the pipeline are all started when the LIF is setup.
> Remove the outdated comment that state otherwise.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

I'll start with the easy ones :-)

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 6 +-----
>  1 file changed, 1 insertion(+), 5 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index e31fb371eaf9..a1f2ba044092 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -221,11 +221,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  		return -EPIPE;
>  	}
>  
> -	/*
> -	 * Enable the VSP1. 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.
> -	 */
> +	/* Enable the VSP1. */
>  	ret = vsp1_device_get(vsp1);
>  	if (ret < 0)
>  		return ret;
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 03/15] v4l: vsp1: Remove unused field from vsp1_drm_pipeline structure
  2018-02-26 21:45   ` Laurent Pinchart
@ 2018-03-28 12:31     ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 12:31 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: dri-devel, linux-renesas-soc

Hi Laurent,

Thanks for the patch,

On 26/02/18 21:45, Laurent Pinchart wrote:
> The vsp1_drm_pipeline enabled field is set but never used. Remove it.
> 

Indeed - not used.

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

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 4 ----
>  drivers/media/platform/vsp1/vsp1_drm.h | 2 --
>  2 files changed, 6 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index a1f2ba044092..a267f12f0cc8 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -273,10 +273,6 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
>   */
>  void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index)
>  {
> -	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
> -	struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index];
> -
> -	drm_pipe->enabled = drm_pipe->pipe.num_inputs != 0;
>  }
>  EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
> index 1cd9db785bf7..9aa19325cbe9 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.h
> +++ b/drivers/media/platform/vsp1/vsp1_drm.h
> @@ -20,13 +20,11 @@
>  /**
>   * vsp1_drm_pipeline - State for the API exposed to the DRM driver
>   * @pipe: the VSP1 pipeline used for display
> - * @enabled: pipeline state at the beginning of an update
>   * @du_complete: frame completion callback for the DU driver (optional)
>   * @du_private: data to be passed to the du_complete callback
>   */
>  struct vsp1_drm_pipeline {
>  	struct vsp1_pipeline pipe;
> -	bool enabled;
>  
>  	/* Frame synchronisation */
>  	void (*du_complete)(void *, bool);
> 

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

* Re: [PATCH 03/15] v4l: vsp1: Remove unused field from vsp1_drm_pipeline structure
@ 2018-03-28 12:31     ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 12:31 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: linux-renesas-soc, dri-devel

Hi Laurent,

Thanks for the patch,

On 26/02/18 21:45, Laurent Pinchart wrote:
> The vsp1_drm_pipeline enabled field is set but never used. Remove it.
> 

Indeed - not used.

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

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 4 ----
>  drivers/media/platform/vsp1/vsp1_drm.h | 2 --
>  2 files changed, 6 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index a1f2ba044092..a267f12f0cc8 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -273,10 +273,6 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
>   */
>  void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index)
>  {
> -	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
> -	struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index];
> -
> -	drm_pipe->enabled = drm_pipe->pipe.num_inputs != 0;
>  }
>  EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
> index 1cd9db785bf7..9aa19325cbe9 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.h
> +++ b/drivers/media/platform/vsp1/vsp1_drm.h
> @@ -20,13 +20,11 @@
>  /**
>   * vsp1_drm_pipeline - State for the API exposed to the DRM driver
>   * @pipe: the VSP1 pipeline used for display
> - * @enabled: pipeline state at the beginning of an update
>   * @du_complete: frame completion callback for the DU driver (optional)
>   * @du_private: data to be passed to the du_complete callback
>   */
>  struct vsp1_drm_pipeline {
>  	struct vsp1_pipeline pipe;
> -	bool enabled;
>  
>  	/* Frame synchronisation */
>  	void (*du_complete)(void *, bool);
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 04/15] v4l: vsp1: Store pipeline pointer in vsp1_entity
  2018-02-26 21:45   ` Laurent Pinchart
@ 2018-03-28 13:46     ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 13:46 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: dri-devel, linux-renesas-soc

Hi Laurent,

Thank you for the patch.

On 26/02/18 21:45, Laurent Pinchart wrote:
> Various types of objects subclassing vsp1_entity currently store a
> pointer to the pipeline. Move the pointer to vsp1_entity to simplify the
> code and avoid storing the pipeline in more entity subclasses later.

This certainly seems like a good improvement to make.

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

Some terse diffstat there to get through - but it all looks good in the end.

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>


> ---
>  drivers/media/platform/vsp1/vsp1_drm.c    | 20 +++++++++++++------
>  drivers/media/platform/vsp1/vsp1_drv.c    |  2 +-
>  drivers/media/platform/vsp1/vsp1_entity.h |  2 ++
>  drivers/media/platform/vsp1/vsp1_histo.c  |  2 +-
>  drivers/media/platform/vsp1/vsp1_histo.h  |  3 ---
>  drivers/media/platform/vsp1/vsp1_pipe.c   | 33 +++++++++----------------------
>  drivers/media/platform/vsp1/vsp1_rwpf.h   |  2 --
>  drivers/media/platform/vsp1/vsp1_video.c  | 17 +++++++---------
>  8 files changed, 34 insertions(+), 47 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index a267f12f0cc8..a7ad85ab0b08 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -120,6 +120,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  			 * inputs.
>  			 */
>  			WARN_ON(list_empty(&rpf->entity.list_pipe));
> +			rpf->entity.pipe = NULL;

Aha - This reads confusingly as a diff ... because first it ensures the entity
is in a pipe with the WARN_ON, but then sets the pipe to NULL. But I'm going to
hazard a guess and say this is the (!cfg) section of the vsp1_du_setup_lif()
call...

/me checks.

Yes, of course it is... so that's fine.


>  			list_del_init(&rpf->entity.list_pipe);
>  			pipe->inputs[i] = NULL;
>  
> @@ -536,8 +537,10 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  			continue;
>  		}
>  
> -		if (list_empty(&rpf->entity.list_pipe))
> +		if (list_empty(&rpf->entity.list_pipe)) {
> +			rpf->entity.pipe = pipe;
>  			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
> +		}
>  
>  		bru->inputs[i].rpf = rpf;
>  		rpf->bru_input = i;
> @@ -562,6 +565,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  			vsp1_dl_list_write(dl, entity->route->reg,
>  					   VI6_DPR_NODE_UNUSED);
>  
> +			entity->pipe = NULL;
>  			list_del_init(&entity->list_pipe);
>  
>  			continue;
> @@ -625,24 +629,28 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
>  
>  		vsp1_pipeline_init(pipe);
>  
> +		pipe->frame_end = vsp1_du_pipeline_frame_end;
> +

Aha - just a code move - I was going to ask why this was here. That's fine.


>  		/*
>  		 * The DRM pipeline is static, add entities manually. The first
>  		 * pipeline uses the BRU and the second pipeline the BRS.
>  		 */
>  		pipe->bru = i == 0 ? &vsp1->bru->entity : &vsp1->brs->entity;
> -		pipe->lif = &vsp1->lif[i]->entity;
>  		pipe->output = vsp1->wpf[i];
> -		pipe->output->pipe = pipe;
> -		pipe->frame_end = vsp1_du_pipeline_frame_end;
> +		pipe->lif = &vsp1->lif[i]->entity;
>  
> +		pipe->bru->pipe = pipe;
>  		pipe->bru->sink = &pipe->output->entity;
>  		pipe->bru->sink_pad = 0;
> +		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
> +
> +		pipe->output->entity.pipe = pipe;

Ick ... pipe->bru->pipe, but pipe->output->entity.pipe ...
 BRU is already an entity, whereas output is an RPF.

A bit painful on the eyes for review - but nothing to be done there I don't think.




>  		pipe->output->entity.sink = pipe->lif;
>  		pipe->output->entity.sink_pad = 0;
> +		list_add_tail(&pipe->output->entity.list_pipe, &pipe->entities);
>  
> -		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
> +		pipe->lif->pipe = pipe;
>  		list_add_tail(&pipe->lif->list_pipe, &pipe->entities);
> -		list_add_tail(&pipe->output->entity.list_pipe, &pipe->entities);
>  	}
>  
>  	/* Disable all RPFs initially. */
> diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
> index eed9516e25e1..58a7993f2306 100644
> --- a/drivers/media/platform/vsp1/vsp1_drv.c
> +++ b/drivers/media/platform/vsp1/vsp1_drv.c
> @@ -63,7 +63,7 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data)
>  		vsp1_write(vsp1, VI6_WPF_IRQ_STA(i), ~status & mask);
>  
>  		if (status & VI6_WFP_IRQ_STA_DFE) {
> -			vsp1_pipeline_frame_end(wpf->pipe);
> +			vsp1_pipeline_frame_end(wpf->entity.pipe);
>  			ret = IRQ_HANDLED;
>  		}
>  	}
> diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
> index 408602ebeb97..c26523c56c05 100644
> --- a/drivers/media/platform/vsp1/vsp1_entity.h
> +++ b/drivers/media/platform/vsp1/vsp1_entity.h
> @@ -106,6 +106,8 @@ struct vsp1_entity {
>  	unsigned int index;
>  	const struct vsp1_route *route;
>  
> +	struct vsp1_pipeline *pipe;
> +
>  	struct list_head list_dev;
>  	struct list_head list_pipe;
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_histo.c b/drivers/media/platform/vsp1/vsp1_histo.c
> index afab77cf4fa5..8638ebc514b4 100644
> --- a/drivers/media/platform/vsp1/vsp1_histo.c
> +++ b/drivers/media/platform/vsp1/vsp1_histo.c
> @@ -61,7 +61,7 @@ void vsp1_histogram_buffer_complete(struct vsp1_histogram *histo,
>  				    struct vsp1_histogram_buffer *buf,
>  				    size_t size)
>  {
> -	struct vsp1_pipeline *pipe = histo->pipe;
> +	struct vsp1_pipeline *pipe = histo->entity.pipe;
>  	unsigned long flags;
>  
>  	/*
> diff --git a/drivers/media/platform/vsp1/vsp1_histo.h b/drivers/media/platform/vsp1/vsp1_histo.h
> index af2874f6031d..e774adbf251f 100644
> --- a/drivers/media/platform/vsp1/vsp1_histo.h
> +++ b/drivers/media/platform/vsp1/vsp1_histo.h
> @@ -25,7 +25,6 @@
>  #include "vsp1_entity.h"
>  
>  struct vsp1_device;
> -struct vsp1_pipeline;
>  
>  #define HISTO_PAD_SINK				0
>  #define HISTO_PAD_SOURCE			1
> @@ -37,8 +36,6 @@ struct vsp1_histogram_buffer {
>  };
>  
>  struct vsp1_histogram {
> -	struct vsp1_pipeline *pipe;
> -
>  	struct vsp1_entity entity;
>  	struct video_device video;
>  	struct media_pad pad;
> diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
> index 44944ac86d9b..99ccbac3256a 100644
> --- a/drivers/media/platform/vsp1/vsp1_pipe.c
> +++ b/drivers/media/platform/vsp1/vsp1_pipe.c
> @@ -185,6 +185,7 @@ const struct vsp1_format_info *vsp1_get_format_info(struct vsp1_device *vsp1,
>  
>  void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
>  {
> +	struct vsp1_entity *entity;
>  	unsigned int i;
>  
>  	if (pipe->bru) {
> @@ -194,29 +195,13 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
>  			bru->inputs[i].rpf = NULL;
>  	}
>  
> -	for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i) {
> -		if (pipe->inputs[i]) {
> -			pipe->inputs[i]->pipe = NULL;
> -			pipe->inputs[i] = NULL;
> -		}
> -	}
> -
> -	if (pipe->output) {
> -		pipe->output->pipe = NULL;
> -		pipe->output = NULL;
> -	}
> +	for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i)
> +		pipe->inputs[i] = NULL;
>  
> -	if (pipe->hgo) {
> -		struct vsp1_hgo *hgo = to_hgo(&pipe->hgo->subdev);
> +	pipe->output = NULL;
>  
> -		hgo->histo.pipe = NULL;
> -	}
> -
> -	if (pipe->hgt) {
> -		struct vsp1_hgt *hgt = to_hgt(&pipe->hgt->subdev);
> -
> -		hgt->histo.pipe = NULL;
> -	}
> +	list_for_each_entry(entity, &pipe->entities, list_pipe)
> +		entity->pipe = NULL;

Excellent - looks like that got cleaned up somewhat thanks to this change.


>  
>  	INIT_LIST_HEAD(&pipe->entities);
>  	pipe->state = VSP1_PIPELINE_STOPPED;
> @@ -423,7 +408,7 @@ void vsp1_pipelines_suspend(struct vsp1_device *vsp1)
>  		if (wpf == NULL)
>  			continue;
>  
> -		pipe = wpf->pipe;
> +		pipe = wpf->entity.pipe;
>  		if (pipe == NULL)
>  			continue;
>  
> @@ -440,7 +425,7 @@ void vsp1_pipelines_suspend(struct vsp1_device *vsp1)
>  		if (wpf == NULL)
>  			continue;
>  
> -		pipe = wpf->pipe;
> +		pipe = wpf->entity.pipe;
>  		if (pipe == NULL)
>  			continue;
>  
> @@ -465,7 +450,7 @@ void vsp1_pipelines_resume(struct vsp1_device *vsp1)
>  		if (wpf == NULL)
>  			continue;
>  
> -		pipe = wpf->pipe;
> +		pipe = wpf->entity.pipe;
>  		if (pipe == NULL)
>  			continue;
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
> index 58215a7ab631..c94ac89abfa7 100644
> --- a/drivers/media/platform/vsp1/vsp1_rwpf.h
> +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
> @@ -27,7 +27,6 @@
>  
>  struct v4l2_ctrl;
>  struct vsp1_dl_manager;
> -struct vsp1_pipeline;
>  struct vsp1_rwpf;
>  struct vsp1_video;
>  
> @@ -39,7 +38,6 @@ struct vsp1_rwpf {
>  	struct vsp1_entity entity;
>  	struct v4l2_ctrl_handler ctrls;
>  
> -	struct vsp1_pipeline *pipe;
>  	struct vsp1_video *video;
>  
>  	unsigned int max_width;
> diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
> index c2d3b8f0f487..cdd53d6cc408 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.c
> +++ b/drivers/media/platform/vsp1/vsp1_video.c
> @@ -324,7 +324,7 @@ static int vsp1_video_pipeline_setup_partitions(struct vsp1_pipeline *pipe)
>  static struct vsp1_vb2_buffer *
>  vsp1_video_complete_buffer(struct vsp1_video *video)
>  {
> -	struct vsp1_pipeline *pipe = video->rwpf->pipe;
> +	struct vsp1_pipeline *pipe = video->rwpf->entity.pipe;
>  	struct vsp1_vb2_buffer *next = NULL;
>  	struct vsp1_vb2_buffer *done;
>  	unsigned long flags;
> @@ -598,20 +598,19 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe,
>  		subdev = media_entity_to_v4l2_subdev(entity);
>  		e = to_vsp1_entity(subdev);
>  		list_add_tail(&e->list_pipe, &pipe->entities);
> +		e->pipe = pipe;
>  
>  		switch (e->type) {
>  		case VSP1_ENTITY_RPF:
>  			rwpf = to_rwpf(subdev);
>  			pipe->inputs[rwpf->entity.index] = rwpf;
>  			rwpf->video->pipe_index = ++pipe->num_inputs;
> -			rwpf->pipe = pipe;
>  			break;
>  
>  		case VSP1_ENTITY_WPF:
>  			rwpf = to_rwpf(subdev);
>  			pipe->output = rwpf;
>  			rwpf->video->pipe_index = 0;
> -			rwpf->pipe = pipe;
>  			break;
>  
>  		case VSP1_ENTITY_LIF:
> @@ -625,12 +624,10 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe,
>  
>  		case VSP1_ENTITY_HGO:
>  			pipe->hgo = e;
> -			to_hgo(subdev)->histo.pipe = pipe;
>  			break;
>  
>  		case VSP1_ENTITY_HGT:
>  			pipe->hgt = e;
> -			to_hgt(subdev)->histo.pipe = pipe;
>  			break;
>  
>  		default:
> @@ -682,7 +679,7 @@ static struct vsp1_pipeline *vsp1_video_pipeline_get(struct vsp1_video *video)
>  	 * Otherwise allocate a new pipeline and initialize it, it will be freed
>  	 * when the last reference is released.
>  	 */
> -	if (!video->rwpf->pipe) {
> +	if (!video->rwpf->entity.pipe) {
>  		pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);
>  		if (!pipe)
>  			return ERR_PTR(-ENOMEM);
> @@ -694,7 +691,7 @@ static struct vsp1_pipeline *vsp1_video_pipeline_get(struct vsp1_video *video)
>  			return ERR_PTR(ret);
>  		}
>  	} else {
> -		pipe = video->rwpf->pipe;
> +		pipe = video->rwpf->entity.pipe;
>  		kref_get(&pipe->kref);
>  	}
>  
> @@ -777,7 +774,7 @@ static void vsp1_video_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_pipeline *pipe = video->rwpf->pipe;
> +	struct vsp1_pipeline *pipe = video->rwpf->entity.pipe;
>  	struct vsp1_vb2_buffer *buf = to_vsp1_vb2_buffer(vbuf);
>  	unsigned long flags;
>  	bool empty;
> @@ -872,7 +869,7 @@ static void vsp1_video_cleanup_pipeline(struct vsp1_pipeline *pipe)
>  static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
>  {
>  	struct vsp1_video *video = vb2_get_drv_priv(vq);
> -	struct vsp1_pipeline *pipe = video->rwpf->pipe;
> +	struct vsp1_pipeline *pipe = video->rwpf->entity.pipe;
>  	bool start_pipeline = false;
>  	unsigned long flags;
>  	int ret;
> @@ -913,7 +910,7 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
>  static void vsp1_video_stop_streaming(struct vb2_queue *vq)
>  {
>  	struct vsp1_video *video = vb2_get_drv_priv(vq);
> -	struct vsp1_pipeline *pipe = video->rwpf->pipe;
> +	struct vsp1_pipeline *pipe = video->rwpf->entity.pipe;
>  	unsigned long flags;
>  	int ret;
>  
> 

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

* Re: [PATCH 04/15] v4l: vsp1: Store pipeline pointer in vsp1_entity
@ 2018-03-28 13:46     ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 13:46 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: linux-renesas-soc, dri-devel

Hi Laurent,

Thank you for the patch.

On 26/02/18 21:45, Laurent Pinchart wrote:
> Various types of objects subclassing vsp1_entity currently store a
> pointer to the pipeline. Move the pointer to vsp1_entity to simplify the
> code and avoid storing the pipeline in more entity subclasses later.

This certainly seems like a good improvement to make.

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

Some terse diffstat there to get through - but it all looks good in the end.

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>


> ---
>  drivers/media/platform/vsp1/vsp1_drm.c    | 20 +++++++++++++------
>  drivers/media/platform/vsp1/vsp1_drv.c    |  2 +-
>  drivers/media/platform/vsp1/vsp1_entity.h |  2 ++
>  drivers/media/platform/vsp1/vsp1_histo.c  |  2 +-
>  drivers/media/platform/vsp1/vsp1_histo.h  |  3 ---
>  drivers/media/platform/vsp1/vsp1_pipe.c   | 33 +++++++++----------------------
>  drivers/media/platform/vsp1/vsp1_rwpf.h   |  2 --
>  drivers/media/platform/vsp1/vsp1_video.c  | 17 +++++++---------
>  8 files changed, 34 insertions(+), 47 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index a267f12f0cc8..a7ad85ab0b08 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -120,6 +120,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  			 * inputs.
>  			 */
>  			WARN_ON(list_empty(&rpf->entity.list_pipe));
> +			rpf->entity.pipe = NULL;

Aha - This reads confusingly as a diff ... because first it ensures the entity
is in a pipe with the WARN_ON, but then sets the pipe to NULL. But I'm going to
hazard a guess and say this is the (!cfg) section of the vsp1_du_setup_lif()
call...

/me checks.

Yes, of course it is... so that's fine.


>  			list_del_init(&rpf->entity.list_pipe);
>  			pipe->inputs[i] = NULL;
>  
> @@ -536,8 +537,10 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  			continue;
>  		}
>  
> -		if (list_empty(&rpf->entity.list_pipe))
> +		if (list_empty(&rpf->entity.list_pipe)) {
> +			rpf->entity.pipe = pipe;
>  			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
> +		}
>  
>  		bru->inputs[i].rpf = rpf;
>  		rpf->bru_input = i;
> @@ -562,6 +565,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  			vsp1_dl_list_write(dl, entity->route->reg,
>  					   VI6_DPR_NODE_UNUSED);
>  
> +			entity->pipe = NULL;
>  			list_del_init(&entity->list_pipe);
>  
>  			continue;
> @@ -625,24 +629,28 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
>  
>  		vsp1_pipeline_init(pipe);
>  
> +		pipe->frame_end = vsp1_du_pipeline_frame_end;
> +

Aha - just a code move - I was going to ask why this was here. That's fine.


>  		/*
>  		 * The DRM pipeline is static, add entities manually. The first
>  		 * pipeline uses the BRU and the second pipeline the BRS.
>  		 */
>  		pipe->bru = i == 0 ? &vsp1->bru->entity : &vsp1->brs->entity;
> -		pipe->lif = &vsp1->lif[i]->entity;
>  		pipe->output = vsp1->wpf[i];
> -		pipe->output->pipe = pipe;
> -		pipe->frame_end = vsp1_du_pipeline_frame_end;
> +		pipe->lif = &vsp1->lif[i]->entity;
>  
> +		pipe->bru->pipe = pipe;
>  		pipe->bru->sink = &pipe->output->entity;
>  		pipe->bru->sink_pad = 0;
> +		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
> +
> +		pipe->output->entity.pipe = pipe;

Ick ... pipe->bru->pipe, but pipe->output->entity.pipe ...
 BRU is already an entity, whereas output is an RPF.

A bit painful on the eyes for review - but nothing to be done there I don't think.




>  		pipe->output->entity.sink = pipe->lif;
>  		pipe->output->entity.sink_pad = 0;
> +		list_add_tail(&pipe->output->entity.list_pipe, &pipe->entities);
>  
> -		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
> +		pipe->lif->pipe = pipe;
>  		list_add_tail(&pipe->lif->list_pipe, &pipe->entities);
> -		list_add_tail(&pipe->output->entity.list_pipe, &pipe->entities);
>  	}
>  
>  	/* Disable all RPFs initially. */
> diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
> index eed9516e25e1..58a7993f2306 100644
> --- a/drivers/media/platform/vsp1/vsp1_drv.c
> +++ b/drivers/media/platform/vsp1/vsp1_drv.c
> @@ -63,7 +63,7 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data)
>  		vsp1_write(vsp1, VI6_WPF_IRQ_STA(i), ~status & mask);
>  
>  		if (status & VI6_WFP_IRQ_STA_DFE) {
> -			vsp1_pipeline_frame_end(wpf->pipe);
> +			vsp1_pipeline_frame_end(wpf->entity.pipe);
>  			ret = IRQ_HANDLED;
>  		}
>  	}
> diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
> index 408602ebeb97..c26523c56c05 100644
> --- a/drivers/media/platform/vsp1/vsp1_entity.h
> +++ b/drivers/media/platform/vsp1/vsp1_entity.h
> @@ -106,6 +106,8 @@ struct vsp1_entity {
>  	unsigned int index;
>  	const struct vsp1_route *route;
>  
> +	struct vsp1_pipeline *pipe;
> +
>  	struct list_head list_dev;
>  	struct list_head list_pipe;
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_histo.c b/drivers/media/platform/vsp1/vsp1_histo.c
> index afab77cf4fa5..8638ebc514b4 100644
> --- a/drivers/media/platform/vsp1/vsp1_histo.c
> +++ b/drivers/media/platform/vsp1/vsp1_histo.c
> @@ -61,7 +61,7 @@ void vsp1_histogram_buffer_complete(struct vsp1_histogram *histo,
>  				    struct vsp1_histogram_buffer *buf,
>  				    size_t size)
>  {
> -	struct vsp1_pipeline *pipe = histo->pipe;
> +	struct vsp1_pipeline *pipe = histo->entity.pipe;
>  	unsigned long flags;
>  
>  	/*
> diff --git a/drivers/media/platform/vsp1/vsp1_histo.h b/drivers/media/platform/vsp1/vsp1_histo.h
> index af2874f6031d..e774adbf251f 100644
> --- a/drivers/media/platform/vsp1/vsp1_histo.h
> +++ b/drivers/media/platform/vsp1/vsp1_histo.h
> @@ -25,7 +25,6 @@
>  #include "vsp1_entity.h"
>  
>  struct vsp1_device;
> -struct vsp1_pipeline;
>  
>  #define HISTO_PAD_SINK				0
>  #define HISTO_PAD_SOURCE			1
> @@ -37,8 +36,6 @@ struct vsp1_histogram_buffer {
>  };
>  
>  struct vsp1_histogram {
> -	struct vsp1_pipeline *pipe;
> -
>  	struct vsp1_entity entity;
>  	struct video_device video;
>  	struct media_pad pad;
> diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
> index 44944ac86d9b..99ccbac3256a 100644
> --- a/drivers/media/platform/vsp1/vsp1_pipe.c
> +++ b/drivers/media/platform/vsp1/vsp1_pipe.c
> @@ -185,6 +185,7 @@ const struct vsp1_format_info *vsp1_get_format_info(struct vsp1_device *vsp1,
>  
>  void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
>  {
> +	struct vsp1_entity *entity;
>  	unsigned int i;
>  
>  	if (pipe->bru) {
> @@ -194,29 +195,13 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
>  			bru->inputs[i].rpf = NULL;
>  	}
>  
> -	for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i) {
> -		if (pipe->inputs[i]) {
> -			pipe->inputs[i]->pipe = NULL;
> -			pipe->inputs[i] = NULL;
> -		}
> -	}
> -
> -	if (pipe->output) {
> -		pipe->output->pipe = NULL;
> -		pipe->output = NULL;
> -	}
> +	for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i)
> +		pipe->inputs[i] = NULL;
>  
> -	if (pipe->hgo) {
> -		struct vsp1_hgo *hgo = to_hgo(&pipe->hgo->subdev);
> +	pipe->output = NULL;
>  
> -		hgo->histo.pipe = NULL;
> -	}
> -
> -	if (pipe->hgt) {
> -		struct vsp1_hgt *hgt = to_hgt(&pipe->hgt->subdev);
> -
> -		hgt->histo.pipe = NULL;
> -	}
> +	list_for_each_entry(entity, &pipe->entities, list_pipe)
> +		entity->pipe = NULL;

Excellent - looks like that got cleaned up somewhat thanks to this change.


>  
>  	INIT_LIST_HEAD(&pipe->entities);
>  	pipe->state = VSP1_PIPELINE_STOPPED;
> @@ -423,7 +408,7 @@ void vsp1_pipelines_suspend(struct vsp1_device *vsp1)
>  		if (wpf == NULL)
>  			continue;
>  
> -		pipe = wpf->pipe;
> +		pipe = wpf->entity.pipe;
>  		if (pipe == NULL)
>  			continue;
>  
> @@ -440,7 +425,7 @@ void vsp1_pipelines_suspend(struct vsp1_device *vsp1)
>  		if (wpf == NULL)
>  			continue;
>  
> -		pipe = wpf->pipe;
> +		pipe = wpf->entity.pipe;
>  		if (pipe == NULL)
>  			continue;
>  
> @@ -465,7 +450,7 @@ void vsp1_pipelines_resume(struct vsp1_device *vsp1)
>  		if (wpf == NULL)
>  			continue;
>  
> -		pipe = wpf->pipe;
> +		pipe = wpf->entity.pipe;
>  		if (pipe == NULL)
>  			continue;
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
> index 58215a7ab631..c94ac89abfa7 100644
> --- a/drivers/media/platform/vsp1/vsp1_rwpf.h
> +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
> @@ -27,7 +27,6 @@
>  
>  struct v4l2_ctrl;
>  struct vsp1_dl_manager;
> -struct vsp1_pipeline;
>  struct vsp1_rwpf;
>  struct vsp1_video;
>  
> @@ -39,7 +38,6 @@ struct vsp1_rwpf {
>  	struct vsp1_entity entity;
>  	struct v4l2_ctrl_handler ctrls;
>  
> -	struct vsp1_pipeline *pipe;
>  	struct vsp1_video *video;
>  
>  	unsigned int max_width;
> diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
> index c2d3b8f0f487..cdd53d6cc408 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.c
> +++ b/drivers/media/platform/vsp1/vsp1_video.c
> @@ -324,7 +324,7 @@ static int vsp1_video_pipeline_setup_partitions(struct vsp1_pipeline *pipe)
>  static struct vsp1_vb2_buffer *
>  vsp1_video_complete_buffer(struct vsp1_video *video)
>  {
> -	struct vsp1_pipeline *pipe = video->rwpf->pipe;
> +	struct vsp1_pipeline *pipe = video->rwpf->entity.pipe;
>  	struct vsp1_vb2_buffer *next = NULL;
>  	struct vsp1_vb2_buffer *done;
>  	unsigned long flags;
> @@ -598,20 +598,19 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe,
>  		subdev = media_entity_to_v4l2_subdev(entity);
>  		e = to_vsp1_entity(subdev);
>  		list_add_tail(&e->list_pipe, &pipe->entities);
> +		e->pipe = pipe;
>  
>  		switch (e->type) {
>  		case VSP1_ENTITY_RPF:
>  			rwpf = to_rwpf(subdev);
>  			pipe->inputs[rwpf->entity.index] = rwpf;
>  			rwpf->video->pipe_index = ++pipe->num_inputs;
> -			rwpf->pipe = pipe;
>  			break;
>  
>  		case VSP1_ENTITY_WPF:
>  			rwpf = to_rwpf(subdev);
>  			pipe->output = rwpf;
>  			rwpf->video->pipe_index = 0;
> -			rwpf->pipe = pipe;
>  			break;
>  
>  		case VSP1_ENTITY_LIF:
> @@ -625,12 +624,10 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe,
>  
>  		case VSP1_ENTITY_HGO:
>  			pipe->hgo = e;
> -			to_hgo(subdev)->histo.pipe = pipe;
>  			break;
>  
>  		case VSP1_ENTITY_HGT:
>  			pipe->hgt = e;
> -			to_hgt(subdev)->histo.pipe = pipe;
>  			break;
>  
>  		default:
> @@ -682,7 +679,7 @@ static struct vsp1_pipeline *vsp1_video_pipeline_get(struct vsp1_video *video)
>  	 * Otherwise allocate a new pipeline and initialize it, it will be freed
>  	 * when the last reference is released.
>  	 */
> -	if (!video->rwpf->pipe) {
> +	if (!video->rwpf->entity.pipe) {
>  		pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);
>  		if (!pipe)
>  			return ERR_PTR(-ENOMEM);
> @@ -694,7 +691,7 @@ static struct vsp1_pipeline *vsp1_video_pipeline_get(struct vsp1_video *video)
>  			return ERR_PTR(ret);
>  		}
>  	} else {
> -		pipe = video->rwpf->pipe;
> +		pipe = video->rwpf->entity.pipe;
>  		kref_get(&pipe->kref);
>  	}
>  
> @@ -777,7 +774,7 @@ static void vsp1_video_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_pipeline *pipe = video->rwpf->pipe;
> +	struct vsp1_pipeline *pipe = video->rwpf->entity.pipe;
>  	struct vsp1_vb2_buffer *buf = to_vsp1_vb2_buffer(vbuf);
>  	unsigned long flags;
>  	bool empty;
> @@ -872,7 +869,7 @@ static void vsp1_video_cleanup_pipeline(struct vsp1_pipeline *pipe)
>  static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
>  {
>  	struct vsp1_video *video = vb2_get_drv_priv(vq);
> -	struct vsp1_pipeline *pipe = video->rwpf->pipe;
> +	struct vsp1_pipeline *pipe = video->rwpf->entity.pipe;
>  	bool start_pipeline = false;
>  	unsigned long flags;
>  	int ret;
> @@ -913,7 +910,7 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
>  static void vsp1_video_stop_streaming(struct vb2_queue *vq)
>  {
>  	struct vsp1_video *video = vb2_get_drv_priv(vq);
> -	struct vsp1_pipeline *pipe = video->rwpf->pipe;
> +	struct vsp1_pipeline *pipe = video->rwpf->entity.pipe;
>  	unsigned long flags;
>  	int ret;
>  
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 05/15] v4l: vsp1: Use vsp1_entity.pipe to check if entity belongs to a pipeline
  2018-02-26 21:45   ` Laurent Pinchart
@ 2018-03-28 14:10     ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 14:10 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: dri-devel, linux-renesas-soc

Hi Laurent,

On 26/02/18 21:45, Laurent Pinchart wrote:
> The DRM pipeline handling code uses the entity's pipe list head to check
> whether the entity is already included in a pipeline. This method is a
> bit fragile in the sense that it uses list_empty() on a list_head that
> is a list member. Replace it by a simpler check for the entity pipe
> pointer.

Yes, excellent.

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

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index a7ad85ab0b08..e210917fdc3f 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -119,9 +119,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  			 * Remove the RPF from the pipe and the list of BRU
>  			 * inputs.
>  			 */
> -			WARN_ON(list_empty(&rpf->entity.list_pipe));
> +			WARN_ON(!rpf->entity.pipe);

Does this WARN_ON() have much value any more ?

I think it could probably be removed... unless there is a race between potential
calls through vsp1_du_atomic_flush() and vsp1_du_setup_lif() - but I would be
very surprised if that wasn't protected at the DRM levels.

 (Removing it if chosen doesn't need to be in this patch though)

>  			rpf->entity.pipe = NULL;
> -			list_del_init(&rpf->entity.list_pipe);
> +			list_del(&rpf->entity.list_pipe);
>  			pipe->inputs[i] = NULL;
>  
>  			bru->inputs[rpf->bru_input].rpf = NULL;
> @@ -537,7 +537,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  			continue;
>  		}
>  
> -		if (list_empty(&rpf->entity.list_pipe)) {
> +		if (!rpf->entity.pipe) {
>  			rpf->entity.pipe = pipe;
>  			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
>  		}
> @@ -566,7 +566,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  					   VI6_DPR_NODE_UNUSED);
>  
>  			entity->pipe = NULL;
> -			list_del_init(&entity->list_pipe);
> +			list_del(&entity->list_pipe);
>  
>  			continue;
>  		}
> 

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

* Re: [PATCH 05/15] v4l: vsp1: Use vsp1_entity.pipe to check if entity belongs to a pipeline
@ 2018-03-28 14:10     ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 14:10 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: linux-renesas-soc, dri-devel

Hi Laurent,

On 26/02/18 21:45, Laurent Pinchart wrote:
> The DRM pipeline handling code uses the entity's pipe list head to check
> whether the entity is already included in a pipeline. This method is a
> bit fragile in the sense that it uses list_empty() on a list_head that
> is a list member. Replace it by a simpler check for the entity pipe
> pointer.

Yes, excellent.

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

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index a7ad85ab0b08..e210917fdc3f 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -119,9 +119,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  			 * Remove the RPF from the pipe and the list of BRU
>  			 * inputs.
>  			 */
> -			WARN_ON(list_empty(&rpf->entity.list_pipe));
> +			WARN_ON(!rpf->entity.pipe);

Does this WARN_ON() have much value any more ?

I think it could probably be removed... unless there is a race between potential
calls through vsp1_du_atomic_flush() and vsp1_du_setup_lif() - but I would be
very surprised if that wasn't protected at the DRM levels.

 (Removing it if chosen doesn't need to be in this patch though)

>  			rpf->entity.pipe = NULL;
> -			list_del_init(&rpf->entity.list_pipe);
> +			list_del(&rpf->entity.list_pipe);
>  			pipe->inputs[i] = NULL;
>  
>  			bru->inputs[rpf->bru_input].rpf = NULL;
> @@ -537,7 +537,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  			continue;
>  		}
>  
> -		if (list_empty(&rpf->entity.list_pipe)) {
> +		if (!rpf->entity.pipe) {
>  			rpf->entity.pipe = pipe;
>  			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
>  		}
> @@ -566,7 +566,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  					   VI6_DPR_NODE_UNUSED);
>  
>  			entity->pipe = NULL;
> -			list_del_init(&entity->list_pipe);
> +			list_del(&entity->list_pipe);
>  
>  			continue;
>  		}
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 06/15] v4l: vsp1: Share duplicated DRM pipeline configuration code
  2018-02-26 21:45   ` Laurent Pinchart
@ 2018-03-28 14:25     ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 14:25 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: dri-devel, linux-renesas-soc



On 26/02/18 21:45, Laurent Pinchart wrote:
> Move the duplicated DRM pipeline configuration code to a function and
> call it from vsp1_du_setup_lif() and vsp1_du_atomic_flush().
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

LGTM.

I thought I had a bit of deja-vu on this patch ... but I can't seem to find
anything already posted.

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 95 +++++++++++++++-------------------
>  1 file changed, 43 insertions(+), 52 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index e210917fdc3f..9a043a915c0b 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -42,6 +42,47 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
>  		drm_pipe->du_complete(drm_pipe->du_private, completed);
>  }
>  
> +/* -----------------------------------------------------------------------------
> + * Pipeline Configuration
> + */
> +
> +/* Configure all entities in the pipeline. */
> +static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
> +{
> +	struct vsp1_entity *entity;
> +	struct vsp1_entity *next;
> +	struct vsp1_dl_list *dl;
> +
> +	dl = vsp1_dl_list_get(pipe->output->dlm);
> +
> +	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
> +		/* Disconnect unused RPFs from the pipeline. */
> +		if (entity->type == VSP1_ENTITY_RPF &&
> +		    !pipe->inputs[entity->index]) {
> +			vsp1_dl_list_write(dl, entity->route->reg,
> +					   VI6_DPR_NODE_UNUSED);
> +
> +			entity->pipe = NULL;
> +			list_del(&entity->list_pipe);
> +
> +			continue;
> +		}
> +
> +		vsp1_entity_route_setup(entity, pipe, dl);
> +
> +		if (entity->ops->configure) {
> +			entity->ops->configure(entity, pipe, dl,
> +					       VSP1_ENTITY_PARAMS_INIT);
> +			entity->ops->configure(entity, pipe, dl,
> +					       VSP1_ENTITY_PARAMS_RUNTIME);
> +			entity->ops->configure(entity, pipe, dl,
> +					       VSP1_ENTITY_PARAMS_PARTITION);
> +		}
> +	}
> +
> +	vsp1_dl_list_commit(dl);
> +}
> +
>  /* -----------------------------------------------------------------------------
>   * DU Driver API
>   */
> @@ -85,9 +126,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	struct vsp1_drm_pipeline *drm_pipe;
>  	struct vsp1_pipeline *pipe;
>  	struct vsp1_bru *bru;
> -	struct vsp1_entity *entity;
> -	struct vsp1_entity *next;
> -	struct vsp1_dl_list *dl;
>  	struct v4l2_subdev_format format;
>  	unsigned long flags;
>  	unsigned int i;
> @@ -239,22 +277,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0);
>  
>  	/* Configure all entities in the pipeline. */
> -	dl = vsp1_dl_list_get(pipe->output->dlm);
> -
> -	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
> -		vsp1_entity_route_setup(entity, pipe, dl);
> -
> -		if (entity->ops->configure) {
> -			entity->ops->configure(entity, pipe, dl,
> -					       VSP1_ENTITY_PARAMS_INIT);
> -			entity->ops->configure(entity, pipe, dl,
> -					       VSP1_ENTITY_PARAMS_RUNTIME);
> -			entity->ops->configure(entity, pipe, dl,
> -					       VSP1_ENTITY_PARAMS_PARTITION);
> -		}
> -	}
> -
> -	vsp1_dl_list_commit(dl);
> +	vsp1_du_pipeline_configure(pipe);
>  
>  	/* Start the pipeline. */
>  	spin_lock_irqsave(&pipe->irqlock, flags);
> @@ -490,15 +513,9 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  	struct vsp1_pipeline *pipe = &drm_pipe->pipe;
>  	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
>  	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
> -	struct vsp1_entity *entity;
> -	struct vsp1_entity *next;
> -	struct vsp1_dl_list *dl;
>  	unsigned int i;
>  	int ret;
>  
> -	/* Prepare the display list. */
> -	dl = vsp1_dl_list_get(pipe->output->dlm);
> -
>  	/* Count the number of enabled inputs and sort them by Z-order. */
>  	pipe->num_inputs = 0;
>  
> @@ -557,33 +574,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  				__func__, rpf->entity.index);
>  	}
>  
> -	/* Configure all entities in the pipeline. */
> -	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
> -		/* Disconnect unused RPFs from the pipeline. */
> -		if (entity->type == VSP1_ENTITY_RPF &&
> -		    !pipe->inputs[entity->index]) {
> -			vsp1_dl_list_write(dl, entity->route->reg,
> -					   VI6_DPR_NODE_UNUSED);
> -
> -			entity->pipe = NULL;
> -			list_del(&entity->list_pipe);
> -
> -			continue;
> -		}
> -
> -		vsp1_entity_route_setup(entity, pipe, dl);
> -
> -		if (entity->ops->configure) {
> -			entity->ops->configure(entity, pipe, dl,
> -					       VSP1_ENTITY_PARAMS_INIT);
> -			entity->ops->configure(entity, pipe, dl,
> -					       VSP1_ENTITY_PARAMS_RUNTIME);
> -			entity->ops->configure(entity, pipe, dl,
> -					       VSP1_ENTITY_PARAMS_PARTITION);
> -		}
> -	}
> -
> -	vsp1_dl_list_commit(dl);
> +	vsp1_du_pipeline_configure(pipe);
>  }
>  EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
>  
> 

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

* Re: [PATCH 06/15] v4l: vsp1: Share duplicated DRM pipeline configuration code
@ 2018-03-28 14:25     ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 14:25 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: linux-renesas-soc, dri-devel



On 26/02/18 21:45, Laurent Pinchart wrote:
> Move the duplicated DRM pipeline configuration code to a function and
> call it from vsp1_du_setup_lif() and vsp1_du_atomic_flush().
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

LGTM.

I thought I had a bit of deja-vu on this patch ... but I can't seem to find
anything already posted.

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 95 +++++++++++++++-------------------
>  1 file changed, 43 insertions(+), 52 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index e210917fdc3f..9a043a915c0b 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -42,6 +42,47 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
>  		drm_pipe->du_complete(drm_pipe->du_private, completed);
>  }
>  
> +/* -----------------------------------------------------------------------------
> + * Pipeline Configuration
> + */
> +
> +/* Configure all entities in the pipeline. */
> +static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
> +{
> +	struct vsp1_entity *entity;
> +	struct vsp1_entity *next;
> +	struct vsp1_dl_list *dl;
> +
> +	dl = vsp1_dl_list_get(pipe->output->dlm);
> +
> +	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
> +		/* Disconnect unused RPFs from the pipeline. */
> +		if (entity->type == VSP1_ENTITY_RPF &&
> +		    !pipe->inputs[entity->index]) {
> +			vsp1_dl_list_write(dl, entity->route->reg,
> +					   VI6_DPR_NODE_UNUSED);
> +
> +			entity->pipe = NULL;
> +			list_del(&entity->list_pipe);
> +
> +			continue;
> +		}
> +
> +		vsp1_entity_route_setup(entity, pipe, dl);
> +
> +		if (entity->ops->configure) {
> +			entity->ops->configure(entity, pipe, dl,
> +					       VSP1_ENTITY_PARAMS_INIT);
> +			entity->ops->configure(entity, pipe, dl,
> +					       VSP1_ENTITY_PARAMS_RUNTIME);
> +			entity->ops->configure(entity, pipe, dl,
> +					       VSP1_ENTITY_PARAMS_PARTITION);
> +		}
> +	}
> +
> +	vsp1_dl_list_commit(dl);
> +}
> +
>  /* -----------------------------------------------------------------------------
>   * DU Driver API
>   */
> @@ -85,9 +126,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	struct vsp1_drm_pipeline *drm_pipe;
>  	struct vsp1_pipeline *pipe;
>  	struct vsp1_bru *bru;
> -	struct vsp1_entity *entity;
> -	struct vsp1_entity *next;
> -	struct vsp1_dl_list *dl;
>  	struct v4l2_subdev_format format;
>  	unsigned long flags;
>  	unsigned int i;
> @@ -239,22 +277,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0);
>  
>  	/* Configure all entities in the pipeline. */
> -	dl = vsp1_dl_list_get(pipe->output->dlm);
> -
> -	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
> -		vsp1_entity_route_setup(entity, pipe, dl);
> -
> -		if (entity->ops->configure) {
> -			entity->ops->configure(entity, pipe, dl,
> -					       VSP1_ENTITY_PARAMS_INIT);
> -			entity->ops->configure(entity, pipe, dl,
> -					       VSP1_ENTITY_PARAMS_RUNTIME);
> -			entity->ops->configure(entity, pipe, dl,
> -					       VSP1_ENTITY_PARAMS_PARTITION);
> -		}
> -	}
> -
> -	vsp1_dl_list_commit(dl);
> +	vsp1_du_pipeline_configure(pipe);
>  
>  	/* Start the pipeline. */
>  	spin_lock_irqsave(&pipe->irqlock, flags);
> @@ -490,15 +513,9 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  	struct vsp1_pipeline *pipe = &drm_pipe->pipe;
>  	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
>  	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
> -	struct vsp1_entity *entity;
> -	struct vsp1_entity *next;
> -	struct vsp1_dl_list *dl;
>  	unsigned int i;
>  	int ret;
>  
> -	/* Prepare the display list. */
> -	dl = vsp1_dl_list_get(pipe->output->dlm);
> -
>  	/* Count the number of enabled inputs and sort them by Z-order. */
>  	pipe->num_inputs = 0;
>  
> @@ -557,33 +574,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  				__func__, rpf->entity.index);
>  	}
>  
> -	/* Configure all entities in the pipeline. */
> -	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
> -		/* Disconnect unused RPFs from the pipeline. */
> -		if (entity->type == VSP1_ENTITY_RPF &&
> -		    !pipe->inputs[entity->index]) {
> -			vsp1_dl_list_write(dl, entity->route->reg,
> -					   VI6_DPR_NODE_UNUSED);
> -
> -			entity->pipe = NULL;
> -			list_del(&entity->list_pipe);
> -
> -			continue;
> -		}
> -
> -		vsp1_entity_route_setup(entity, pipe, dl);
> -
> -		if (entity->ops->configure) {
> -			entity->ops->configure(entity, pipe, dl,
> -					       VSP1_ENTITY_PARAMS_INIT);
> -			entity->ops->configure(entity, pipe, dl,
> -					       VSP1_ENTITY_PARAMS_RUNTIME);
> -			entity->ops->configure(entity, pipe, dl,
> -					       VSP1_ENTITY_PARAMS_PARTITION);
> -		}
> -	}
> -
> -	vsp1_dl_list_commit(dl);
> +	vsp1_du_pipeline_configure(pipe);
>  }
>  EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
>  
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 07/15] v4l: vsp1: Move DRM atomic commit pipeline setup to separate function
  2018-02-26 21:45   ` Laurent Pinchart
@ 2018-03-28 14:43     ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 14:43 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: dri-devel, linux-renesas-soc

Hi Laurent,

On 26/02/18 21:45, Laurent Pinchart wrote:
> The DRM pipeline setup code used at atomic commit time is similar to the
> setup code used when enabling the pipeline. Move it to a separate
> function in order to share it.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Assuming no hidden secret code addition in this code move that I haven't seen..

Only a minor nit below asking if the function should be pluralised (_inputs,
rather than _input)

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>


> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 347 +++++++++++++++++----------------
>  1 file changed, 180 insertions(+), 167 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 9a043a915c0b..7bf697ba7969 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -46,6 +46,185 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
>   * Pipeline Configuration
>   */
>  
> +/* Setup one RPF and the connected BRU sink pad. */
> +static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
> +				      struct vsp1_pipeline *pipe,
> +				      struct vsp1_rwpf *rpf,
> +				      unsigned int bru_input)
> +{
> +	struct v4l2_subdev_selection sel;
> +	struct v4l2_subdev_format format;
> +	const struct v4l2_rect *crop;
> +	int ret;
> +
> +	/*
> +	 * Configure the format on the RPF sink pad and propagate it up to the
> +	 * BRU sink pad.
> +	 */
> +	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
> +
> +	memset(&format, 0, sizeof(format));
> +	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> +	format.pad = RWPF_PAD_SINK;
> +	format.format.width = crop->width + crop->left;
> +	format.format.height = crop->height + crop->top;
> +	format.format.code = rpf->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 = *crop;
> +
> +	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 = bru_input;
> +
> +	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
> +			       &format);
> +	if (ret < 0)
> +		return ret;
> +
> +	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
> +		__func__, format.format.width, format.format.height,
> +		format.format.code, BRU_NAME(pipe->bru), format.pad);
> +
> +	sel.pad = bru_input;
> +	sel.target = V4L2_SEL_TGT_COMPOSE;
> +	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
> +
> +	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL,
> +			       &sel);
> +	if (ret < 0)
> +		return ret;
> +
> +	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
> +		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
> +		BRU_NAME(pipe->bru), sel.pad);
> +
> +	return 0;
> +}
> +
> +static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
> +{
> +	return vsp1->drm->inputs[rpf->entity.index].zpos;
> +}
> +
> +/* Setup the input side of the pipeline (RPFs and BRU sink pads). */
> +static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,

Minor nit - shouldn't this be _setup_inputs(..)
as we could have multiple inputs, and it configures them all.


> +					struct vsp1_pipeline *pipe)
> +{
> +	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
> +	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
> +	unsigned int i;
> +	int ret;
> +
> +	/* Count the number of enabled inputs and sort them by Z-order. */
> +	pipe->num_inputs = 0;
> +
> +	for (i = 0; i < vsp1->info->rpf_count; ++i) {
> +		struct vsp1_rwpf *rpf = vsp1->rpf[i];
> +		unsigned int j;
> +
> +		/*
> +		 * Make sure we don't accept more inputs than the hardware can
> +		 * handle. This is a temporary fix to avoid display stall, we
> +		 * need to instead allocate the BRU or BRS to display pipelines
> +		 * dynamically based on the number of planes they each use.
> +		 */
> +		if (pipe->num_inputs >= pipe->bru->source_pad)
> +			pipe->inputs[i] = NULL;
> +
> +		if (!pipe->inputs[i])
> +			continue;
> +
> +		/* Insert the RPF in the sorted RPFs array. */
> +		for (j = pipe->num_inputs++; j > 0; --j) {
> +			if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf))
> +				break;
> +			inputs[j] = inputs[j-1];
> +		}
> +
> +		inputs[j] = rpf;
> +	}
> +
> +	/* Setup the RPF input pipeline for every enabled input. */
> +	for (i = 0; i < pipe->bru->source_pad; ++i) {
> +		struct vsp1_rwpf *rpf = inputs[i];
> +
> +		if (!rpf) {
> +			bru->inputs[i].rpf = NULL;
> +			continue;
> +		}
> +
> +		if (!rpf->entity.pipe) {
> +			rpf->entity.pipe = pipe;
> +			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
> +		}
> +
> +		bru->inputs[i].rpf = rpf;
> +		rpf->bru_input = i;
> +		rpf->entity.sink = pipe->bru;
> +		rpf->entity.sink_pad = i;
> +
> +		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
> +			__func__, rpf->entity.index, BRU_NAME(pipe->bru), i);
> +
> +		ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, i);
> +		if (ret < 0) {
> +			dev_err(vsp1->dev,
> +				"%s: failed to setup RPF.%u\n",
> +				__func__, rpf->entity.index);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
>  /* Configure all entities in the pipeline. */
>  static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
>  {
> @@ -396,111 +575,6 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index,
>  }
>  EXPORT_SYMBOL_GPL(vsp1_du_atomic_update);
>  
> -static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1,
> -				  struct vsp1_pipeline *pipe,
> -				  struct vsp1_rwpf *rpf, unsigned int bru_input)
> -{
> -	struct v4l2_subdev_selection sel;
> -	struct v4l2_subdev_format format;
> -	const struct v4l2_rect *crop;
> -	int ret;
> -
> -	/*
> -	 * Configure the format on the RPF sink pad and propagate it up to the
> -	 * BRU sink pad.
> -	 */
> -	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
> -
> -	memset(&format, 0, sizeof(format));
> -	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> -	format.pad = RWPF_PAD_SINK;
> -	format.format.width = crop->width + crop->left;
> -	format.format.height = crop->height + crop->top;
> -	format.format.code = rpf->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 = *crop;
> -
> -	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 = bru_input;
> -
> -	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
> -			       &format);
> -	if (ret < 0)
> -		return ret;
> -
> -	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
> -		__func__, format.format.width, format.format.height,
> -		format.format.code, BRU_NAME(pipe->bru), format.pad);
> -
> -	sel.pad = bru_input;
> -	sel.target = V4L2_SEL_TGT_COMPOSE;
> -	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
> -
> -	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL,
> -			       &sel);
> -	if (ret < 0)
> -		return ret;
> -
> -	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
> -		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
> -		BRU_NAME(pipe->bru), sel.pad);
> -
> -	return 0;
> -}
> -
> -static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
> -{
> -	return vsp1->drm->inputs[rpf->entity.index].zpos;
> -}
> -
>  /**
>   * vsp1_du_atomic_flush - Commit an atomic update
>   * @dev: the VSP device
> @@ -511,69 +585,8 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
>  	struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index];
>  	struct vsp1_pipeline *pipe = &drm_pipe->pipe;
> -	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
> -	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
> -	unsigned int i;
> -	int ret;
> -
> -	/* Count the number of enabled inputs and sort them by Z-order. */
> -	pipe->num_inputs = 0;
> -
> -	for (i = 0; i < vsp1->info->rpf_count; ++i) {
> -		struct vsp1_rwpf *rpf = vsp1->rpf[i];
> -		unsigned int j;
> -
> -		/*
> -		 * Make sure we don't accept more inputs than the hardware can
> -		 * handle. This is a temporary fix to avoid display stall, we
> -		 * need to instead allocate the BRU or BRS to display pipelines
> -		 * dynamically based on the number of planes they each use.
> -		 */
> -		if (pipe->num_inputs >= pipe->bru->source_pad)
> -			pipe->inputs[i] = NULL;
> -
> -		if (!pipe->inputs[i])
> -			continue;
> -
> -		/* Insert the RPF in the sorted RPFs array. */
> -		for (j = pipe->num_inputs++; j > 0; --j) {
> -			if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf))
> -				break;
> -			inputs[j] = inputs[j-1];
> -		}
> -
> -		inputs[j] = rpf;
> -	}
> -
> -	/* Setup the RPF input pipeline for every enabled input. */
> -	for (i = 0; i < pipe->bru->source_pad; ++i) {
> -		struct vsp1_rwpf *rpf = inputs[i];
> -
> -		if (!rpf) {
> -			bru->inputs[i].rpf = NULL;
> -			continue;
> -		}
> -
> -		if (!rpf->entity.pipe) {
> -			rpf->entity.pipe = pipe;
> -			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
> -		}
> -
> -		bru->inputs[i].rpf = rpf;
> -		rpf->bru_input = i;
> -		rpf->entity.sink = pipe->bru;
> -		rpf->entity.sink_pad = i;
> -
> -		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
> -			__func__, rpf->entity.index, BRU_NAME(pipe->bru), i);
> -
> -		ret = vsp1_du_setup_rpf_pipe(vsp1, pipe, rpf, i);
> -		if (ret < 0)
> -			dev_err(vsp1->dev,
> -				"%s: failed to setup RPF.%u\n",
> -				__func__, rpf->entity.index);
> -	}
>  
> +	vsp1_du_pipeline_setup_input(vsp1, pipe);
>  	vsp1_du_pipeline_configure(pipe);
>  }
>  EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
> 

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

* Re: [PATCH 07/15] v4l: vsp1: Move DRM atomic commit pipeline setup to separate function
@ 2018-03-28 14:43     ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 14:43 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: linux-renesas-soc, dri-devel

Hi Laurent,

On 26/02/18 21:45, Laurent Pinchart wrote:
> The DRM pipeline setup code used at atomic commit time is similar to the
> setup code used when enabling the pipeline. Move it to a separate
> function in order to share it.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Assuming no hidden secret code addition in this code move that I haven't seen..

Only a minor nit below asking if the function should be pluralised (_inputs,
rather than _input)

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>


> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 347 +++++++++++++++++----------------
>  1 file changed, 180 insertions(+), 167 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 9a043a915c0b..7bf697ba7969 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -46,6 +46,185 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
>   * Pipeline Configuration
>   */
>  
> +/* Setup one RPF and the connected BRU sink pad. */
> +static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
> +				      struct vsp1_pipeline *pipe,
> +				      struct vsp1_rwpf *rpf,
> +				      unsigned int bru_input)
> +{
> +	struct v4l2_subdev_selection sel;
> +	struct v4l2_subdev_format format;
> +	const struct v4l2_rect *crop;
> +	int ret;
> +
> +	/*
> +	 * Configure the format on the RPF sink pad and propagate it up to the
> +	 * BRU sink pad.
> +	 */
> +	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
> +
> +	memset(&format, 0, sizeof(format));
> +	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> +	format.pad = RWPF_PAD_SINK;
> +	format.format.width = crop->width + crop->left;
> +	format.format.height = crop->height + crop->top;
> +	format.format.code = rpf->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 = *crop;
> +
> +	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 = bru_input;
> +
> +	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
> +			       &format);
> +	if (ret < 0)
> +		return ret;
> +
> +	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
> +		__func__, format.format.width, format.format.height,
> +		format.format.code, BRU_NAME(pipe->bru), format.pad);
> +
> +	sel.pad = bru_input;
> +	sel.target = V4L2_SEL_TGT_COMPOSE;
> +	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
> +
> +	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL,
> +			       &sel);
> +	if (ret < 0)
> +		return ret;
> +
> +	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
> +		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
> +		BRU_NAME(pipe->bru), sel.pad);
> +
> +	return 0;
> +}
> +
> +static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
> +{
> +	return vsp1->drm->inputs[rpf->entity.index].zpos;
> +}
> +
> +/* Setup the input side of the pipeline (RPFs and BRU sink pads). */
> +static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,

Minor nit - shouldn't this be _setup_inputs(..)
as we could have multiple inputs, and it configures them all.


> +					struct vsp1_pipeline *pipe)
> +{
> +	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
> +	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
> +	unsigned int i;
> +	int ret;
> +
> +	/* Count the number of enabled inputs and sort them by Z-order. */
> +	pipe->num_inputs = 0;
> +
> +	for (i = 0; i < vsp1->info->rpf_count; ++i) {
> +		struct vsp1_rwpf *rpf = vsp1->rpf[i];
> +		unsigned int j;
> +
> +		/*
> +		 * Make sure we don't accept more inputs than the hardware can
> +		 * handle. This is a temporary fix to avoid display stall, we
> +		 * need to instead allocate the BRU or BRS to display pipelines
> +		 * dynamically based on the number of planes they each use.
> +		 */
> +		if (pipe->num_inputs >= pipe->bru->source_pad)
> +			pipe->inputs[i] = NULL;
> +
> +		if (!pipe->inputs[i])
> +			continue;
> +
> +		/* Insert the RPF in the sorted RPFs array. */
> +		for (j = pipe->num_inputs++; j > 0; --j) {
> +			if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf))
> +				break;
> +			inputs[j] = inputs[j-1];
> +		}
> +
> +		inputs[j] = rpf;
> +	}
> +
> +	/* Setup the RPF input pipeline for every enabled input. */
> +	for (i = 0; i < pipe->bru->source_pad; ++i) {
> +		struct vsp1_rwpf *rpf = inputs[i];
> +
> +		if (!rpf) {
> +			bru->inputs[i].rpf = NULL;
> +			continue;
> +		}
> +
> +		if (!rpf->entity.pipe) {
> +			rpf->entity.pipe = pipe;
> +			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
> +		}
> +
> +		bru->inputs[i].rpf = rpf;
> +		rpf->bru_input = i;
> +		rpf->entity.sink = pipe->bru;
> +		rpf->entity.sink_pad = i;
> +
> +		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
> +			__func__, rpf->entity.index, BRU_NAME(pipe->bru), i);
> +
> +		ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, i);
> +		if (ret < 0) {
> +			dev_err(vsp1->dev,
> +				"%s: failed to setup RPF.%u\n",
> +				__func__, rpf->entity.index);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
>  /* Configure all entities in the pipeline. */
>  static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
>  {
> @@ -396,111 +575,6 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index,
>  }
>  EXPORT_SYMBOL_GPL(vsp1_du_atomic_update);
>  
> -static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1,
> -				  struct vsp1_pipeline *pipe,
> -				  struct vsp1_rwpf *rpf, unsigned int bru_input)
> -{
> -	struct v4l2_subdev_selection sel;
> -	struct v4l2_subdev_format format;
> -	const struct v4l2_rect *crop;
> -	int ret;
> -
> -	/*
> -	 * Configure the format on the RPF sink pad and propagate it up to the
> -	 * BRU sink pad.
> -	 */
> -	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
> -
> -	memset(&format, 0, sizeof(format));
> -	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> -	format.pad = RWPF_PAD_SINK;
> -	format.format.width = crop->width + crop->left;
> -	format.format.height = crop->height + crop->top;
> -	format.format.code = rpf->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 = *crop;
> -
> -	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 = bru_input;
> -
> -	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
> -			       &format);
> -	if (ret < 0)
> -		return ret;
> -
> -	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
> -		__func__, format.format.width, format.format.height,
> -		format.format.code, BRU_NAME(pipe->bru), format.pad);
> -
> -	sel.pad = bru_input;
> -	sel.target = V4L2_SEL_TGT_COMPOSE;
> -	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
> -
> -	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL,
> -			       &sel);
> -	if (ret < 0)
> -		return ret;
> -
> -	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
> -		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
> -		BRU_NAME(pipe->bru), sel.pad);
> -
> -	return 0;
> -}
> -
> -static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
> -{
> -	return vsp1->drm->inputs[rpf->entity.index].zpos;
> -}
> -
>  /**
>   * vsp1_du_atomic_flush - Commit an atomic update
>   * @dev: the VSP device
> @@ -511,69 +585,8 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
>  	struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index];
>  	struct vsp1_pipeline *pipe = &drm_pipe->pipe;
> -	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
> -	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
> -	unsigned int i;
> -	int ret;
> -
> -	/* Count the number of enabled inputs and sort them by Z-order. */
> -	pipe->num_inputs = 0;
> -
> -	for (i = 0; i < vsp1->info->rpf_count; ++i) {
> -		struct vsp1_rwpf *rpf = vsp1->rpf[i];
> -		unsigned int j;
> -
> -		/*
> -		 * Make sure we don't accept more inputs than the hardware can
> -		 * handle. This is a temporary fix to avoid display stall, we
> -		 * need to instead allocate the BRU or BRS to display pipelines
> -		 * dynamically based on the number of planes they each use.
> -		 */
> -		if (pipe->num_inputs >= pipe->bru->source_pad)
> -			pipe->inputs[i] = NULL;
> -
> -		if (!pipe->inputs[i])
> -			continue;
> -
> -		/* Insert the RPF in the sorted RPFs array. */
> -		for (j = pipe->num_inputs++; j > 0; --j) {
> -			if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf))
> -				break;
> -			inputs[j] = inputs[j-1];
> -		}
> -
> -		inputs[j] = rpf;
> -	}
> -
> -	/* Setup the RPF input pipeline for every enabled input. */
> -	for (i = 0; i < pipe->bru->source_pad; ++i) {
> -		struct vsp1_rwpf *rpf = inputs[i];
> -
> -		if (!rpf) {
> -			bru->inputs[i].rpf = NULL;
> -			continue;
> -		}
> -
> -		if (!rpf->entity.pipe) {
> -			rpf->entity.pipe = pipe;
> -			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
> -		}
> -
> -		bru->inputs[i].rpf = rpf;
> -		rpf->bru_input = i;
> -		rpf->entity.sink = pipe->bru;
> -		rpf->entity.sink_pad = i;
> -
> -		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
> -			__func__, rpf->entity.index, BRU_NAME(pipe->bru), i);
> -
> -		ret = vsp1_du_setup_rpf_pipe(vsp1, pipe, rpf, i);
> -		if (ret < 0)
> -			dev_err(vsp1->dev,
> -				"%s: failed to setup RPF.%u\n",
> -				__func__, rpf->entity.index);
> -	}
>  
> +	vsp1_du_pipeline_setup_input(vsp1, pipe);
>  	vsp1_du_pipeline_configure(pipe);
>  }
>  EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 09/15] v4l: vsp1: Replace manual DRM pipeline input setup in vsp1_du_setup_lif
  2018-02-26 21:45   ` Laurent Pinchart
@ 2018-03-28 15:01     ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 15:01 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: dri-devel, linux-renesas-soc

Hi Laurent,

On 26/02/18 21:45, Laurent Pinchart wrote:
> The vsp1_du_setup_lif() function setups the DRM pipeline input manually.

s/ setups the / sets up the /

> This duplicates the code from the vsp1_du_pipeline_setup_input()
> function. Replace the manual implementation by a call to the function.
> 
> As the pipeline has no enabled input in vsp1_du_setup_lif(), the
> vsp1_du_pipeline_setup_input() function will not setup any RPF, and will
> thus not setup formats on the BRU sink pads. This isn't a problem as all
> inputs are disabled, and the BRU sink pads will be reconfigured from the
> atomic commit handler when inputs will be enabled.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Aside from the above,

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 40 +++++-----------------------------
>  1 file changed, 6 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 6ad8aa6c8138..00ce99bd1605 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -412,47 +412,19 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	dev_dbg(vsp1->dev, "%s: configuring LIF%u with format %ux%u\n",
>  		__func__, pipe_index, cfg->width, cfg->height);
>  
> -	/*
> -	 * Configure the format at the BRU sinks and propagate it through the
> -	 * pipeline.
> -	 */
> +	/* Setup formats through the pipeline. */
> +	ret = vsp1_du_pipeline_setup_input(vsp1, pipe);
> +	if (ret < 0)
> +		return ret;
> +
>  	memset(&format, 0, sizeof(format));
>  	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> -
> -	for (i = 0; i < pipe->bru->source_pad; ++i) {
> -		format.pad = i;
> -
> -		format.format.width = cfg->width;
> -		format.format.height = cfg->height;
> -		format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
> -		format.format.field = V4L2_FIELD_NONE;
> -
> -		ret = v4l2_subdev_call(&pipe->bru->subdev, pad,
> -				       set_fmt, NULL, &format);
> -		if (ret < 0)
> -			return ret;
> -
> -		dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
> -			__func__, format.format.width, format.format.height,
> -			format.format.code, BRU_NAME(pipe->bru), i);
> -	}
> -
> -	format.pad = pipe->bru->source_pad;
> +	format.pad = RWPF_PAD_SINK;
>  	format.format.width = cfg->width;
>  	format.format.height = cfg->height;
>  	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
>  	format.format.field = V4L2_FIELD_NONE;
>  
> -	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
> -			       &format);
> -	if (ret < 0)
> -		return ret;
> -
> -	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
> -		__func__, format.format.width, format.format.height,
> -		format.format.code, BRU_NAME(pipe->bru), i);
> -
> -	format.pad = RWPF_PAD_SINK;
>  	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL,
>  			       &format);
>  	if (ret < 0)
> 

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

* Re: [PATCH 09/15] v4l: vsp1: Replace manual DRM pipeline input setup in vsp1_du_setup_lif
@ 2018-03-28 15:01     ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 15:01 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: linux-renesas-soc, dri-devel

Hi Laurent,

On 26/02/18 21:45, Laurent Pinchart wrote:
> The vsp1_du_setup_lif() function setups the DRM pipeline input manually.

s/ setups the / sets up the /

> This duplicates the code from the vsp1_du_pipeline_setup_input()
> function. Replace the manual implementation by a call to the function.
> 
> As the pipeline has no enabled input in vsp1_du_setup_lif(), the
> vsp1_du_pipeline_setup_input() function will not setup any RPF, and will
> thus not setup formats on the BRU sink pads. This isn't a problem as all
> inputs are disabled, and the BRU sink pads will be reconfigured from the
> atomic commit handler when inputs will be enabled.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Aside from the above,

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 40 +++++-----------------------------
>  1 file changed, 6 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 6ad8aa6c8138..00ce99bd1605 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -412,47 +412,19 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	dev_dbg(vsp1->dev, "%s: configuring LIF%u with format %ux%u\n",
>  		__func__, pipe_index, cfg->width, cfg->height);
>  
> -	/*
> -	 * Configure the format at the BRU sinks and propagate it through the
> -	 * pipeline.
> -	 */
> +	/* Setup formats through the pipeline. */
> +	ret = vsp1_du_pipeline_setup_input(vsp1, pipe);
> +	if (ret < 0)
> +		return ret;
> +
>  	memset(&format, 0, sizeof(format));
>  	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> -
> -	for (i = 0; i < pipe->bru->source_pad; ++i) {
> -		format.pad = i;
> -
> -		format.format.width = cfg->width;
> -		format.format.height = cfg->height;
> -		format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
> -		format.format.field = V4L2_FIELD_NONE;
> -
> -		ret = v4l2_subdev_call(&pipe->bru->subdev, pad,
> -				       set_fmt, NULL, &format);
> -		if (ret < 0)
> -			return ret;
> -
> -		dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
> -			__func__, format.format.width, format.format.height,
> -			format.format.code, BRU_NAME(pipe->bru), i);
> -	}
> -
> -	format.pad = pipe->bru->source_pad;
> +	format.pad = RWPF_PAD_SINK;
>  	format.format.width = cfg->width;
>  	format.format.height = cfg->height;
>  	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
>  	format.format.field = V4L2_FIELD_NONE;
>  
> -	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
> -			       &format);
> -	if (ret < 0)
> -		return ret;
> -
> -	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
> -		__func__, format.format.width, format.format.height,
> -		format.format.code, BRU_NAME(pipe->bru), i);
> -
> -	format.pad = RWPF_PAD_SINK;
>  	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL,
>  			       &format);
>  	if (ret < 0)
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 08/15] v4l: vsp1: Setup BRU at atomic commit time
  2018-02-26 21:45   ` Laurent Pinchart
@ 2018-03-28 19:01     ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 19:01 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: dri-devel, linux-renesas-soc

Hi Laurent,

On 26/02/18 21:45, Laurent Pinchart wrote:
> To implement fully dynamic plane assignment to pipelines, we need to
> reassign the BRU and BRS to the DRM pipelines in the atomic commit
> handler. In preparation for this setup factor out the BRU source pad
> code and call it both at LIF setup and atomic commit time.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Oops .. skipped one.

But this looks ok to me.

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 56 +++++++++++++++++++++++++++++++++-
>  drivers/media/platform/vsp1/vsp1_drm.h |  5 +++
>  2 files changed, 60 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 7bf697ba7969..6ad8aa6c8138 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -148,12 +148,51 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
>  	return 0;
>  }
>  
> +/* Setup the BRU source pad. */
> +static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
> +				      struct vsp1_pipeline *pipe)
> +{
> +	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
> +	struct v4l2_subdev_format format = {
> +		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
> +	};
> +	int ret;
> +
> +	/*
> +	 * Configure the format on the BRU source and verify that it matches the
> +	 * requested format. We don't set the media bus code as it is configured
> +	 * on the BRU sink pad 0 and propagated inside the entity, not on the
> +	 * source pad.
> +	 */
> +	format.pad = pipe->bru->source_pad;
> +	format.format.width = drm_pipe->width;
> +	format.format.height = drm_pipe->height;
> +	format.format.field = V4L2_FIELD_NONE;
> +
> +	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
> +			       &format);
> +	if (ret < 0)
> +		return ret;
> +
> +	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
> +		__func__, format.format.width, format.format.height,
> +		format.format.code, BRU_NAME(pipe->bru), pipe->bru->source_pad);
> +
> +	if (format.format.width != drm_pipe->width ||
> +	    format.format.height != drm_pipe->height) {
> +		dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__);
> +		return -EPIPE;
> +	}
> +
> +	return 0;
> +}
> +
>  static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
>  {
>  	return vsp1->drm->inputs[rpf->entity.index].zpos;
>  }
>  
> -/* Setup the input side of the pipeline (RPFs and BRU sink pads). */
> +/* Setup the input side of the pipeline (RPFs and BRU). */
>  static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  					struct vsp1_pipeline *pipe)
>  {
> @@ -191,6 +230,18 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  		inputs[j] = rpf;
>  	}
>  
> +	/*
> +	 * Setup the BRU. This must be done before setting up the RPF input
> +	 * pipelines as the BRU sink compose rectangles depend on the BRU source
> +	 * format.
> +	 */
> +	ret = vsp1_du_pipeline_setup_bru(vsp1, pipe);
> +	if (ret < 0) {
> +		dev_err(vsp1->dev, "%s: failed to setup %s source\n", __func__,
> +			BRU_NAME(pipe->bru));
> +		return ret;
> +	}
> +
>  	/* Setup the RPF input pipeline for every enabled input. */
>  	for (i = 0; i < pipe->bru->source_pad; ++i) {
>  		struct vsp1_rwpf *rpf = inputs[i];
> @@ -355,6 +406,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  		return 0;
>  	}
>  
> +	drm_pipe->width = cfg->width;
> +	drm_pipe->height = cfg->height;
> +
>  	dev_dbg(vsp1->dev, "%s: configuring LIF%u with format %ux%u\n",
>  		__func__, pipe_index, cfg->width, cfg->height);
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
> index 9aa19325cbe9..c8dd75ba01f6 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.h
> +++ b/drivers/media/platform/vsp1/vsp1_drm.h
> @@ -20,12 +20,17 @@
>  /**
>   * vsp1_drm_pipeline - State for the API exposed to the DRM driver
>   * @pipe: the VSP1 pipeline used for display
> + * @width: output display width
> + * @height: output display height
>   * @du_complete: frame completion callback for the DU driver (optional)
>   * @du_private: data to be passed to the du_complete callback
>   */
>  struct vsp1_drm_pipeline {
>  	struct vsp1_pipeline pipe;
>  
> +	unsigned int width;
> +	unsigned int height;
> +
>  	/* Frame synchronisation */
>  	void (*du_complete)(void *, bool);
>  	void *du_private;
> 

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

* Re: [PATCH 08/15] v4l: vsp1: Setup BRU at atomic commit time
@ 2018-03-28 19:01     ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 19:01 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: linux-renesas-soc, dri-devel

Hi Laurent,

On 26/02/18 21:45, Laurent Pinchart wrote:
> To implement fully dynamic plane assignment to pipelines, we need to
> reassign the BRU and BRS to the DRM pipelines in the atomic commit
> handler. In preparation for this setup factor out the BRU source pad
> code and call it both at LIF setup and atomic commit time.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Oops .. skipped one.

But this looks ok to me.

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 56 +++++++++++++++++++++++++++++++++-
>  drivers/media/platform/vsp1/vsp1_drm.h |  5 +++
>  2 files changed, 60 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 7bf697ba7969..6ad8aa6c8138 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -148,12 +148,51 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
>  	return 0;
>  }
>  
> +/* Setup the BRU source pad. */
> +static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
> +				      struct vsp1_pipeline *pipe)
> +{
> +	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
> +	struct v4l2_subdev_format format = {
> +		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
> +	};
> +	int ret;
> +
> +	/*
> +	 * Configure the format on the BRU source and verify that it matches the
> +	 * requested format. We don't set the media bus code as it is configured
> +	 * on the BRU sink pad 0 and propagated inside the entity, not on the
> +	 * source pad.
> +	 */
> +	format.pad = pipe->bru->source_pad;
> +	format.format.width = drm_pipe->width;
> +	format.format.height = drm_pipe->height;
> +	format.format.field = V4L2_FIELD_NONE;
> +
> +	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
> +			       &format);
> +	if (ret < 0)
> +		return ret;
> +
> +	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
> +		__func__, format.format.width, format.format.height,
> +		format.format.code, BRU_NAME(pipe->bru), pipe->bru->source_pad);
> +
> +	if (format.format.width != drm_pipe->width ||
> +	    format.format.height != drm_pipe->height) {
> +		dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__);
> +		return -EPIPE;
> +	}
> +
> +	return 0;
> +}
> +
>  static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
>  {
>  	return vsp1->drm->inputs[rpf->entity.index].zpos;
>  }
>  
> -/* Setup the input side of the pipeline (RPFs and BRU sink pads). */
> +/* Setup the input side of the pipeline (RPFs and BRU). */
>  static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  					struct vsp1_pipeline *pipe)
>  {
> @@ -191,6 +230,18 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  		inputs[j] = rpf;
>  	}
>  
> +	/*
> +	 * Setup the BRU. This must be done before setting up the RPF input
> +	 * pipelines as the BRU sink compose rectangles depend on the BRU source
> +	 * format.
> +	 */
> +	ret = vsp1_du_pipeline_setup_bru(vsp1, pipe);
> +	if (ret < 0) {
> +		dev_err(vsp1->dev, "%s: failed to setup %s source\n", __func__,
> +			BRU_NAME(pipe->bru));
> +		return ret;
> +	}
> +
>  	/* Setup the RPF input pipeline for every enabled input. */
>  	for (i = 0; i < pipe->bru->source_pad; ++i) {
>  		struct vsp1_rwpf *rpf = inputs[i];
> @@ -355,6 +406,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  		return 0;
>  	}
>  
> +	drm_pipe->width = cfg->width;
> +	drm_pipe->height = cfg->height;
> +
>  	dev_dbg(vsp1->dev, "%s: configuring LIF%u with format %ux%u\n",
>  		__func__, pipe_index, cfg->width, cfg->height);
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
> index 9aa19325cbe9..c8dd75ba01f6 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.h
> +++ b/drivers/media/platform/vsp1/vsp1_drm.h
> @@ -20,12 +20,17 @@
>  /**
>   * vsp1_drm_pipeline - State for the API exposed to the DRM driver
>   * @pipe: the VSP1 pipeline used for display
> + * @width: output display width
> + * @height: output display height
>   * @du_complete: frame completion callback for the DU driver (optional)
>   * @du_private: data to be passed to the du_complete callback
>   */
>  struct vsp1_drm_pipeline {
>  	struct vsp1_pipeline pipe;
>  
> +	unsigned int width;
> +	unsigned int height;
> +
>  	/* Frame synchronisation */
>  	void (*du_complete)(void *, bool);
>  	void *du_private;
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 02/15] v4l: vsp1: Remove outdated comment
  2018-03-28 12:27     ` Kieran Bingham
@ 2018-03-28 19:04       ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 19:04 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: dri-devel, linux-renesas-soc

On 28/03/18 13:27, Kieran Bingham wrote:
> Hi Laurent,
> 
> Thank you for the patch.
> 
> On 26/02/18 21:45, Laurent Pinchart wrote:
>> The entities in the pipeline are all started when the LIF is setup.
>> Remove the outdated comment that state otherwise.
>>
>> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> 
> I'll start with the easy ones :-)

In fact, couldn't this patch be squashed into [PATCH 01/15] in this series ?

--
Kieran


> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> 
>> ---
>>  drivers/media/platform/vsp1/vsp1_drm.c | 6 +-----
>>  1 file changed, 1 insertion(+), 5 deletions(-)
>>
>> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
>> index e31fb371eaf9..a1f2ba044092 100644
>> --- a/drivers/media/platform/vsp1/vsp1_drm.c
>> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
>> @@ -221,11 +221,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>>  		return -EPIPE;
>>  	}
>>  
>> -	/*
>> -	 * Enable the VSP1. 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.
>> -	 */
>> +	/* Enable the VSP1. */
>>  	ret = vsp1_device_get(vsp1);
>>  	if (ret < 0)
>>  		return ret;
>>

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

* Re: [PATCH 02/15] v4l: vsp1: Remove outdated comment
@ 2018-03-28 19:04       ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-28 19:04 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: linux-renesas-soc, dri-devel

On 28/03/18 13:27, Kieran Bingham wrote:
> Hi Laurent,
> 
> Thank you for the patch.
> 
> On 26/02/18 21:45, Laurent Pinchart wrote:
>> The entities in the pipeline are all started when the LIF is setup.
>> Remove the outdated comment that state otherwise.
>>
>> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> 
> I'll start with the easy ones :-)

In fact, couldn't this patch be squashed into [PATCH 01/15] in this series ?

--
Kieran


> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> 
>> ---
>>  drivers/media/platform/vsp1/vsp1_drm.c | 6 +-----
>>  1 file changed, 1 insertion(+), 5 deletions(-)
>>
>> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
>> index e31fb371eaf9..a1f2ba044092 100644
>> --- a/drivers/media/platform/vsp1/vsp1_drm.c
>> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
>> @@ -221,11 +221,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>>  		return -EPIPE;
>>  	}
>>  
>> -	/*
>> -	 * Enable the VSP1. 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.
>> -	 */
>> +	/* Enable the VSP1. */
>>  	ret = vsp1_device_get(vsp1);
>>  	if (ret < 0)
>>  		return ret;
>>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 02/15] v4l: vsp1: Remove outdated comment
  2018-03-28 19:04       ` Kieran Bingham
@ 2018-03-29  6:51         ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-03-29  6:51 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: Laurent Pinchart, linux-media, dri-devel, linux-renesas-soc

Hi Kieran,

On Wednesday, 28 March 2018 22:04:49 EEST Kieran Bingham wrote:
> On 28/03/18 13:27, Kieran Bingham wrote:
> > On 26/02/18 21:45, Laurent Pinchart wrote:
> >> The entities in the pipeline are all started when the LIF is setup.
> >> Remove the outdated comment that state otherwise.
> >> 
> >> Signed-off-by: Laurent Pinchart
> >> <laurent.pinchart+renesas@ideasonboard.com>
> > 
> > I'll start with the easy ones :-)
> 
> In fact, couldn't this patch be squashed into [PATCH 01/15] in this series ?

I suppose it could, I'll do so.

> > Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> > 
> >> ---
> >> 
> >>  drivers/media/platform/vsp1/vsp1_drm.c | 6 +-----
> >>  1 file changed, 1 insertion(+), 5 deletions(-)
> >> 
> >> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c
> >> b/drivers/media/platform/vsp1/vsp1_drm.c index
> >> e31fb371eaf9..a1f2ba044092 100644
> >> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> >> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> >> @@ -221,11 +221,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned
> >> int pipe_index,>> 
> >>  		return -EPIPE;
> >>  	
> >>  	}
> >> 
> >> -	/*
> >> -	 * Enable the VSP1. 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.
> >> -	 */
> >> +	/* Enable the VSP1. */
> >> 
> >>  	ret = vsp1_device_get(vsp1);
> >>  	if (ret < 0)
> >>  	
> >>  		return ret;


-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 02/15] v4l: vsp1: Remove outdated comment
@ 2018-03-29  6:51         ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-03-29  6:51 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: linux-renesas-soc, Laurent Pinchart, dri-devel, linux-media

Hi Kieran,

On Wednesday, 28 March 2018 22:04:49 EEST Kieran Bingham wrote:
> On 28/03/18 13:27, Kieran Bingham wrote:
> > On 26/02/18 21:45, Laurent Pinchart wrote:
> >> The entities in the pipeline are all started when the LIF is setup.
> >> Remove the outdated comment that state otherwise.
> >> 
> >> Signed-off-by: Laurent Pinchart
> >> <laurent.pinchart+renesas@ideasonboard.com>
> > 
> > I'll start with the easy ones :-)
> 
> In fact, couldn't this patch be squashed into [PATCH 01/15] in this series ?

I suppose it could, I'll do so.

> > Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> > 
> >> ---
> >> 
> >>  drivers/media/platform/vsp1/vsp1_drm.c | 6 +-----
> >>  1 file changed, 1 insertion(+), 5 deletions(-)
> >> 
> >> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c
> >> b/drivers/media/platform/vsp1/vsp1_drm.c index
> >> e31fb371eaf9..a1f2ba044092 100644
> >> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> >> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> >> @@ -221,11 +221,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned
> >> int pipe_index,>> 
> >>  		return -EPIPE;
> >>  	
> >>  	}
> >> 
> >> -	/*
> >> -	 * Enable the VSP1. 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.
> >> -	 */
> >> +	/* Enable the VSP1. */
> >> 
> >>  	ret = vsp1_device_get(vsp1);
> >>  	if (ret < 0)
> >>  	
> >>  		return ret;


-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 05/15] v4l: vsp1: Use vsp1_entity.pipe to check if entity belongs to a pipeline
  2018-03-28 14:10     ` Kieran Bingham
@ 2018-03-29  7:00       ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-03-29  7:00 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: Laurent Pinchart, linux-media, dri-devel, linux-renesas-soc

Hi Kieran,

On Wednesday, 28 March 2018 17:10:10 EEST Kieran Bingham wrote:
> On 26/02/18 21:45, Laurent Pinchart wrote:
> > The DRM pipeline handling code uses the entity's pipe list head to check
> > whether the entity is already included in a pipeline. This method is a
> > bit fragile in the sense that it uses list_empty() on a list_head that
> > is a list member. Replace it by a simpler check for the entity pipe
> > pointer.
> 
> Yes, excellent.
> 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> 
> > ---
> > 
> >  drivers/media/platform/vsp1/vsp1_drm.c | 8 ++++----
> >  1 file changed, 4 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c
> > b/drivers/media/platform/vsp1/vsp1_drm.c index a7ad85ab0b08..e210917fdc3f
> > 100644
> > --- a/drivers/media/platform/vsp1/vsp1_drm.c
> > +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> > @@ -119,9 +119,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int
> > pipe_index,> 
> >  			 * Remove the RPF from the pipe and the list of BRU
> >  			 * inputs.
> >  			 */
> > 
> > -			WARN_ON(list_empty(&rpf->entity.list_pipe));
> > +			WARN_ON(!rpf->entity.pipe);
> 
> Does this WARN_ON() have much value any more ?
> 
> I think it could probably be removed... unless there is a race between
> potential calls through vsp1_du_atomic_flush() and vsp1_du_setup_lif() -
> but I would be very surprised if that wasn't protected at the DRM levels.

It should indeed be protected at the DRM level. The purpose of the WARN_ON() 
is twofold, it catches both bugs in the VSP1 driver (but I don't expect any 
bug here, so from that point of view the WARN_ON isn't needed), but also 
misbehaviours in the callers. There hasn't been any so far though, so maybe we 
could indeed remove the WARN_ON(). It just makes me feel a bit safer but 
probably not in any rational way :-)

>  (Removing it if chosen doesn't need to be in this patch though)
> 
> >  			rpf->entity.pipe = NULL;
> > 
> > -			list_del_init(&rpf->entity.list_pipe);
> > +			list_del(&rpf->entity.list_pipe);
> > 
> >  			pipe->inputs[i] = NULL;
> >  			
> >  			bru->inputs[rpf->bru_input].rpf = NULL;
> > 
> > @@ -537,7 +537,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned
> > int pipe_index)> 
> >  			continue;
> >  		
> >  		}
> > 
> > -		if (list_empty(&rpf->entity.list_pipe)) {
> > +		if (!rpf->entity.pipe) {
> > 
> >  			rpf->entity.pipe = pipe;
> >  			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
> >  		
> >  		}
> > 
> > @@ -566,7 +566,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned
> > int pipe_index)> 
> >  					   VI6_DPR_NODE_UNUSED);
> >  			
> >  			entity->pipe = NULL;
> > 
> > -			list_del_init(&entity->list_pipe);
> > +			list_del(&entity->list_pipe);
> > 
> >  			continue;
> >  		
> >  		}

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 05/15] v4l: vsp1: Use vsp1_entity.pipe to check if entity belongs to a pipeline
@ 2018-03-29  7:00       ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-03-29  7:00 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: linux-renesas-soc, Laurent Pinchart, dri-devel, linux-media

Hi Kieran,

On Wednesday, 28 March 2018 17:10:10 EEST Kieran Bingham wrote:
> On 26/02/18 21:45, Laurent Pinchart wrote:
> > The DRM pipeline handling code uses the entity's pipe list head to check
> > whether the entity is already included in a pipeline. This method is a
> > bit fragile in the sense that it uses list_empty() on a list_head that
> > is a list member. Replace it by a simpler check for the entity pipe
> > pointer.
> 
> Yes, excellent.
> 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> 
> > ---
> > 
> >  drivers/media/platform/vsp1/vsp1_drm.c | 8 ++++----
> >  1 file changed, 4 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c
> > b/drivers/media/platform/vsp1/vsp1_drm.c index a7ad85ab0b08..e210917fdc3f
> > 100644
> > --- a/drivers/media/platform/vsp1/vsp1_drm.c
> > +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> > @@ -119,9 +119,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int
> > pipe_index,> 
> >  			 * Remove the RPF from the pipe and the list of BRU
> >  			 * inputs.
> >  			 */
> > 
> > -			WARN_ON(list_empty(&rpf->entity.list_pipe));
> > +			WARN_ON(!rpf->entity.pipe);
> 
> Does this WARN_ON() have much value any more ?
> 
> I think it could probably be removed... unless there is a race between
> potential calls through vsp1_du_atomic_flush() and vsp1_du_setup_lif() -
> but I would be very surprised if that wasn't protected at the DRM levels.

It should indeed be protected at the DRM level. The purpose of the WARN_ON() 
is twofold, it catches both bugs in the VSP1 driver (but I don't expect any 
bug here, so from that point of view the WARN_ON isn't needed), but also 
misbehaviours in the callers. There hasn't been any so far though, so maybe we 
could indeed remove the WARN_ON(). It just makes me feel a bit safer but 
probably not in any rational way :-)

>  (Removing it if chosen doesn't need to be in this patch though)
> 
> >  			rpf->entity.pipe = NULL;
> > 
> > -			list_del_init(&rpf->entity.list_pipe);
> > +			list_del(&rpf->entity.list_pipe);
> > 
> >  			pipe->inputs[i] = NULL;
> >  			
> >  			bru->inputs[rpf->bru_input].rpf = NULL;
> > 
> > @@ -537,7 +537,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned
> > int pipe_index)> 
> >  			continue;
> >  		
> >  		}
> > 
> > -		if (list_empty(&rpf->entity.list_pipe)) {
> > +		if (!rpf->entity.pipe) {
> > 
> >  			rpf->entity.pipe = pipe;
> >  			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
> >  		
> >  		}
> > 
> > @@ -566,7 +566,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned
> > int pipe_index)> 
> >  					   VI6_DPR_NODE_UNUSED);
> >  			
> >  			entity->pipe = NULL;
> > 
> > -			list_del_init(&entity->list_pipe);
> > +			list_del(&entity->list_pipe);
> > 
> >  			continue;
> >  		
> >  		}

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 07/15] v4l: vsp1: Move DRM atomic commit pipeline setup to separate function
  2018-03-28 14:43     ` Kieran Bingham
@ 2018-03-29  7:08       ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-03-29  7:08 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: Laurent Pinchart, linux-media, dri-devel, linux-renesas-soc

Hi Kieran,

On Wednesday, 28 March 2018 17:43:13 EEST Kieran Bingham wrote:
> On 26/02/18 21:45, Laurent Pinchart wrote:
> > The DRM pipeline setup code used at atomic commit time is similar to the
> > setup code used when enabling the pipeline. Move it to a separate
> > function in order to share it.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> Assuming no hidden secret code addition in this code move that I haven't
> seen..
> 
> Only a minor nit below asking if the function should be pluralised (_inputs,
> rather than _input)

I'll fix that in v2, thanks.

> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> 
> > ---
> > 
> >  drivers/media/platform/vsp1/vsp1_drm.c | 347
> >  +++++++++++++++++---------------- 1 file changed, 180 insertions(+), 167
> >  deletions(-)
> > 
> > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c
> > b/drivers/media/platform/vsp1/vsp1_drm.c index 9a043a915c0b..7bf697ba7969
> > 100644
> > --- a/drivers/media/platform/vsp1/vsp1_drm.c
> > +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> > @@ -46,6 +46,185 @@ static void vsp1_du_pipeline_frame_end(struct
> > vsp1_pipeline *pipe,> 
> >   * Pipeline Configuration
> >   */
> > 
> > +/* Setup one RPF and the connected BRU sink pad. */
> > +static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
> > +				      struct vsp1_pipeline *pipe,
> > +				      struct vsp1_rwpf *rpf,
> > +				      unsigned int bru_input)
> > +{
> > +	struct v4l2_subdev_selection sel;
> > +	struct v4l2_subdev_format format;
> > +	const struct v4l2_rect *crop;
> > +	int ret;
> > +
> > +	/*
> > +	 * Configure the format on the RPF sink pad and propagate it up to the
> > +	 * BRU sink pad.
> > +	 */
> > +	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
> > +
> > +	memset(&format, 0, sizeof(format));
> > +	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> > +	format.pad = RWPF_PAD_SINK;
> > +	format.format.width = crop->width + crop->left;
> > +	format.format.height = crop->height + crop->top;
> > +	format.format.code = rpf->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 = *crop;
> > +
> > +	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 = bru_input;
> > +
> > +	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
> > +			       &format);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
> > +		__func__, format.format.width, format.format.height,
> > +		format.format.code, BRU_NAME(pipe->bru), format.pad);
> > +
> > +	sel.pad = bru_input;
> > +	sel.target = V4L2_SEL_TGT_COMPOSE;
> > +	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
> > +
> > +	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL,
> > +			       &sel);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
> > +		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
> > +		BRU_NAME(pipe->bru), sel.pad);
> > +
> > +	return 0;
> > +}
> > +
> > +static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf
> > *rpf) +{
> > +	return vsp1->drm->inputs[rpf->entity.index].zpos;
> > +}
> > +
> > +/* Setup the input side of the pipeline (RPFs and BRU sink pads). */
> > +static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
> 
> Minor nit - shouldn't this be _setup_inputs(..)
> as we could have multiple inputs, and it configures them all.
> 
> > +					struct vsp1_pipeline *pipe)
> > +{
> > +	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
> > +	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
> > +	unsigned int i;
> > +	int ret;
> > +
> > +	/* Count the number of enabled inputs and sort them by Z-order. */
> > +	pipe->num_inputs = 0;
> > +
> > +	for (i = 0; i < vsp1->info->rpf_count; ++i) {
> > +		struct vsp1_rwpf *rpf = vsp1->rpf[i];
> > +		unsigned int j;
> > +
> > +		/*
> > +		 * Make sure we don't accept more inputs than the hardware can
> > +		 * handle. This is a temporary fix to avoid display stall, we
> > +		 * need to instead allocate the BRU or BRS to display pipelines
> > +		 * dynamically based on the number of planes they each use.
> > +		 */
> > +		if (pipe->num_inputs >= pipe->bru->source_pad)
> > +			pipe->inputs[i] = NULL;
> > +
> > +		if (!pipe->inputs[i])
> > +			continue;
> > +
> > +		/* Insert the RPF in the sorted RPFs array. */
> > +		for (j = pipe->num_inputs++; j > 0; --j) {
> > +			if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf))
> > +				break;
> > +			inputs[j] = inputs[j-1];
> > +		}
> > +
> > +		inputs[j] = rpf;
> > +	}
> > +
> > +	/* Setup the RPF input pipeline for every enabled input. */
> > +	for (i = 0; i < pipe->bru->source_pad; ++i) {
> > +		struct vsp1_rwpf *rpf = inputs[i];
> > +
> > +		if (!rpf) {
> > +			bru->inputs[i].rpf = NULL;
> > +			continue;
> > +		}
> > +
> > +		if (!rpf->entity.pipe) {
> > +			rpf->entity.pipe = pipe;
> > +			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
> > +		}
> > +
> > +		bru->inputs[i].rpf = rpf;
> > +		rpf->bru_input = i;
> > +		rpf->entity.sink = pipe->bru;
> > +		rpf->entity.sink_pad = i;
> > +
> > +		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
> > +			__func__, rpf->entity.index, BRU_NAME(pipe->bru), i);
> > +
> > +		ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, i);
> > +		if (ret < 0) {
> > +			dev_err(vsp1->dev,
> > +				"%s: failed to setup RPF.%u\n",
> > +				__func__, rpf->entity.index);
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > 
> >  /* Configure all entities in the pipeline. */
> >  static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
> >  {
> > 
> > @@ -396,111 +575,6 @@ int vsp1_du_atomic_update(struct device *dev,
> > unsigned int pipe_index,> 
> >  }
> >  EXPORT_SYMBOL_GPL(vsp1_du_atomic_update);
> > 
> > -static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1,
> > -				  struct vsp1_pipeline *pipe,
> > -				  struct vsp1_rwpf *rpf, unsigned int bru_input)
> > -{
> > -	struct v4l2_subdev_selection sel;
> > -	struct v4l2_subdev_format format;
> > -	const struct v4l2_rect *crop;
> > -	int ret;
> > -
> > -	/*
> > -	 * Configure the format on the RPF sink pad and propagate it up to the
> > -	 * BRU sink pad.
> > -	 */
> > -	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
> > -
> > -	memset(&format, 0, sizeof(format));
> > -	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> > -	format.pad = RWPF_PAD_SINK;
> > -	format.format.width = crop->width + crop->left;
> > -	format.format.height = crop->height + crop->top;
> > -	format.format.code = rpf->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 = *crop;
> > -
> > -	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 = bru_input;
> > -
> > -	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
> > -			       &format);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
> > -		__func__, format.format.width, format.format.height,
> > -		format.format.code, BRU_NAME(pipe->bru), format.pad);
> > -
> > -	sel.pad = bru_input;
> > -	sel.target = V4L2_SEL_TGT_COMPOSE;
> > -	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
> > -
> > -	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL,
> > -			       &sel);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
> > -		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
> > -		BRU_NAME(pipe->bru), sel.pad);
> > -
> > -	return 0;
> > -}
> > -
> > -static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf
> > *rpf) -{
> > -	return vsp1->drm->inputs[rpf->entity.index].zpos;
> > -}
> > -
> > 
> >  /**
> >  
> >   * vsp1_du_atomic_flush - Commit an atomic update
> >   * @dev: the VSP device
> > 
> > @@ -511,69 +585,8 @@ void vsp1_du_atomic_flush(struct device *dev,
> > unsigned int pipe_index)> 
> >  	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
> >  	struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index];
> >  	struct vsp1_pipeline *pipe = &drm_pipe->pipe;
> > 
> > -	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
> > -	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
> > -	unsigned int i;
> > -	int ret;
> > -
> > -	/* Count the number of enabled inputs and sort them by Z-order. */
> > -	pipe->num_inputs = 0;
> > -
> > -	for (i = 0; i < vsp1->info->rpf_count; ++i) {
> > -		struct vsp1_rwpf *rpf = vsp1->rpf[i];
> > -		unsigned int j;
> > -
> > -		/*
> > -		 * Make sure we don't accept more inputs than the hardware can
> > -		 * handle. This is a temporary fix to avoid display stall, we
> > -		 * need to instead allocate the BRU or BRS to display pipelines
> > -		 * dynamically based on the number of planes they each use.
> > -		 */
> > -		if (pipe->num_inputs >= pipe->bru->source_pad)
> > -			pipe->inputs[i] = NULL;
> > -
> > -		if (!pipe->inputs[i])
> > -			continue;
> > -
> > -		/* Insert the RPF in the sorted RPFs array. */
> > -		for (j = pipe->num_inputs++; j > 0; --j) {
> > -			if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf))
> > -				break;
> > -			inputs[j] = inputs[j-1];
> > -		}
> > -
> > -		inputs[j] = rpf;
> > -	}
> > -
> > -	/* Setup the RPF input pipeline for every enabled input. */
> > -	for (i = 0; i < pipe->bru->source_pad; ++i) {
> > -		struct vsp1_rwpf *rpf = inputs[i];
> > -
> > -		if (!rpf) {
> > -			bru->inputs[i].rpf = NULL;
> > -			continue;
> > -		}
> > -
> > -		if (!rpf->entity.pipe) {
> > -			rpf->entity.pipe = pipe;
> > -			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
> > -		}
> > -
> > -		bru->inputs[i].rpf = rpf;
> > -		rpf->bru_input = i;
> > -		rpf->entity.sink = pipe->bru;
> > -		rpf->entity.sink_pad = i;
> > -
> > -		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
> > -			__func__, rpf->entity.index, BRU_NAME(pipe->bru), i);
> > -
> > -		ret = vsp1_du_setup_rpf_pipe(vsp1, pipe, rpf, i);
> > -		if (ret < 0)
> > -			dev_err(vsp1->dev,
> > -				"%s: failed to setup RPF.%u\n",
> > -				__func__, rpf->entity.index);
> > -	}
> > 
> > +	vsp1_du_pipeline_setup_input(vsp1, pipe);
> > 
> >  	vsp1_du_pipeline_configure(pipe);
> >  
> >  }
> >  EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);


-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 07/15] v4l: vsp1: Move DRM atomic commit pipeline setup to separate function
@ 2018-03-29  7:08       ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-03-29  7:08 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: linux-renesas-soc, Laurent Pinchart, dri-devel, linux-media

Hi Kieran,

On Wednesday, 28 March 2018 17:43:13 EEST Kieran Bingham wrote:
> On 26/02/18 21:45, Laurent Pinchart wrote:
> > The DRM pipeline setup code used at atomic commit time is similar to the
> > setup code used when enabling the pipeline. Move it to a separate
> > function in order to share it.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> Assuming no hidden secret code addition in this code move that I haven't
> seen..
> 
> Only a minor nit below asking if the function should be pluralised (_inputs,
> rather than _input)

I'll fix that in v2, thanks.

> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> 
> > ---
> > 
> >  drivers/media/platform/vsp1/vsp1_drm.c | 347
> >  +++++++++++++++++---------------- 1 file changed, 180 insertions(+), 167
> >  deletions(-)
> > 
> > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c
> > b/drivers/media/platform/vsp1/vsp1_drm.c index 9a043a915c0b..7bf697ba7969
> > 100644
> > --- a/drivers/media/platform/vsp1/vsp1_drm.c
> > +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> > @@ -46,6 +46,185 @@ static void vsp1_du_pipeline_frame_end(struct
> > vsp1_pipeline *pipe,> 
> >   * Pipeline Configuration
> >   */
> > 
> > +/* Setup one RPF and the connected BRU sink pad. */
> > +static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
> > +				      struct vsp1_pipeline *pipe,
> > +				      struct vsp1_rwpf *rpf,
> > +				      unsigned int bru_input)
> > +{
> > +	struct v4l2_subdev_selection sel;
> > +	struct v4l2_subdev_format format;
> > +	const struct v4l2_rect *crop;
> > +	int ret;
> > +
> > +	/*
> > +	 * Configure the format on the RPF sink pad and propagate it up to the
> > +	 * BRU sink pad.
> > +	 */
> > +	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
> > +
> > +	memset(&format, 0, sizeof(format));
> > +	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> > +	format.pad = RWPF_PAD_SINK;
> > +	format.format.width = crop->width + crop->left;
> > +	format.format.height = crop->height + crop->top;
> > +	format.format.code = rpf->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 = *crop;
> > +
> > +	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 = bru_input;
> > +
> > +	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
> > +			       &format);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
> > +		__func__, format.format.width, format.format.height,
> > +		format.format.code, BRU_NAME(pipe->bru), format.pad);
> > +
> > +	sel.pad = bru_input;
> > +	sel.target = V4L2_SEL_TGT_COMPOSE;
> > +	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
> > +
> > +	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL,
> > +			       &sel);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
> > +		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
> > +		BRU_NAME(pipe->bru), sel.pad);
> > +
> > +	return 0;
> > +}
> > +
> > +static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf
> > *rpf) +{
> > +	return vsp1->drm->inputs[rpf->entity.index].zpos;
> > +}
> > +
> > +/* Setup the input side of the pipeline (RPFs and BRU sink pads). */
> > +static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
> 
> Minor nit - shouldn't this be _setup_inputs(..)
> as we could have multiple inputs, and it configures them all.
> 
> > +					struct vsp1_pipeline *pipe)
> > +{
> > +	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
> > +	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
> > +	unsigned int i;
> > +	int ret;
> > +
> > +	/* Count the number of enabled inputs and sort them by Z-order. */
> > +	pipe->num_inputs = 0;
> > +
> > +	for (i = 0; i < vsp1->info->rpf_count; ++i) {
> > +		struct vsp1_rwpf *rpf = vsp1->rpf[i];
> > +		unsigned int j;
> > +
> > +		/*
> > +		 * Make sure we don't accept more inputs than the hardware can
> > +		 * handle. This is a temporary fix to avoid display stall, we
> > +		 * need to instead allocate the BRU or BRS to display pipelines
> > +		 * dynamically based on the number of planes they each use.
> > +		 */
> > +		if (pipe->num_inputs >= pipe->bru->source_pad)
> > +			pipe->inputs[i] = NULL;
> > +
> > +		if (!pipe->inputs[i])
> > +			continue;
> > +
> > +		/* Insert the RPF in the sorted RPFs array. */
> > +		for (j = pipe->num_inputs++; j > 0; --j) {
> > +			if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf))
> > +				break;
> > +			inputs[j] = inputs[j-1];
> > +		}
> > +
> > +		inputs[j] = rpf;
> > +	}
> > +
> > +	/* Setup the RPF input pipeline for every enabled input. */
> > +	for (i = 0; i < pipe->bru->source_pad; ++i) {
> > +		struct vsp1_rwpf *rpf = inputs[i];
> > +
> > +		if (!rpf) {
> > +			bru->inputs[i].rpf = NULL;
> > +			continue;
> > +		}
> > +
> > +		if (!rpf->entity.pipe) {
> > +			rpf->entity.pipe = pipe;
> > +			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
> > +		}
> > +
> > +		bru->inputs[i].rpf = rpf;
> > +		rpf->bru_input = i;
> > +		rpf->entity.sink = pipe->bru;
> > +		rpf->entity.sink_pad = i;
> > +
> > +		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
> > +			__func__, rpf->entity.index, BRU_NAME(pipe->bru), i);
> > +
> > +		ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, i);
> > +		if (ret < 0) {
> > +			dev_err(vsp1->dev,
> > +				"%s: failed to setup RPF.%u\n",
> > +				__func__, rpf->entity.index);
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > 
> >  /* Configure all entities in the pipeline. */
> >  static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
> >  {
> > 
> > @@ -396,111 +575,6 @@ int vsp1_du_atomic_update(struct device *dev,
> > unsigned int pipe_index,> 
> >  }
> >  EXPORT_SYMBOL_GPL(vsp1_du_atomic_update);
> > 
> > -static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1,
> > -				  struct vsp1_pipeline *pipe,
> > -				  struct vsp1_rwpf *rpf, unsigned int bru_input)
> > -{
> > -	struct v4l2_subdev_selection sel;
> > -	struct v4l2_subdev_format format;
> > -	const struct v4l2_rect *crop;
> > -	int ret;
> > -
> > -	/*
> > -	 * Configure the format on the RPF sink pad and propagate it up to the
> > -	 * BRU sink pad.
> > -	 */
> > -	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
> > -
> > -	memset(&format, 0, sizeof(format));
> > -	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> > -	format.pad = RWPF_PAD_SINK;
> > -	format.format.width = crop->width + crop->left;
> > -	format.format.height = crop->height + crop->top;
> > -	format.format.code = rpf->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 = *crop;
> > -
> > -	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 = bru_input;
> > -
> > -	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
> > -			       &format);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
> > -		__func__, format.format.width, format.format.height,
> > -		format.format.code, BRU_NAME(pipe->bru), format.pad);
> > -
> > -	sel.pad = bru_input;
> > -	sel.target = V4L2_SEL_TGT_COMPOSE;
> > -	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
> > -
> > -	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL,
> > -			       &sel);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
> > -		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
> > -		BRU_NAME(pipe->bru), sel.pad);
> > -
> > -	return 0;
> > -}
> > -
> > -static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf
> > *rpf) -{
> > -	return vsp1->drm->inputs[rpf->entity.index].zpos;
> > -}
> > -
> > 
> >  /**
> >  
> >   * vsp1_du_atomic_flush - Commit an atomic update
> >   * @dev: the VSP device
> > 
> > @@ -511,69 +585,8 @@ void vsp1_du_atomic_flush(struct device *dev,
> > unsigned int pipe_index)> 
> >  	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
> >  	struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index];
> >  	struct vsp1_pipeline *pipe = &drm_pipe->pipe;
> > 
> > -	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
> > -	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
> > -	unsigned int i;
> > -	int ret;
> > -
> > -	/* Count the number of enabled inputs and sort them by Z-order. */
> > -	pipe->num_inputs = 0;
> > -
> > -	for (i = 0; i < vsp1->info->rpf_count; ++i) {
> > -		struct vsp1_rwpf *rpf = vsp1->rpf[i];
> > -		unsigned int j;
> > -
> > -		/*
> > -		 * Make sure we don't accept more inputs than the hardware can
> > -		 * handle. This is a temporary fix to avoid display stall, we
> > -		 * need to instead allocate the BRU or BRS to display pipelines
> > -		 * dynamically based on the number of planes they each use.
> > -		 */
> > -		if (pipe->num_inputs >= pipe->bru->source_pad)
> > -			pipe->inputs[i] = NULL;
> > -
> > -		if (!pipe->inputs[i])
> > -			continue;
> > -
> > -		/* Insert the RPF in the sorted RPFs array. */
> > -		for (j = pipe->num_inputs++; j > 0; --j) {
> > -			if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf))
> > -				break;
> > -			inputs[j] = inputs[j-1];
> > -		}
> > -
> > -		inputs[j] = rpf;
> > -	}
> > -
> > -	/* Setup the RPF input pipeline for every enabled input. */
> > -	for (i = 0; i < pipe->bru->source_pad; ++i) {
> > -		struct vsp1_rwpf *rpf = inputs[i];
> > -
> > -		if (!rpf) {
> > -			bru->inputs[i].rpf = NULL;
> > -			continue;
> > -		}
> > -
> > -		if (!rpf->entity.pipe) {
> > -			rpf->entity.pipe = pipe;
> > -			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
> > -		}
> > -
> > -		bru->inputs[i].rpf = rpf;
> > -		rpf->bru_input = i;
> > -		rpf->entity.sink = pipe->bru;
> > -		rpf->entity.sink_pad = i;
> > -
> > -		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
> > -			__func__, rpf->entity.index, BRU_NAME(pipe->bru), i);
> > -
> > -		ret = vsp1_du_setup_rpf_pipe(vsp1, pipe, rpf, i);
> > -		if (ret < 0)
> > -			dev_err(vsp1->dev,
> > -				"%s: failed to setup RPF.%u\n",
> > -				__func__, rpf->entity.index);
> > -	}
> > 
> > +	vsp1_du_pipeline_setup_input(vsp1, pipe);
> > 
> >  	vsp1_du_pipeline_configure(pipe);
> >  
> >  }
> >  EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);


-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 12/15] v4l: vsp1: Generalize detection of entity removal from DRM pipeline
  2018-02-26 21:45   ` Laurent Pinchart
@ 2018-03-29 11:37     ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-29 11:37 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: dri-devel, linux-renesas-soc

Hi Laurent,

Thank you for the patch,

On 26/02/18 21:45, Laurent Pinchart wrote:
> When disabling a DRM plane, the corresponding RPF is only marked as
> removed from the pipeline in the atomic update handler, with the actual
> removal happening when configuring the pipeline at atomic commit time.
> This is required as the RPF has to be disabled in the hardware, which
> can't be done from the atomic update handler.
> 
> The current implementation is RPF-specific. Make it independent of the
> entity type by using the entity's pipe pointer to mark removal from the
> pipeline. This will allow using the mechanism to remove BRU instances.

Nice improvement ...

> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index d705a6e9fa1d..6c60b72b6f50 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -346,13 +346,12 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
>  	dl = vsp1_dl_list_get(pipe->output->dlm);
>  
>  	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
> -		/* Disconnect unused RPFs from the pipeline. */
> -		if (entity->type == VSP1_ENTITY_RPF &&
> -		    !pipe->inputs[entity->index]) {
> +		/* Disconnect unused entities from the pipeline. */
> +		if (!entity->pipe) {
>  			vsp1_dl_list_write(dl, entity->route->reg,
>  					   VI6_DPR_NODE_UNUSED);

I don't think it's a problem, as we don't unset the entity->pipe for arbitrary
entities, but what happens if we set an HGO/HGT entity to NULL (these currently
have 0 as the route->reg. This would risk writing VI6_DPR_NODE_UNUSED to the
VI6_CMD(0) register?

In fact any entity in the pipeline with a null pipe pointer could cause this...
so we'd best be sure that they are right. Otherwise this could cause some crazy
bugs manifesting with the hardware doing something unexpected.

Assuming that won't be a problem,

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

>  
> -			entity->pipe = NULL;
> +			entity->sink = NULL;
>  			list_del(&entity->list_pipe);
>  
>  			continue;
> @@ -569,10 +568,11 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index,
>  			rpf_index);
>  
>  		/*
> -		 * Remove the RPF from the pipe's inputs. The atomic flush
> -		 * handler will disable the input and remove the entity from the
> -		 * pipe's entities list.
> +		 * Remove the RPF from the pipeline's inputs. Keep it in the
> +		 * pipeline's entity list to let vsp1_du_pipeline_configure()
> +		 * remove it from the hardware pipeline.
>  		 */
> +		rpf->entity.pipe = NULL;
>  		drm_pipe->pipe.inputs[rpf_index] = NULL;
>  		return 0;
>  	}
> 

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

* Re: [PATCH 12/15] v4l: vsp1: Generalize detection of entity removal from DRM pipeline
@ 2018-03-29 11:37     ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-29 11:37 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: linux-renesas-soc, dri-devel

Hi Laurent,

Thank you for the patch,

On 26/02/18 21:45, Laurent Pinchart wrote:
> When disabling a DRM plane, the corresponding RPF is only marked as
> removed from the pipeline in the atomic update handler, with the actual
> removal happening when configuring the pipeline at atomic commit time.
> This is required as the RPF has to be disabled in the hardware, which
> can't be done from the atomic update handler.
> 
> The current implementation is RPF-specific. Make it independent of the
> entity type by using the entity's pipe pointer to mark removal from the
> pipeline. This will allow using the mechanism to remove BRU instances.

Nice improvement ...

> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index d705a6e9fa1d..6c60b72b6f50 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -346,13 +346,12 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
>  	dl = vsp1_dl_list_get(pipe->output->dlm);
>  
>  	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
> -		/* Disconnect unused RPFs from the pipeline. */
> -		if (entity->type == VSP1_ENTITY_RPF &&
> -		    !pipe->inputs[entity->index]) {
> +		/* Disconnect unused entities from the pipeline. */
> +		if (!entity->pipe) {
>  			vsp1_dl_list_write(dl, entity->route->reg,
>  					   VI6_DPR_NODE_UNUSED);

I don't think it's a problem, as we don't unset the entity->pipe for arbitrary
entities, but what happens if we set an HGO/HGT entity to NULL (these currently
have 0 as the route->reg. This would risk writing VI6_DPR_NODE_UNUSED to the
VI6_CMD(0) register?

In fact any entity in the pipeline with a null pipe pointer could cause this...
so we'd best be sure that they are right. Otherwise this could cause some crazy
bugs manifesting with the hardware doing something unexpected.

Assuming that won't be a problem,

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

>  
> -			entity->pipe = NULL;
> +			entity->sink = NULL;
>  			list_del(&entity->list_pipe);
>  
>  			continue;
> @@ -569,10 +568,11 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index,
>  			rpf_index);
>  
>  		/*
> -		 * Remove the RPF from the pipe's inputs. The atomic flush
> -		 * handler will disable the input and remove the entity from the
> -		 * pipe's entities list.
> +		 * Remove the RPF from the pipeline's inputs. Keep it in the
> +		 * pipeline's entity list to let vsp1_du_pipeline_configure()
> +		 * remove it from the hardware pipeline.
>  		 */
> +		rpf->entity.pipe = NULL;
>  		drm_pipe->pipe.inputs[rpf_index] = NULL;
>  		return 0;
>  	}
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 10/15] v4l: vsp1: Move DRM pipeline output setup code to a function
  2018-02-26 21:45   ` Laurent Pinchart
@ 2018-03-29 11:49     ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-29 11:49 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: dri-devel, linux-renesas-soc

Hi Laurent,

Thank you for another patch :D

On 26/02/18 21:45, Laurent Pinchart wrote:
> In order to make the vsp1_du_setup_lif() easier to read, and for
> symmetry with the DRM pipeline input setup, move the pipeline output
> setup code to a separate function.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Just an easy code move. And I agree it improves things.

Small question below, but otherwise:

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 107 +++++++++++++++++++--------------
>  1 file changed, 61 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 00ce99bd1605..1c8adda47440 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -276,6 +276,66 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  	return 0;
>  }
>  
> +/* Setup the output side of the pipeline (WPF and LIF). */
> +static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
> +					 struct vsp1_pipeline *pipe)
> +{
> +	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
> +	struct v4l2_subdev_format format = {
> +		.which = V4L2_SUBDEV_FORMAT_ACTIVE,

Why do you initialise this .which here, but all the other member variables below.

Wouldn't it make more sense to group all of this initialisation together? or is
there a distinction in keeping the .which separate.

(Perhaps this is just a way to initialise the rest of the structure to 0,
without using the memset?)


> +	};
> +	int ret;
> +
> +	format.pad = RWPF_PAD_SINK;
> +	format.format.width = drm_pipe->width;
> +	format.format.height = drm_pipe->height;
> +	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
> +	format.format.field = V4L2_FIELD_NONE;
> +
> +	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL,
> +			       &format);
> +	if (ret < 0)
> +		return ret;
> +
> +	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF%u sink\n",
> +		__func__, format.format.width, format.format.height,
> +		format.format.code, pipe->output->entity.index);
> +
> +	format.pad = RWPF_PAD_SOURCE;
> +	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, get_fmt, NULL,
> +			       &format);
> +	if (ret < 0)
> +		return ret;
> +
> +	dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF%u source\n",
> +		__func__, format.format.width, format.format.height,
> +		format.format.code, pipe->output->entity.index);
> +
> +	format.pad = LIF_PAD_SINK;
> +	ret = v4l2_subdev_call(&pipe->lif->subdev, pad, set_fmt, NULL,
> +			       &format);
> +	if (ret < 0)
> +		return ret;
> +
> +	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF%u sink\n",
> +		__func__, format.format.width, format.format.height,
> +		format.format.code, pipe->lif->index);
> +
> +	/*
> +	 * Verify that the format at the output of the pipeline matches the
> +	 * requested frame size and media bus code.
> +	 */
> +	if (format.format.width != drm_pipe->width ||
> +	    format.format.height != drm_pipe->height ||
> +	    format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) {
> +		dev_dbg(vsp1->dev, "%s: format mismatch on LIF%u\n", __func__,
> +			pipe->lif->index);
> +		return -EPIPE;
> +	}
> +
> +	return 0;
> +}
> +
>  /* Configure all entities in the pipeline. */
>  static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
>  {
> @@ -356,7 +416,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	struct vsp1_drm_pipeline *drm_pipe;
>  	struct vsp1_pipeline *pipe;
>  	struct vsp1_bru *bru;
> -	struct v4l2_subdev_format format;
>  	unsigned long flags;
>  	unsigned int i;
>  	int ret;
> @@ -417,54 +476,10 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	if (ret < 0)
>  		return ret;
>  
> -	memset(&format, 0, sizeof(format));
> -	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> -	format.pad = RWPF_PAD_SINK;
> -	format.format.width = cfg->width;
> -	format.format.height = cfg->height;
> -	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
> -	format.format.field = V4L2_FIELD_NONE;
> -
> -	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL,
> -			       &format);
> +	ret = vsp1_du_pipeline_setup_output(vsp1, pipe);
>  	if (ret < 0)
>  		return ret;
>  
> -	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF%u sink\n",
> -		__func__, format.format.width, format.format.height,
> -		format.format.code, pipe->output->entity.index);
> -
> -	format.pad = RWPF_PAD_SOURCE;
> -	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, get_fmt, NULL,
> -			       &format);
> -	if (ret < 0)
> -		return ret;
> -
> -	dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF%u source\n",
> -		__func__, format.format.width, format.format.height,
> -		format.format.code, pipe->output->entity.index);
> -
> -	format.pad = LIF_PAD_SINK;
> -	ret = v4l2_subdev_call(&pipe->lif->subdev, pad, set_fmt, NULL,
> -			       &format);
> -	if (ret < 0)
> -		return ret;
> -
> -	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF%u sink\n",
> -		__func__, format.format.width, format.format.height,
> -		format.format.code, pipe_index);
> -
> -	/*
> -	 * Verify that the format at the output of the pipeline matches the
> -	 * requested frame size and media bus code.
> -	 */
> -	if (format.format.width != cfg->width ||
> -	    format.format.height != cfg->height ||
> -	    format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) {
> -		dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__);
> -		return -EPIPE;
> -	}
> -
>  	/* Enable the VSP1. */
>  	ret = vsp1_device_get(vsp1);
>  	if (ret < 0)
> 

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

* Re: [PATCH 10/15] v4l: vsp1: Move DRM pipeline output setup code to a function
@ 2018-03-29 11:49     ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-03-29 11:49 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: linux-renesas-soc, dri-devel

Hi Laurent,

Thank you for another patch :D

On 26/02/18 21:45, Laurent Pinchart wrote:
> In order to make the vsp1_du_setup_lif() easier to read, and for
> symmetry with the DRM pipeline input setup, move the pipeline output
> setup code to a separate function.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Just an easy code move. And I agree it improves things.

Small question below, but otherwise:

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 107 +++++++++++++++++++--------------
>  1 file changed, 61 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 00ce99bd1605..1c8adda47440 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -276,6 +276,66 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  	return 0;
>  }
>  
> +/* Setup the output side of the pipeline (WPF and LIF). */
> +static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
> +					 struct vsp1_pipeline *pipe)
> +{
> +	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
> +	struct v4l2_subdev_format format = {
> +		.which = V4L2_SUBDEV_FORMAT_ACTIVE,

Why do you initialise this .which here, but all the other member variables below.

Wouldn't it make more sense to group all of this initialisation together? or is
there a distinction in keeping the .which separate.

(Perhaps this is just a way to initialise the rest of the structure to 0,
without using the memset?)


> +	};
> +	int ret;
> +
> +	format.pad = RWPF_PAD_SINK;
> +	format.format.width = drm_pipe->width;
> +	format.format.height = drm_pipe->height;
> +	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
> +	format.format.field = V4L2_FIELD_NONE;
> +
> +	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL,
> +			       &format);
> +	if (ret < 0)
> +		return ret;
> +
> +	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF%u sink\n",
> +		__func__, format.format.width, format.format.height,
> +		format.format.code, pipe->output->entity.index);
> +
> +	format.pad = RWPF_PAD_SOURCE;
> +	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, get_fmt, NULL,
> +			       &format);
> +	if (ret < 0)
> +		return ret;
> +
> +	dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF%u source\n",
> +		__func__, format.format.width, format.format.height,
> +		format.format.code, pipe->output->entity.index);
> +
> +	format.pad = LIF_PAD_SINK;
> +	ret = v4l2_subdev_call(&pipe->lif->subdev, pad, set_fmt, NULL,
> +			       &format);
> +	if (ret < 0)
> +		return ret;
> +
> +	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF%u sink\n",
> +		__func__, format.format.width, format.format.height,
> +		format.format.code, pipe->lif->index);
> +
> +	/*
> +	 * Verify that the format at the output of the pipeline matches the
> +	 * requested frame size and media bus code.
> +	 */
> +	if (format.format.width != drm_pipe->width ||
> +	    format.format.height != drm_pipe->height ||
> +	    format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) {
> +		dev_dbg(vsp1->dev, "%s: format mismatch on LIF%u\n", __func__,
> +			pipe->lif->index);
> +		return -EPIPE;
> +	}
> +
> +	return 0;
> +}
> +
>  /* Configure all entities in the pipeline. */
>  static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
>  {
> @@ -356,7 +416,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	struct vsp1_drm_pipeline *drm_pipe;
>  	struct vsp1_pipeline *pipe;
>  	struct vsp1_bru *bru;
> -	struct v4l2_subdev_format format;
>  	unsigned long flags;
>  	unsigned int i;
>  	int ret;
> @@ -417,54 +476,10 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	if (ret < 0)
>  		return ret;
>  
> -	memset(&format, 0, sizeof(format));
> -	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> -	format.pad = RWPF_PAD_SINK;
> -	format.format.width = cfg->width;
> -	format.format.height = cfg->height;
> -	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
> -	format.format.field = V4L2_FIELD_NONE;
> -
> -	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL,
> -			       &format);
> +	ret = vsp1_du_pipeline_setup_output(vsp1, pipe);
>  	if (ret < 0)
>  		return ret;
>  
> -	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF%u sink\n",
> -		__func__, format.format.width, format.format.height,
> -		format.format.code, pipe->output->entity.index);
> -
> -	format.pad = RWPF_PAD_SOURCE;
> -	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, get_fmt, NULL,
> -			       &format);
> -	if (ret < 0)
> -		return ret;
> -
> -	dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF%u source\n",
> -		__func__, format.format.width, format.format.height,
> -		format.format.code, pipe->output->entity.index);
> -
> -	format.pad = LIF_PAD_SINK;
> -	ret = v4l2_subdev_call(&pipe->lif->subdev, pad, set_fmt, NULL,
> -			       &format);
> -	if (ret < 0)
> -		return ret;
> -
> -	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF%u sink\n",
> -		__func__, format.format.width, format.format.height,
> -		format.format.code, pipe_index);
> -
> -	/*
> -	 * Verify that the format at the output of the pipeline matches the
> -	 * requested frame size and media bus code.
> -	 */
> -	if (format.format.width != cfg->width ||
> -	    format.format.height != cfg->height ||
> -	    format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) {
> -		dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__);
> -		return -EPIPE;
> -	}
> -
>  	/* Enable the VSP1. */
>  	ret = vsp1_device_get(vsp1);
>  	if (ret < 0)
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 10/15] v4l: vsp1: Move DRM pipeline output setup code to a function
  2018-03-29 11:49     ` Kieran Bingham
@ 2018-04-02 12:35       ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-04-02 12:35 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: Laurent Pinchart, linux-media, dri-devel, linux-renesas-soc

Hi Kieran,

On Thursday, 29 March 2018 14:49:12 EEST Kieran Bingham wrote:
> Hi Laurent,
> 
> Thank you for another patch :D

You're welcome, there will be more ;-)

> On 26/02/18 21:45, Laurent Pinchart wrote:
> > In order to make the vsp1_du_setup_lif() easier to read, and for
> > symmetry with the DRM pipeline input setup, move the pipeline output
> > setup code to a separate function.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> Just an easy code move. And I agree it improves things.
> 
> Small question below, but otherwise:
> 
> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> 
> > ---
> > 
> >  drivers/media/platform/vsp1/vsp1_drm.c | 107 ++++++++++++++++------------
> >  1 file changed, 61 insertions(+), 46 deletions(-)
> > 
> > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c
> > b/drivers/media/platform/vsp1/vsp1_drm.c index 00ce99bd1605..1c8adda47440
> > 100644
> > --- a/drivers/media/platform/vsp1/vsp1_drm.c
> > +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> > @@ -276,6 +276,66 @@ static int vsp1_du_pipeline_setup_input(struct
> > vsp1_device *vsp1,
> >  	return 0;
> >  
> >  }
> > 
> > +/* Setup the output side of the pipeline (WPF and LIF). */
> > +static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
> > +					 struct vsp1_pipeline *pipe)
> > +{
> > +	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
> > +	struct v4l2_subdev_format format = {
> > +		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
> 
> Why do you initialise this .which here, but all the other member variables
> below.
> 
> Wouldn't it make more sense to group all of this initialisation together? or
> is there a distinction in keeping the .which separate.
> 
> (Perhaps this is just a way to initialise the rest of the structure to 0,
> without using the memset?)

The initialization of the .which field is indeed there to avoid the memset, 
but other than that there's no particular reason. I find it clearer to keep 
the initialization of the structure close to the code that makes use of it 
(the next v4l2_subdev_call in this case).

As initializing all members when declaring the variable doesn't make a change 
in code size (gcc 6.4.0) but increases .rodata by 18 bytes and decreases 
__modver by the same amount, I'm tempted to leave it as-is unless you think it 
should be changed.

> > +	};
> > +	int ret;
> > +
> > +	format.pad = RWPF_PAD_SINK;
> > +	format.format.width = drm_pipe->width;
> > +	format.format.height = drm_pipe->height;
> > +	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
> > +	format.format.field = V4L2_FIELD_NONE;
> > +
> > +	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, 
NULL,
> > +			       &format);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF%u sink\n",
> > +		__func__, format.format.width, format.format.height,
> > +		format.format.code, pipe->output->entity.index);
> > +
> > +	format.pad = RWPF_PAD_SOURCE;
> > +	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, get_fmt, 
NULL,
> > +			       &format);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF%u source\n",
> > +		__func__, format.format.width, format.format.height,
> > +		format.format.code, pipe->output->entity.index);
> > +
> > +	format.pad = LIF_PAD_SINK;
> > +	ret = v4l2_subdev_call(&pipe->lif->subdev, pad, set_fmt, NULL,
> > +			       &format);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF%u sink\n",
> > +		__func__, format.format.width, format.format.height,
> > +		format.format.code, pipe->lif->index);
> > +
> > +	/*
> > +	 * Verify that the format at the output of the pipeline matches the
> > +	 * requested frame size and media bus code.
> > +	 */
> > +	if (format.format.width != drm_pipe->width ||
> > +	    format.format.height != drm_pipe->height ||
> > +	    format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) {
> > +		dev_dbg(vsp1->dev, "%s: format mismatch on LIF%u\n", __func__,
> > +			pipe->lif->index);
> > +		return -EPIPE;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > 
> >  /* Configure all entities in the pipeline. */
> >  static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
> >  {
> > 
> > @@ -356,7 +416,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int
> > pipe_index,> 
> >  	struct vsp1_drm_pipeline *drm_pipe;
> >  	struct vsp1_pipeline *pipe;
> >  	struct vsp1_bru *bru;
> > 
> > -	struct v4l2_subdev_format format;
> > 
> >  	unsigned long flags;
> >  	unsigned int i;
> >  	int ret;
> > 
> > @@ -417,54 +476,10 @@ int vsp1_du_setup_lif(struct device *dev, unsigned
> > int pipe_index,> 
> >  	if (ret < 0)
> >  	
> >  		return ret;
> > 
> > -	memset(&format, 0, sizeof(format));
> > -	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> > -	format.pad = RWPF_PAD_SINK;
> > -	format.format.width = cfg->width;
> > -	format.format.height = cfg->height;
> > -	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
> > -	format.format.field = V4L2_FIELD_NONE;
> > -
> > -	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, 
NULL,
> > -			       &format);
> > +	ret = vsp1_du_pipeline_setup_output(vsp1, pipe);
> > 
> >  	if (ret < 0)
> >  	
> >  		return ret;
> > 
> > -	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF%u sink\n",
> > -		__func__, format.format.width, format.format.height,
> > -		format.format.code, pipe->output->entity.index);
> > -
> > -	format.pad = RWPF_PAD_SOURCE;
> > -	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, get_fmt, 
NULL,
> > -			       &format);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF%u source\n",
> > -		__func__, format.format.width, format.format.height,
> > -		format.format.code, pipe->output->entity.index);
> > -
> > -	format.pad = LIF_PAD_SINK;
> > -	ret = v4l2_subdev_call(&pipe->lif->subdev, pad, set_fmt, NULL,
> > -			       &format);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF%u sink\n",
> > -		__func__, format.format.width, format.format.height,
> > -		format.format.code, pipe_index);
> > -
> > -	/*
> > -	 * Verify that the format at the output of the pipeline matches the
> > -	 * requested frame size and media bus code.
> > -	 */
> > -	if (format.format.width != cfg->width ||
> > -	    format.format.height != cfg->height ||
> > -	    format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) {
> > -		dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__);
> > -		return -EPIPE;
> > -	}
> > -
> > 
> >  	/* Enable the VSP1. */
> >  	ret = vsp1_device_get(vsp1);
> >  	if (ret < 0)

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 10/15] v4l: vsp1: Move DRM pipeline output setup code to a function
@ 2018-04-02 12:35       ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-04-02 12:35 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: linux-renesas-soc, Laurent Pinchart, dri-devel, linux-media

Hi Kieran,

On Thursday, 29 March 2018 14:49:12 EEST Kieran Bingham wrote:
> Hi Laurent,
> 
> Thank you for another patch :D

You're welcome, there will be more ;-)

> On 26/02/18 21:45, Laurent Pinchart wrote:
> > In order to make the vsp1_du_setup_lif() easier to read, and for
> > symmetry with the DRM pipeline input setup, move the pipeline output
> > setup code to a separate function.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> Just an easy code move. And I agree it improves things.
> 
> Small question below, but otherwise:
> 
> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> 
> > ---
> > 
> >  drivers/media/platform/vsp1/vsp1_drm.c | 107 ++++++++++++++++------------
> >  1 file changed, 61 insertions(+), 46 deletions(-)
> > 
> > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c
> > b/drivers/media/platform/vsp1/vsp1_drm.c index 00ce99bd1605..1c8adda47440
> > 100644
> > --- a/drivers/media/platform/vsp1/vsp1_drm.c
> > +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> > @@ -276,6 +276,66 @@ static int vsp1_du_pipeline_setup_input(struct
> > vsp1_device *vsp1,
> >  	return 0;
> >  
> >  }
> > 
> > +/* Setup the output side of the pipeline (WPF and LIF). */
> > +static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
> > +					 struct vsp1_pipeline *pipe)
> > +{
> > +	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
> > +	struct v4l2_subdev_format format = {
> > +		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
> 
> Why do you initialise this .which here, but all the other member variables
> below.
> 
> Wouldn't it make more sense to group all of this initialisation together? or
> is there a distinction in keeping the .which separate.
> 
> (Perhaps this is just a way to initialise the rest of the structure to 0,
> without using the memset?)

The initialization of the .which field is indeed there to avoid the memset, 
but other than that there's no particular reason. I find it clearer to keep 
the initialization of the structure close to the code that makes use of it 
(the next v4l2_subdev_call in this case).

As initializing all members when declaring the variable doesn't make a change 
in code size (gcc 6.4.0) but increases .rodata by 18 bytes and decreases 
__modver by the same amount, I'm tempted to leave it as-is unless you think it 
should be changed.

> > +	};
> > +	int ret;
> > +
> > +	format.pad = RWPF_PAD_SINK;
> > +	format.format.width = drm_pipe->width;
> > +	format.format.height = drm_pipe->height;
> > +	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
> > +	format.format.field = V4L2_FIELD_NONE;
> > +
> > +	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, 
NULL,
> > +			       &format);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF%u sink\n",
> > +		__func__, format.format.width, format.format.height,
> > +		format.format.code, pipe->output->entity.index);
> > +
> > +	format.pad = RWPF_PAD_SOURCE;
> > +	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, get_fmt, 
NULL,
> > +			       &format);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF%u source\n",
> > +		__func__, format.format.width, format.format.height,
> > +		format.format.code, pipe->output->entity.index);
> > +
> > +	format.pad = LIF_PAD_SINK;
> > +	ret = v4l2_subdev_call(&pipe->lif->subdev, pad, set_fmt, NULL,
> > +			       &format);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF%u sink\n",
> > +		__func__, format.format.width, format.format.height,
> > +		format.format.code, pipe->lif->index);
> > +
> > +	/*
> > +	 * Verify that the format at the output of the pipeline matches the
> > +	 * requested frame size and media bus code.
> > +	 */
> > +	if (format.format.width != drm_pipe->width ||
> > +	    format.format.height != drm_pipe->height ||
> > +	    format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) {
> > +		dev_dbg(vsp1->dev, "%s: format mismatch on LIF%u\n", __func__,
> > +			pipe->lif->index);
> > +		return -EPIPE;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > 
> >  /* Configure all entities in the pipeline. */
> >  static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
> >  {
> > 
> > @@ -356,7 +416,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int
> > pipe_index,> 
> >  	struct vsp1_drm_pipeline *drm_pipe;
> >  	struct vsp1_pipeline *pipe;
> >  	struct vsp1_bru *bru;
> > 
> > -	struct v4l2_subdev_format format;
> > 
> >  	unsigned long flags;
> >  	unsigned int i;
> >  	int ret;
> > 
> > @@ -417,54 +476,10 @@ int vsp1_du_setup_lif(struct device *dev, unsigned
> > int pipe_index,> 
> >  	if (ret < 0)
> >  	
> >  		return ret;
> > 
> > -	memset(&format, 0, sizeof(format));
> > -	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
> > -	format.pad = RWPF_PAD_SINK;
> > -	format.format.width = cfg->width;
> > -	format.format.height = cfg->height;
> > -	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
> > -	format.format.field = V4L2_FIELD_NONE;
> > -
> > -	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, 
NULL,
> > -			       &format);
> > +	ret = vsp1_du_pipeline_setup_output(vsp1, pipe);
> > 
> >  	if (ret < 0)
> >  	
> >  		return ret;
> > 
> > -	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on WPF%u sink\n",
> > -		__func__, format.format.width, format.format.height,
> > -		format.format.code, pipe->output->entity.index);
> > -
> > -	format.pad = RWPF_PAD_SOURCE;
> > -	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, get_fmt, 
NULL,
> > -			       &format);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	dev_dbg(vsp1->dev, "%s: got format %ux%u (%x) on WPF%u source\n",
> > -		__func__, format.format.width, format.format.height,
> > -		format.format.code, pipe->output->entity.index);
> > -
> > -	format.pad = LIF_PAD_SINK;
> > -	ret = v4l2_subdev_call(&pipe->lif->subdev, pad, set_fmt, NULL,
> > -			       &format);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on LIF%u sink\n",
> > -		__func__, format.format.width, format.format.height,
> > -		format.format.code, pipe_index);
> > -
> > -	/*
> > -	 * Verify that the format at the output of the pipeline matches the
> > -	 * requested frame size and media bus code.
> > -	 */
> > -	if (format.format.width != cfg->width ||
> > -	    format.format.height != cfg->height ||
> > -	    format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) {
> > -		dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__);
> > -		return -EPIPE;
> > -	}
> > -
> > 
> >  	/* Enable the VSP1. */
> >  	ret = vsp1_device_get(vsp1);
> >  	if (ret < 0)

-- 
Regards,

Laurent Pinchart



_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 12/15] v4l: vsp1: Generalize detection of entity removal from DRM pipeline
  2018-03-29 11:37     ` Kieran Bingham
@ 2018-04-02 12:57       ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-04-02 12:57 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: Laurent Pinchart, linux-media, dri-devel, linux-renesas-soc

Hi Kieran,

On Thursday, 29 March 2018 14:37:07 EEST Kieran Bingham wrote:
> On 26/02/18 21:45, Laurent Pinchart wrote:
> > When disabling a DRM plane, the corresponding RPF is only marked as
> > removed from the pipeline in the atomic update handler, with the actual
> > removal happening when configuring the pipeline at atomic commit time.
> > This is required as the RPF has to be disabled in the hardware, which
> > can't be done from the atomic update handler.
> > 
> > The current implementation is RPF-specific. Make it independent of the
> > entity type by using the entity's pipe pointer to mark removal from the
> > pipeline. This will allow using the mechanism to remove BRU instances.
> 
> Nice improvement ...
> 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/media/platform/vsp1/vsp1_drm.c | 14 +++++++-------
> >  1 file changed, 7 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c
> > b/drivers/media/platform/vsp1/vsp1_drm.c index d705a6e9fa1d..6c60b72b6f50
> > 100644
> > --- a/drivers/media/platform/vsp1/vsp1_drm.c
> > +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> > @@ -346,13 +346,12 @@ static void vsp1_du_pipeline_configure(struct
> > vsp1_pipeline *pipe)
> >  	dl = vsp1_dl_list_get(pipe->output->dlm);
> >  	
> >  	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
> > -		/* Disconnect unused RPFs from the pipeline. */
> > -		if (entity->type == VSP1_ENTITY_RPF &&
> > -		    !pipe->inputs[entity->index]) {
> > +		/* Disconnect unused entities from the pipeline. */
> > +		if (!entity->pipe) {
> >  			vsp1_dl_list_write(dl, entity->route->reg,
> >  					   VI6_DPR_NODE_UNUSED);
> 
> I don't think it's a problem, as we don't unset the entity->pipe for
> arbitrary entities, but what happens if we set an HGO/HGT entity to NULL
> (these currently have 0 as the route->reg. This would risk writing
> VI6_DPR_NODE_UNUSED to the VI6_CMD(0) register?
> 
> In fact any entity in the pipeline with a null pipe pointer could cause
> this... so we'd best be sure that they are right. Otherwise this could
> cause some crazy bugs manifesting with the hardware doing something
> unexpected.

First of all, this code handles the DRM pipeline only, which can't contain an 
HGO or HGT. If we ever have to add an HGO or HGT to the DRM pipeline (I don't 
see a use case for now, but who knows), this will sure need to be fixed, among 
other things because the VI6_DPR_HGO_SMPPT and VI6_DPR_HGT_SMPPT registers 
would need to be configured.

This being said, the idea behind this code is that when an entity is added to 
a pipeline, it will be added to the pipeline's entities list, and its pipe 
field will be set to point to the pipeline object. Removing an entity from a 
pipeline thus requires the opposite actions, removing it from the entities 
list and setting the pipe field to NULL.

Due to the architecture of the DRM pipeline handling code, there is a need to 
reconfigure routing when an entity is removed from a pipeline. We can't 
reconfigure routing at the point where we get notified that entities need to 
be removed from the pipeline. We thus need to track removed entities, and then 
reconfigure routing later. This patch implements such a mechanism by using the 
pipe pointer to track entity removal, and then removes them from the 
pipeline's list of entities later after reconfiguring routing.

You are worried that any entity in the pipeline with a NULL pipe pointer could 
cause issues. The pipe pointer is set to a non-NULL value when an entity is 
added to the pipeline, so the only way for the pipe pointer to be NULL here is 
for an entity that was part of a pipeline to be removed from it. As the HGO 
and HGT entities are never added to the pipeline, that's not an issue.

> Assuming that won't be a problem,

I believe that assumption to be correct :-)

> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> 
> > -			entity->pipe = NULL;
> > +			entity->sink = NULL;
> >  			list_del(&entity->list_pipe);
> >  			
> >  			continue;
> > @@ -569,10 +568,11 @@ int vsp1_du_atomic_update(struct device *dev,
> > unsigned int pipe_index,
> >  			rpf_index);
> >  		
> >  		/*
> > -		 * Remove the RPF from the pipe's inputs. The atomic flush
> > -		 * handler will disable the input and remove the entity from the
> > -		 * pipe's entities list.
> > +		 * Remove the RPF from the pipeline's inputs. Keep it in the
> > +		 * pipeline's entity list to let vsp1_du_pipeline_configure()
> > +		 * remove it from the hardware pipeline.
> >  		 */
> > +		rpf->entity.pipe = NULL;
> >  		drm_pipe->pipe.inputs[rpf_index] = NULL;
> >  		return 0;
> >  	}

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 12/15] v4l: vsp1: Generalize detection of entity removal from DRM pipeline
@ 2018-04-02 12:57       ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-04-02 12:57 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: linux-renesas-soc, Laurent Pinchart, dri-devel, linux-media

Hi Kieran,

On Thursday, 29 March 2018 14:37:07 EEST Kieran Bingham wrote:
> On 26/02/18 21:45, Laurent Pinchart wrote:
> > When disabling a DRM plane, the corresponding RPF is only marked as
> > removed from the pipeline in the atomic update handler, with the actual
> > removal happening when configuring the pipeline at atomic commit time.
> > This is required as the RPF has to be disabled in the hardware, which
> > can't be done from the atomic update handler.
> > 
> > The current implementation is RPF-specific. Make it independent of the
> > entity type by using the entity's pipe pointer to mark removal from the
> > pipeline. This will allow using the mechanism to remove BRU instances.
> 
> Nice improvement ...
> 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/media/platform/vsp1/vsp1_drm.c | 14 +++++++-------
> >  1 file changed, 7 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c
> > b/drivers/media/platform/vsp1/vsp1_drm.c index d705a6e9fa1d..6c60b72b6f50
> > 100644
> > --- a/drivers/media/platform/vsp1/vsp1_drm.c
> > +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> > @@ -346,13 +346,12 @@ static void vsp1_du_pipeline_configure(struct
> > vsp1_pipeline *pipe)
> >  	dl = vsp1_dl_list_get(pipe->output->dlm);
> >  	
> >  	list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) {
> > -		/* Disconnect unused RPFs from the pipeline. */
> > -		if (entity->type == VSP1_ENTITY_RPF &&
> > -		    !pipe->inputs[entity->index]) {
> > +		/* Disconnect unused entities from the pipeline. */
> > +		if (!entity->pipe) {
> >  			vsp1_dl_list_write(dl, entity->route->reg,
> >  					   VI6_DPR_NODE_UNUSED);
> 
> I don't think it's a problem, as we don't unset the entity->pipe for
> arbitrary entities, but what happens if we set an HGO/HGT entity to NULL
> (these currently have 0 as the route->reg. This would risk writing
> VI6_DPR_NODE_UNUSED to the VI6_CMD(0) register?
> 
> In fact any entity in the pipeline with a null pipe pointer could cause
> this... so we'd best be sure that they are right. Otherwise this could
> cause some crazy bugs manifesting with the hardware doing something
> unexpected.

First of all, this code handles the DRM pipeline only, which can't contain an 
HGO or HGT. If we ever have to add an HGO or HGT to the DRM pipeline (I don't 
see a use case for now, but who knows), this will sure need to be fixed, among 
other things because the VI6_DPR_HGO_SMPPT and VI6_DPR_HGT_SMPPT registers 
would need to be configured.

This being said, the idea behind this code is that when an entity is added to 
a pipeline, it will be added to the pipeline's entities list, and its pipe 
field will be set to point to the pipeline object. Removing an entity from a 
pipeline thus requires the opposite actions, removing it from the entities 
list and setting the pipe field to NULL.

Due to the architecture of the DRM pipeline handling code, there is a need to 
reconfigure routing when an entity is removed from a pipeline. We can't 
reconfigure routing at the point where we get notified that entities need to 
be removed from the pipeline. We thus need to track removed entities, and then 
reconfigure routing later. This patch implements such a mechanism by using the 
pipe pointer to track entity removal, and then removes them from the 
pipeline's list of entities later after reconfiguring routing.

You are worried that any entity in the pipeline with a NULL pipe pointer could 
cause issues. The pipe pointer is set to a non-NULL value when an entity is 
added to the pipeline, so the only way for the pipe pointer to be NULL here is 
for an entity that was part of a pipeline to be removed from it. As the HGO 
and HGT entities are never added to the pipeline, that's not an issue.

> Assuming that won't be a problem,

I believe that assumption to be correct :-)

> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> 
> > -			entity->pipe = NULL;
> > +			entity->sink = NULL;
> >  			list_del(&entity->list_pipe);
> >  			
> >  			continue;
> > @@ -569,10 +568,11 @@ int vsp1_du_atomic_update(struct device *dev,
> > unsigned int pipe_index,
> >  			rpf_index);
> >  		
> >  		/*
> > -		 * Remove the RPF from the pipe's inputs. The atomic flush
> > -		 * handler will disable the input and remove the entity from the
> > -		 * pipe's entities list.
> > +		 * Remove the RPF from the pipeline's inputs. Keep it in the
> > +		 * pipeline's entity list to let vsp1_du_pipeline_configure()
> > +		 * remove it from the hardware pipeline.
> >  		 */
> > +		rpf->entity.pipe = NULL;
> >  		drm_pipe->pipe.inputs[rpf_index] = NULL;
> >  		return 0;
> >  	}

-- 
Regards,

Laurent Pinchart



_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 01/15] v4l: vsp1: Don't start/stop media pipeline for DRM
  2018-02-26 21:45   ` Laurent Pinchart
@ 2018-04-04 15:35     ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-04-04 15:35 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: dri-devel, linux-renesas-soc

Hi Laurent,

On 26/02/18 21:45, Laurent Pinchart wrote:
> The DRM support code manages a pipeline of VSP entities, each backed by
> a media entity. When starting or stopping the pipeline, it starts and
> stops the media pipeline through the media API in order to store the
> pipeline pointer in every entity.
> 
> The driver doesn't use the pipe pointer in media entities, neither does
> it rely on the other effects of the media_pipeline_start() and
> media_pipeline_stop() functions. Furthermore, as the media links for the
> DRM pipeline are never set up correctly, and as the pipeline can be
> modified dynamically when enabling or disabling planes, the current
> implementation is not correct. Remove the incorrect and unneeded code.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 18 +++---------------
>  1 file changed, 3 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index b8fee1834253..e31fb371eaf9 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -109,8 +109,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  		if (ret == -ETIMEDOUT)
>  			dev_err(vsp1->dev, "DRM pipeline stop timeout\n");
>  
> -		media_pipeline_stop(&pipe->output->entity.subdev.entity);
> -
>  		for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i) {
>  			struct vsp1_rwpf *rpf = pipe->inputs[i];
>  
> @@ -224,11 +222,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	}
>  
>  	/*
> -	 * 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.
> +	 * Enable the VSP1. 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)
> @@ -241,14 +237,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	drm_pipe->du_complete = cfg->callback;
>  	drm_pipe->du_private = cfg->callback_data;
>  
> -	ret = media_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;
> -	}
> -
>  	/* Disable the display interrupts. */
>  	vsp1_write(vsp1, VI6_DISP_IRQ_STA, 0);
>  	vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0);
> 

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

* Re: [PATCH 01/15] v4l: vsp1: Don't start/stop media pipeline for DRM
@ 2018-04-04 15:35     ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-04-04 15:35 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: linux-renesas-soc, dri-devel

Hi Laurent,

On 26/02/18 21:45, Laurent Pinchart wrote:
> The DRM support code manages a pipeline of VSP entities, each backed by
> a media entity. When starting or stopping the pipeline, it starts and
> stops the media pipeline through the media API in order to store the
> pipeline pointer in every entity.
> 
> The driver doesn't use the pipe pointer in media entities, neither does
> it rely on the other effects of the media_pipeline_start() and
> media_pipeline_stop() functions. Furthermore, as the media links for the
> DRM pipeline are never set up correctly, and as the pipeline can be
> modified dynamically when enabling or disabling planes, the current
> implementation is not correct. Remove the incorrect and unneeded code.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 18 +++---------------
>  1 file changed, 3 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index b8fee1834253..e31fb371eaf9 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -109,8 +109,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  		if (ret == -ETIMEDOUT)
>  			dev_err(vsp1->dev, "DRM pipeline stop timeout\n");
>  
> -		media_pipeline_stop(&pipe->output->entity.subdev.entity);
> -
>  		for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i) {
>  			struct vsp1_rwpf *rpf = pipe->inputs[i];
>  
> @@ -224,11 +222,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	}
>  
>  	/*
> -	 * 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.
> +	 * Enable the VSP1. 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)
> @@ -241,14 +237,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	drm_pipe->du_complete = cfg->callback;
>  	drm_pipe->du_private = cfg->callback_data;
>  
> -	ret = media_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;
> -	}
> -
>  	/* Disable the display interrupts. */
>  	vsp1_write(vsp1, VI6_DISP_IRQ_STA, 0);
>  	vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0);
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 13/15] v4l: vsp1: Assign BRU and BRS to pipelines dynamically
  2018-02-26 21:45   ` Laurent Pinchart
@ 2018-04-04 16:00     ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-04-04 16:00 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: dri-devel, linux-renesas-soc

Hi Laurent,

Thank you for the patch.

I don't envy you on having to deal with this one ... it's a bit of a pain ...

On 26/02/18 21:45, Laurent Pinchart wrote:
> The VSPDL variant drives two DU channels through two LIF and two
> blenders, BRU and BRS. The DU channels thus share the five available
> VSPDL inputs and expose them as five KMS planes.
> 
> The current implementation assigns the BRS to the second LIF and thus
> artificially limits the number of planes for the second display channel
> to two at most.
> 
> Lift this artificial limitation by assigning the BRU and BRS to the
> display pipelines on demand based on the number of planes used by each
> pipeline. When a display pipeline needs more than two inputs and the BRU
> is already in use by the other pipeline, this requires reconfiguring the
> other pipeline to free the BRU before processing, which can result in
> frame drop on both pipelines.

So this is a hard one!
 - Having to dynamically reconfigure "someone else's" pipes ...


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

Except for the recursion, which is unavoidable, and the lock handling across
function calls which is ... unavoidable I think as well (at least for the
moment), my only quibble is the naming of the 'notify' variable, which is not
particularly clear in terms of who it notifies. (Internal, vs DRM)

I'll leave it up to you to decide whether or not to rename it though, and if
you're happy with the naming then fine.

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>


> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 160 +++++++++++++++++++++++++++------
>  drivers/media/platform/vsp1/vsp1_drm.h |   9 ++
>  2 files changed, 144 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 6c60b72b6f50..87e31ba0ddf5 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -39,7 +39,13 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
>  	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
>  
>  	if (drm_pipe->du_complete)
> -		drm_pipe->du_complete(drm_pipe->du_private, completed);
> +		drm_pipe->du_complete(drm_pipe->du_private,
> +				      completed && !notify);
> +
> +	if (notify) {
> +		drm_pipe->force_bru_release = false;
> +		wake_up(&drm_pipe->wait_queue);
> +	}

Notify seems such a nondescript verb to use here, and confuses me against who we
are notifying  - and why (it's an internal notification, but notify makes me
think we are 'notifying' the DU - which is exactly the opposite).

(Perhaps this is actually a comment for the previous patch, but I've gone
out-of-order, due to the complexities here...)

Could this be 'internal', 'released' or 'reconfigured', or something to
distinguish that this frame-end is not a normal frame-completion event ?


>  }
>  
>  /* -----------------------------------------------------------------------------
> @@ -149,6 +155,10 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
>  }
>  
>  /* Setup the BRU source pad. */
> +static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
> +					struct vsp1_pipeline *pipe);
> +static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe);
> +

Ohhh lovely, recursion...
Ohhh lovely, recursion...

>  static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
>  				      struct vsp1_pipeline *pipe)
>  {
> @@ -156,8 +166,93 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
>  	struct v4l2_subdev_format format = {
>  		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
>  	};
> +	struct vsp1_entity *bru;
>  	int ret;
>  
> +	/*
> +	 * Pick a BRU:
> +	 * - If we need more than two inputs, use the main BRU.
> +	 * - Otherwise, if we are not forced to release our BRU, keep it.
> +	 * - Else, use any free BRU (randomly starting with the main BRU).
> +	 */
> +	if (pipe->num_inputs > 2)
> +		bru = &vsp1->bru->entity;
> +	else if (pipe->bru && !drm_pipe->force_bru_release)
> +		bru = pipe->bru;
> +	else if (!vsp1->bru->entity.pipe)
> +		bru = &vsp1->bru->entity;
> +	else
> +		bru = &vsp1->brs->entity;


Ok - that tooks some iterations to go through - but I think it covers all the bases.

> +
> +	/* Switch BRU if needed. */
> +	if (bru != pipe->bru) {
> +		struct vsp1_entity *released_bru = NULL;
> +
> +		/* Release our BRU if we have one. */
> +		if (pipe->bru) {
> +			/*
> +			 * The BRU might be acquired by the other pipeline in
> +			 * the next step. We must thus remove it from the list
> +			 * of entities for this pipeline. The other pipeline's
> +			 * hardware configuration will reconfigure the BRU
> +			 * routing.
> +			 *
> +			 * However, if the other pipeline doesn't acquire our
> +			 * BRU, we need to keep it in the list, otherwise the
> +			 * hardware configuration step won't disconnect it from
> +			 * the pipeline. To solve this, store the released BRU
> +			 * pointer to add it back to the list of entities later
> +			 * if it isn't acquired by the other pipeline.
> +			 */
> +			released_bru = pipe->bru;
> +
> +			list_del(&pipe->bru->list_pipe);
> +			pipe->bru->sink = NULL;
> +			pipe->bru->pipe = NULL;
> +			pipe->bru = NULL;
> +		}
> +
> +		/*
> +		 * If the BRU we need is in use, force the owner pipeline to
> +		 * switch to the other BRU and wait until the switch completes.
> +		 */
> +		if (bru->pipe) {
> +			struct vsp1_drm_pipeline *owner_pipe;
> +
> +			owner_pipe = to_vsp1_drm_pipeline(bru->pipe);
> +			owner_pipe->force_bru_release = true;
> +
> +			vsp1_du_pipeline_setup_input(vsp1, &owner_pipe->pipe);
> +			vsp1_du_pipeline_configure(&owner_pipe->pipe);
> +
> +			ret = wait_event_timeout(owner_pipe->wait_queue,
> +						 !owner_pipe->force_bru_release,
> +						 msecs_to_jiffies(500));
> +			if (ret == 0)
> +				dev_warn(vsp1->dev,
> +					 "DRM pipeline %u reconfiguration timeout\n",
> +					 owner_pipe->pipe.lif->index);
> +		}
> +
> +		/*
> +		 * If the BRU we have released previously hasn't been acquired
> +		 * by the other pipeline, add it back to the entities list (with
> +		 * the pipe pointer NULL) to let vsp1_du_pipeline_configure()
> +		 * disconnect it from the hardware pipeline.
> +		 */
> +		if (released_bru && !released_bru->pipe)
> +			list_add_tail(&released_bru->list_pipe,
> +				      &pipe->entities);
> +
> +		/* Add the BRU to the pipeline. */
> +		pipe->bru = bru;
> +		pipe->bru->pipe = pipe;
> +		pipe->bru->sink = &pipe->output->entity;
> +		pipe->bru->sink_pad = 0;
> +
> +		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
> +	}
> +


Phew ... that's quite some chunk of interacting code ...

I've gone through it with the combinations of two pipes, 1 and 2, then swapping
them around when say pipe 2 has 3 inputs.

It seems to scan through OK in my head ... but I think I've gone a bit
cross-eyed now :D


Have we got some tests in place for the various combinations of paths through here ?


>  	/*
>  	 * Configure the format on the BRU source and verify that it matches the
>  	 * requested format. We don't set the media bus code as it is configured
> @@ -197,7 +292,7 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  					struct vsp1_pipeline *pipe)
>  {
>  	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
> -	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
> +	struct vsp1_bru *bru;
>  	unsigned int i;
>  	int ret;
>  
> @@ -208,15 +303,6 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  		struct vsp1_rwpf *rpf = vsp1->rpf[i];
>  		unsigned int j;
>  
> -		/*
> -		 * Make sure we don't accept more inputs than the hardware can
> -		 * handle. This is a temporary fix to avoid display stall, we
> -		 * need to instead allocate the BRU or BRS to display pipelines
> -		 * dynamically based on the number of planes they each use.
> -		 */
> -		if (pipe->num_inputs >= pipe->bru->source_pad)
> -			pipe->inputs[i] = NULL;
> -
>  		if (!pipe->inputs[i])
>  			continue;
>  
> @@ -242,6 +328,8 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  		return ret;
>  	}
>  
> +	bru = to_bru(&pipe->bru->subdev);
> +
>  	/* Setup the RPF input pipeline for every enabled input. */
>  	for (i = 0; i < pipe->bru->source_pad; ++i) {
>  		struct vsp1_rwpf *rpf = inputs[i];
> @@ -339,6 +427,7 @@ static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
>  /* Configure all entities in the pipeline. */
>  static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
>  {
> +	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
>  	struct vsp1_entity *entity;
>  	struct vsp1_entity *next;
>  	struct vsp1_dl_list *dl;
> @@ -369,7 +458,7 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
>  		}
>  	}
>  
> -	vsp1_dl_list_commit(dl, false);
> +	vsp1_dl_list_commit(dl, drm_pipe->force_bru_release);
>  }
>  
>  /* -----------------------------------------------------------------------------
> @@ -414,7 +503,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
>  	struct vsp1_drm_pipeline *drm_pipe;
>  	struct vsp1_pipeline *pipe;
> -	struct vsp1_bru *bru;
>  	unsigned long flags;
>  	unsigned int i;
>  	int ret;
> @@ -424,9 +512,14 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  
>  	drm_pipe = &vsp1->drm->pipe[pipe_index];
>  	pipe = &drm_pipe->pipe;
> -	bru = to_bru(&pipe->bru->subdev);
>  
>  	if (!cfg) {
> +		struct vsp1_bru *bru;
> +
> +		mutex_lock(&vsp1->drm->lock);
> +
> +		bru = to_bru(&pipe->bru->subdev);
> +
>  		/*
>  		 * NULL configuration means the CRTC is being disabled, stop
>  		 * the pipeline and turn the light off.
> @@ -456,6 +549,12 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  		drm_pipe->du_complete = NULL;
>  		pipe->num_inputs = 0;
>  
> +		list_del(&pipe->bru->list_pipe);
> +		pipe->bru->pipe = NULL;
> +		pipe->bru = NULL;
> +
> +		mutex_unlock(&vsp1->drm->lock);
> +
>  		vsp1_dlm_reset(pipe->output->dlm);
>  		vsp1_device_put(vsp1);
>  
> @@ -470,19 +569,21 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	dev_dbg(vsp1->dev, "%s: configuring LIF%u with format %ux%u\n",
>  		__func__, pipe_index, cfg->width, cfg->height);
>  
> +	mutex_lock(&vsp1->drm->lock);
> +
>  	/* Setup formats through the pipeline. */
>  	ret = vsp1_du_pipeline_setup_input(vsp1, pipe);
>  	if (ret < 0)
> -		return ret;
> +		goto unlock;
>  
>  	ret = vsp1_du_pipeline_setup_output(vsp1, pipe);
>  	if (ret < 0)
> -		return ret;
> +		goto unlock;
>  
>  	/* Enable the VSP1. */
>  	ret = vsp1_device_get(vsp1);
>  	if (ret < 0)
> -		return ret;
> +		goto unlock;
>  
>  	/*
>  	 * Register a callback to allow us to notify the DRM driver of frame
> @@ -498,6 +599,12 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	/* Configure all entities in the pipeline. */
>  	vsp1_du_pipeline_configure(pipe);
>  
> +unlock:
> +	mutex_unlock(&vsp1->drm->lock);
> +
> +	if (ret < 0)
> +		return ret;
> +
>  	/* Start the pipeline. */
>  	spin_lock_irqsave(&pipe->irqlock, flags);
>  	vsp1_pipeline_run(pipe);
> @@ -516,6 +623,9 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
>   */
>  void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index)
>  {
> +	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
> +
> +	mutex_lock(&vsp1->drm->lock);

Ouch ... we have to lock ...

>  }
>  EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
>  
> @@ -629,6 +739,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  
>  	vsp1_du_pipeline_setup_input(vsp1, pipe);
>  	vsp1_du_pipeline_configure(pipe);
> +	mutex_unlock(&vsp1->drm->lock);

And unlock in different functions ? :-(

(Yes, I see that we do - because we are crossing pipes...)


>  }
>  EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
>  
> @@ -667,28 +778,26 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
>  	if (!vsp1->drm)
>  		return -ENOMEM;
>  
> +	mutex_init(&vsp1->drm->lock);
> +
>  	/* Create one DRM pipeline per LIF. */
>  	for (i = 0; i < vsp1->info->lif_count; ++i) {
>  		struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[i];
>  		struct vsp1_pipeline *pipe = &drm_pipe->pipe;
>  
> +		init_waitqueue_head(&drm_pipe->wait_queue);
> +
>  		vsp1_pipeline_init(pipe);
>  
>  		pipe->frame_end = vsp1_du_pipeline_frame_end;
>  
>  		/*
> -		 * The DRM pipeline is static, add entities manually. The first
> -		 * pipeline uses the BRU and the second pipeline the BRS.
> +		 * The output side of the DRM pipeline is static, add the
> +		 * corresponding entities manually.
>  		 */
> -		pipe->bru = i == 0 ? &vsp1->bru->entity : &vsp1->brs->entity;
>  		pipe->output = vsp1->wpf[i];
>  		pipe->lif = &vsp1->lif[i]->entity;
>  
> -		pipe->bru->pipe = pipe;
> -		pipe->bru->sink = &pipe->output->entity;
> -		pipe->bru->sink_pad = 0;
> -		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
> -
>  		pipe->output->entity.pipe = pipe;
>  		pipe->output->entity.sink = pipe->lif;
>  		pipe->output->entity.sink_pad = 0;
> @@ -710,4 +819,5 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
>  
>  void vsp1_drm_cleanup(struct vsp1_device *vsp1)
>  {
> +	mutex_destroy(&vsp1->drm->lock);
>  }
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
> index c8dd75ba01f6..c84bc1c456c0 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.h
> +++ b/drivers/media/platform/vsp1/vsp1_drm.h
> @@ -13,7 +13,9 @@
>  #ifndef __VSP1_DRM_H__
>  #define __VSP1_DRM_H__
>  
> +#include <linux/mutex.h>
>  #include <linux/videodev2.h>
> +#include <linux/wait.h>
>  
>  #include "vsp1_pipe.h"
>  
> @@ -22,6 +24,8 @@
>   * @pipe: the VSP1 pipeline used for display
>   * @width: output display width
>   * @height: output display height
> + * @force_bru_release: when set, release the BRU during the next reconfiguration
> + * @wait_queue: wait queue to wait for BRU release completion
>   * @du_complete: frame completion callback for the DU driver (optional)
>   * @du_private: data to be passed to the du_complete callback
>   */
> @@ -31,6 +35,9 @@ struct vsp1_drm_pipeline {
>  	unsigned int width;
>  	unsigned int height;
>  
> +	bool force_bru_release;
> +	wait_queue_head_t wait_queue;
> +
>  	/* Frame synchronisation */
>  	void (*du_complete)(void *, bool);
>  	void *du_private;
> @@ -39,11 +46,13 @@ struct vsp1_drm_pipeline {
>  /**
>   * vsp1_drm - State for the API exposed to the DRM driver
>   * @pipe: the VSP1 DRM pipeline used for display
> + * @lock: protects the BRU and BRS allocation
>   * @inputs: source crop rectangle, destination compose rectangle and z-order
>   *	position for every input (indexed by RPF index)
>   */
>  struct vsp1_drm {
>  	struct vsp1_drm_pipeline pipe[VSP1_MAX_LIF];
> +	struct mutex lock;
>  
>  	struct {
>  		struct v4l2_rect crop;
> 

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

* Re: [PATCH 13/15] v4l: vsp1: Assign BRU and BRS to pipelines dynamically
@ 2018-04-04 16:00     ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-04-04 16:00 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: linux-renesas-soc, dri-devel

Hi Laurent,

Thank you for the patch.

I don't envy you on having to deal with this one ... it's a bit of a pain ...

On 26/02/18 21:45, Laurent Pinchart wrote:
> The VSPDL variant drives two DU channels through two LIF and two
> blenders, BRU and BRS. The DU channels thus share the five available
> VSPDL inputs and expose them as five KMS planes.
> 
> The current implementation assigns the BRS to the second LIF and thus
> artificially limits the number of planes for the second display channel
> to two at most.
> 
> Lift this artificial limitation by assigning the BRU and BRS to the
> display pipelines on demand based on the number of planes used by each
> pipeline. When a display pipeline needs more than two inputs and the BRU
> is already in use by the other pipeline, this requires reconfiguring the
> other pipeline to free the BRU before processing, which can result in
> frame drop on both pipelines.

So this is a hard one!
 - Having to dynamically reconfigure "someone else's" pipes ...


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

Except for the recursion, which is unavoidable, and the lock handling across
function calls which is ... unavoidable I think as well (at least for the
moment), my only quibble is the naming of the 'notify' variable, which is not
particularly clear in terms of who it notifies. (Internal, vs DRM)

I'll leave it up to you to decide whether or not to rename it though, and if
you're happy with the naming then fine.

Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>


> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 160 +++++++++++++++++++++++++++------
>  drivers/media/platform/vsp1/vsp1_drm.h |   9 ++
>  2 files changed, 144 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 6c60b72b6f50..87e31ba0ddf5 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -39,7 +39,13 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
>  	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
>  
>  	if (drm_pipe->du_complete)
> -		drm_pipe->du_complete(drm_pipe->du_private, completed);
> +		drm_pipe->du_complete(drm_pipe->du_private,
> +				      completed && !notify);
> +
> +	if (notify) {
> +		drm_pipe->force_bru_release = false;
> +		wake_up(&drm_pipe->wait_queue);
> +	}

Notify seems such a nondescript verb to use here, and confuses me against who we
are notifying  - and why (it's an internal notification, but notify makes me
think we are 'notifying' the DU - which is exactly the opposite).

(Perhaps this is actually a comment for the previous patch, but I've gone
out-of-order, due to the complexities here...)

Could this be 'internal', 'released' or 'reconfigured', or something to
distinguish that this frame-end is not a normal frame-completion event ?


>  }
>  
>  /* -----------------------------------------------------------------------------
> @@ -149,6 +155,10 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
>  }
>  
>  /* Setup the BRU source pad. */
> +static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
> +					struct vsp1_pipeline *pipe);
> +static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe);
> +

Ohhh lovely, recursion...
Ohhh lovely, recursion...

>  static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
>  				      struct vsp1_pipeline *pipe)
>  {
> @@ -156,8 +166,93 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
>  	struct v4l2_subdev_format format = {
>  		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
>  	};
> +	struct vsp1_entity *bru;
>  	int ret;
>  
> +	/*
> +	 * Pick a BRU:
> +	 * - If we need more than two inputs, use the main BRU.
> +	 * - Otherwise, if we are not forced to release our BRU, keep it.
> +	 * - Else, use any free BRU (randomly starting with the main BRU).
> +	 */
> +	if (pipe->num_inputs > 2)
> +		bru = &vsp1->bru->entity;
> +	else if (pipe->bru && !drm_pipe->force_bru_release)
> +		bru = pipe->bru;
> +	else if (!vsp1->bru->entity.pipe)
> +		bru = &vsp1->bru->entity;
> +	else
> +		bru = &vsp1->brs->entity;


Ok - that tooks some iterations to go through - but I think it covers all the bases.

> +
> +	/* Switch BRU if needed. */
> +	if (bru != pipe->bru) {
> +		struct vsp1_entity *released_bru = NULL;
> +
> +		/* Release our BRU if we have one. */
> +		if (pipe->bru) {
> +			/*
> +			 * The BRU might be acquired by the other pipeline in
> +			 * the next step. We must thus remove it from the list
> +			 * of entities for this pipeline. The other pipeline's
> +			 * hardware configuration will reconfigure the BRU
> +			 * routing.
> +			 *
> +			 * However, if the other pipeline doesn't acquire our
> +			 * BRU, we need to keep it in the list, otherwise the
> +			 * hardware configuration step won't disconnect it from
> +			 * the pipeline. To solve this, store the released BRU
> +			 * pointer to add it back to the list of entities later
> +			 * if it isn't acquired by the other pipeline.
> +			 */
> +			released_bru = pipe->bru;
> +
> +			list_del(&pipe->bru->list_pipe);
> +			pipe->bru->sink = NULL;
> +			pipe->bru->pipe = NULL;
> +			pipe->bru = NULL;
> +		}
> +
> +		/*
> +		 * If the BRU we need is in use, force the owner pipeline to
> +		 * switch to the other BRU and wait until the switch completes.
> +		 */
> +		if (bru->pipe) {
> +			struct vsp1_drm_pipeline *owner_pipe;
> +
> +			owner_pipe = to_vsp1_drm_pipeline(bru->pipe);
> +			owner_pipe->force_bru_release = true;
> +
> +			vsp1_du_pipeline_setup_input(vsp1, &owner_pipe->pipe);
> +			vsp1_du_pipeline_configure(&owner_pipe->pipe);
> +
> +			ret = wait_event_timeout(owner_pipe->wait_queue,
> +						 !owner_pipe->force_bru_release,
> +						 msecs_to_jiffies(500));
> +			if (ret == 0)
> +				dev_warn(vsp1->dev,
> +					 "DRM pipeline %u reconfiguration timeout\n",
> +					 owner_pipe->pipe.lif->index);
> +		}
> +
> +		/*
> +		 * If the BRU we have released previously hasn't been acquired
> +		 * by the other pipeline, add it back to the entities list (with
> +		 * the pipe pointer NULL) to let vsp1_du_pipeline_configure()
> +		 * disconnect it from the hardware pipeline.
> +		 */
> +		if (released_bru && !released_bru->pipe)
> +			list_add_tail(&released_bru->list_pipe,
> +				      &pipe->entities);
> +
> +		/* Add the BRU to the pipeline. */
> +		pipe->bru = bru;
> +		pipe->bru->pipe = pipe;
> +		pipe->bru->sink = &pipe->output->entity;
> +		pipe->bru->sink_pad = 0;
> +
> +		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
> +	}
> +


Phew ... that's quite some chunk of interacting code ...

I've gone through it with the combinations of two pipes, 1 and 2, then swapping
them around when say pipe 2 has 3 inputs.

It seems to scan through OK in my head ... but I think I've gone a bit
cross-eyed now :D


Have we got some tests in place for the various combinations of paths through here ?


>  	/*
>  	 * Configure the format on the BRU source and verify that it matches the
>  	 * requested format. We don't set the media bus code as it is configured
> @@ -197,7 +292,7 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  					struct vsp1_pipeline *pipe)
>  {
>  	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
> -	struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
> +	struct vsp1_bru *bru;
>  	unsigned int i;
>  	int ret;
>  
> @@ -208,15 +303,6 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  		struct vsp1_rwpf *rpf = vsp1->rpf[i];
>  		unsigned int j;
>  
> -		/*
> -		 * Make sure we don't accept more inputs than the hardware can
> -		 * handle. This is a temporary fix to avoid display stall, we
> -		 * need to instead allocate the BRU or BRS to display pipelines
> -		 * dynamically based on the number of planes they each use.
> -		 */
> -		if (pipe->num_inputs >= pipe->bru->source_pad)
> -			pipe->inputs[i] = NULL;
> -
>  		if (!pipe->inputs[i])
>  			continue;
>  
> @@ -242,6 +328,8 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  		return ret;
>  	}
>  
> +	bru = to_bru(&pipe->bru->subdev);
> +
>  	/* Setup the RPF input pipeline for every enabled input. */
>  	for (i = 0; i < pipe->bru->source_pad; ++i) {
>  		struct vsp1_rwpf *rpf = inputs[i];
> @@ -339,6 +427,7 @@ static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
>  /* Configure all entities in the pipeline. */
>  static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
>  {
> +	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
>  	struct vsp1_entity *entity;
>  	struct vsp1_entity *next;
>  	struct vsp1_dl_list *dl;
> @@ -369,7 +458,7 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
>  		}
>  	}
>  
> -	vsp1_dl_list_commit(dl, false);
> +	vsp1_dl_list_commit(dl, drm_pipe->force_bru_release);
>  }
>  
>  /* -----------------------------------------------------------------------------
> @@ -414,7 +503,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
>  	struct vsp1_drm_pipeline *drm_pipe;
>  	struct vsp1_pipeline *pipe;
> -	struct vsp1_bru *bru;
>  	unsigned long flags;
>  	unsigned int i;
>  	int ret;
> @@ -424,9 +512,14 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  
>  	drm_pipe = &vsp1->drm->pipe[pipe_index];
>  	pipe = &drm_pipe->pipe;
> -	bru = to_bru(&pipe->bru->subdev);
>  
>  	if (!cfg) {
> +		struct vsp1_bru *bru;
> +
> +		mutex_lock(&vsp1->drm->lock);
> +
> +		bru = to_bru(&pipe->bru->subdev);
> +
>  		/*
>  		 * NULL configuration means the CRTC is being disabled, stop
>  		 * the pipeline and turn the light off.
> @@ -456,6 +549,12 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  		drm_pipe->du_complete = NULL;
>  		pipe->num_inputs = 0;
>  
> +		list_del(&pipe->bru->list_pipe);
> +		pipe->bru->pipe = NULL;
> +		pipe->bru = NULL;
> +
> +		mutex_unlock(&vsp1->drm->lock);
> +
>  		vsp1_dlm_reset(pipe->output->dlm);
>  		vsp1_device_put(vsp1);
>  
> @@ -470,19 +569,21 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	dev_dbg(vsp1->dev, "%s: configuring LIF%u with format %ux%u\n",
>  		__func__, pipe_index, cfg->width, cfg->height);
>  
> +	mutex_lock(&vsp1->drm->lock);
> +
>  	/* Setup formats through the pipeline. */
>  	ret = vsp1_du_pipeline_setup_input(vsp1, pipe);
>  	if (ret < 0)
> -		return ret;
> +		goto unlock;
>  
>  	ret = vsp1_du_pipeline_setup_output(vsp1, pipe);
>  	if (ret < 0)
> -		return ret;
> +		goto unlock;
>  
>  	/* Enable the VSP1. */
>  	ret = vsp1_device_get(vsp1);
>  	if (ret < 0)
> -		return ret;
> +		goto unlock;
>  
>  	/*
>  	 * Register a callback to allow us to notify the DRM driver of frame
> @@ -498,6 +599,12 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	/* Configure all entities in the pipeline. */
>  	vsp1_du_pipeline_configure(pipe);
>  
> +unlock:
> +	mutex_unlock(&vsp1->drm->lock);
> +
> +	if (ret < 0)
> +		return ret;
> +
>  	/* Start the pipeline. */
>  	spin_lock_irqsave(&pipe->irqlock, flags);
>  	vsp1_pipeline_run(pipe);
> @@ -516,6 +623,9 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
>   */
>  void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index)
>  {
> +	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
> +
> +	mutex_lock(&vsp1->drm->lock);

Ouch ... we have to lock ...

>  }
>  EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
>  
> @@ -629,6 +739,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned int pipe_index)
>  
>  	vsp1_du_pipeline_setup_input(vsp1, pipe);
>  	vsp1_du_pipeline_configure(pipe);
> +	mutex_unlock(&vsp1->drm->lock);

And unlock in different functions ? :-(

(Yes, I see that we do - because we are crossing pipes...)


>  }
>  EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);
>  
> @@ -667,28 +778,26 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
>  	if (!vsp1->drm)
>  		return -ENOMEM;
>  
> +	mutex_init(&vsp1->drm->lock);
> +
>  	/* Create one DRM pipeline per LIF. */
>  	for (i = 0; i < vsp1->info->lif_count; ++i) {
>  		struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[i];
>  		struct vsp1_pipeline *pipe = &drm_pipe->pipe;
>  
> +		init_waitqueue_head(&drm_pipe->wait_queue);
> +
>  		vsp1_pipeline_init(pipe);
>  
>  		pipe->frame_end = vsp1_du_pipeline_frame_end;
>  
>  		/*
> -		 * The DRM pipeline is static, add entities manually. The first
> -		 * pipeline uses the BRU and the second pipeline the BRS.
> +		 * The output side of the DRM pipeline is static, add the
> +		 * corresponding entities manually.
>  		 */
> -		pipe->bru = i == 0 ? &vsp1->bru->entity : &vsp1->brs->entity;
>  		pipe->output = vsp1->wpf[i];
>  		pipe->lif = &vsp1->lif[i]->entity;
>  
> -		pipe->bru->pipe = pipe;
> -		pipe->bru->sink = &pipe->output->entity;
> -		pipe->bru->sink_pad = 0;
> -		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
> -
>  		pipe->output->entity.pipe = pipe;
>  		pipe->output->entity.sink = pipe->lif;
>  		pipe->output->entity.sink_pad = 0;
> @@ -710,4 +819,5 @@ int vsp1_drm_init(struct vsp1_device *vsp1)
>  
>  void vsp1_drm_cleanup(struct vsp1_device *vsp1)
>  {
> +	mutex_destroy(&vsp1->drm->lock);
>  }
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
> index c8dd75ba01f6..c84bc1c456c0 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.h
> +++ b/drivers/media/platform/vsp1/vsp1_drm.h
> @@ -13,7 +13,9 @@
>  #ifndef __VSP1_DRM_H__
>  #define __VSP1_DRM_H__
>  
> +#include <linux/mutex.h>
>  #include <linux/videodev2.h>
> +#include <linux/wait.h>
>  
>  #include "vsp1_pipe.h"
>  
> @@ -22,6 +24,8 @@
>   * @pipe: the VSP1 pipeline used for display
>   * @width: output display width
>   * @height: output display height
> + * @force_bru_release: when set, release the BRU during the next reconfiguration
> + * @wait_queue: wait queue to wait for BRU release completion
>   * @du_complete: frame completion callback for the DU driver (optional)
>   * @du_private: data to be passed to the du_complete callback
>   */
> @@ -31,6 +35,9 @@ struct vsp1_drm_pipeline {
>  	unsigned int width;
>  	unsigned int height;
>  
> +	bool force_bru_release;
> +	wait_queue_head_t wait_queue;
> +
>  	/* Frame synchronisation */
>  	void (*du_complete)(void *, bool);
>  	void *du_private;
> @@ -39,11 +46,13 @@ struct vsp1_drm_pipeline {
>  /**
>   * vsp1_drm - State for the API exposed to the DRM driver
>   * @pipe: the VSP1 DRM pipeline used for display
> + * @lock: protects the BRU and BRS allocation
>   * @inputs: source crop rectangle, destination compose rectangle and z-order
>   *	position for every input (indexed by RPF index)
>   */
>  struct vsp1_drm {
>  	struct vsp1_drm_pipeline pipe[VSP1_MAX_LIF];
> +	struct mutex lock;
>  
>  	struct {
>  		struct v4l2_rect crop;
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 10/15] v4l: vsp1: Move DRM pipeline output setup code to a function
  2018-04-02 12:35       ` Laurent Pinchart
@ 2018-04-04 16:15         ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-04-04 16:15 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Laurent Pinchart, linux-media, dri-devel, linux-renesas-soc

Hi Laurent,

On 02/04/18 13:35, Laurent Pinchart wrote:

<snip>

>>> +/* Setup the output side of the pipeline (WPF and LIF). */
>>> +static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
>>> +					 struct vsp1_pipeline *pipe)
>>> +{
>>> +	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
>>> +	struct v4l2_subdev_format format = {
>>> +		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
>>
>> Why do you initialise this .which here, but all the other member variables
>> below.
>>
>> Wouldn't it make more sense to group all of this initialisation together? or
>> is there a distinction in keeping the .which separate.
>>
>> (Perhaps this is just a way to initialise the rest of the structure to 0,
>> without using the memset?)
> 
> The initialization of the .which field is indeed there to avoid the memset, 
> but other than that there's no particular reason. I find it clearer to keep 
> the initialization of the structure close to the code that makes use of it 
> (the next v4l2_subdev_call in this case).
> 
> As initializing all members when declaring the variable doesn't make a change 
> in code size (gcc 6.4.0) but increases .rodata by 18 bytes and decreases 
> __modver by the same amount, I'm tempted to leave it as-is unless you think it 
> should be changed.

I'm happy to leave it as is - the query was as much to understand why the change
was the way it was :D

But on that logic (reducing .rodata, or rather not increasing it) what's the
benefit of initialising with one (random/psuedo random) member variable over
initialising to all zero, then initialising the .which alongside the rest of
them? Wouldn't the compiler just use the zero page or such to initialise then?


This way is fine if you are happy with how it reads :D


--
Kieran


>>> +	};
>>> +	int ret;
>>> +
>>> +	format.pad = RWPF_PAD_SINK;
>>> +	format.format.width = drm_pipe->width;
>>> +	format.format.height = drm_pipe->height;
>>> +	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
>>> +	format.format.field = V4L2_FIELD_NONE;
>>> +
>>> +	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, 
> NULL,
>>> +			       &format);
>>> +	if (ret < 0)
>>> +		return ret;
>>> +

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

* Re: [PATCH 10/15] v4l: vsp1: Move DRM pipeline output setup code to a function
@ 2018-04-04 16:15         ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-04-04 16:15 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-renesas-soc, Laurent Pinchart, dri-devel, linux-media

Hi Laurent,

On 02/04/18 13:35, Laurent Pinchart wrote:

<snip>

>>> +/* Setup the output side of the pipeline (WPF and LIF). */
>>> +static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
>>> +					 struct vsp1_pipeline *pipe)
>>> +{
>>> +	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
>>> +	struct v4l2_subdev_format format = {
>>> +		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
>>
>> Why do you initialise this .which here, but all the other member variables
>> below.
>>
>> Wouldn't it make more sense to group all of this initialisation together? or
>> is there a distinction in keeping the .which separate.
>>
>> (Perhaps this is just a way to initialise the rest of the structure to 0,
>> without using the memset?)
> 
> The initialization of the .which field is indeed there to avoid the memset, 
> but other than that there's no particular reason. I find it clearer to keep 
> the initialization of the structure close to the code that makes use of it 
> (the next v4l2_subdev_call in this case).
> 
> As initializing all members when declaring the variable doesn't make a change 
> in code size (gcc 6.4.0) but increases .rodata by 18 bytes and decreases 
> __modver by the same amount, I'm tempted to leave it as-is unless you think it 
> should be changed.

I'm happy to leave it as is - the query was as much to understand why the change
was the way it was :D

But on that logic (reducing .rodata, or rather not increasing it) what's the
benefit of initialising with one (random/psuedo random) member variable over
initialising to all zero, then initialising the .which alongside the rest of
them? Wouldn't the compiler just use the zero page or such to initialise then?


This way is fine if you are happy with how it reads :D


--
Kieran


>>> +	};
>>> +	int ret;
>>> +
>>> +	format.pad = RWPF_PAD_SINK;
>>> +	format.format.width = drm_pipe->width;
>>> +	format.format.height = drm_pipe->height;
>>> +	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
>>> +	format.format.field = V4L2_FIELD_NONE;
>>> +
>>> +	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, 
> NULL,
>>> +			       &format);
>>> +	if (ret < 0)
>>> +		return ret;
>>> +
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 11/15] v4l: vsp1: Add per-display list completion notification support
  2018-02-26 21:45   ` Laurent Pinchart
@ 2018-04-04 16:16     ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-04-04 16:16 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: dri-devel, linux-renesas-soc

Hi Laurent,

On 26/02/18 21:45, Laurent Pinchart wrote:
> Display list completion is already reported to the frame end handler,
> but that mechanism is global to all display lists. In order to implement
> BRU and BRS reassignment in DRM pipelines we will need to wait for
> completion of a particular display list. Extend the display list and
> frame end handler APIs to support such a notification.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/media/platform/vsp1/vsp1_dl.c    | 27 +++++++++++++++++++++++++--
>  drivers/media/platform/vsp1/vsp1_dl.h    |  4 ++--
>  drivers/media/platform/vsp1/vsp1_drm.c   |  4 ++--
>  drivers/media/platform/vsp1/vsp1_pipe.c  |  5 +++--
>  drivers/media/platform/vsp1/vsp1_pipe.h  |  3 ++-
>  drivers/media/platform/vsp1/vsp1_video.c |  4 ++--
>  6 files changed, 36 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c
> index 0b86ed01e85d..eb2971218e28 100644
> --- a/drivers/media/platform/vsp1/vsp1_dl.c
> +++ b/drivers/media/platform/vsp1/vsp1_dl.c
> @@ -72,6 +72,7 @@ struct vsp1_dl_body {
>   * @fragments: list of extra display list bodies
>   * @has_chain: if true, indicates that there's a partition chain
>   * @chain: entry in the display list partition chain
> + * @notify: whether the display list completion should be notified
>   */
>  struct vsp1_dl_list {
>  	struct list_head list;
> @@ -85,6 +86,8 @@ struct vsp1_dl_list {
>  
>  	bool has_chain;
>  	struct list_head chain;
> +
> +	bool notify;
>  };
>  
>  enum vsp1_dl_mode {
> @@ -550,8 +553,16 @@ static void vsp1_dl_list_commit_continuous(struct vsp1_dl_list *dl)
>  	 * case we can't replace the queued list by the new one, as we could
>  	 * race with the hardware. We thus mark the update as pending, it will
>  	 * be queued up to the hardware by the frame end interrupt handler.
> +	 *
> +	 * If a display list is already pending we simply drop it as the new
> +	 * display list is assumed to contain a more recent configuration. It is
> +	 * an error if the already pending list has the notify flag set, as
> +	 * there is then a process waiting for that list to complete. This
> +	 * shouldn't happen as the waiting process should perform proper
> +	 * locking, but warn just in case.
>  	 */
>  	if (vsp1_dl_list_hw_update_pending(dlm)) {
> +		WARN_ON(dlm->pending && dlm->pending->notify);
>  		__vsp1_dl_list_put(dlm->pending);
>  		dlm->pending = dl;
>  		return;
> @@ -581,7 +592,7 @@ static void vsp1_dl_list_commit_singleshot(struct vsp1_dl_list *dl)
>  	dlm->active = dl;
>  }
>  
> -void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
> +void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool notify)

Rather than changing the vsp1_dl_list_commit() function - would it be nicer to
have an API to request or set the notify property? :

@@..@@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
...
+	/* The BRx will be released, without sending an update to DRM */
+	if (drm_pipe->force_bru_release)
+		vsp1_dl_list_request_internal_notify(dl);

	vsp1_dl_list_commit(dl);
...


>  {
>  	struct vsp1_dl_manager *dlm = dl->dlm;
>  	struct vsp1_dl_list *dl_child;
> @@ -598,6 +609,8 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
>  		}
>  	}
>  
> +	dl->notify = notify;
> +
>  	spin_lock_irqsave(&dlm->lock, flags);
>  
>  	if (dlm->singleshot)
> @@ -615,16 +628,23 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
>  /**
>   * vsp1_dlm_irq_frame_end - Display list handler for the frame end interrupt
>   * @dlm: the display list manager
> + * @notify: whether the display list that completed has notification enabled
>   *
>   * Return true if the previous display list has completed at frame end, or false
>   * if it has been delayed by one frame because the display list commit raced
>   * with the frame end interrupt. The function always returns true in header mode
>   * as display list processing is then not continuous and races never occur.
> + *
> + * Upon return, the @notify parameter is set to true if the previous display
> + * list has completed and had been queued with the notify flag, or to false
> + * otherwise. Notification is only supported for continuous mode.
>   */
> -bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
> +bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm, bool *notify)
>  {
>  	bool completed = false;
>  
> +	*notify = false;
> +
>  	spin_lock(&dlm->lock);
>  
>  	/*
> @@ -652,6 +672,9 @@ bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
>  	 * frame end interrupt. The display list thus becomes active.
>  	 */
>  	if (dlm->queued) {
> +		*notify = dlm->queued->notify;
> +		dlm->queued->notify = false;
> +
>  		__vsp1_dl_list_put(dlm->active);
>  		dlm->active = dlm->queued;
>  		dlm->queued = NULL;
> diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h
> index ee3508172f0a..480c6b0dd2e4 100644
> --- a/drivers/media/platform/vsp1/vsp1_dl.h
> +++ b/drivers/media/platform/vsp1/vsp1_dl.h
> @@ -27,12 +27,12 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
>  					unsigned int prealloc);
>  void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm);
>  void vsp1_dlm_reset(struct vsp1_dl_manager *dlm);
> -bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm);
> +bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm, bool *notify);
>  
>  struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm);
>  void vsp1_dl_list_put(struct vsp1_dl_list *dl);
>  void vsp1_dl_list_write(struct vsp1_dl_list *dl, u32 reg, u32 data);
> -void vsp1_dl_list_commit(struct vsp1_dl_list *dl);
> +void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool notify);
>  
>  struct vsp1_dl_body *vsp1_dl_fragment_alloc(struct vsp1_device *vsp1,
>  					    unsigned int num_entries);
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 1c8adda47440..d705a6e9fa1d 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -34,7 +34,7 @@
>   */
>  
>  static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
> -				       bool completed)
> +				       bool completed, bool notify)
>  {
>  	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
>  
> @@ -370,7 +370,7 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
>  		}
>  	}
>  
> -	vsp1_dl_list_commit(dl);
> +	vsp1_dl_list_commit(dl, false);
>  }
>  
>  /* -----------------------------------------------------------------------------
> diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
> index 99ccbac3256a..4d819c9019f4 100644
> --- a/drivers/media/platform/vsp1/vsp1_pipe.c
> +++ b/drivers/media/platform/vsp1/vsp1_pipe.c
> @@ -316,6 +316,7 @@ bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe)
>  void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
>  {
>  	bool completed;
> +	bool notify;
>  
>  	if (pipe == NULL)
>  		return;
> @@ -325,7 +326,7 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
>  	 * up being postponed by one frame. @completed represents whether the
>  	 * active frame was finished or postponed.
>  	 */
> -	completed = vsp1_dlm_irq_frame_end(pipe->output->dlm);
> +	completed = vsp1_dlm_irq_frame_end(pipe->output->dlm, &notify);
>  

Eugh ... two return values, one passed back through the return, and the other
passed as a pointer.

What about converting this to some flags which get passed into the
pipe->frame_end() instead?

>  	if (pipe->hgo)
>  		vsp1_hgo_frame_end(pipe->hgo);
> @@ -338,7 +339,7 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
>  	 * frame_end to account for vblank events.
>  	 */
>  	if (pipe->frame_end)
> -		pipe->frame_end(pipe, completed);
> +		pipe->frame_end(pipe, completed, notify);
>  
>  	pipe->sequence++;
>  }
> diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
> index dfff9b5685fe..482711024fa2 100644
> --- a/drivers/media/platform/vsp1/vsp1_pipe.h
> +++ b/drivers/media/platform/vsp1/vsp1_pipe.h
> @@ -118,7 +118,8 @@ struct vsp1_pipeline {
>  	enum vsp1_pipeline_state state;
>  	wait_queue_head_t wq;
>  
> -	void (*frame_end)(struct vsp1_pipeline *pipe, bool completed);
> +	void (*frame_end)(struct vsp1_pipeline *pipe, bool completed,
> +			  bool notify);
>  
>  	struct mutex lock;
>  	struct kref kref;
> diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
> index cdd53d6cc408..483b4259e1b4 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.c
> +++ b/drivers/media/platform/vsp1/vsp1_video.c
> @@ -437,14 +437,14 @@ static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe)
>  	}
>  
>  	/* Complete, and commit the head display list. */
> -	vsp1_dl_list_commit(pipe->dl);
> +	vsp1_dl_list_commit(pipe->dl, false);
>  	pipe->dl = NULL;
>  
>  	vsp1_pipeline_run(pipe);
>  }
>  
>  static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe,
> -					  bool completed)
> +					  bool completed, bool notify)
>  {
>  	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
>  	enum vsp1_pipeline_state state;
> 

--
Kieran

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

* Re: [PATCH 11/15] v4l: vsp1: Add per-display list completion notification support
@ 2018-04-04 16:16     ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-04-04 16:16 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: linux-renesas-soc, dri-devel

Hi Laurent,

On 26/02/18 21:45, Laurent Pinchart wrote:
> Display list completion is already reported to the frame end handler,
> but that mechanism is global to all display lists. In order to implement
> BRU and BRS reassignment in DRM pipelines we will need to wait for
> completion of a particular display list. Extend the display list and
> frame end handler APIs to support such a notification.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/media/platform/vsp1/vsp1_dl.c    | 27 +++++++++++++++++++++++++--
>  drivers/media/platform/vsp1/vsp1_dl.h    |  4 ++--
>  drivers/media/platform/vsp1/vsp1_drm.c   |  4 ++--
>  drivers/media/platform/vsp1/vsp1_pipe.c  |  5 +++--
>  drivers/media/platform/vsp1/vsp1_pipe.h  |  3 ++-
>  drivers/media/platform/vsp1/vsp1_video.c |  4 ++--
>  6 files changed, 36 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c
> index 0b86ed01e85d..eb2971218e28 100644
> --- a/drivers/media/platform/vsp1/vsp1_dl.c
> +++ b/drivers/media/platform/vsp1/vsp1_dl.c
> @@ -72,6 +72,7 @@ struct vsp1_dl_body {
>   * @fragments: list of extra display list bodies
>   * @has_chain: if true, indicates that there's a partition chain
>   * @chain: entry in the display list partition chain
> + * @notify: whether the display list completion should be notified
>   */
>  struct vsp1_dl_list {
>  	struct list_head list;
> @@ -85,6 +86,8 @@ struct vsp1_dl_list {
>  
>  	bool has_chain;
>  	struct list_head chain;
> +
> +	bool notify;
>  };
>  
>  enum vsp1_dl_mode {
> @@ -550,8 +553,16 @@ static void vsp1_dl_list_commit_continuous(struct vsp1_dl_list *dl)
>  	 * case we can't replace the queued list by the new one, as we could
>  	 * race with the hardware. We thus mark the update as pending, it will
>  	 * be queued up to the hardware by the frame end interrupt handler.
> +	 *
> +	 * If a display list is already pending we simply drop it as the new
> +	 * display list is assumed to contain a more recent configuration. It is
> +	 * an error if the already pending list has the notify flag set, as
> +	 * there is then a process waiting for that list to complete. This
> +	 * shouldn't happen as the waiting process should perform proper
> +	 * locking, but warn just in case.
>  	 */
>  	if (vsp1_dl_list_hw_update_pending(dlm)) {
> +		WARN_ON(dlm->pending && dlm->pending->notify);
>  		__vsp1_dl_list_put(dlm->pending);
>  		dlm->pending = dl;
>  		return;
> @@ -581,7 +592,7 @@ static void vsp1_dl_list_commit_singleshot(struct vsp1_dl_list *dl)
>  	dlm->active = dl;
>  }
>  
> -void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
> +void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool notify)

Rather than changing the vsp1_dl_list_commit() function - would it be nicer to
have an API to request or set the notify property? :

@@..@@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
...
+	/* The BRx will be released, without sending an update to DRM */
+	if (drm_pipe->force_bru_release)
+		vsp1_dl_list_request_internal_notify(dl);

	vsp1_dl_list_commit(dl);
...


>  {
>  	struct vsp1_dl_manager *dlm = dl->dlm;
>  	struct vsp1_dl_list *dl_child;
> @@ -598,6 +609,8 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
>  		}
>  	}
>  
> +	dl->notify = notify;
> +
>  	spin_lock_irqsave(&dlm->lock, flags);
>  
>  	if (dlm->singleshot)
> @@ -615,16 +628,23 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
>  /**
>   * vsp1_dlm_irq_frame_end - Display list handler for the frame end interrupt
>   * @dlm: the display list manager
> + * @notify: whether the display list that completed has notification enabled
>   *
>   * Return true if the previous display list has completed at frame end, or false
>   * if it has been delayed by one frame because the display list commit raced
>   * with the frame end interrupt. The function always returns true in header mode
>   * as display list processing is then not continuous and races never occur.
> + *
> + * Upon return, the @notify parameter is set to true if the previous display
> + * list has completed and had been queued with the notify flag, or to false
> + * otherwise. Notification is only supported for continuous mode.
>   */
> -bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
> +bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm, bool *notify)
>  {
>  	bool completed = false;
>  
> +	*notify = false;
> +
>  	spin_lock(&dlm->lock);
>  
>  	/*
> @@ -652,6 +672,9 @@ bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
>  	 * frame end interrupt. The display list thus becomes active.
>  	 */
>  	if (dlm->queued) {
> +		*notify = dlm->queued->notify;
> +		dlm->queued->notify = false;
> +
>  		__vsp1_dl_list_put(dlm->active);
>  		dlm->active = dlm->queued;
>  		dlm->queued = NULL;
> diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h
> index ee3508172f0a..480c6b0dd2e4 100644
> --- a/drivers/media/platform/vsp1/vsp1_dl.h
> +++ b/drivers/media/platform/vsp1/vsp1_dl.h
> @@ -27,12 +27,12 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
>  					unsigned int prealloc);
>  void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm);
>  void vsp1_dlm_reset(struct vsp1_dl_manager *dlm);
> -bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm);
> +bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm, bool *notify);
>  
>  struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm);
>  void vsp1_dl_list_put(struct vsp1_dl_list *dl);
>  void vsp1_dl_list_write(struct vsp1_dl_list *dl, u32 reg, u32 data);
> -void vsp1_dl_list_commit(struct vsp1_dl_list *dl);
> +void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool notify);
>  
>  struct vsp1_dl_body *vsp1_dl_fragment_alloc(struct vsp1_device *vsp1,
>  					    unsigned int num_entries);
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 1c8adda47440..d705a6e9fa1d 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -34,7 +34,7 @@
>   */
>  
>  static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
> -				       bool completed)
> +				       bool completed, bool notify)
>  {
>  	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
>  
> @@ -370,7 +370,7 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
>  		}
>  	}
>  
> -	vsp1_dl_list_commit(dl);
> +	vsp1_dl_list_commit(dl, false);
>  }
>  
>  /* -----------------------------------------------------------------------------
> diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
> index 99ccbac3256a..4d819c9019f4 100644
> --- a/drivers/media/platform/vsp1/vsp1_pipe.c
> +++ b/drivers/media/platform/vsp1/vsp1_pipe.c
> @@ -316,6 +316,7 @@ bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe)
>  void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
>  {
>  	bool completed;
> +	bool notify;
>  
>  	if (pipe == NULL)
>  		return;
> @@ -325,7 +326,7 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
>  	 * up being postponed by one frame. @completed represents whether the
>  	 * active frame was finished or postponed.
>  	 */
> -	completed = vsp1_dlm_irq_frame_end(pipe->output->dlm);
> +	completed = vsp1_dlm_irq_frame_end(pipe->output->dlm, &notify);
>  

Eugh ... two return values, one passed back through the return, and the other
passed as a pointer.

What about converting this to some flags which get passed into the
pipe->frame_end() instead?

>  	if (pipe->hgo)
>  		vsp1_hgo_frame_end(pipe->hgo);
> @@ -338,7 +339,7 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
>  	 * frame_end to account for vblank events.
>  	 */
>  	if (pipe->frame_end)
> -		pipe->frame_end(pipe, completed);
> +		pipe->frame_end(pipe, completed, notify);
>  
>  	pipe->sequence++;
>  }
> diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
> index dfff9b5685fe..482711024fa2 100644
> --- a/drivers/media/platform/vsp1/vsp1_pipe.h
> +++ b/drivers/media/platform/vsp1/vsp1_pipe.h
> @@ -118,7 +118,8 @@ struct vsp1_pipeline {
>  	enum vsp1_pipeline_state state;
>  	wait_queue_head_t wq;
>  
> -	void (*frame_end)(struct vsp1_pipeline *pipe, bool completed);
> +	void (*frame_end)(struct vsp1_pipeline *pipe, bool completed,
> +			  bool notify);
>  
>  	struct mutex lock;
>  	struct kref kref;
> diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
> index cdd53d6cc408..483b4259e1b4 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.c
> +++ b/drivers/media/platform/vsp1/vsp1_video.c
> @@ -437,14 +437,14 @@ static void vsp1_video_pipeline_run(struct vsp1_pipeline *pipe)
>  	}
>  
>  	/* Complete, and commit the head display list. */
> -	vsp1_dl_list_commit(pipe->dl);
> +	vsp1_dl_list_commit(pipe->dl, false);
>  	pipe->dl = NULL;
>  
>  	vsp1_pipeline_run(pipe);
>  }
>  
>  static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe,
> -					  bool completed)
> +					  bool completed, bool notify)
>  {
>  	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
>  	enum vsp1_pipeline_state state;
> 

--
Kieran
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 14/15] v4l: vsp1: Add BRx dynamic assignment debugging messages
  2018-02-26 21:45   ` Laurent Pinchart
@ 2018-04-04 16:17     ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-04-04 16:17 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: dri-devel, linux-renesas-soc

Hi Laurent,

On 26/02/18 21:45, Laurent Pinchart wrote:
> Dynamic assignment of the BRU and BRS to pipelines is prone to
> regressions, add messages to make debugging easier. Keep it as a
> separate commit to ease removal of those messages once the code will
> deem to be completely stable.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Not really a review required here so much, so I'll just :

Acked-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 87e31ba0ddf5..521bbc227110 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -190,6 +190,10 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
>  
>  		/* Release our BRU if we have one. */
>  		if (pipe->bru) {
> +			dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
> +				__func__, pipe->lif->index,
> +				BRU_NAME(pipe->bru));
> +
>  			/*
>  			 * The BRU might be acquired by the other pipeline in
>  			 * the next step. We must thus remove it from the list
> @@ -219,6 +223,9 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
>  		if (bru->pipe) {
>  			struct vsp1_drm_pipeline *owner_pipe;
>  
> +			dev_dbg(vsp1->dev, "%s: pipe %u: waiting for %s\n",
> +				__func__, pipe->lif->index, BRU_NAME(bru));
> +
>  			owner_pipe = to_vsp1_drm_pipeline(bru->pipe);
>  			owner_pipe->force_bru_release = true;
>  
> @@ -245,6 +252,9 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
>  				      &pipe->entities);
>  
>  		/* Add the BRU to the pipeline. */
> +		dev_dbg(vsp1->dev, "%s: pipe %u: acquired %s\n",
> +			__func__, pipe->lif->index, BRU_NAME(bru));
> +
>  		pipe->bru = bru;
>  		pipe->bru->pipe = pipe;
>  		pipe->bru->sink = &pipe->output->entity;
> @@ -549,6 +559,10 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  		drm_pipe->du_complete = NULL;
>  		pipe->num_inputs = 0;
>  
> +		dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
> +			__func__, pipe->lif->index,
> +			BRU_NAME(pipe->bru));
> +
>  		list_del(&pipe->bru->list_pipe);
>  		pipe->bru->pipe = NULL;
>  		pipe->bru = NULL;
> 

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

* Re: [PATCH 14/15] v4l: vsp1: Add BRx dynamic assignment debugging messages
@ 2018-04-04 16:17     ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-04-04 16:17 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: linux-renesas-soc, dri-devel

Hi Laurent,

On 26/02/18 21:45, Laurent Pinchart wrote:
> Dynamic assignment of the BRU and BRS to pipelines is prone to
> regressions, add messages to make debugging easier. Keep it as a
> separate commit to ease removal of those messages once the code will
> deem to be completely stable.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Not really a review required here so much, so I'll just :

Acked-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

> ---
>  drivers/media/platform/vsp1/vsp1_drm.c | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 87e31ba0ddf5..521bbc227110 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -190,6 +190,10 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
>  
>  		/* Release our BRU if we have one. */
>  		if (pipe->bru) {
> +			dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
> +				__func__, pipe->lif->index,
> +				BRU_NAME(pipe->bru));
> +
>  			/*
>  			 * The BRU might be acquired by the other pipeline in
>  			 * the next step. We must thus remove it from the list
> @@ -219,6 +223,9 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
>  		if (bru->pipe) {
>  			struct vsp1_drm_pipeline *owner_pipe;
>  
> +			dev_dbg(vsp1->dev, "%s: pipe %u: waiting for %s\n",
> +				__func__, pipe->lif->index, BRU_NAME(bru));
> +
>  			owner_pipe = to_vsp1_drm_pipeline(bru->pipe);
>  			owner_pipe->force_bru_release = true;
>  
> @@ -245,6 +252,9 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
>  				      &pipe->entities);
>  
>  		/* Add the BRU to the pipeline. */
> +		dev_dbg(vsp1->dev, "%s: pipe %u: acquired %s\n",
> +			__func__, pipe->lif->index, BRU_NAME(bru));
> +
>  		pipe->bru = bru;
>  		pipe->bru->pipe = pipe;
>  		pipe->bru->sink = &pipe->output->entity;
> @@ -549,6 +559,10 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  		drm_pipe->du_complete = NULL;
>  		pipe->num_inputs = 0;
>  
> +		dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
> +			__func__, pipe->lif->index,
> +			BRU_NAME(pipe->bru));
> +
>  		list_del(&pipe->bru->list_pipe);
>  		pipe->bru->pipe = NULL;
>  		pipe->bru = NULL;
> 

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 15/15] v4l: vsp1: Rename BRU to BRx
  2018-02-26 21:45   ` Laurent Pinchart
@ 2018-04-04 16:23     ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-04-04 16:23 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: dri-devel, linux-renesas-soc

Hi Laurent,

And so - the final patch (of the series)

On 26/02/18 21:45, Laurent Pinchart wrote:
> Some VSP instances have two blending units named BRU (Blend/ROP Unit)
> and BRS (Blend/ROP Sub unit). The BRS is a smaller version of the BRU
> with only two inputs, but otherwise offers similar features and offers
> the same register interface. The BRU and BRS can be used exchangeably in> VSP pipelines (provided no more than two inputs are needed).
> 
> Due to historical reasons, the VSP1 driver implements support for both
> the BRU and BRS through objects named vsp1_bru. The code uses the name
> BRU to refer to either the BRU or the BRS, except in a few places where
> noted explicitly. This creates confusion.
> 
> In an effort to avoid confusion, rename the vsp1_bru object and the
> corresponding API to vsp1_brx, and use BRx to refer to blend unit
> instances regardless of their type. The names BRU and BRS are retained
> where reference to a particular blend unit type is needed, as well as in
> hardware registers to stay close to the datasheet.
> 

I fully approve of this change, though I can see there will be some conflicts /
fixups needed when you rebase this - and depending upon when other series get in.

Thus - rather than do a full review, for now I'll just say:

Acked-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

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



> ---
>  drivers/media/platform/vsp1/Makefile               |   2 +-
>  drivers/media/platform/vsp1/vsp1.h                 |   6 +-
>  .../media/platform/vsp1/{vsp1_bru.c => vsp1_brx.c} | 202 ++++++++++-----------
>  .../media/platform/vsp1/{vsp1_bru.h => vsp1_brx.h} |  18 +-
>  drivers/media/platform/vsp1/vsp1_drm.c             | 172 +++++++++---------
>  drivers/media/platform/vsp1/vsp1_drm.h             |   6 +-
>  drivers/media/platform/vsp1/vsp1_drv.c             |   6 +-
>  drivers/media/platform/vsp1/vsp1_pipe.c            |  12 +-
>  drivers/media/platform/vsp1/vsp1_pipe.h            |   4 +-
>  drivers/media/platform/vsp1/vsp1_rpf.c             |  12 +-
>  drivers/media/platform/vsp1/vsp1_rwpf.h            |   2 +-
>  drivers/media/platform/vsp1/vsp1_video.c           |  16 +-
>  drivers/media/platform/vsp1/vsp1_wpf.c             |   8 +-
>  13 files changed, 233 insertions(+), 233 deletions(-)
>  rename drivers/media/platform/vsp1/{vsp1_bru.c => vsp1_brx.c} (63%)
>  rename drivers/media/platform/vsp1/{vsp1_bru.h => vsp1_brx.h} (66%)
> 
> diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile
> index f5cd6f0491cb..596775f932c0 100644
> --- a/drivers/media/platform/vsp1/Makefile
> +++ b/drivers/media/platform/vsp1/Makefile
> @@ -3,7 +3,7 @@ vsp1-y					:= vsp1_drv.o vsp1_entity.o vsp1_pipe.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_clu.o vsp1_hsit.o vsp1_lut.o
> -vsp1-y					+= vsp1_bru.o vsp1_sru.o vsp1_uds.o
> +vsp1-y					+= vsp1_brx.o vsp1_sru.o vsp1_uds.o
>  vsp1-y					+= vsp1_hgo.o vsp1_hgt.o vsp1_histo.o
>  vsp1-y					+= vsp1_lif.o
>  
> diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
> index 78ef838416b3..894cc725c2d4 100644
> --- a/drivers/media/platform/vsp1/vsp1.h
> +++ b/drivers/media/platform/vsp1/vsp1.h
> @@ -30,7 +30,7 @@ struct rcar_fcp_device;
>  struct vsp1_drm;
>  struct vsp1_entity;
>  struct vsp1_platform_data;
> -struct vsp1_bru;
> +struct vsp1_brx;
>  struct vsp1_clu;
>  struct vsp1_hgo;
>  struct vsp1_hgt;
> @@ -78,8 +78,8 @@ struct vsp1_device {
>  	struct rcar_fcp_device *fcp;
>  	struct device *bus_master;
>  
> -	struct vsp1_bru *brs;
> -	struct vsp1_bru *bru;
> +	struct vsp1_brx *brs;
> +	struct vsp1_brx *bru;
>  	struct vsp1_clu *clu;
>  	struct vsp1_hgo *hgo;
>  	struct vsp1_hgt *hgt;
> diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_brx.c
> similarity index 63%
> rename from drivers/media/platform/vsp1/vsp1_bru.c
> rename to drivers/media/platform/vsp1/vsp1_brx.c
> index e8fd2ae3b3eb..b4af1d546022 100644
> --- a/drivers/media/platform/vsp1/vsp1_bru.c
> +++ b/drivers/media/platform/vsp1/vsp1_brx.c
> @@ -1,5 +1,5 @@
>  /*
> - * vsp1_bru.c  --  R-Car VSP1 Blend ROP Unit
> + * vsp1_brx.c  --  R-Car VSP1 Blend ROP Unit (BRU and BRS)
>   *
>   * Copyright (C) 2013 Renesas Corporation
>   *
> @@ -17,45 +17,45 @@
>  #include <media/v4l2-subdev.h>
>  
>  #include "vsp1.h"
> -#include "vsp1_bru.h"
> +#include "vsp1_brx.h"
>  #include "vsp1_dl.h"
>  #include "vsp1_pipe.h"
>  #include "vsp1_rwpf.h"
>  #include "vsp1_video.h"
>  
> -#define BRU_MIN_SIZE				1U
> -#define BRU_MAX_SIZE				8190U
> +#define BRX_MIN_SIZE				1U
> +#define BRX_MAX_SIZE				8190U
>  
>  /* -----------------------------------------------------------------------------
>   * Device Access
>   */
>  
> -static inline void vsp1_bru_write(struct vsp1_bru *bru, struct vsp1_dl_list *dl,
> +static inline void vsp1_brx_write(struct vsp1_brx *brx, struct vsp1_dl_list *dl,
>  				  u32 reg, u32 data)
>  {
> -	vsp1_dl_list_write(dl, bru->base + reg, data);
> +	vsp1_dl_list_write(dl, brx->base + reg, data);
>  }
>  
>  /* -----------------------------------------------------------------------------
>   * Controls
>   */
>  
> -static int bru_s_ctrl(struct v4l2_ctrl *ctrl)
> +static int brx_s_ctrl(struct v4l2_ctrl *ctrl)
>  {
> -	struct vsp1_bru *bru =
> -		container_of(ctrl->handler, struct vsp1_bru, ctrls);
> +	struct vsp1_brx *brx =
> +		container_of(ctrl->handler, struct vsp1_brx, ctrls);
>  
>  	switch (ctrl->id) {
>  	case V4L2_CID_BG_COLOR:
> -		bru->bgcolor = ctrl->val;
> +		brx->bgcolor = ctrl->val;
>  		break;
>  	}
>  
>  	return 0;
>  }
>  
> -static const struct v4l2_ctrl_ops bru_ctrl_ops = {
> -	.s_ctrl = bru_s_ctrl,
> +static const struct v4l2_ctrl_ops brx_ctrl_ops = {
> +	.s_ctrl = brx_s_ctrl,
>  };
>  
>  /* -----------------------------------------------------------------------------
> @@ -63,12 +63,12 @@ static const struct v4l2_ctrl_ops bru_ctrl_ops = {
>   */
>  
>  /*
> - * The BRU can't perform format conversion, all sink and source formats must be
> + * The BRx can't perform format conversion, all sink and source formats must be
>   * identical. We pick the format on the first sink pad (pad 0) and propagate it
>   * to all other pads.
>   */
>  
> -static int bru_enum_mbus_code(struct v4l2_subdev *subdev,
> +static int brx_enum_mbus_code(struct v4l2_subdev *subdev,
>  			      struct v4l2_subdev_pad_config *cfg,
>  			      struct v4l2_subdev_mbus_code_enum *code)
>  {
> @@ -81,7 +81,7 @@ static int bru_enum_mbus_code(struct v4l2_subdev *subdev,
>  					  ARRAY_SIZE(codes));
>  }
>  
> -static int bru_enum_frame_size(struct v4l2_subdev *subdev,
> +static int brx_enum_frame_size(struct v4l2_subdev *subdev,
>  			       struct v4l2_subdev_pad_config *cfg,
>  			       struct v4l2_subdev_frame_size_enum *fse)
>  {
> @@ -92,29 +92,29 @@ static int bru_enum_frame_size(struct v4l2_subdev *subdev,
>  	    fse->code != MEDIA_BUS_FMT_AYUV8_1X32)
>  		return -EINVAL;
>  
> -	fse->min_width = BRU_MIN_SIZE;
> -	fse->max_width = BRU_MAX_SIZE;
> -	fse->min_height = BRU_MIN_SIZE;
> -	fse->max_height = BRU_MAX_SIZE;
> +	fse->min_width = BRX_MIN_SIZE;
> +	fse->max_width = BRX_MAX_SIZE;
> +	fse->min_height = BRX_MIN_SIZE;
> +	fse->max_height = BRX_MAX_SIZE;
>  
>  	return 0;
>  }
>  
> -static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru,
> +static struct v4l2_rect *brx_get_compose(struct vsp1_brx *brx,
>  					 struct v4l2_subdev_pad_config *cfg,
>  					 unsigned int pad)
>  {
> -	return v4l2_subdev_get_try_compose(&bru->entity.subdev, cfg, pad);
> +	return v4l2_subdev_get_try_compose(&brx->entity.subdev, cfg, pad);
>  }
>  
> -static void bru_try_format(struct vsp1_bru *bru,
> +static void brx_try_format(struct vsp1_brx *brx,
>  			   struct v4l2_subdev_pad_config *config,
>  			   unsigned int pad, struct v4l2_mbus_framefmt *fmt)
>  {
>  	struct v4l2_mbus_framefmt *format;
>  
>  	switch (pad) {
> -	case BRU_PAD_SINK(0):
> +	case BRX_PAD_SINK(0):
>  		/* Default to YUV if the requested format is not supported. */
>  		if (fmt->code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
>  		    fmt->code != MEDIA_BUS_FMT_AYUV8_1X32)
> @@ -122,46 +122,46 @@ static void bru_try_format(struct vsp1_bru *bru,
>  		break;
>  
>  	default:
> -		/* The BRU can't perform format conversion. */
> -		format = vsp1_entity_get_pad_format(&bru->entity, config,
> -						    BRU_PAD_SINK(0));
> +		/* The BRx can't perform format conversion. */
> +		format = vsp1_entity_get_pad_format(&brx->entity, config,
> +						    BRX_PAD_SINK(0));
>  		fmt->code = format->code;
>  		break;
>  	}
>  
> -	fmt->width = clamp(fmt->width, BRU_MIN_SIZE, BRU_MAX_SIZE);
> -	fmt->height = clamp(fmt->height, BRU_MIN_SIZE, BRU_MAX_SIZE);
> +	fmt->width = clamp(fmt->width, BRX_MIN_SIZE, BRX_MAX_SIZE);
> +	fmt->height = clamp(fmt->height, BRX_MIN_SIZE, BRX_MAX_SIZE);
>  	fmt->field = V4L2_FIELD_NONE;
>  	fmt->colorspace = V4L2_COLORSPACE_SRGB;
>  }
>  
> -static int bru_set_format(struct v4l2_subdev *subdev,
> +static int brx_set_format(struct v4l2_subdev *subdev,
>  			  struct v4l2_subdev_pad_config *cfg,
>  			  struct v4l2_subdev_format *fmt)
>  {
> -	struct vsp1_bru *bru = to_bru(subdev);
> +	struct vsp1_brx *brx = to_brx(subdev);
>  	struct v4l2_subdev_pad_config *config;
>  	struct v4l2_mbus_framefmt *format;
>  	int ret = 0;
>  
> -	mutex_lock(&bru->entity.lock);
> +	mutex_lock(&brx->entity.lock);
>  
> -	config = vsp1_entity_get_pad_config(&bru->entity, cfg, fmt->which);
> +	config = vsp1_entity_get_pad_config(&brx->entity, cfg, fmt->which);
>  	if (!config) {
>  		ret = -EINVAL;
>  		goto done;
>  	}
>  
> -	bru_try_format(bru, config, fmt->pad, &fmt->format);
> +	brx_try_format(brx, config, fmt->pad, &fmt->format);
>  
> -	format = vsp1_entity_get_pad_format(&bru->entity, config, fmt->pad);
> +	format = vsp1_entity_get_pad_format(&brx->entity, config, fmt->pad);
>  	*format = fmt->format;
>  
>  	/* Reset the compose rectangle */
> -	if (fmt->pad != bru->entity.source_pad) {
> +	if (fmt->pad != brx->entity.source_pad) {
>  		struct v4l2_rect *compose;
>  
> -		compose = bru_get_compose(bru, config, fmt->pad);
> +		compose = brx_get_compose(brx, config, fmt->pad);
>  		compose->left = 0;
>  		compose->top = 0;
>  		compose->width = format->width;
> @@ -169,48 +169,48 @@ static int bru_set_format(struct v4l2_subdev *subdev,
>  	}
>  
>  	/* Propagate the format code to all pads */
> -	if (fmt->pad == BRU_PAD_SINK(0)) {
> +	if (fmt->pad == BRX_PAD_SINK(0)) {
>  		unsigned int i;
>  
> -		for (i = 0; i <= bru->entity.source_pad; ++i) {
> -			format = vsp1_entity_get_pad_format(&bru->entity,
> +		for (i = 0; i <= brx->entity.source_pad; ++i) {
> +			format = vsp1_entity_get_pad_format(&brx->entity,
>  							    config, i);
>  			format->code = fmt->format.code;
>  		}
>  	}
>  
>  done:
> -	mutex_unlock(&bru->entity.lock);
> +	mutex_unlock(&brx->entity.lock);
>  	return ret;
>  }
>  
> -static int bru_get_selection(struct v4l2_subdev *subdev,
> +static int brx_get_selection(struct v4l2_subdev *subdev,
>  			     struct v4l2_subdev_pad_config *cfg,
>  			     struct v4l2_subdev_selection *sel)
>  {
> -	struct vsp1_bru *bru = to_bru(subdev);
> +	struct vsp1_brx *brx = to_brx(subdev);
>  	struct v4l2_subdev_pad_config *config;
>  
> -	if (sel->pad == bru->entity.source_pad)
> +	if (sel->pad == brx->entity.source_pad)
>  		return -EINVAL;
>  
>  	switch (sel->target) {
>  	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
>  		sel->r.left = 0;
>  		sel->r.top = 0;
> -		sel->r.width = BRU_MAX_SIZE;
> -		sel->r.height = BRU_MAX_SIZE;
> +		sel->r.width = BRX_MAX_SIZE;
> +		sel->r.height = BRX_MAX_SIZE;
>  		return 0;
>  
>  	case V4L2_SEL_TGT_COMPOSE:
> -		config = vsp1_entity_get_pad_config(&bru->entity, cfg,
> +		config = vsp1_entity_get_pad_config(&brx->entity, cfg,
>  						    sel->which);
>  		if (!config)
>  			return -EINVAL;
>  
> -		mutex_lock(&bru->entity.lock);
> -		sel->r = *bru_get_compose(bru, config, sel->pad);
> -		mutex_unlock(&bru->entity.lock);
> +		mutex_lock(&brx->entity.lock);
> +		sel->r = *brx_get_compose(brx, config, sel->pad);
> +		mutex_unlock(&brx->entity.lock);
>  		return 0;
>  
>  	default:
> @@ -218,25 +218,25 @@ static int bru_get_selection(struct v4l2_subdev *subdev,
>  	}
>  }
>  
> -static int bru_set_selection(struct v4l2_subdev *subdev,
> +static int brx_set_selection(struct v4l2_subdev *subdev,
>  			     struct v4l2_subdev_pad_config *cfg,
>  			     struct v4l2_subdev_selection *sel)
>  {
> -	struct vsp1_bru *bru = to_bru(subdev);
> +	struct vsp1_brx *brx = to_brx(subdev);
>  	struct v4l2_subdev_pad_config *config;
>  	struct v4l2_mbus_framefmt *format;
>  	struct v4l2_rect *compose;
>  	int ret = 0;
>  
> -	if (sel->pad == bru->entity.source_pad)
> +	if (sel->pad == brx->entity.source_pad)
>  		return -EINVAL;
>  
>  	if (sel->target != V4L2_SEL_TGT_COMPOSE)
>  		return -EINVAL;
>  
> -	mutex_lock(&bru->entity.lock);
> +	mutex_lock(&brx->entity.lock);
>  
> -	config = vsp1_entity_get_pad_config(&bru->entity, cfg, sel->which);
> +	config = vsp1_entity_get_pad_config(&brx->entity, cfg, sel->which);
>  	if (!config) {
>  		ret = -EINVAL;
>  		goto done;
> @@ -246,8 +246,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, config,
> -					    bru->entity.source_pad);
> +	format = vsp1_entity_get_pad_format(&brx->entity, config,
> +					    brx->entity.source_pad);
>  	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);
>  
> @@ -255,42 +255,42 @@ static int bru_set_selection(struct v4l2_subdev *subdev,
>  	 * Scaling isn't supported, the compose rectangle size must be identical
>  	 * to the sink format size.
>  	 */
> -	format = vsp1_entity_get_pad_format(&bru->entity, config, sel->pad);
> +	format = vsp1_entity_get_pad_format(&brx->entity, config, sel->pad);
>  	sel->r.width = format->width;
>  	sel->r.height = format->height;
>  
> -	compose = bru_get_compose(bru, config, sel->pad);
> +	compose = brx_get_compose(brx, config, sel->pad);
>  	*compose = sel->r;
>  
>  done:
> -	mutex_unlock(&bru->entity.lock);
> +	mutex_unlock(&brx->entity.lock);
>  	return ret;
>  }
>  
> -static const struct v4l2_subdev_pad_ops bru_pad_ops = {
> +static const struct v4l2_subdev_pad_ops brx_pad_ops = {
>  	.init_cfg = vsp1_entity_init_cfg,
> -	.enum_mbus_code = bru_enum_mbus_code,
> -	.enum_frame_size = bru_enum_frame_size,
> +	.enum_mbus_code = brx_enum_mbus_code,
> +	.enum_frame_size = brx_enum_frame_size,
>  	.get_fmt = vsp1_subdev_get_pad_format,
> -	.set_fmt = bru_set_format,
> -	.get_selection = bru_get_selection,
> -	.set_selection = bru_set_selection,
> +	.set_fmt = brx_set_format,
> +	.get_selection = brx_get_selection,
> +	.set_selection = brx_set_selection,
>  };
>  
> -static const struct v4l2_subdev_ops bru_ops = {
> -	.pad    = &bru_pad_ops,
> +static const struct v4l2_subdev_ops brx_ops = {
> +	.pad    = &brx_pad_ops,
>  };
>  
>  /* -----------------------------------------------------------------------------
>   * VSP1 Entity Operations
>   */
>  
> -static void bru_configure(struct vsp1_entity *entity,
> +static void brx_configure(struct vsp1_entity *entity,
>  			  struct vsp1_pipeline *pipe,
>  			  struct vsp1_dl_list *dl,
>  			  enum vsp1_entity_params params)
>  {
> -	struct vsp1_bru *bru = to_bru(&entity->subdev);
> +	struct vsp1_brx *brx = to_brx(&entity->subdev);
>  	struct v4l2_mbus_framefmt *format;
>  	unsigned int flags;
>  	unsigned int i;
> @@ -298,8 +298,8 @@ static void bru_configure(struct vsp1_entity *entity,
>  	if (params != VSP1_ENTITY_PARAMS_INIT)
>  		return;
>  
> -	format = vsp1_entity_get_pad_format(&bru->entity, bru->entity.config,
> -					    bru->entity.source_pad);
> +	format = vsp1_entity_get_pad_format(&brx->entity, brx->entity.config,
> +					    brx->entity.source_pad);
>  
>  	/*
>  	 * The hardware is extremely flexible but we have no userspace API to
> @@ -313,7 +313,7 @@ static void bru_configure(struct vsp1_entity *entity,
>  	 * format at the pipeline output is premultiplied.
>  	 */
>  	flags = pipe->output ? pipe->output->format.flags : 0;
> -	vsp1_bru_write(bru, dl, VI6_BRU_INCTRL,
> +	vsp1_brx_write(brx, dl, VI6_BRU_INCTRL,
>  		       flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ?
>  		       0 : VI6_BRU_INCTRL_NRM);
>  
> @@ -321,12 +321,12 @@ static void bru_configure(struct vsp1_entity *entity,
>  	 * Set the background position to cover the whole output image and
>  	 * configure its color.
>  	 */
> -	vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_SIZE,
> +	vsp1_brx_write(brx, dl, VI6_BRU_VIRRPF_SIZE,
>  		       (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) |
>  		       (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT));
> -	vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_LOC, 0);
> +	vsp1_brx_write(brx, dl, VI6_BRU_VIRRPF_LOC, 0);
>  
> -	vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_COL, bru->bgcolor |
> +	vsp1_brx_write(brx, dl, VI6_BRU_VIRRPF_COL, brx->bgcolor |
>  		       (0xff << VI6_BRU_VIRRPF_COL_A_SHIFT));
>  
>  	/*
> @@ -336,25 +336,25 @@ static void bru_configure(struct vsp1_entity *entity,
>  	 * unit.
>  	 */
>  	if (entity->type == VSP1_ENTITY_BRU)
> -		vsp1_bru_write(bru, dl, VI6_BRU_ROP,
> +		vsp1_brx_write(brx, dl, VI6_BRU_ROP,
>  			       VI6_BRU_ROP_DSTSEL_BRUIN(1) |
>  			       VI6_BRU_ROP_CROP(VI6_ROP_NOP) |
>  			       VI6_BRU_ROP_AROP(VI6_ROP_NOP));
>  
> -	for (i = 0; i < bru->entity.source_pad; ++i) {
> +	for (i = 0; i < brx->entity.source_pad; ++i) {
>  		bool premultiplied = false;
>  		u32 ctrl = 0;
>  
>  		/*
> -		 * Configure all Blend/ROP units corresponding to an enabled BRU
> +		 * Configure all Blend/ROP units corresponding to an enabled BRx
>  		 * input for alpha blending. Blend/ROP units corresponding to
> -		 * disabled BRU inputs are used in ROP NOP mode to ignore the
> +		 * disabled BRx inputs are used in ROP NOP mode to ignore the
>  		 * SRC input.
>  		 */
> -		if (bru->inputs[i].rpf) {
> +		if (brx->inputs[i].rpf) {
>  			ctrl |= VI6_BRU_CTRL_RBC;
>  
> -			premultiplied = bru->inputs[i].rpf->format.flags
> +			premultiplied = brx->inputs[i].rpf->format.flags
>  				      & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA;
>  		} else {
>  			ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP)
> @@ -378,7 +378,7 @@ static void bru_configure(struct vsp1_entity *entity,
>  		if (!(entity->type == VSP1_ENTITY_BRU && i == 1))
>  			ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i);
>  
> -		vsp1_bru_write(bru, dl, VI6_BRU_CTRL(i), ctrl);
> +		vsp1_brx_write(brx, dl, VI6_BRU_CTRL(i), ctrl);
>  
>  		/*
>  		 * Harcode the blending formula to
> @@ -393,7 +393,7 @@ static void bru_configure(struct vsp1_entity *entity,
>  		 *
>  		 * otherwise.
>  		 */
> -		vsp1_bru_write(bru, dl, VI6_BRU_BLD(i),
> +		vsp1_brx_write(brx, dl, VI6_BRU_BLD(i),
>  			       VI6_BRU_BLD_CCMDX_255_SRC_A |
>  			       (premultiplied ? VI6_BRU_BLD_CCMDY_COEFY :
>  						VI6_BRU_BLD_CCMDY_SRC_A) |
> @@ -403,29 +403,29 @@ static void bru_configure(struct vsp1_entity *entity,
>  	}
>  }
>  
> -static const struct vsp1_entity_operations bru_entity_ops = {
> -	.configure = bru_configure,
> +static const struct vsp1_entity_operations brx_entity_ops = {
> +	.configure = brx_configure,
>  };
>  
>  /* -----------------------------------------------------------------------------
>   * Initialization and Cleanup
>   */
>  
> -struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1,
> +struct vsp1_brx *vsp1_brx_create(struct vsp1_device *vsp1,
>  				 enum vsp1_entity_type type)
>  {
> -	struct vsp1_bru *bru;
> +	struct vsp1_brx *brx;
>  	unsigned int num_pads;
>  	const char *name;
>  	int ret;
>  
> -	bru = devm_kzalloc(vsp1->dev, sizeof(*bru), GFP_KERNEL);
> -	if (bru == NULL)
> +	brx = devm_kzalloc(vsp1->dev, sizeof(*brx), GFP_KERNEL);
> +	if (brx == NULL)
>  		return ERR_PTR(-ENOMEM);
>  
> -	bru->base = type == VSP1_ENTITY_BRU ? VI6_BRU_BASE : VI6_BRS_BASE;
> -	bru->entity.ops = &bru_entity_ops;
> -	bru->entity.type = type;
> +	brx->base = type == VSP1_ENTITY_BRU ? VI6_BRU_BASE : VI6_BRS_BASE;
> +	brx->entity.ops = &brx_entity_ops;
> +	brx->entity.type = type;
>  
>  	if (type == VSP1_ENTITY_BRU) {
>  		num_pads = vsp1->info->num_bru_inputs + 1;
> @@ -435,26 +435,26 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1,
>  		name = "brs";
>  	}
>  
> -	ret = vsp1_entity_init(vsp1, &bru->entity, name, num_pads, &bru_ops,
> +	ret = vsp1_entity_init(vsp1, &brx->entity, name, num_pads, &brx_ops,
>  			       MEDIA_ENT_F_PROC_VIDEO_COMPOSER);
>  	if (ret < 0)
>  		return ERR_PTR(ret);
>  
>  	/* Initialize the control handler. */
> -	v4l2_ctrl_handler_init(&bru->ctrls, 1);
> -	v4l2_ctrl_new_std(&bru->ctrls, &bru_ctrl_ops, V4L2_CID_BG_COLOR,
> +	v4l2_ctrl_handler_init(&brx->ctrls, 1);
> +	v4l2_ctrl_new_std(&brx->ctrls, &brx_ctrl_ops, V4L2_CID_BG_COLOR,
>  			  0, 0xffffff, 1, 0);
>  
> -	bru->bgcolor = 0;
> +	brx->bgcolor = 0;
>  
> -	bru->entity.subdev.ctrl_handler = &bru->ctrls;
> +	brx->entity.subdev.ctrl_handler = &brx->ctrls;
>  
> -	if (bru->ctrls.error) {
> +	if (brx->ctrls.error) {
>  		dev_err(vsp1->dev, "%s: failed to initialize controls\n", name);
> -		ret = bru->ctrls.error;
> -		vsp1_entity_destroy(&bru->entity);
> +		ret = brx->ctrls.error;
> +		vsp1_entity_destroy(&brx->entity);
>  		return ERR_PTR(ret);
>  	}
>  
> -	return bru;
> +	return brx;
>  }
> diff --git a/drivers/media/platform/vsp1/vsp1_bru.h b/drivers/media/platform/vsp1/vsp1_brx.h
> similarity index 66%
> rename from drivers/media/platform/vsp1/vsp1_bru.h
> rename to drivers/media/platform/vsp1/vsp1_brx.h
> index c98ed96d8de6..927aa4254c0f 100644
> --- a/drivers/media/platform/vsp1/vsp1_bru.h
> +++ b/drivers/media/platform/vsp1/vsp1_brx.h
> @@ -1,5 +1,5 @@
>  /*
> - * vsp1_bru.h  --  R-Car VSP1 Blend ROP Unit
> + * vsp1_brx.h  --  R-Car VSP1 Blend ROP Unit (BRU and BRS)
>   *
>   * Copyright (C) 2013 Renesas Corporation
>   *
> @@ -10,8 +10,8 @@
>   * the Free Software Foundation; either version 2 of the License, or
>   * (at your option) any later version.
>   */
> -#ifndef __VSP1_BRU_H__
> -#define __VSP1_BRU_H__
> +#ifndef __VSP1_BRX_H__
> +#define __VSP1_BRX_H__
>  
>  #include <media/media-entity.h>
>  #include <media/v4l2-ctrls.h>
> @@ -22,9 +22,9 @@
>  struct vsp1_device;
>  struct vsp1_rwpf;
>  
> -#define BRU_PAD_SINK(n)				(n)
> +#define BRX_PAD_SINK(n)				(n)
>  
> -struct vsp1_bru {
> +struct vsp1_brx {
>  	struct vsp1_entity entity;
>  	unsigned int base;
>  
> @@ -37,12 +37,12 @@ struct vsp1_bru {
>  	u32 bgcolor;
>  };
>  
> -static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev)
> +static inline struct vsp1_brx *to_brx(struct v4l2_subdev *subdev)
>  {
> -	return container_of(subdev, struct vsp1_bru, entity.subdev);
> +	return container_of(subdev, struct vsp1_brx, entity.subdev);
>  }
>  
> -struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1,
> +struct vsp1_brx *vsp1_brx_create(struct vsp1_device *vsp1,
>  				 enum vsp1_entity_type type);
>  
> -#endif /* __VSP1_BRU_H__ */
> +#endif /* __VSP1_BRX_H__ */
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 521bbc227110..50496343bbdb 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -20,14 +20,14 @@
>  #include <media/vsp1.h>
>  
>  #include "vsp1.h"
> -#include "vsp1_bru.h"
> +#include "vsp1_brx.h"
>  #include "vsp1_dl.h"
>  #include "vsp1_drm.h"
>  #include "vsp1_lif.h"
>  #include "vsp1_pipe.h"
>  #include "vsp1_rwpf.h"
>  
> -#define BRU_NAME(e)	(e)->type == VSP1_ENTITY_BRU ? "BRU" : "BRS"
> +#define BRX_NAME(e)	(e)->type == VSP1_ENTITY_BRU ? "BRU" : "BRS"
>  
>  /* -----------------------------------------------------------------------------
>   * Interrupt Handling
> @@ -43,7 +43,7 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
>  				      completed && !notify);
>  
>  	if (notify) {
> -		drm_pipe->force_bru_release = false;
> +		drm_pipe->force_brx_release = false;
>  		wake_up(&drm_pipe->wait_queue);
>  	}
>  }
> @@ -52,11 +52,11 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
>   * Pipeline Configuration
>   */
>  
> -/* Setup one RPF and the connected BRU sink pad. */
> +/* Setup one RPF and the connected BRx sink pad. */
>  static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
>  				      struct vsp1_pipeline *pipe,
>  				      struct vsp1_rwpf *rpf,
> -				      unsigned int bru_input)
> +				      unsigned int brx_input)
>  {
>  	struct v4l2_subdev_selection sel;
>  	struct v4l2_subdev_format format;
> @@ -65,7 +65,7 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
>  
>  	/*
>  	 * Configure the format on the RPF sink pad and propagate it up to the
> -	 * BRU sink pad.
> +	 * BRx sink pad.
>  	 */
>  	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
>  
> @@ -126,114 +126,114 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
>  	if (ret < 0)
>  		return ret;
>  
> -	/* BRU sink, propagate the format from the RPF source. */
> -	format.pad = bru_input;
> +	/* BRx sink, propagate the format from the RPF source. */
> +	format.pad = brx_input;
>  
> -	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
> +	ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_fmt, NULL,
>  			       &format);
>  	if (ret < 0)
>  		return ret;
>  
>  	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
>  		__func__, format.format.width, format.format.height,
> -		format.format.code, BRU_NAME(pipe->bru), format.pad);
> +		format.format.code, BRX_NAME(pipe->brx), format.pad);
>  
> -	sel.pad = bru_input;
> +	sel.pad = brx_input;
>  	sel.target = V4L2_SEL_TGT_COMPOSE;
>  	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
>  
> -	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL,
> +	ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_selection, NULL,
>  			       &sel);
>  	if (ret < 0)
>  		return ret;
>  
>  	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
>  		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
> -		BRU_NAME(pipe->bru), sel.pad);
> +		BRX_NAME(pipe->brx), sel.pad);
>  
>  	return 0;
>  }
>  
> -/* Setup the BRU source pad. */
> +/* Setup the BRx source pad. */
>  static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  					struct vsp1_pipeline *pipe);
>  static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe);
>  
> -static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
> +static int vsp1_du_pipeline_setup_brx(struct vsp1_device *vsp1,
>  				      struct vsp1_pipeline *pipe)
>  {
>  	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
>  	struct v4l2_subdev_format format = {
>  		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
>  	};
> -	struct vsp1_entity *bru;
> +	struct vsp1_entity *brx;
>  	int ret;
>  
>  	/*
> -	 * Pick a BRU:
> -	 * - If we need more than two inputs, use the main BRU.
> -	 * - Otherwise, if we are not forced to release our BRU, keep it.
> -	 * - Else, use any free BRU (randomly starting with the main BRU).
> +	 * Pick a BRx:
> +	 * - If we need more than two inputs, use the BRU.
> +	 * - Otherwise, if we are not forced to release our BRx, keep it.
> +	 * - Else, use any free BRx (randomly starting with the BRU).
>  	 */
>  	if (pipe->num_inputs > 2)
> -		bru = &vsp1->bru->entity;
> -	else if (pipe->bru && !drm_pipe->force_bru_release)
> -		bru = pipe->bru;
> +		brx = &vsp1->bru->entity;
> +	else if (pipe->brx && !drm_pipe->force_brx_release)
> +		brx = pipe->brx;
>  	else if (!vsp1->bru->entity.pipe)
> -		bru = &vsp1->bru->entity;
> +		brx = &vsp1->bru->entity;
>  	else
> -		bru = &vsp1->brs->entity;
> +		brx = &vsp1->brs->entity;
>  
> -	/* Switch BRU if needed. */
> -	if (bru != pipe->bru) {
> -		struct vsp1_entity *released_bru = NULL;
> +	/* Switch BRx if needed. */
> +	if (brx != pipe->brx) {
> +		struct vsp1_entity *released_brx = NULL;
>  
> -		/* Release our BRU if we have one. */
> -		if (pipe->bru) {
> +		/* Release our BRx if we have one. */
> +		if (pipe->brx) {
>  			dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
>  				__func__, pipe->lif->index,
> -				BRU_NAME(pipe->bru));
> +				BRX_NAME(pipe->brx));
>  
>  			/*
> -			 * The BRU might be acquired by the other pipeline in
> +			 * The BRx might be acquired by the other pipeline in
>  			 * the next step. We must thus remove it from the list
>  			 * of entities for this pipeline. The other pipeline's
> -			 * hardware configuration will reconfigure the BRU
> +			 * hardware configuration will reconfigure the BRx
>  			 * routing.
>  			 *
>  			 * However, if the other pipeline doesn't acquire our
> -			 * BRU, we need to keep it in the list, otherwise the
> +			 * BRx, we need to keep it in the list, otherwise the
>  			 * hardware configuration step won't disconnect it from
> -			 * the pipeline. To solve this, store the released BRU
> +			 * the pipeline. To solve this, store the released BRx
>  			 * pointer to add it back to the list of entities later
>  			 * if it isn't acquired by the other pipeline.
>  			 */
> -			released_bru = pipe->bru;
> +			released_brx = pipe->brx;
>  
> -			list_del(&pipe->bru->list_pipe);
> -			pipe->bru->sink = NULL;
> -			pipe->bru->pipe = NULL;
> -			pipe->bru = NULL;
> +			list_del(&pipe->brx->list_pipe);
> +			pipe->brx->sink = NULL;
> +			pipe->brx->pipe = NULL;
> +			pipe->brx = NULL;
>  		}
>  
>  		/*
> -		 * If the BRU we need is in use, force the owner pipeline to
> -		 * switch to the other BRU and wait until the switch completes.
> +		 * If the BRx we need is in use, force the owner pipeline to
> +		 * switch to the other BRx and wait until the switch completes.
>  		 */
> -		if (bru->pipe) {
> +		if (brx->pipe) {
>  			struct vsp1_drm_pipeline *owner_pipe;
>  
>  			dev_dbg(vsp1->dev, "%s: pipe %u: waiting for %s\n",
> -				__func__, pipe->lif->index, BRU_NAME(bru));
> +				__func__, pipe->lif->index, BRX_NAME(brx));
>  
> -			owner_pipe = to_vsp1_drm_pipeline(bru->pipe);
> -			owner_pipe->force_bru_release = true;
> +			owner_pipe = to_vsp1_drm_pipeline(brx->pipe);
> +			owner_pipe->force_brx_release = true;
>  
>  			vsp1_du_pipeline_setup_input(vsp1, &owner_pipe->pipe);
>  			vsp1_du_pipeline_configure(&owner_pipe->pipe);
>  
>  			ret = wait_event_timeout(owner_pipe->wait_queue,
> -						 !owner_pipe->force_bru_release,
> +						 !owner_pipe->force_brx_release,
>  						 msecs_to_jiffies(500));
>  			if (ret == 0)
>  				dev_warn(vsp1->dev,
> @@ -242,46 +242,46 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
>  		}
>  
>  		/*
> -		 * If the BRU we have released previously hasn't been acquired
> +		 * If the BRx we have released previously hasn't been acquired
>  		 * by the other pipeline, add it back to the entities list (with
>  		 * the pipe pointer NULL) to let vsp1_du_pipeline_configure()
>  		 * disconnect it from the hardware pipeline.
>  		 */
> -		if (released_bru && !released_bru->pipe)
> -			list_add_tail(&released_bru->list_pipe,
> +		if (released_brx && !released_brx->pipe)
> +			list_add_tail(&released_brx->list_pipe,
>  				      &pipe->entities);
>  
> -		/* Add the BRU to the pipeline. */
> +		/* Add the BRx to the pipeline. */
>  		dev_dbg(vsp1->dev, "%s: pipe %u: acquired %s\n",
> -			__func__, pipe->lif->index, BRU_NAME(bru));
> +			__func__, pipe->lif->index, BRX_NAME(brx));
>  
> -		pipe->bru = bru;
> -		pipe->bru->pipe = pipe;
> -		pipe->bru->sink = &pipe->output->entity;
> -		pipe->bru->sink_pad = 0;
> +		pipe->brx = brx;
> +		pipe->brx->pipe = pipe;
> +		pipe->brx->sink = &pipe->output->entity;
> +		pipe->brx->sink_pad = 0;
>  
> -		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
> +		list_add_tail(&pipe->brx->list_pipe, &pipe->entities);
>  	}
>  
>  	/*
> -	 * Configure the format on the BRU source and verify that it matches the
> +	 * Configure the format on the BRx source and verify that it matches the
>  	 * requested format. We don't set the media bus code as it is configured
> -	 * on the BRU sink pad 0 and propagated inside the entity, not on the
> +	 * on the BRx sink pad 0 and propagated inside the entity, not on the
>  	 * source pad.
>  	 */
> -	format.pad = pipe->bru->source_pad;
> +	format.pad = pipe->brx->source_pad;
>  	format.format.width = drm_pipe->width;
>  	format.format.height = drm_pipe->height;
>  	format.format.field = V4L2_FIELD_NONE;
>  
> -	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
> +	ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_fmt, NULL,
>  			       &format);
>  	if (ret < 0)
>  		return ret;
>  
>  	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
>  		__func__, format.format.width, format.format.height,
> -		format.format.code, BRU_NAME(pipe->bru), pipe->bru->source_pad);
> +		format.format.code, BRX_NAME(pipe->brx), pipe->brx->source_pad);
>  
>  	if (format.format.width != drm_pipe->width ||
>  	    format.format.height != drm_pipe->height) {
> @@ -297,12 +297,12 @@ static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
>  	return vsp1->drm->inputs[rpf->entity.index].zpos;
>  }
>  
> -/* Setup the input side of the pipeline (RPFs and BRU). */
> +/* Setup the input side of the pipeline (RPFs and BRx). */
>  static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  					struct vsp1_pipeline *pipe)
>  {
>  	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
> -	struct vsp1_bru *bru;
> +	struct vsp1_brx *brx;
>  	unsigned int i;
>  	int ret;
>  
> @@ -327,25 +327,25 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  	}
>  
>  	/*
> -	 * Setup the BRU. This must be done before setting up the RPF input
> -	 * pipelines as the BRU sink compose rectangles depend on the BRU source
> +	 * Setup the BRx. This must be done before setting up the RPF input
> +	 * pipelines as the BRx sink compose rectangles depend on the BRx source
>  	 * format.
>  	 */
> -	ret = vsp1_du_pipeline_setup_bru(vsp1, pipe);
> +	ret = vsp1_du_pipeline_setup_brx(vsp1, pipe);
>  	if (ret < 0) {
>  		dev_err(vsp1->dev, "%s: failed to setup %s source\n", __func__,
> -			BRU_NAME(pipe->bru));
> +			BRX_NAME(pipe->brx));
>  		return ret;
>  	}
>  
> -	bru = to_bru(&pipe->bru->subdev);
> +	brx = to_brx(&pipe->brx->subdev);
>  
>  	/* Setup the RPF input pipeline for every enabled input. */
> -	for (i = 0; i < pipe->bru->source_pad; ++i) {
> +	for (i = 0; i < pipe->brx->source_pad; ++i) {
>  		struct vsp1_rwpf *rpf = inputs[i];
>  
>  		if (!rpf) {
> -			bru->inputs[i].rpf = NULL;
> +			brx->inputs[i].rpf = NULL;
>  			continue;
>  		}
>  
> @@ -354,13 +354,13 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
>  		}
>  
> -		bru->inputs[i].rpf = rpf;
> -		rpf->bru_input = i;
> -		rpf->entity.sink = pipe->bru;
> +		brx->inputs[i].rpf = rpf;
> +		rpf->brx_input = i;
> +		rpf->entity.sink = pipe->brx;
>  		rpf->entity.sink_pad = i;
>  
>  		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
> -			__func__, rpf->entity.index, BRU_NAME(pipe->bru), i);
> +			__func__, rpf->entity.index, BRX_NAME(pipe->brx), i);
>  
>  		ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, i);
>  		if (ret < 0) {
> @@ -468,7 +468,7 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
>  		}
>  	}
>  
> -	vsp1_dl_list_commit(dl, drm_pipe->force_bru_release);
> +	vsp1_dl_list_commit(dl, drm_pipe->force_brx_release);
>  }
>  
>  /* -----------------------------------------------------------------------------
> @@ -493,8 +493,8 @@ EXPORT_SYMBOL_GPL(vsp1_du_init);
>   * @cfg: the LIF configuration
>   *
>   * Configure the output part of VSP DRM pipeline for the given frame @cfg.width
> - * and @cfg.height. This sets up formats on the blend unit (BRU or BRS) source
> - * pad, the WPF sink and source pads, and the LIF sink pad.
> + * and @cfg.height. This sets up formats on the BRx source pad, the WPF sink and
> + * source pads, and the LIF sink pad.
>   *
>   * The @pipe_index argument selects which DRM pipeline to setup. The number of
>   * available pipelines depend on the VSP instance.
> @@ -524,11 +524,11 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	pipe = &drm_pipe->pipe;
>  
>  	if (!cfg) {
> -		struct vsp1_bru *bru;
> +		struct vsp1_brx *brx;
>  
>  		mutex_lock(&vsp1->drm->lock);
>  
> -		bru = to_bru(&pipe->bru->subdev);
> +		brx = to_brx(&pipe->brx->subdev);
>  
>  		/*
>  		 * NULL configuration means the CRTC is being disabled, stop
> @@ -545,7 +545,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  				continue;
>  
>  			/*
> -			 * Remove the RPF from the pipe and the list of BRU
> +			 * Remove the RPF from the pipe and the list of BRx
>  			 * inputs.
>  			 */
>  			WARN_ON(!rpf->entity.pipe);
> @@ -553,7 +553,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  			list_del(&rpf->entity.list_pipe);
>  			pipe->inputs[i] = NULL;
>  
> -			bru->inputs[rpf->bru_input].rpf = NULL;
> +			brx->inputs[rpf->brx_input].rpf = NULL;
>  		}
>  
>  		drm_pipe->du_complete = NULL;
> @@ -561,11 +561,11 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  
>  		dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
>  			__func__, pipe->lif->index,
> -			BRU_NAME(pipe->bru));
> +			BRX_NAME(pipe->brx));
>  
> -		list_del(&pipe->bru->list_pipe);
> -		pipe->bru->pipe = NULL;
> -		pipe->bru = NULL;
> +		list_del(&pipe->brx->list_pipe);
> +		pipe->brx->pipe = NULL;
> +		pipe->brx = NULL;
>  
>  		mutex_unlock(&vsp1->drm->lock);
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
> index c84bc1c456c0..d738cc57f0e3 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.h
> +++ b/drivers/media/platform/vsp1/vsp1_drm.h
> @@ -24,8 +24,8 @@
>   * @pipe: the VSP1 pipeline used for display
>   * @width: output display width
>   * @height: output display height
> - * @force_bru_release: when set, release the BRU during the next reconfiguration
> - * @wait_queue: wait queue to wait for BRU release completion
> + * @force_brx_release: when set, release the BRx during the next reconfiguration
> + * @wait_queue: wait queue to wait for BRx release completion
>   * @du_complete: frame completion callback for the DU driver (optional)
>   * @du_private: data to be passed to the du_complete callback
>   */
> @@ -35,7 +35,7 @@ struct vsp1_drm_pipeline {
>  	unsigned int width;
>  	unsigned int height;
>  
> -	bool force_bru_release;
> +	bool force_brx_release;
>  	wait_queue_head_t wait_queue;
>  
>  	/* Frame synchronisation */
> diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
> index 58a7993f2306..f41cd70409db 100644
> --- a/drivers/media/platform/vsp1/vsp1_drv.c
> +++ b/drivers/media/platform/vsp1/vsp1_drv.c
> @@ -26,7 +26,7 @@
>  #include <media/v4l2-subdev.h>
>  
>  #include "vsp1.h"
> -#include "vsp1_bru.h"
> +#include "vsp1_brx.h"
>  #include "vsp1_clu.h"
>  #include "vsp1_dl.h"
>  #include "vsp1_drm.h"
> @@ -269,7 +269,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
>  
>  	/* Instantiate all the entities. */
>  	if (vsp1->info->features & VSP1_HAS_BRS) {
> -		vsp1->brs = vsp1_bru_create(vsp1, VSP1_ENTITY_BRS);
> +		vsp1->brs = vsp1_brx_create(vsp1, VSP1_ENTITY_BRS);
>  		if (IS_ERR(vsp1->brs)) {
>  			ret = PTR_ERR(vsp1->brs);
>  			goto done;
> @@ -279,7 +279,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
>  	}
>  
>  	if (vsp1->info->features & VSP1_HAS_BRU) {
> -		vsp1->bru = vsp1_bru_create(vsp1, VSP1_ENTITY_BRU);
> +		vsp1->bru = vsp1_brx_create(vsp1, VSP1_ENTITY_BRU);
>  		if (IS_ERR(vsp1->bru)) {
>  			ret = PTR_ERR(vsp1->bru);
>  			goto done;
> diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
> index 4d819c9019f4..45da3ff10955 100644
> --- a/drivers/media/platform/vsp1/vsp1_pipe.c
> +++ b/drivers/media/platform/vsp1/vsp1_pipe.c
> @@ -20,7 +20,7 @@
>  #include <media/v4l2-subdev.h>
>  
>  #include "vsp1.h"
> -#include "vsp1_bru.h"
> +#include "vsp1_brx.h"
>  #include "vsp1_dl.h"
>  #include "vsp1_entity.h"
>  #include "vsp1_hgo.h"
> @@ -188,11 +188,11 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
>  	struct vsp1_entity *entity;
>  	unsigned int i;
>  
> -	if (pipe->bru) {
> -		struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
> +	if (pipe->brx) {
> +		struct vsp1_brx *brx = to_brx(&pipe->brx->subdev);
>  
> -		for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i)
> -			bru->inputs[i].rpf = NULL;
> +		for (i = 0; i < ARRAY_SIZE(brx->inputs); ++i)
> +			brx->inputs[i].rpf = NULL;
>  	}
>  
>  	for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i)
> @@ -207,7 +207,7 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
>  	pipe->state = VSP1_PIPELINE_STOPPED;
>  	pipe->buffers_ready = 0;
>  	pipe->num_inputs = 0;
> -	pipe->bru = NULL;
> +	pipe->brx = NULL;
>  	pipe->hgo = NULL;
>  	pipe->hgt = NULL;
>  	pipe->lif = NULL;
> diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
> index 482711024fa2..9eca9fe16724 100644
> --- a/drivers/media/platform/vsp1/vsp1_pipe.h
> +++ b/drivers/media/platform/vsp1/vsp1_pipe.h
> @@ -99,7 +99,7 @@ struct vsp1_partition {
>   * @num_inputs: number of RPFs
>   * @inputs: array of RPFs in the pipeline (indexed by RPF index)
>   * @output: WPF at the output of the pipeline
> - * @bru: BRU entity, if present
> + * @brx: BRx entity, if present
>   * @hgo: HGO entity, if present
>   * @hgt: HGT entity, if present
>   * @lif: LIF entity, if present
> @@ -130,7 +130,7 @@ struct vsp1_pipeline {
>  	unsigned int num_inputs;
>  	struct vsp1_rwpf *inputs[VSP1_MAX_RPF];
>  	struct vsp1_rwpf *output;
> -	struct vsp1_entity *bru;
> +	struct vsp1_entity *brx;
>  	struct vsp1_entity *hgo;
>  	struct vsp1_entity *hgt;
>  	struct vsp1_entity *lif;
> diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
> index fe0633da5a5f..7e74c2015070 100644
> --- a/drivers/media/platform/vsp1/vsp1_rpf.c
> +++ b/drivers/media/platform/vsp1/vsp1_rpf.c
> @@ -167,12 +167,12 @@ static void rpf_configure(struct vsp1_entity *entity,
>  	vsp1_rpf_write(rpf, dl, VI6_RPF_DSWAP, fmtinfo->swap);
>  
>  	/* Output location */
> -	if (pipe->bru) {
> +	if (pipe->brx) {
>  		const struct v4l2_rect *compose;
>  
> -		compose = vsp1_entity_get_pad_selection(pipe->bru,
> -							pipe->bru->config,
> -							rpf->bru_input,
> +		compose = vsp1_entity_get_pad_selection(pipe->brx,
> +							pipe->brx->config,
> +							rpf->brx_input,
>  							V4L2_SEL_TGT_COMPOSE);
>  		left = compose->left;
>  		top = compose->top;
> @@ -191,10 +191,10 @@ static void rpf_configure(struct vsp1_entity *entity,
>  	 * alpha channel by a fixed global alpha value, and multiply the pixel
>  	 * components to convert the input to premultiplied alpha.
>  	 *
> -	 * As alpha premultiplication is available in the BRU for both Gen2 and
> +	 * As alpha premultiplication is available in the BRx for both Gen2 and
>  	 * Gen3 we handle it there and use the Gen3 alpha multiplier for global
>  	 * alpha multiplication only. This however prevents conversion to
> -	 * premultiplied alpha if no BRU is present in the pipeline. If that use
> +	 * premultiplied alpha if no BRx is present in the pipeline. If that use
>  	 * case turns out to be useful we will revisit the implementation (for
>  	 * Gen3 only).
>  	 *
> diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
> index c94ac89abfa7..915aeadb21dd 100644
> --- a/drivers/media/platform/vsp1/vsp1_rwpf.h
> +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
> @@ -45,7 +45,7 @@ struct vsp1_rwpf {
>  
>  	struct v4l2_pix_format_mplane format;
>  	const struct vsp1_format_info *fmtinfo;
> -	unsigned int bru_input;
> +	unsigned int brx_input;
>  
>  	unsigned int alpha;
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
> index 483b4259e1b4..1958d241d19b 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.c
> +++ b/drivers/media/platform/vsp1/vsp1_video.c
> @@ -28,7 +28,7 @@
>  #include <media/videobuf2-dma-contig.h>
>  
>  #include "vsp1.h"
> -#include "vsp1_bru.h"
> +#include "vsp1_brx.h"
>  #include "vsp1_dl.h"
>  #include "vsp1_entity.h"
>  #include "vsp1_hgo.h"
> @@ -488,7 +488,7 @@ static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
>  	struct media_entity_enum ent_enum;
>  	struct vsp1_entity *entity;
>  	struct media_pad *pad;
> -	struct vsp1_bru *bru = NULL;
> +	struct vsp1_brx *brx = NULL;
>  	int ret;
>  
>  	ret = media_entity_enum_init(&ent_enum, &input->entity.vsp1->media_dev);
> @@ -524,14 +524,14 @@ static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
>  		if (entity->type == VSP1_ENTITY_BRU ||
>  		    entity->type == VSP1_ENTITY_BRS) {
>  			/* BRU and BRS can't be chained. */
> -			if (bru) {
> +			if (brx) {
>  				ret = -EPIPE;
>  				goto out;
>  			}
>  
> -			bru = to_bru(&entity->subdev);
> -			bru->inputs[pad->index].rpf = input;
> -			input->bru_input = pad->index;
> +			brx = to_brx(&entity->subdev);
> +			brx->inputs[pad->index].rpf = input;
> +			input->brx_input = pad->index;
>  		}
>  
>  		/* We've reached the WPF, we're done. */
> @@ -553,7 +553,7 @@ static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
>  			}
>  
>  			pipe->uds = entity;
> -			pipe->uds_input = bru ? &bru->entity : &input->entity;
> +			pipe->uds_input = brx ? &brx->entity : &input->entity;
>  		}
>  
>  		/* Follow the source link, ignoring any HGO or HGT. */
> @@ -619,7 +619,7 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe,
>  
>  		case VSP1_ENTITY_BRU:
>  		case VSP1_ENTITY_BRS:
> -			pipe->bru = e;
> +			pipe->brx = e;
>  			break;
>  
>  		case VSP1_ENTITY_HGO:
> diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
> index f7f3b4b2c2de..76f2686e292f 100644
> --- a/drivers/media/platform/vsp1/vsp1_wpf.c
> +++ b/drivers/media/platform/vsp1/vsp1_wpf.c
> @@ -436,7 +436,7 @@ static void wpf_configure(struct vsp1_entity *entity,
>  	vsp1_dl_list_write(dl, VI6_WPF_WRBCK_CTRL, 0);
>  
>  	/*
> -	 * Sources. If the pipeline has a single input and BRU is not used,
> +	 * Sources. If the pipeline has a single input and BRx is not used,
>  	 * configure it as the master layer. Otherwise configure all
>  	 * inputs as sub-layers and select the virtual RPF as the master
>  	 * layer.
> @@ -447,13 +447,13 @@ static void wpf_configure(struct vsp1_entity *entity,
>  		if (!input)
>  			continue;
>  
> -		srcrpf |= (!pipe->bru && pipe->num_inputs == 1)
> +		srcrpf |= (!pipe->brx && pipe->num_inputs == 1)
>  			? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index)
>  			: VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index);
>  	}
>  
> -	if (pipe->bru || pipe->num_inputs > 1)
> -		srcrpf |= pipe->bru->type == VSP1_ENTITY_BRU
> +	if (pipe->brx || pipe->num_inputs > 1)
> +		srcrpf |= pipe->brx->type == VSP1_ENTITY_BRU
>  			? VI6_WPF_SRCRPF_VIRACT_MST
>  			: VI6_WPF_SRCRPF_VIRACT2_MST;
>  
> 

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

* Re: [PATCH 15/15] v4l: vsp1: Rename BRU to BRx
@ 2018-04-04 16:23     ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-04-04 16:23 UTC (permalink / raw)
  To: Laurent Pinchart, linux-media; +Cc: linux-renesas-soc, dri-devel

Hi Laurent,

And so - the final patch (of the series)

On 26/02/18 21:45, Laurent Pinchart wrote:
> Some VSP instances have two blending units named BRU (Blend/ROP Unit)
> and BRS (Blend/ROP Sub unit). The BRS is a smaller version of the BRU
> with only two inputs, but otherwise offers similar features and offers
> the same register interface. The BRU and BRS can be used exchangeably in> VSP pipelines (provided no more than two inputs are needed).
> 
> Due to historical reasons, the VSP1 driver implements support for both
> the BRU and BRS through objects named vsp1_bru. The code uses the name
> BRU to refer to either the BRU or the BRS, except in a few places where
> noted explicitly. This creates confusion.
> 
> In an effort to avoid confusion, rename the vsp1_bru object and the
> corresponding API to vsp1_brx, and use BRx to refer to blend unit
> instances regardless of their type. The names BRU and BRS are retained
> where reference to a particular blend unit type is needed, as well as in
> hardware registers to stay close to the datasheet.
> 

I fully approve of this change, though I can see there will be some conflicts /
fixups needed when you rebase this - and depending upon when other series get in.

Thus - rather than do a full review, for now I'll just say:

Acked-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

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



> ---
>  drivers/media/platform/vsp1/Makefile               |   2 +-
>  drivers/media/platform/vsp1/vsp1.h                 |   6 +-
>  .../media/platform/vsp1/{vsp1_bru.c => vsp1_brx.c} | 202 ++++++++++-----------
>  .../media/platform/vsp1/{vsp1_bru.h => vsp1_brx.h} |  18 +-
>  drivers/media/platform/vsp1/vsp1_drm.c             | 172 +++++++++---------
>  drivers/media/platform/vsp1/vsp1_drm.h             |   6 +-
>  drivers/media/platform/vsp1/vsp1_drv.c             |   6 +-
>  drivers/media/platform/vsp1/vsp1_pipe.c            |  12 +-
>  drivers/media/platform/vsp1/vsp1_pipe.h            |   4 +-
>  drivers/media/platform/vsp1/vsp1_rpf.c             |  12 +-
>  drivers/media/platform/vsp1/vsp1_rwpf.h            |   2 +-
>  drivers/media/platform/vsp1/vsp1_video.c           |  16 +-
>  drivers/media/platform/vsp1/vsp1_wpf.c             |   8 +-
>  13 files changed, 233 insertions(+), 233 deletions(-)
>  rename drivers/media/platform/vsp1/{vsp1_bru.c => vsp1_brx.c} (63%)
>  rename drivers/media/platform/vsp1/{vsp1_bru.h => vsp1_brx.h} (66%)
> 
> diff --git a/drivers/media/platform/vsp1/Makefile b/drivers/media/platform/vsp1/Makefile
> index f5cd6f0491cb..596775f932c0 100644
> --- a/drivers/media/platform/vsp1/Makefile
> +++ b/drivers/media/platform/vsp1/Makefile
> @@ -3,7 +3,7 @@ vsp1-y					:= vsp1_drv.o vsp1_entity.o vsp1_pipe.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_clu.o vsp1_hsit.o vsp1_lut.o
> -vsp1-y					+= vsp1_bru.o vsp1_sru.o vsp1_uds.o
> +vsp1-y					+= vsp1_brx.o vsp1_sru.o vsp1_uds.o
>  vsp1-y					+= vsp1_hgo.o vsp1_hgt.o vsp1_histo.o
>  vsp1-y					+= vsp1_lif.o
>  
> diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
> index 78ef838416b3..894cc725c2d4 100644
> --- a/drivers/media/platform/vsp1/vsp1.h
> +++ b/drivers/media/platform/vsp1/vsp1.h
> @@ -30,7 +30,7 @@ struct rcar_fcp_device;
>  struct vsp1_drm;
>  struct vsp1_entity;
>  struct vsp1_platform_data;
> -struct vsp1_bru;
> +struct vsp1_brx;
>  struct vsp1_clu;
>  struct vsp1_hgo;
>  struct vsp1_hgt;
> @@ -78,8 +78,8 @@ struct vsp1_device {
>  	struct rcar_fcp_device *fcp;
>  	struct device *bus_master;
>  
> -	struct vsp1_bru *brs;
> -	struct vsp1_bru *bru;
> +	struct vsp1_brx *brs;
> +	struct vsp1_brx *bru;
>  	struct vsp1_clu *clu;
>  	struct vsp1_hgo *hgo;
>  	struct vsp1_hgt *hgt;
> diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_brx.c
> similarity index 63%
> rename from drivers/media/platform/vsp1/vsp1_bru.c
> rename to drivers/media/platform/vsp1/vsp1_brx.c
> index e8fd2ae3b3eb..b4af1d546022 100644
> --- a/drivers/media/platform/vsp1/vsp1_bru.c
> +++ b/drivers/media/platform/vsp1/vsp1_brx.c
> @@ -1,5 +1,5 @@
>  /*
> - * vsp1_bru.c  --  R-Car VSP1 Blend ROP Unit
> + * vsp1_brx.c  --  R-Car VSP1 Blend ROP Unit (BRU and BRS)
>   *
>   * Copyright (C) 2013 Renesas Corporation
>   *
> @@ -17,45 +17,45 @@
>  #include <media/v4l2-subdev.h>
>  
>  #include "vsp1.h"
> -#include "vsp1_bru.h"
> +#include "vsp1_brx.h"
>  #include "vsp1_dl.h"
>  #include "vsp1_pipe.h"
>  #include "vsp1_rwpf.h"
>  #include "vsp1_video.h"
>  
> -#define BRU_MIN_SIZE				1U
> -#define BRU_MAX_SIZE				8190U
> +#define BRX_MIN_SIZE				1U
> +#define BRX_MAX_SIZE				8190U
>  
>  /* -----------------------------------------------------------------------------
>   * Device Access
>   */
>  
> -static inline void vsp1_bru_write(struct vsp1_bru *bru, struct vsp1_dl_list *dl,
> +static inline void vsp1_brx_write(struct vsp1_brx *brx, struct vsp1_dl_list *dl,
>  				  u32 reg, u32 data)
>  {
> -	vsp1_dl_list_write(dl, bru->base + reg, data);
> +	vsp1_dl_list_write(dl, brx->base + reg, data);
>  }
>  
>  /* -----------------------------------------------------------------------------
>   * Controls
>   */
>  
> -static int bru_s_ctrl(struct v4l2_ctrl *ctrl)
> +static int brx_s_ctrl(struct v4l2_ctrl *ctrl)
>  {
> -	struct vsp1_bru *bru =
> -		container_of(ctrl->handler, struct vsp1_bru, ctrls);
> +	struct vsp1_brx *brx =
> +		container_of(ctrl->handler, struct vsp1_brx, ctrls);
>  
>  	switch (ctrl->id) {
>  	case V4L2_CID_BG_COLOR:
> -		bru->bgcolor = ctrl->val;
> +		brx->bgcolor = ctrl->val;
>  		break;
>  	}
>  
>  	return 0;
>  }
>  
> -static const struct v4l2_ctrl_ops bru_ctrl_ops = {
> -	.s_ctrl = bru_s_ctrl,
> +static const struct v4l2_ctrl_ops brx_ctrl_ops = {
> +	.s_ctrl = brx_s_ctrl,
>  };
>  
>  /* -----------------------------------------------------------------------------
> @@ -63,12 +63,12 @@ static const struct v4l2_ctrl_ops bru_ctrl_ops = {
>   */
>  
>  /*
> - * The BRU can't perform format conversion, all sink and source formats must be
> + * The BRx can't perform format conversion, all sink and source formats must be
>   * identical. We pick the format on the first sink pad (pad 0) and propagate it
>   * to all other pads.
>   */
>  
> -static int bru_enum_mbus_code(struct v4l2_subdev *subdev,
> +static int brx_enum_mbus_code(struct v4l2_subdev *subdev,
>  			      struct v4l2_subdev_pad_config *cfg,
>  			      struct v4l2_subdev_mbus_code_enum *code)
>  {
> @@ -81,7 +81,7 @@ static int bru_enum_mbus_code(struct v4l2_subdev *subdev,
>  					  ARRAY_SIZE(codes));
>  }
>  
> -static int bru_enum_frame_size(struct v4l2_subdev *subdev,
> +static int brx_enum_frame_size(struct v4l2_subdev *subdev,
>  			       struct v4l2_subdev_pad_config *cfg,
>  			       struct v4l2_subdev_frame_size_enum *fse)
>  {
> @@ -92,29 +92,29 @@ static int bru_enum_frame_size(struct v4l2_subdev *subdev,
>  	    fse->code != MEDIA_BUS_FMT_AYUV8_1X32)
>  		return -EINVAL;
>  
> -	fse->min_width = BRU_MIN_SIZE;
> -	fse->max_width = BRU_MAX_SIZE;
> -	fse->min_height = BRU_MIN_SIZE;
> -	fse->max_height = BRU_MAX_SIZE;
> +	fse->min_width = BRX_MIN_SIZE;
> +	fse->max_width = BRX_MAX_SIZE;
> +	fse->min_height = BRX_MIN_SIZE;
> +	fse->max_height = BRX_MAX_SIZE;
>  
>  	return 0;
>  }
>  
> -static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru,
> +static struct v4l2_rect *brx_get_compose(struct vsp1_brx *brx,
>  					 struct v4l2_subdev_pad_config *cfg,
>  					 unsigned int pad)
>  {
> -	return v4l2_subdev_get_try_compose(&bru->entity.subdev, cfg, pad);
> +	return v4l2_subdev_get_try_compose(&brx->entity.subdev, cfg, pad);
>  }
>  
> -static void bru_try_format(struct vsp1_bru *bru,
> +static void brx_try_format(struct vsp1_brx *brx,
>  			   struct v4l2_subdev_pad_config *config,
>  			   unsigned int pad, struct v4l2_mbus_framefmt *fmt)
>  {
>  	struct v4l2_mbus_framefmt *format;
>  
>  	switch (pad) {
> -	case BRU_PAD_SINK(0):
> +	case BRX_PAD_SINK(0):
>  		/* Default to YUV if the requested format is not supported. */
>  		if (fmt->code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
>  		    fmt->code != MEDIA_BUS_FMT_AYUV8_1X32)
> @@ -122,46 +122,46 @@ static void bru_try_format(struct vsp1_bru *bru,
>  		break;
>  
>  	default:
> -		/* The BRU can't perform format conversion. */
> -		format = vsp1_entity_get_pad_format(&bru->entity, config,
> -						    BRU_PAD_SINK(0));
> +		/* The BRx can't perform format conversion. */
> +		format = vsp1_entity_get_pad_format(&brx->entity, config,
> +						    BRX_PAD_SINK(0));
>  		fmt->code = format->code;
>  		break;
>  	}
>  
> -	fmt->width = clamp(fmt->width, BRU_MIN_SIZE, BRU_MAX_SIZE);
> -	fmt->height = clamp(fmt->height, BRU_MIN_SIZE, BRU_MAX_SIZE);
> +	fmt->width = clamp(fmt->width, BRX_MIN_SIZE, BRX_MAX_SIZE);
> +	fmt->height = clamp(fmt->height, BRX_MIN_SIZE, BRX_MAX_SIZE);
>  	fmt->field = V4L2_FIELD_NONE;
>  	fmt->colorspace = V4L2_COLORSPACE_SRGB;
>  }
>  
> -static int bru_set_format(struct v4l2_subdev *subdev,
> +static int brx_set_format(struct v4l2_subdev *subdev,
>  			  struct v4l2_subdev_pad_config *cfg,
>  			  struct v4l2_subdev_format *fmt)
>  {
> -	struct vsp1_bru *bru = to_bru(subdev);
> +	struct vsp1_brx *brx = to_brx(subdev);
>  	struct v4l2_subdev_pad_config *config;
>  	struct v4l2_mbus_framefmt *format;
>  	int ret = 0;
>  
> -	mutex_lock(&bru->entity.lock);
> +	mutex_lock(&brx->entity.lock);
>  
> -	config = vsp1_entity_get_pad_config(&bru->entity, cfg, fmt->which);
> +	config = vsp1_entity_get_pad_config(&brx->entity, cfg, fmt->which);
>  	if (!config) {
>  		ret = -EINVAL;
>  		goto done;
>  	}
>  
> -	bru_try_format(bru, config, fmt->pad, &fmt->format);
> +	brx_try_format(brx, config, fmt->pad, &fmt->format);
>  
> -	format = vsp1_entity_get_pad_format(&bru->entity, config, fmt->pad);
> +	format = vsp1_entity_get_pad_format(&brx->entity, config, fmt->pad);
>  	*format = fmt->format;
>  
>  	/* Reset the compose rectangle */
> -	if (fmt->pad != bru->entity.source_pad) {
> +	if (fmt->pad != brx->entity.source_pad) {
>  		struct v4l2_rect *compose;
>  
> -		compose = bru_get_compose(bru, config, fmt->pad);
> +		compose = brx_get_compose(brx, config, fmt->pad);
>  		compose->left = 0;
>  		compose->top = 0;
>  		compose->width = format->width;
> @@ -169,48 +169,48 @@ static int bru_set_format(struct v4l2_subdev *subdev,
>  	}
>  
>  	/* Propagate the format code to all pads */
> -	if (fmt->pad == BRU_PAD_SINK(0)) {
> +	if (fmt->pad == BRX_PAD_SINK(0)) {
>  		unsigned int i;
>  
> -		for (i = 0; i <= bru->entity.source_pad; ++i) {
> -			format = vsp1_entity_get_pad_format(&bru->entity,
> +		for (i = 0; i <= brx->entity.source_pad; ++i) {
> +			format = vsp1_entity_get_pad_format(&brx->entity,
>  							    config, i);
>  			format->code = fmt->format.code;
>  		}
>  	}
>  
>  done:
> -	mutex_unlock(&bru->entity.lock);
> +	mutex_unlock(&brx->entity.lock);
>  	return ret;
>  }
>  
> -static int bru_get_selection(struct v4l2_subdev *subdev,
> +static int brx_get_selection(struct v4l2_subdev *subdev,
>  			     struct v4l2_subdev_pad_config *cfg,
>  			     struct v4l2_subdev_selection *sel)
>  {
> -	struct vsp1_bru *bru = to_bru(subdev);
> +	struct vsp1_brx *brx = to_brx(subdev);
>  	struct v4l2_subdev_pad_config *config;
>  
> -	if (sel->pad == bru->entity.source_pad)
> +	if (sel->pad == brx->entity.source_pad)
>  		return -EINVAL;
>  
>  	switch (sel->target) {
>  	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
>  		sel->r.left = 0;
>  		sel->r.top = 0;
> -		sel->r.width = BRU_MAX_SIZE;
> -		sel->r.height = BRU_MAX_SIZE;
> +		sel->r.width = BRX_MAX_SIZE;
> +		sel->r.height = BRX_MAX_SIZE;
>  		return 0;
>  
>  	case V4L2_SEL_TGT_COMPOSE:
> -		config = vsp1_entity_get_pad_config(&bru->entity, cfg,
> +		config = vsp1_entity_get_pad_config(&brx->entity, cfg,
>  						    sel->which);
>  		if (!config)
>  			return -EINVAL;
>  
> -		mutex_lock(&bru->entity.lock);
> -		sel->r = *bru_get_compose(bru, config, sel->pad);
> -		mutex_unlock(&bru->entity.lock);
> +		mutex_lock(&brx->entity.lock);
> +		sel->r = *brx_get_compose(brx, config, sel->pad);
> +		mutex_unlock(&brx->entity.lock);
>  		return 0;
>  
>  	default:
> @@ -218,25 +218,25 @@ static int bru_get_selection(struct v4l2_subdev *subdev,
>  	}
>  }
>  
> -static int bru_set_selection(struct v4l2_subdev *subdev,
> +static int brx_set_selection(struct v4l2_subdev *subdev,
>  			     struct v4l2_subdev_pad_config *cfg,
>  			     struct v4l2_subdev_selection *sel)
>  {
> -	struct vsp1_bru *bru = to_bru(subdev);
> +	struct vsp1_brx *brx = to_brx(subdev);
>  	struct v4l2_subdev_pad_config *config;
>  	struct v4l2_mbus_framefmt *format;
>  	struct v4l2_rect *compose;
>  	int ret = 0;
>  
> -	if (sel->pad == bru->entity.source_pad)
> +	if (sel->pad == brx->entity.source_pad)
>  		return -EINVAL;
>  
>  	if (sel->target != V4L2_SEL_TGT_COMPOSE)
>  		return -EINVAL;
>  
> -	mutex_lock(&bru->entity.lock);
> +	mutex_lock(&brx->entity.lock);
>  
> -	config = vsp1_entity_get_pad_config(&bru->entity, cfg, sel->which);
> +	config = vsp1_entity_get_pad_config(&brx->entity, cfg, sel->which);
>  	if (!config) {
>  		ret = -EINVAL;
>  		goto done;
> @@ -246,8 +246,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, config,
> -					    bru->entity.source_pad);
> +	format = vsp1_entity_get_pad_format(&brx->entity, config,
> +					    brx->entity.source_pad);
>  	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);
>  
> @@ -255,42 +255,42 @@ static int bru_set_selection(struct v4l2_subdev *subdev,
>  	 * Scaling isn't supported, the compose rectangle size must be identical
>  	 * to the sink format size.
>  	 */
> -	format = vsp1_entity_get_pad_format(&bru->entity, config, sel->pad);
> +	format = vsp1_entity_get_pad_format(&brx->entity, config, sel->pad);
>  	sel->r.width = format->width;
>  	sel->r.height = format->height;
>  
> -	compose = bru_get_compose(bru, config, sel->pad);
> +	compose = brx_get_compose(brx, config, sel->pad);
>  	*compose = sel->r;
>  
>  done:
> -	mutex_unlock(&bru->entity.lock);
> +	mutex_unlock(&brx->entity.lock);
>  	return ret;
>  }
>  
> -static const struct v4l2_subdev_pad_ops bru_pad_ops = {
> +static const struct v4l2_subdev_pad_ops brx_pad_ops = {
>  	.init_cfg = vsp1_entity_init_cfg,
> -	.enum_mbus_code = bru_enum_mbus_code,
> -	.enum_frame_size = bru_enum_frame_size,
> +	.enum_mbus_code = brx_enum_mbus_code,
> +	.enum_frame_size = brx_enum_frame_size,
>  	.get_fmt = vsp1_subdev_get_pad_format,
> -	.set_fmt = bru_set_format,
> -	.get_selection = bru_get_selection,
> -	.set_selection = bru_set_selection,
> +	.set_fmt = brx_set_format,
> +	.get_selection = brx_get_selection,
> +	.set_selection = brx_set_selection,
>  };
>  
> -static const struct v4l2_subdev_ops bru_ops = {
> -	.pad    = &bru_pad_ops,
> +static const struct v4l2_subdev_ops brx_ops = {
> +	.pad    = &brx_pad_ops,
>  };
>  
>  /* -----------------------------------------------------------------------------
>   * VSP1 Entity Operations
>   */
>  
> -static void bru_configure(struct vsp1_entity *entity,
> +static void brx_configure(struct vsp1_entity *entity,
>  			  struct vsp1_pipeline *pipe,
>  			  struct vsp1_dl_list *dl,
>  			  enum vsp1_entity_params params)
>  {
> -	struct vsp1_bru *bru = to_bru(&entity->subdev);
> +	struct vsp1_brx *brx = to_brx(&entity->subdev);
>  	struct v4l2_mbus_framefmt *format;
>  	unsigned int flags;
>  	unsigned int i;
> @@ -298,8 +298,8 @@ static void bru_configure(struct vsp1_entity *entity,
>  	if (params != VSP1_ENTITY_PARAMS_INIT)
>  		return;
>  
> -	format = vsp1_entity_get_pad_format(&bru->entity, bru->entity.config,
> -					    bru->entity.source_pad);
> +	format = vsp1_entity_get_pad_format(&brx->entity, brx->entity.config,
> +					    brx->entity.source_pad);
>  
>  	/*
>  	 * The hardware is extremely flexible but we have no userspace API to
> @@ -313,7 +313,7 @@ static void bru_configure(struct vsp1_entity *entity,
>  	 * format at the pipeline output is premultiplied.
>  	 */
>  	flags = pipe->output ? pipe->output->format.flags : 0;
> -	vsp1_bru_write(bru, dl, VI6_BRU_INCTRL,
> +	vsp1_brx_write(brx, dl, VI6_BRU_INCTRL,
>  		       flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ?
>  		       0 : VI6_BRU_INCTRL_NRM);
>  
> @@ -321,12 +321,12 @@ static void bru_configure(struct vsp1_entity *entity,
>  	 * Set the background position to cover the whole output image and
>  	 * configure its color.
>  	 */
> -	vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_SIZE,
> +	vsp1_brx_write(brx, dl, VI6_BRU_VIRRPF_SIZE,
>  		       (format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) |
>  		       (format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT));
> -	vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_LOC, 0);
> +	vsp1_brx_write(brx, dl, VI6_BRU_VIRRPF_LOC, 0);
>  
> -	vsp1_bru_write(bru, dl, VI6_BRU_VIRRPF_COL, bru->bgcolor |
> +	vsp1_brx_write(brx, dl, VI6_BRU_VIRRPF_COL, brx->bgcolor |
>  		       (0xff << VI6_BRU_VIRRPF_COL_A_SHIFT));
>  
>  	/*
> @@ -336,25 +336,25 @@ static void bru_configure(struct vsp1_entity *entity,
>  	 * unit.
>  	 */
>  	if (entity->type == VSP1_ENTITY_BRU)
> -		vsp1_bru_write(bru, dl, VI6_BRU_ROP,
> +		vsp1_brx_write(brx, dl, VI6_BRU_ROP,
>  			       VI6_BRU_ROP_DSTSEL_BRUIN(1) |
>  			       VI6_BRU_ROP_CROP(VI6_ROP_NOP) |
>  			       VI6_BRU_ROP_AROP(VI6_ROP_NOP));
>  
> -	for (i = 0; i < bru->entity.source_pad; ++i) {
> +	for (i = 0; i < brx->entity.source_pad; ++i) {
>  		bool premultiplied = false;
>  		u32 ctrl = 0;
>  
>  		/*
> -		 * Configure all Blend/ROP units corresponding to an enabled BRU
> +		 * Configure all Blend/ROP units corresponding to an enabled BRx
>  		 * input for alpha blending. Blend/ROP units corresponding to
> -		 * disabled BRU inputs are used in ROP NOP mode to ignore the
> +		 * disabled BRx inputs are used in ROP NOP mode to ignore the
>  		 * SRC input.
>  		 */
> -		if (bru->inputs[i].rpf) {
> +		if (brx->inputs[i].rpf) {
>  			ctrl |= VI6_BRU_CTRL_RBC;
>  
> -			premultiplied = bru->inputs[i].rpf->format.flags
> +			premultiplied = brx->inputs[i].rpf->format.flags
>  				      & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA;
>  		} else {
>  			ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP)
> @@ -378,7 +378,7 @@ static void bru_configure(struct vsp1_entity *entity,
>  		if (!(entity->type == VSP1_ENTITY_BRU && i == 1))
>  			ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i);
>  
> -		vsp1_bru_write(bru, dl, VI6_BRU_CTRL(i), ctrl);
> +		vsp1_brx_write(brx, dl, VI6_BRU_CTRL(i), ctrl);
>  
>  		/*
>  		 * Harcode the blending formula to
> @@ -393,7 +393,7 @@ static void bru_configure(struct vsp1_entity *entity,
>  		 *
>  		 * otherwise.
>  		 */
> -		vsp1_bru_write(bru, dl, VI6_BRU_BLD(i),
> +		vsp1_brx_write(brx, dl, VI6_BRU_BLD(i),
>  			       VI6_BRU_BLD_CCMDX_255_SRC_A |
>  			       (premultiplied ? VI6_BRU_BLD_CCMDY_COEFY :
>  						VI6_BRU_BLD_CCMDY_SRC_A) |
> @@ -403,29 +403,29 @@ static void bru_configure(struct vsp1_entity *entity,
>  	}
>  }
>  
> -static const struct vsp1_entity_operations bru_entity_ops = {
> -	.configure = bru_configure,
> +static const struct vsp1_entity_operations brx_entity_ops = {
> +	.configure = brx_configure,
>  };
>  
>  /* -----------------------------------------------------------------------------
>   * Initialization and Cleanup
>   */
>  
> -struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1,
> +struct vsp1_brx *vsp1_brx_create(struct vsp1_device *vsp1,
>  				 enum vsp1_entity_type type)
>  {
> -	struct vsp1_bru *bru;
> +	struct vsp1_brx *brx;
>  	unsigned int num_pads;
>  	const char *name;
>  	int ret;
>  
> -	bru = devm_kzalloc(vsp1->dev, sizeof(*bru), GFP_KERNEL);
> -	if (bru == NULL)
> +	brx = devm_kzalloc(vsp1->dev, sizeof(*brx), GFP_KERNEL);
> +	if (brx == NULL)
>  		return ERR_PTR(-ENOMEM);
>  
> -	bru->base = type == VSP1_ENTITY_BRU ? VI6_BRU_BASE : VI6_BRS_BASE;
> -	bru->entity.ops = &bru_entity_ops;
> -	bru->entity.type = type;
> +	brx->base = type == VSP1_ENTITY_BRU ? VI6_BRU_BASE : VI6_BRS_BASE;
> +	brx->entity.ops = &brx_entity_ops;
> +	brx->entity.type = type;
>  
>  	if (type == VSP1_ENTITY_BRU) {
>  		num_pads = vsp1->info->num_bru_inputs + 1;
> @@ -435,26 +435,26 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1,
>  		name = "brs";
>  	}
>  
> -	ret = vsp1_entity_init(vsp1, &bru->entity, name, num_pads, &bru_ops,
> +	ret = vsp1_entity_init(vsp1, &brx->entity, name, num_pads, &brx_ops,
>  			       MEDIA_ENT_F_PROC_VIDEO_COMPOSER);
>  	if (ret < 0)
>  		return ERR_PTR(ret);
>  
>  	/* Initialize the control handler. */
> -	v4l2_ctrl_handler_init(&bru->ctrls, 1);
> -	v4l2_ctrl_new_std(&bru->ctrls, &bru_ctrl_ops, V4L2_CID_BG_COLOR,
> +	v4l2_ctrl_handler_init(&brx->ctrls, 1);
> +	v4l2_ctrl_new_std(&brx->ctrls, &brx_ctrl_ops, V4L2_CID_BG_COLOR,
>  			  0, 0xffffff, 1, 0);
>  
> -	bru->bgcolor = 0;
> +	brx->bgcolor = 0;
>  
> -	bru->entity.subdev.ctrl_handler = &bru->ctrls;
> +	brx->entity.subdev.ctrl_handler = &brx->ctrls;
>  
> -	if (bru->ctrls.error) {
> +	if (brx->ctrls.error) {
>  		dev_err(vsp1->dev, "%s: failed to initialize controls\n", name);
> -		ret = bru->ctrls.error;
> -		vsp1_entity_destroy(&bru->entity);
> +		ret = brx->ctrls.error;
> +		vsp1_entity_destroy(&brx->entity);
>  		return ERR_PTR(ret);
>  	}
>  
> -	return bru;
> +	return brx;
>  }
> diff --git a/drivers/media/platform/vsp1/vsp1_bru.h b/drivers/media/platform/vsp1/vsp1_brx.h
> similarity index 66%
> rename from drivers/media/platform/vsp1/vsp1_bru.h
> rename to drivers/media/platform/vsp1/vsp1_brx.h
> index c98ed96d8de6..927aa4254c0f 100644
> --- a/drivers/media/platform/vsp1/vsp1_bru.h
> +++ b/drivers/media/platform/vsp1/vsp1_brx.h
> @@ -1,5 +1,5 @@
>  /*
> - * vsp1_bru.h  --  R-Car VSP1 Blend ROP Unit
> + * vsp1_brx.h  --  R-Car VSP1 Blend ROP Unit (BRU and BRS)
>   *
>   * Copyright (C) 2013 Renesas Corporation
>   *
> @@ -10,8 +10,8 @@
>   * the Free Software Foundation; either version 2 of the License, or
>   * (at your option) any later version.
>   */
> -#ifndef __VSP1_BRU_H__
> -#define __VSP1_BRU_H__
> +#ifndef __VSP1_BRX_H__
> +#define __VSP1_BRX_H__
>  
>  #include <media/media-entity.h>
>  #include <media/v4l2-ctrls.h>
> @@ -22,9 +22,9 @@
>  struct vsp1_device;
>  struct vsp1_rwpf;
>  
> -#define BRU_PAD_SINK(n)				(n)
> +#define BRX_PAD_SINK(n)				(n)
>  
> -struct vsp1_bru {
> +struct vsp1_brx {
>  	struct vsp1_entity entity;
>  	unsigned int base;
>  
> @@ -37,12 +37,12 @@ struct vsp1_bru {
>  	u32 bgcolor;
>  };
>  
> -static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev)
> +static inline struct vsp1_brx *to_brx(struct v4l2_subdev *subdev)
>  {
> -	return container_of(subdev, struct vsp1_bru, entity.subdev);
> +	return container_of(subdev, struct vsp1_brx, entity.subdev);
>  }
>  
> -struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1,
> +struct vsp1_brx *vsp1_brx_create(struct vsp1_device *vsp1,
>  				 enum vsp1_entity_type type);
>  
> -#endif /* __VSP1_BRU_H__ */
> +#endif /* __VSP1_BRX_H__ */
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c
> index 521bbc227110..50496343bbdb 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.c
> +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> @@ -20,14 +20,14 @@
>  #include <media/vsp1.h>
>  
>  #include "vsp1.h"
> -#include "vsp1_bru.h"
> +#include "vsp1_brx.h"
>  #include "vsp1_dl.h"
>  #include "vsp1_drm.h"
>  #include "vsp1_lif.h"
>  #include "vsp1_pipe.h"
>  #include "vsp1_rwpf.h"
>  
> -#define BRU_NAME(e)	(e)->type == VSP1_ENTITY_BRU ? "BRU" : "BRS"
> +#define BRX_NAME(e)	(e)->type == VSP1_ENTITY_BRU ? "BRU" : "BRS"
>  
>  /* -----------------------------------------------------------------------------
>   * Interrupt Handling
> @@ -43,7 +43,7 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
>  				      completed && !notify);
>  
>  	if (notify) {
> -		drm_pipe->force_bru_release = false;
> +		drm_pipe->force_brx_release = false;
>  		wake_up(&drm_pipe->wait_queue);
>  	}
>  }
> @@ -52,11 +52,11 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
>   * Pipeline Configuration
>   */
>  
> -/* Setup one RPF and the connected BRU sink pad. */
> +/* Setup one RPF and the connected BRx sink pad. */
>  static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
>  				      struct vsp1_pipeline *pipe,
>  				      struct vsp1_rwpf *rpf,
> -				      unsigned int bru_input)
> +				      unsigned int brx_input)
>  {
>  	struct v4l2_subdev_selection sel;
>  	struct v4l2_subdev_format format;
> @@ -65,7 +65,7 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
>  
>  	/*
>  	 * Configure the format on the RPF sink pad and propagate it up to the
> -	 * BRU sink pad.
> +	 * BRx sink pad.
>  	 */
>  	crop = &vsp1->drm->inputs[rpf->entity.index].crop;
>  
> @@ -126,114 +126,114 @@ static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1,
>  	if (ret < 0)
>  		return ret;
>  
> -	/* BRU sink, propagate the format from the RPF source. */
> -	format.pad = bru_input;
> +	/* BRx sink, propagate the format from the RPF source. */
> +	format.pad = brx_input;
>  
> -	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
> +	ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_fmt, NULL,
>  			       &format);
>  	if (ret < 0)
>  		return ret;
>  
>  	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
>  		__func__, format.format.width, format.format.height,
> -		format.format.code, BRU_NAME(pipe->bru), format.pad);
> +		format.format.code, BRX_NAME(pipe->brx), format.pad);
>  
> -	sel.pad = bru_input;
> +	sel.pad = brx_input;
>  	sel.target = V4L2_SEL_TGT_COMPOSE;
>  	sel.r = vsp1->drm->inputs[rpf->entity.index].compose;
>  
> -	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL,
> +	ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_selection, NULL,
>  			       &sel);
>  	if (ret < 0)
>  		return ret;
>  
>  	dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n",
>  		__func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height,
> -		BRU_NAME(pipe->bru), sel.pad);
> +		BRX_NAME(pipe->brx), sel.pad);
>  
>  	return 0;
>  }
>  
> -/* Setup the BRU source pad. */
> +/* Setup the BRx source pad. */
>  static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  					struct vsp1_pipeline *pipe);
>  static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe);
>  
> -static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
> +static int vsp1_du_pipeline_setup_brx(struct vsp1_device *vsp1,
>  				      struct vsp1_pipeline *pipe)
>  {
>  	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
>  	struct v4l2_subdev_format format = {
>  		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
>  	};
> -	struct vsp1_entity *bru;
> +	struct vsp1_entity *brx;
>  	int ret;
>  
>  	/*
> -	 * Pick a BRU:
> -	 * - If we need more than two inputs, use the main BRU.
> -	 * - Otherwise, if we are not forced to release our BRU, keep it.
> -	 * - Else, use any free BRU (randomly starting with the main BRU).
> +	 * Pick a BRx:
> +	 * - If we need more than two inputs, use the BRU.
> +	 * - Otherwise, if we are not forced to release our BRx, keep it.
> +	 * - Else, use any free BRx (randomly starting with the BRU).
>  	 */
>  	if (pipe->num_inputs > 2)
> -		bru = &vsp1->bru->entity;
> -	else if (pipe->bru && !drm_pipe->force_bru_release)
> -		bru = pipe->bru;
> +		brx = &vsp1->bru->entity;
> +	else if (pipe->brx && !drm_pipe->force_brx_release)
> +		brx = pipe->brx;
>  	else if (!vsp1->bru->entity.pipe)
> -		bru = &vsp1->bru->entity;
> +		brx = &vsp1->bru->entity;
>  	else
> -		bru = &vsp1->brs->entity;
> +		brx = &vsp1->brs->entity;
>  
> -	/* Switch BRU if needed. */
> -	if (bru != pipe->bru) {
> -		struct vsp1_entity *released_bru = NULL;
> +	/* Switch BRx if needed. */
> +	if (brx != pipe->brx) {
> +		struct vsp1_entity *released_brx = NULL;
>  
> -		/* Release our BRU if we have one. */
> -		if (pipe->bru) {
> +		/* Release our BRx if we have one. */
> +		if (pipe->brx) {
>  			dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
>  				__func__, pipe->lif->index,
> -				BRU_NAME(pipe->bru));
> +				BRX_NAME(pipe->brx));
>  
>  			/*
> -			 * The BRU might be acquired by the other pipeline in
> +			 * The BRx might be acquired by the other pipeline in
>  			 * the next step. We must thus remove it from the list
>  			 * of entities for this pipeline. The other pipeline's
> -			 * hardware configuration will reconfigure the BRU
> +			 * hardware configuration will reconfigure the BRx
>  			 * routing.
>  			 *
>  			 * However, if the other pipeline doesn't acquire our
> -			 * BRU, we need to keep it in the list, otherwise the
> +			 * BRx, we need to keep it in the list, otherwise the
>  			 * hardware configuration step won't disconnect it from
> -			 * the pipeline. To solve this, store the released BRU
> +			 * the pipeline. To solve this, store the released BRx
>  			 * pointer to add it back to the list of entities later
>  			 * if it isn't acquired by the other pipeline.
>  			 */
> -			released_bru = pipe->bru;
> +			released_brx = pipe->brx;
>  
> -			list_del(&pipe->bru->list_pipe);
> -			pipe->bru->sink = NULL;
> -			pipe->bru->pipe = NULL;
> -			pipe->bru = NULL;
> +			list_del(&pipe->brx->list_pipe);
> +			pipe->brx->sink = NULL;
> +			pipe->brx->pipe = NULL;
> +			pipe->brx = NULL;
>  		}
>  
>  		/*
> -		 * If the BRU we need is in use, force the owner pipeline to
> -		 * switch to the other BRU and wait until the switch completes.
> +		 * If the BRx we need is in use, force the owner pipeline to
> +		 * switch to the other BRx and wait until the switch completes.
>  		 */
> -		if (bru->pipe) {
> +		if (brx->pipe) {
>  			struct vsp1_drm_pipeline *owner_pipe;
>  
>  			dev_dbg(vsp1->dev, "%s: pipe %u: waiting for %s\n",
> -				__func__, pipe->lif->index, BRU_NAME(bru));
> +				__func__, pipe->lif->index, BRX_NAME(brx));
>  
> -			owner_pipe = to_vsp1_drm_pipeline(bru->pipe);
> -			owner_pipe->force_bru_release = true;
> +			owner_pipe = to_vsp1_drm_pipeline(brx->pipe);
> +			owner_pipe->force_brx_release = true;
>  
>  			vsp1_du_pipeline_setup_input(vsp1, &owner_pipe->pipe);
>  			vsp1_du_pipeline_configure(&owner_pipe->pipe);
>  
>  			ret = wait_event_timeout(owner_pipe->wait_queue,
> -						 !owner_pipe->force_bru_release,
> +						 !owner_pipe->force_brx_release,
>  						 msecs_to_jiffies(500));
>  			if (ret == 0)
>  				dev_warn(vsp1->dev,
> @@ -242,46 +242,46 @@ static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
>  		}
>  
>  		/*
> -		 * If the BRU we have released previously hasn't been acquired
> +		 * If the BRx we have released previously hasn't been acquired
>  		 * by the other pipeline, add it back to the entities list (with
>  		 * the pipe pointer NULL) to let vsp1_du_pipeline_configure()
>  		 * disconnect it from the hardware pipeline.
>  		 */
> -		if (released_bru && !released_bru->pipe)
> -			list_add_tail(&released_bru->list_pipe,
> +		if (released_brx && !released_brx->pipe)
> +			list_add_tail(&released_brx->list_pipe,
>  				      &pipe->entities);
>  
> -		/* Add the BRU to the pipeline. */
> +		/* Add the BRx to the pipeline. */
>  		dev_dbg(vsp1->dev, "%s: pipe %u: acquired %s\n",
> -			__func__, pipe->lif->index, BRU_NAME(bru));
> +			__func__, pipe->lif->index, BRX_NAME(brx));
>  
> -		pipe->bru = bru;
> -		pipe->bru->pipe = pipe;
> -		pipe->bru->sink = &pipe->output->entity;
> -		pipe->bru->sink_pad = 0;
> +		pipe->brx = brx;
> +		pipe->brx->pipe = pipe;
> +		pipe->brx->sink = &pipe->output->entity;
> +		pipe->brx->sink_pad = 0;
>  
> -		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
> +		list_add_tail(&pipe->brx->list_pipe, &pipe->entities);
>  	}
>  
>  	/*
> -	 * Configure the format on the BRU source and verify that it matches the
> +	 * Configure the format on the BRx source and verify that it matches the
>  	 * requested format. We don't set the media bus code as it is configured
> -	 * on the BRU sink pad 0 and propagated inside the entity, not on the
> +	 * on the BRx sink pad 0 and propagated inside the entity, not on the
>  	 * source pad.
>  	 */
> -	format.pad = pipe->bru->source_pad;
> +	format.pad = pipe->brx->source_pad;
>  	format.format.width = drm_pipe->width;
>  	format.format.height = drm_pipe->height;
>  	format.format.field = V4L2_FIELD_NONE;
>  
> -	ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL,
> +	ret = v4l2_subdev_call(&pipe->brx->subdev, pad, set_fmt, NULL,
>  			       &format);
>  	if (ret < 0)
>  		return ret;
>  
>  	dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n",
>  		__func__, format.format.width, format.format.height,
> -		format.format.code, BRU_NAME(pipe->bru), pipe->bru->source_pad);
> +		format.format.code, BRX_NAME(pipe->brx), pipe->brx->source_pad);
>  
>  	if (format.format.width != drm_pipe->width ||
>  	    format.format.height != drm_pipe->height) {
> @@ -297,12 +297,12 @@ static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf)
>  	return vsp1->drm->inputs[rpf->entity.index].zpos;
>  }
>  
> -/* Setup the input side of the pipeline (RPFs and BRU). */
> +/* Setup the input side of the pipeline (RPFs and BRx). */
>  static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  					struct vsp1_pipeline *pipe)
>  {
>  	struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, };
> -	struct vsp1_bru *bru;
> +	struct vsp1_brx *brx;
>  	unsigned int i;
>  	int ret;
>  
> @@ -327,25 +327,25 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  	}
>  
>  	/*
> -	 * Setup the BRU. This must be done before setting up the RPF input
> -	 * pipelines as the BRU sink compose rectangles depend on the BRU source
> +	 * Setup the BRx. This must be done before setting up the RPF input
> +	 * pipelines as the BRx sink compose rectangles depend on the BRx source
>  	 * format.
>  	 */
> -	ret = vsp1_du_pipeline_setup_bru(vsp1, pipe);
> +	ret = vsp1_du_pipeline_setup_brx(vsp1, pipe);
>  	if (ret < 0) {
>  		dev_err(vsp1->dev, "%s: failed to setup %s source\n", __func__,
> -			BRU_NAME(pipe->bru));
> +			BRX_NAME(pipe->brx));
>  		return ret;
>  	}
>  
> -	bru = to_bru(&pipe->bru->subdev);
> +	brx = to_brx(&pipe->brx->subdev);
>  
>  	/* Setup the RPF input pipeline for every enabled input. */
> -	for (i = 0; i < pipe->bru->source_pad; ++i) {
> +	for (i = 0; i < pipe->brx->source_pad; ++i) {
>  		struct vsp1_rwpf *rpf = inputs[i];
>  
>  		if (!rpf) {
> -			bru->inputs[i].rpf = NULL;
> +			brx->inputs[i].rpf = NULL;
>  			continue;
>  		}
>  
> @@ -354,13 +354,13 @@ static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
>  			list_add_tail(&rpf->entity.list_pipe, &pipe->entities);
>  		}
>  
> -		bru->inputs[i].rpf = rpf;
> -		rpf->bru_input = i;
> -		rpf->entity.sink = pipe->bru;
> +		brx->inputs[i].rpf = rpf;
> +		rpf->brx_input = i;
> +		rpf->entity.sink = pipe->brx;
>  		rpf->entity.sink_pad = i;
>  
>  		dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n",
> -			__func__, rpf->entity.index, BRU_NAME(pipe->bru), i);
> +			__func__, rpf->entity.index, BRX_NAME(pipe->brx), i);
>  
>  		ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, i);
>  		if (ret < 0) {
> @@ -468,7 +468,7 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
>  		}
>  	}
>  
> -	vsp1_dl_list_commit(dl, drm_pipe->force_bru_release);
> +	vsp1_dl_list_commit(dl, drm_pipe->force_brx_release);
>  }
>  
>  /* -----------------------------------------------------------------------------
> @@ -493,8 +493,8 @@ EXPORT_SYMBOL_GPL(vsp1_du_init);
>   * @cfg: the LIF configuration
>   *
>   * Configure the output part of VSP DRM pipeline for the given frame @cfg.width
> - * and @cfg.height. This sets up formats on the blend unit (BRU or BRS) source
> - * pad, the WPF sink and source pads, and the LIF sink pad.
> + * and @cfg.height. This sets up formats on the BRx source pad, the WPF sink and
> + * source pads, and the LIF sink pad.
>   *
>   * The @pipe_index argument selects which DRM pipeline to setup. The number of
>   * available pipelines depend on the VSP instance.
> @@ -524,11 +524,11 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  	pipe = &drm_pipe->pipe;
>  
>  	if (!cfg) {
> -		struct vsp1_bru *bru;
> +		struct vsp1_brx *brx;
>  
>  		mutex_lock(&vsp1->drm->lock);
>  
> -		bru = to_bru(&pipe->bru->subdev);
> +		brx = to_brx(&pipe->brx->subdev);
>  
>  		/*
>  		 * NULL configuration means the CRTC is being disabled, stop
> @@ -545,7 +545,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  				continue;
>  
>  			/*
> -			 * Remove the RPF from the pipe and the list of BRU
> +			 * Remove the RPF from the pipe and the list of BRx
>  			 * inputs.
>  			 */
>  			WARN_ON(!rpf->entity.pipe);
> @@ -553,7 +553,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  			list_del(&rpf->entity.list_pipe);
>  			pipe->inputs[i] = NULL;
>  
> -			bru->inputs[rpf->bru_input].rpf = NULL;
> +			brx->inputs[rpf->brx_input].rpf = NULL;
>  		}
>  
>  		drm_pipe->du_complete = NULL;
> @@ -561,11 +561,11 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index,
>  
>  		dev_dbg(vsp1->dev, "%s: pipe %u: releasing %s\n",
>  			__func__, pipe->lif->index,
> -			BRU_NAME(pipe->bru));
> +			BRX_NAME(pipe->brx));
>  
> -		list_del(&pipe->bru->list_pipe);
> -		pipe->bru->pipe = NULL;
> -		pipe->bru = NULL;
> +		list_del(&pipe->brx->list_pipe);
> +		pipe->brx->pipe = NULL;
> +		pipe->brx = NULL;
>  
>  		mutex_unlock(&vsp1->drm->lock);
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h
> index c84bc1c456c0..d738cc57f0e3 100644
> --- a/drivers/media/platform/vsp1/vsp1_drm.h
> +++ b/drivers/media/platform/vsp1/vsp1_drm.h
> @@ -24,8 +24,8 @@
>   * @pipe: the VSP1 pipeline used for display
>   * @width: output display width
>   * @height: output display height
> - * @force_bru_release: when set, release the BRU during the next reconfiguration
> - * @wait_queue: wait queue to wait for BRU release completion
> + * @force_brx_release: when set, release the BRx during the next reconfiguration
> + * @wait_queue: wait queue to wait for BRx release completion
>   * @du_complete: frame completion callback for the DU driver (optional)
>   * @du_private: data to be passed to the du_complete callback
>   */
> @@ -35,7 +35,7 @@ struct vsp1_drm_pipeline {
>  	unsigned int width;
>  	unsigned int height;
>  
> -	bool force_bru_release;
> +	bool force_brx_release;
>  	wait_queue_head_t wait_queue;
>  
>  	/* Frame synchronisation */
> diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
> index 58a7993f2306..f41cd70409db 100644
> --- a/drivers/media/platform/vsp1/vsp1_drv.c
> +++ b/drivers/media/platform/vsp1/vsp1_drv.c
> @@ -26,7 +26,7 @@
>  #include <media/v4l2-subdev.h>
>  
>  #include "vsp1.h"
> -#include "vsp1_bru.h"
> +#include "vsp1_brx.h"
>  #include "vsp1_clu.h"
>  #include "vsp1_dl.h"
>  #include "vsp1_drm.h"
> @@ -269,7 +269,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
>  
>  	/* Instantiate all the entities. */
>  	if (vsp1->info->features & VSP1_HAS_BRS) {
> -		vsp1->brs = vsp1_bru_create(vsp1, VSP1_ENTITY_BRS);
> +		vsp1->brs = vsp1_brx_create(vsp1, VSP1_ENTITY_BRS);
>  		if (IS_ERR(vsp1->brs)) {
>  			ret = PTR_ERR(vsp1->brs);
>  			goto done;
> @@ -279,7 +279,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1)
>  	}
>  
>  	if (vsp1->info->features & VSP1_HAS_BRU) {
> -		vsp1->bru = vsp1_bru_create(vsp1, VSP1_ENTITY_BRU);
> +		vsp1->bru = vsp1_brx_create(vsp1, VSP1_ENTITY_BRU);
>  		if (IS_ERR(vsp1->bru)) {
>  			ret = PTR_ERR(vsp1->bru);
>  			goto done;
> diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c
> index 4d819c9019f4..45da3ff10955 100644
> --- a/drivers/media/platform/vsp1/vsp1_pipe.c
> +++ b/drivers/media/platform/vsp1/vsp1_pipe.c
> @@ -20,7 +20,7 @@
>  #include <media/v4l2-subdev.h>
>  
>  #include "vsp1.h"
> -#include "vsp1_bru.h"
> +#include "vsp1_brx.h"
>  #include "vsp1_dl.h"
>  #include "vsp1_entity.h"
>  #include "vsp1_hgo.h"
> @@ -188,11 +188,11 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
>  	struct vsp1_entity *entity;
>  	unsigned int i;
>  
> -	if (pipe->bru) {
> -		struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
> +	if (pipe->brx) {
> +		struct vsp1_brx *brx = to_brx(&pipe->brx->subdev);
>  
> -		for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i)
> -			bru->inputs[i].rpf = NULL;
> +		for (i = 0; i < ARRAY_SIZE(brx->inputs); ++i)
> +			brx->inputs[i].rpf = NULL;
>  	}
>  
>  	for (i = 0; i < ARRAY_SIZE(pipe->inputs); ++i)
> @@ -207,7 +207,7 @@ void vsp1_pipeline_reset(struct vsp1_pipeline *pipe)
>  	pipe->state = VSP1_PIPELINE_STOPPED;
>  	pipe->buffers_ready = 0;
>  	pipe->num_inputs = 0;
> -	pipe->bru = NULL;
> +	pipe->brx = NULL;
>  	pipe->hgo = NULL;
>  	pipe->hgt = NULL;
>  	pipe->lif = NULL;
> diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h b/drivers/media/platform/vsp1/vsp1_pipe.h
> index 482711024fa2..9eca9fe16724 100644
> --- a/drivers/media/platform/vsp1/vsp1_pipe.h
> +++ b/drivers/media/platform/vsp1/vsp1_pipe.h
> @@ -99,7 +99,7 @@ struct vsp1_partition {
>   * @num_inputs: number of RPFs
>   * @inputs: array of RPFs in the pipeline (indexed by RPF index)
>   * @output: WPF at the output of the pipeline
> - * @bru: BRU entity, if present
> + * @brx: BRx entity, if present
>   * @hgo: HGO entity, if present
>   * @hgt: HGT entity, if present
>   * @lif: LIF entity, if present
> @@ -130,7 +130,7 @@ struct vsp1_pipeline {
>  	unsigned int num_inputs;
>  	struct vsp1_rwpf *inputs[VSP1_MAX_RPF];
>  	struct vsp1_rwpf *output;
> -	struct vsp1_entity *bru;
> +	struct vsp1_entity *brx;
>  	struct vsp1_entity *hgo;
>  	struct vsp1_entity *hgt;
>  	struct vsp1_entity *lif;
> diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
> index fe0633da5a5f..7e74c2015070 100644
> --- a/drivers/media/platform/vsp1/vsp1_rpf.c
> +++ b/drivers/media/platform/vsp1/vsp1_rpf.c
> @@ -167,12 +167,12 @@ static void rpf_configure(struct vsp1_entity *entity,
>  	vsp1_rpf_write(rpf, dl, VI6_RPF_DSWAP, fmtinfo->swap);
>  
>  	/* Output location */
> -	if (pipe->bru) {
> +	if (pipe->brx) {
>  		const struct v4l2_rect *compose;
>  
> -		compose = vsp1_entity_get_pad_selection(pipe->bru,
> -							pipe->bru->config,
> -							rpf->bru_input,
> +		compose = vsp1_entity_get_pad_selection(pipe->brx,
> +							pipe->brx->config,
> +							rpf->brx_input,
>  							V4L2_SEL_TGT_COMPOSE);
>  		left = compose->left;
>  		top = compose->top;
> @@ -191,10 +191,10 @@ static void rpf_configure(struct vsp1_entity *entity,
>  	 * alpha channel by a fixed global alpha value, and multiply the pixel
>  	 * components to convert the input to premultiplied alpha.
>  	 *
> -	 * As alpha premultiplication is available in the BRU for both Gen2 and
> +	 * As alpha premultiplication is available in the BRx for both Gen2 and
>  	 * Gen3 we handle it there and use the Gen3 alpha multiplier for global
>  	 * alpha multiplication only. This however prevents conversion to
> -	 * premultiplied alpha if no BRU is present in the pipeline. If that use
> +	 * premultiplied alpha if no BRx is present in the pipeline. If that use
>  	 * case turns out to be useful we will revisit the implementation (for
>  	 * Gen3 only).
>  	 *
> diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
> index c94ac89abfa7..915aeadb21dd 100644
> --- a/drivers/media/platform/vsp1/vsp1_rwpf.h
> +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
> @@ -45,7 +45,7 @@ struct vsp1_rwpf {
>  
>  	struct v4l2_pix_format_mplane format;
>  	const struct vsp1_format_info *fmtinfo;
> -	unsigned int bru_input;
> +	unsigned int brx_input;
>  
>  	unsigned int alpha;
>  
> diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
> index 483b4259e1b4..1958d241d19b 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.c
> +++ b/drivers/media/platform/vsp1/vsp1_video.c
> @@ -28,7 +28,7 @@
>  #include <media/videobuf2-dma-contig.h>
>  
>  #include "vsp1.h"
> -#include "vsp1_bru.h"
> +#include "vsp1_brx.h"
>  #include "vsp1_dl.h"
>  #include "vsp1_entity.h"
>  #include "vsp1_hgo.h"
> @@ -488,7 +488,7 @@ static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
>  	struct media_entity_enum ent_enum;
>  	struct vsp1_entity *entity;
>  	struct media_pad *pad;
> -	struct vsp1_bru *bru = NULL;
> +	struct vsp1_brx *brx = NULL;
>  	int ret;
>  
>  	ret = media_entity_enum_init(&ent_enum, &input->entity.vsp1->media_dev);
> @@ -524,14 +524,14 @@ static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
>  		if (entity->type == VSP1_ENTITY_BRU ||
>  		    entity->type == VSP1_ENTITY_BRS) {
>  			/* BRU and BRS can't be chained. */
> -			if (bru) {
> +			if (brx) {
>  				ret = -EPIPE;
>  				goto out;
>  			}
>  
> -			bru = to_bru(&entity->subdev);
> -			bru->inputs[pad->index].rpf = input;
> -			input->bru_input = pad->index;
> +			brx = to_brx(&entity->subdev);
> +			brx->inputs[pad->index].rpf = input;
> +			input->brx_input = pad->index;
>  		}
>  
>  		/* We've reached the WPF, we're done. */
> @@ -553,7 +553,7 @@ static int vsp1_video_pipeline_build_branch(struct vsp1_pipeline *pipe,
>  			}
>  
>  			pipe->uds = entity;
> -			pipe->uds_input = bru ? &bru->entity : &input->entity;
> +			pipe->uds_input = brx ? &brx->entity : &input->entity;
>  		}
>  
>  		/* Follow the source link, ignoring any HGO or HGT. */
> @@ -619,7 +619,7 @@ static int vsp1_video_pipeline_build(struct vsp1_pipeline *pipe,
>  
>  		case VSP1_ENTITY_BRU:
>  		case VSP1_ENTITY_BRS:
> -			pipe->bru = e;
> +			pipe->brx = e;
>  			break;
>  
>  		case VSP1_ENTITY_HGO:
> diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
> index f7f3b4b2c2de..76f2686e292f 100644
> --- a/drivers/media/platform/vsp1/vsp1_wpf.c
> +++ b/drivers/media/platform/vsp1/vsp1_wpf.c
> @@ -436,7 +436,7 @@ static void wpf_configure(struct vsp1_entity *entity,
>  	vsp1_dl_list_write(dl, VI6_WPF_WRBCK_CTRL, 0);
>  
>  	/*
> -	 * Sources. If the pipeline has a single input and BRU is not used,
> +	 * Sources. If the pipeline has a single input and BRx is not used,
>  	 * configure it as the master layer. Otherwise configure all
>  	 * inputs as sub-layers and select the virtual RPF as the master
>  	 * layer.
> @@ -447,13 +447,13 @@ static void wpf_configure(struct vsp1_entity *entity,
>  		if (!input)
>  			continue;
>  
> -		srcrpf |= (!pipe->bru && pipe->num_inputs == 1)
> +		srcrpf |= (!pipe->brx && pipe->num_inputs == 1)
>  			? VI6_WPF_SRCRPF_RPF_ACT_MST(input->entity.index)
>  			: VI6_WPF_SRCRPF_RPF_ACT_SUB(input->entity.index);
>  	}
>  
> -	if (pipe->bru || pipe->num_inputs > 1)
> -		srcrpf |= pipe->bru->type == VSP1_ENTITY_BRU
> +	if (pipe->brx || pipe->num_inputs > 1)
> +		srcrpf |= pipe->brx->type == VSP1_ENTITY_BRU
>  			? VI6_WPF_SRCRPF_VIRACT_MST
>  			: VI6_WPF_SRCRPF_VIRACT2_MST;
>  
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 10/15] v4l: vsp1: Move DRM pipeline output setup code to a function
  2018-04-04 16:15         ` Kieran Bingham
@ 2018-04-04 21:05           ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-04-04 21:05 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: Laurent Pinchart, linux-media, dri-devel, linux-renesas-soc

Hi Kieran,

On Wednesday, 4 April 2018 19:15:19 EEST Kieran Bingham wrote:
> On 02/04/18 13:35, Laurent Pinchart wrote:
> 
> <snip>
> 
> >>> +/* Setup the output side of the pipeline (WPF and LIF). */
> >>> +static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
> >>> +					 struct vsp1_pipeline *pipe)
> >>> +{
> >>> +	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
> >>> +	struct v4l2_subdev_format format = {
> >>> +		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
> >> 
> >> Why do you initialise this .which here, but all the other member
> >> variables below.
> >> 
> >> Wouldn't it make more sense to group all of this initialisation together?
> >> or is there a distinction in keeping the .which separate.
> >> 
> >> (Perhaps this is just a way to initialise the rest of the structure to 0,
> >> without using the memset?)
> > 
> > The initialization of the .which field is indeed there to avoid the
> > memset, but other than that there's no particular reason. I find it
> > clearer to keep the initialization of the structure close to the code that
> > makes use of it (the next v4l2_subdev_call in this case).
> > 
> > As initializing all members when declaring the variable doesn't make a
> > change in code size (gcc 6.4.0) but increases .rodata by 18 bytes and
> > decreases __modver by the same amount, I'm tempted to leave it as-is
> > unless you think it should be changed.
> 
> I'm happy to leave it as is - the query was as much to understand why the
> change was the way it was :D
> 
> But on that logic (reducing .rodata, or rather not increasing it) what's the
> benefit of initialising with one (random/psuedo random) member variable
> over initialising to all zero, then initialising the .which alongside the
> rest of them? Wouldn't the compiler just use the zero page or such to
> initialise then?

I've just tested that, and it seems to generate the exact same code. I'll 
initialize the structure to 0 when declaring it and move the which field 
initialization with the other fields.

> This way is fine if you are happy with how it reads :D
> 
> >>> +	};
> >>> +	int ret;
> >>> +
> >>> +	format.pad = RWPF_PAD_SINK;
> >>> +	format.format.width = drm_pipe->width;
> >>> +	format.format.height = drm_pipe->height;
> >>> +	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
> >>> +	format.format.field = V4L2_FIELD_NONE;
> >>> +
> >>> +	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt,
> > 
> > NULL,
> > 
> >>> +			       &format);
> >>> +	if (ret < 0)
> >>> +		return ret;
> >>> +

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 10/15] v4l: vsp1: Move DRM pipeline output setup code to a function
@ 2018-04-04 21:05           ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-04-04 21:05 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: linux-renesas-soc, Laurent Pinchart, dri-devel, linux-media

Hi Kieran,

On Wednesday, 4 April 2018 19:15:19 EEST Kieran Bingham wrote:
> On 02/04/18 13:35, Laurent Pinchart wrote:
> 
> <snip>
> 
> >>> +/* Setup the output side of the pipeline (WPF and LIF). */
> >>> +static int vsp1_du_pipeline_setup_output(struct vsp1_device *vsp1,
> >>> +					 struct vsp1_pipeline *pipe)
> >>> +{
> >>> +	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
> >>> +	struct v4l2_subdev_format format = {
> >>> +		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
> >> 
> >> Why do you initialise this .which here, but all the other member
> >> variables below.
> >> 
> >> Wouldn't it make more sense to group all of this initialisation together?
> >> or is there a distinction in keeping the .which separate.
> >> 
> >> (Perhaps this is just a way to initialise the rest of the structure to 0,
> >> without using the memset?)
> > 
> > The initialization of the .which field is indeed there to avoid the
> > memset, but other than that there's no particular reason. I find it
> > clearer to keep the initialization of the structure close to the code that
> > makes use of it (the next v4l2_subdev_call in this case).
> > 
> > As initializing all members when declaring the variable doesn't make a
> > change in code size (gcc 6.4.0) but increases .rodata by 18 bytes and
> > decreases __modver by the same amount, I'm tempted to leave it as-is
> > unless you think it should be changed.
> 
> I'm happy to leave it as is - the query was as much to understand why the
> change was the way it was :D
> 
> But on that logic (reducing .rodata, or rather not increasing it) what's the
> benefit of initialising with one (random/psuedo random) member variable
> over initialising to all zero, then initialising the .which alongside the
> rest of them? Wouldn't the compiler just use the zero page or such to
> initialise then?

I've just tested that, and it seems to generate the exact same code. I'll 
initialize the structure to 0 when declaring it and move the which field 
initialization with the other fields.

> This way is fine if you are happy with how it reads :D
> 
> >>> +	};
> >>> +	int ret;
> >>> +
> >>> +	format.pad = RWPF_PAD_SINK;
> >>> +	format.format.width = drm_pipe->width;
> >>> +	format.format.height = drm_pipe->height;
> >>> +	format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
> >>> +	format.format.field = V4L2_FIELD_NONE;
> >>> +
> >>> +	ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt,
> > 
> > NULL,
> > 
> >>> +			       &format);
> >>> +	if (ret < 0)
> >>> +		return ret;
> >>> +

-- 
Regards,

Laurent Pinchart



_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 11/15] v4l: vsp1: Add per-display list completion notification support
  2018-04-04 16:16     ` Kieran Bingham
@ 2018-04-04 21:43       ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-04-04 21:43 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: Laurent Pinchart, linux-media, dri-devel, linux-renesas-soc

Hi Kieran,

On Wednesday, 4 April 2018 19:16:46 EEST Kieran Bingham wrote:
> On 26/02/18 21:45, Laurent Pinchart wrote:
> > Display list completion is already reported to the frame end handler,
> > but that mechanism is global to all display lists. In order to implement
> > BRU and BRS reassignment in DRM pipelines we will need to wait for
> > completion of a particular display list. Extend the display list and
> > frame end handler APIs to support such a notification.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/media/platform/vsp1/vsp1_dl.c    | 27 +++++++++++++++++++++++++--
> >  drivers/media/platform/vsp1/vsp1_dl.h    |  4 ++--
> >  drivers/media/platform/vsp1/vsp1_drm.c   |  4 ++--
> >  drivers/media/platform/vsp1/vsp1_pipe.c  |  5 +++--
> >  drivers/media/platform/vsp1/vsp1_pipe.h  |  3 ++-
> >  drivers/media/platform/vsp1/vsp1_video.c |  4 ++--
> >  6 files changed, 36 insertions(+), 11 deletions(-)
> > 
> > diff --git a/drivers/media/platform/vsp1/vsp1_dl.c
> > b/drivers/media/platform/vsp1/vsp1_dl.c index 0b86ed01e85d..eb2971218e28
> > 100644
> > --- a/drivers/media/platform/vsp1/vsp1_dl.c
> > +++ b/drivers/media/platform/vsp1/vsp1_dl.c
> > @@ -72,6 +72,7 @@ struct vsp1_dl_body {
> >   * @fragments: list of extra display list bodies
> >   * @has_chain: if true, indicates that there's a partition chain
> >   * @chain: entry in the display list partition chain
> > + * @notify: whether the display list completion should be notified
> >   */
> >  struct vsp1_dl_list {
> >  	struct list_head list;
> > @@ -85,6 +86,8 @@ struct vsp1_dl_list {
> >  	bool has_chain;
> >  	struct list_head chain;
> > +
> > +	bool notify;
> >  };
> >  
> >  enum vsp1_dl_mode {
> > @@ -550,8 +553,16 @@ static void vsp1_dl_list_commit_continuous(struct
> > vsp1_dl_list *dl)> 
> >  	 * case we can't replace the queued list by the new one, as we could
> >  	 * race with the hardware. We thus mark the update as pending, it will
> >  	 * be queued up to the hardware by the frame end interrupt handler.
> > +	 *
> > +	 * If a display list is already pending we simply drop it as the new
> > +	 * display list is assumed to contain a more recent configuration. It
> > is
> > +	 * an error if the already pending list has the notify flag set, as
> > +	 * there is then a process waiting for that list to complete. This
> > +	 * shouldn't happen as the waiting process should perform proper
> > +	 * locking, but warn just in case.
> >  	 */
> >  	if (vsp1_dl_list_hw_update_pending(dlm)) {
> > +		WARN_ON(dlm->pending && dlm->pending->notify);
> >  		__vsp1_dl_list_put(dlm->pending);
> >  		dlm->pending = dl;
> > 
> > @@ -581,7 +592,7 @@ static void vsp1_dl_list_commit_singleshot(struct
> > vsp1_dl_list *dl)
> >  	dlm->active = dl;
> >  }
> > 
> > -void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
> > +void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool notify)
> 
> Rather than changing the vsp1_dl_list_commit() function - would it be nicer
> to have an API to request or set the notify property? :
> 
> @@..@@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
> ...
> +	/* The BRx will be released, without sending an update to DRM */
> +	if (drm_pipe->force_bru_release)
> +		vsp1_dl_list_request_internal_notify(dl);
> 
> 	vsp1_dl_list_commit(dl);
> ...

That's not a bad idea, but I wonder if it's worth it as we'll have to call an 
extra function for what is essentially an internal API. On the other hand this 
isn't a common case, so it's not a hot code path. We could also argue equally 
that it is the commit that is internal or that it is the display list that is 
for internal purpose. Do you think an extra function call is better ? If you 
do I'll change it.

> >  {
> >  	struct vsp1_dl_manager *dlm = dl->dlm;
> >  	struct vsp1_dl_list *dl_child;
> > @@ -598,6 +609,8 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
> >  		}
> >  	}
> > 
> > +	dl->notify = notify;
> > +
> >  	spin_lock_irqsave(&dlm->lock, flags);
> >  	
> >  	if (dlm->singleshot)
> > @@ -615,16 +628,23 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
> >  /**
> >   * vsp1_dlm_irq_frame_end - Display list handler for the frame end
> >   interrupt
> >   * @dlm: the display list manager
> > + * @notify: whether the display list that completed has notification
> > enabled
> >   *
> >   * Return true if the previous display list has completed at frame end,
> >   or false
> >   * if it has been delayed by one frame because the display list commit
> >   raced
> >   * with the frame end interrupt. The function always returns true in
> >   header mode
> >   * as display list processing is then not continuous and races never
> >   occur.
> > + *
> > + * Upon return, the @notify parameter is set to true if the previous
> > display
> > + * list has completed and had been queued with the notify flag, or to
> > false
> > + * otherwise. Notification is only supported for continuous mode.
> >   */
> > -bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
> > +bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm, bool *notify)
> >  {
> >  	bool completed = false;
> > 
> > +	*notify = false;
> > +
> >  	spin_lock(&dlm->lock);
> >  	
> >  	/*
> > @@ -652,6 +672,9 @@ bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager
> > *dlm)
> >  	 * frame end interrupt. The display list thus becomes active.
> >  	 */
> >  	if (dlm->queued) {
> > +		*notify = dlm->queued->notify;
> > +		dlm->queued->notify = false;
> > +
> >  		__vsp1_dl_list_put(dlm->active);
> >  		dlm->active = dlm->queued;
> >  		dlm->queued = NULL;
> > diff --git a/drivers/media/platform/vsp1/vsp1_dl.h
> > b/drivers/media/platform/vsp1/vsp1_dl.h index ee3508172f0a..480c6b0dd2e4
> > 100644
> > --- a/drivers/media/platform/vsp1/vsp1_dl.h
> > +++ b/drivers/media/platform/vsp1/vsp1_dl.h
> > @@ -27,12 +27,12 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct
> > vsp1_device *vsp1,
> >  					unsigned int prealloc);
> >  void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm);
> >  void vsp1_dlm_reset(struct vsp1_dl_manager *dlm);
> > -bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm);
> > +bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm, bool *notify);
> > 
> >  struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm);
> >  void vsp1_dl_list_put(struct vsp1_dl_list *dl);
> >  void vsp1_dl_list_write(struct vsp1_dl_list *dl, u32 reg, u32 data);
> > -void vsp1_dl_list_commit(struct vsp1_dl_list *dl);
> > +void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool notify);
> > 
> >  struct vsp1_dl_body *vsp1_dl_fragment_alloc(struct vsp1_device *vsp1,
> >  					    unsigned int num_entries);
> > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c
> > b/drivers/media/platform/vsp1/vsp1_drm.c index 1c8adda47440..d705a6e9fa1d
> > 100644
> > --- a/drivers/media/platform/vsp1/vsp1_drm.c
> > +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> > @@ -34,7 +34,7 @@
> >   */
> >  
> >  static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
> > -				       bool completed)
> > +				       bool completed, bool notify)
> >  {
> >  	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
> > 
> > @@ -370,7 +370,7 @@ static void vsp1_du_pipeline_configure(struct
> > vsp1_pipeline *pipe)
> >  		}
> >  	}
> > 
> > -	vsp1_dl_list_commit(dl);
> > +	vsp1_dl_list_commit(dl, false);
> >  }
> >  
> >  /* ----------------------------------------------------------------------
> > diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c
> > b/drivers/media/platform/vsp1/vsp1_pipe.c index
> > 99ccbac3256a..4d819c9019f4 100644
> > --- a/drivers/media/platform/vsp1/vsp1_pipe.c
> > +++ b/drivers/media/platform/vsp1/vsp1_pipe.c
> > @@ -316,6 +316,7 @@ bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe)
> >  void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
> >  {
> >  	bool completed;
> > +	bool notify;
> > 
> >  	if (pipe == NULL)
> >  		return;
> > @@ -325,7 +326,7 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline
> > *pipe)
> >  	 * up being postponed by one frame. @completed represents whether the
> >  	 * active frame was finished or postponed.
> >  	 */
> > -	completed = vsp1_dlm_irq_frame_end(pipe->output->dlm);
> > +	completed = vsp1_dlm_irq_frame_end(pipe->output->dlm, &notify);
> 
> Eugh ... two return values, one passed back through the return, and the
> other passed as a pointer.

I don't like it much either :-/

> What about converting this to some flags which get passed into the
> pipe->frame_end() instead?

That's a very good idea, I'll do that.

> >  	if (pipe->hgo)
> >  		vsp1_hgo_frame_end(pipe->hgo);
> > 
> > @@ -338,7 +339,7 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline
> > *pipe)> 
> >  	 * frame_end to account for vblank events.
> >  	 */
> >  	if (pipe->frame_end)
> > -		pipe->frame_end(pipe, completed);
> > +		pipe->frame_end(pipe, completed, notify);
> > 
> >  	pipe->sequence++;
> >  }
> > 
> > diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h
> > b/drivers/media/platform/vsp1/vsp1_pipe.h index
> > dfff9b5685fe..482711024fa2 100644
> > --- a/drivers/media/platform/vsp1/vsp1_pipe.h
> > +++ b/drivers/media/platform/vsp1/vsp1_pipe.h
> > @@ -118,7 +118,8 @@ struct vsp1_pipeline {
> >  	enum vsp1_pipeline_state state;
> >  	wait_queue_head_t wq;
> > 
> > -	void (*frame_end)(struct vsp1_pipeline *pipe, bool completed);
> > +	void (*frame_end)(struct vsp1_pipeline *pipe, bool completed,
> > +			  bool notify);
> > 
> >  	struct mutex lock;
> >  	struct kref kref;
> > diff --git a/drivers/media/platform/vsp1/vsp1_video.c
> > b/drivers/media/platform/vsp1/vsp1_video.c index
> > cdd53d6cc408..483b4259e1b4 100644
> > --- a/drivers/media/platform/vsp1/vsp1_video.c
> > +++ b/drivers/media/platform/vsp1/vsp1_video.c
> > @@ -437,14 +437,14 @@ static void vsp1_video_pipeline_run(struct
> > vsp1_pipeline *pipe)> 
> >  	}
> >  	
> >  	/* Complete, and commit the head display list. */
> > -	vsp1_dl_list_commit(pipe->dl);
> > +	vsp1_dl_list_commit(pipe->dl, false);
> > 
> >  	pipe->dl = NULL;
> >  	
> >  	vsp1_pipeline_run(pipe);
> >  }
> >  
> >  static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe,
> > -					  bool completed)
> > +					  bool completed, bool notify)
> >  {
> >  	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
> >  	enum vsp1_pipeline_state state;

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 11/15] v4l: vsp1: Add per-display list completion notification support
@ 2018-04-04 21:43       ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-04-04 21:43 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: linux-renesas-soc, Laurent Pinchart, dri-devel, linux-media

Hi Kieran,

On Wednesday, 4 April 2018 19:16:46 EEST Kieran Bingham wrote:
> On 26/02/18 21:45, Laurent Pinchart wrote:
> > Display list completion is already reported to the frame end handler,
> > but that mechanism is global to all display lists. In order to implement
> > BRU and BRS reassignment in DRM pipelines we will need to wait for
> > completion of a particular display list. Extend the display list and
> > frame end handler APIs to support such a notification.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/media/platform/vsp1/vsp1_dl.c    | 27 +++++++++++++++++++++++++--
> >  drivers/media/platform/vsp1/vsp1_dl.h    |  4 ++--
> >  drivers/media/platform/vsp1/vsp1_drm.c   |  4 ++--
> >  drivers/media/platform/vsp1/vsp1_pipe.c  |  5 +++--
> >  drivers/media/platform/vsp1/vsp1_pipe.h  |  3 ++-
> >  drivers/media/platform/vsp1/vsp1_video.c |  4 ++--
> >  6 files changed, 36 insertions(+), 11 deletions(-)
> > 
> > diff --git a/drivers/media/platform/vsp1/vsp1_dl.c
> > b/drivers/media/platform/vsp1/vsp1_dl.c index 0b86ed01e85d..eb2971218e28
> > 100644
> > --- a/drivers/media/platform/vsp1/vsp1_dl.c
> > +++ b/drivers/media/platform/vsp1/vsp1_dl.c
> > @@ -72,6 +72,7 @@ struct vsp1_dl_body {
> >   * @fragments: list of extra display list bodies
> >   * @has_chain: if true, indicates that there's a partition chain
> >   * @chain: entry in the display list partition chain
> > + * @notify: whether the display list completion should be notified
> >   */
> >  struct vsp1_dl_list {
> >  	struct list_head list;
> > @@ -85,6 +86,8 @@ struct vsp1_dl_list {
> >  	bool has_chain;
> >  	struct list_head chain;
> > +
> > +	bool notify;
> >  };
> >  
> >  enum vsp1_dl_mode {
> > @@ -550,8 +553,16 @@ static void vsp1_dl_list_commit_continuous(struct
> > vsp1_dl_list *dl)> 
> >  	 * case we can't replace the queued list by the new one, as we could
> >  	 * race with the hardware. We thus mark the update as pending, it will
> >  	 * be queued up to the hardware by the frame end interrupt handler.
> > +	 *
> > +	 * If a display list is already pending we simply drop it as the new
> > +	 * display list is assumed to contain a more recent configuration. It
> > is
> > +	 * an error if the already pending list has the notify flag set, as
> > +	 * there is then a process waiting for that list to complete. This
> > +	 * shouldn't happen as the waiting process should perform proper
> > +	 * locking, but warn just in case.
> >  	 */
> >  	if (vsp1_dl_list_hw_update_pending(dlm)) {
> > +		WARN_ON(dlm->pending && dlm->pending->notify);
> >  		__vsp1_dl_list_put(dlm->pending);
> >  		dlm->pending = dl;
> > 
> > @@ -581,7 +592,7 @@ static void vsp1_dl_list_commit_singleshot(struct
> > vsp1_dl_list *dl)
> >  	dlm->active = dl;
> >  }
> > 
> > -void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
> > +void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool notify)
> 
> Rather than changing the vsp1_dl_list_commit() function - would it be nicer
> to have an API to request or set the notify property? :
> 
> @@..@@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
> ...
> +	/* The BRx will be released, without sending an update to DRM */
> +	if (drm_pipe->force_bru_release)
> +		vsp1_dl_list_request_internal_notify(dl);
> 
> 	vsp1_dl_list_commit(dl);
> ...

That's not a bad idea, but I wonder if it's worth it as we'll have to call an 
extra function for what is essentially an internal API. On the other hand this 
isn't a common case, so it's not a hot code path. We could also argue equally 
that it is the commit that is internal or that it is the display list that is 
for internal purpose. Do you think an extra function call is better ? If you 
do I'll change it.

> >  {
> >  	struct vsp1_dl_manager *dlm = dl->dlm;
> >  	struct vsp1_dl_list *dl_child;
> > @@ -598,6 +609,8 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
> >  		}
> >  	}
> > 
> > +	dl->notify = notify;
> > +
> >  	spin_lock_irqsave(&dlm->lock, flags);
> >  	
> >  	if (dlm->singleshot)
> > @@ -615,16 +628,23 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
> >  /**
> >   * vsp1_dlm_irq_frame_end - Display list handler for the frame end
> >   interrupt
> >   * @dlm: the display list manager
> > + * @notify: whether the display list that completed has notification
> > enabled
> >   *
> >   * Return true if the previous display list has completed at frame end,
> >   or false
> >   * if it has been delayed by one frame because the display list commit
> >   raced
> >   * with the frame end interrupt. The function always returns true in
> >   header mode
> >   * as display list processing is then not continuous and races never
> >   occur.
> > + *
> > + * Upon return, the @notify parameter is set to true if the previous
> > display
> > + * list has completed and had been queued with the notify flag, or to
> > false
> > + * otherwise. Notification is only supported for continuous mode.
> >   */
> > -bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
> > +bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm, bool *notify)
> >  {
> >  	bool completed = false;
> > 
> > +	*notify = false;
> > +
> >  	spin_lock(&dlm->lock);
> >  	
> >  	/*
> > @@ -652,6 +672,9 @@ bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager
> > *dlm)
> >  	 * frame end interrupt. The display list thus becomes active.
> >  	 */
> >  	if (dlm->queued) {
> > +		*notify = dlm->queued->notify;
> > +		dlm->queued->notify = false;
> > +
> >  		__vsp1_dl_list_put(dlm->active);
> >  		dlm->active = dlm->queued;
> >  		dlm->queued = NULL;
> > diff --git a/drivers/media/platform/vsp1/vsp1_dl.h
> > b/drivers/media/platform/vsp1/vsp1_dl.h index ee3508172f0a..480c6b0dd2e4
> > 100644
> > --- a/drivers/media/platform/vsp1/vsp1_dl.h
> > +++ b/drivers/media/platform/vsp1/vsp1_dl.h
> > @@ -27,12 +27,12 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct
> > vsp1_device *vsp1,
> >  					unsigned int prealloc);
> >  void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm);
> >  void vsp1_dlm_reset(struct vsp1_dl_manager *dlm);
> > -bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm);
> > +bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm, bool *notify);
> > 
> >  struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm);
> >  void vsp1_dl_list_put(struct vsp1_dl_list *dl);
> >  void vsp1_dl_list_write(struct vsp1_dl_list *dl, u32 reg, u32 data);
> > -void vsp1_dl_list_commit(struct vsp1_dl_list *dl);
> > +void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool notify);
> > 
> >  struct vsp1_dl_body *vsp1_dl_fragment_alloc(struct vsp1_device *vsp1,
> >  					    unsigned int num_entries);
> > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c
> > b/drivers/media/platform/vsp1/vsp1_drm.c index 1c8adda47440..d705a6e9fa1d
> > 100644
> > --- a/drivers/media/platform/vsp1/vsp1_drm.c
> > +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> > @@ -34,7 +34,7 @@
> >   */
> >  
> >  static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe,
> > -				       bool completed)
> > +				       bool completed, bool notify)
> >  {
> >  	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
> > 
> > @@ -370,7 +370,7 @@ static void vsp1_du_pipeline_configure(struct
> > vsp1_pipeline *pipe)
> >  		}
> >  	}
> > 
> > -	vsp1_dl_list_commit(dl);
> > +	vsp1_dl_list_commit(dl, false);
> >  }
> >  
> >  /* ----------------------------------------------------------------------
> > diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c
> > b/drivers/media/platform/vsp1/vsp1_pipe.c index
> > 99ccbac3256a..4d819c9019f4 100644
> > --- a/drivers/media/platform/vsp1/vsp1_pipe.c
> > +++ b/drivers/media/platform/vsp1/vsp1_pipe.c
> > @@ -316,6 +316,7 @@ bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe)
> >  void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
> >  {
> >  	bool completed;
> > +	bool notify;
> > 
> >  	if (pipe == NULL)
> >  		return;
> > @@ -325,7 +326,7 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline
> > *pipe)
> >  	 * up being postponed by one frame. @completed represents whether the
> >  	 * active frame was finished or postponed.
> >  	 */
> > -	completed = vsp1_dlm_irq_frame_end(pipe->output->dlm);
> > +	completed = vsp1_dlm_irq_frame_end(pipe->output->dlm, &notify);
> 
> Eugh ... two return values, one passed back through the return, and the
> other passed as a pointer.

I don't like it much either :-/

> What about converting this to some flags which get passed into the
> pipe->frame_end() instead?

That's a very good idea, I'll do that.

> >  	if (pipe->hgo)
> >  		vsp1_hgo_frame_end(pipe->hgo);
> > 
> > @@ -338,7 +339,7 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline
> > *pipe)> 
> >  	 * frame_end to account for vblank events.
> >  	 */
> >  	if (pipe->frame_end)
> > -		pipe->frame_end(pipe, completed);
> > +		pipe->frame_end(pipe, completed, notify);
> > 
> >  	pipe->sequence++;
> >  }
> > 
> > diff --git a/drivers/media/platform/vsp1/vsp1_pipe.h
> > b/drivers/media/platform/vsp1/vsp1_pipe.h index
> > dfff9b5685fe..482711024fa2 100644
> > --- a/drivers/media/platform/vsp1/vsp1_pipe.h
> > +++ b/drivers/media/platform/vsp1/vsp1_pipe.h
> > @@ -118,7 +118,8 @@ struct vsp1_pipeline {
> >  	enum vsp1_pipeline_state state;
> >  	wait_queue_head_t wq;
> > 
> > -	void (*frame_end)(struct vsp1_pipeline *pipe, bool completed);
> > +	void (*frame_end)(struct vsp1_pipeline *pipe, bool completed,
> > +			  bool notify);
> > 
> >  	struct mutex lock;
> >  	struct kref kref;
> > diff --git a/drivers/media/platform/vsp1/vsp1_video.c
> > b/drivers/media/platform/vsp1/vsp1_video.c index
> > cdd53d6cc408..483b4259e1b4 100644
> > --- a/drivers/media/platform/vsp1/vsp1_video.c
> > +++ b/drivers/media/platform/vsp1/vsp1_video.c
> > @@ -437,14 +437,14 @@ static void vsp1_video_pipeline_run(struct
> > vsp1_pipeline *pipe)> 
> >  	}
> >  	
> >  	/* Complete, and commit the head display list. */
> > -	vsp1_dl_list_commit(pipe->dl);
> > +	vsp1_dl_list_commit(pipe->dl, false);
> > 
> >  	pipe->dl = NULL;
> >  	
> >  	vsp1_pipeline_run(pipe);
> >  }
> >  
> >  static void vsp1_video_pipeline_frame_end(struct vsp1_pipeline *pipe,
> > -					  bool completed)
> > +					  bool completed, bool notify)
> >  {
> >  	struct vsp1_device *vsp1 = pipe->output->entity.vsp1;
> >  	enum vsp1_pipeline_state state;

-- 
Regards,

Laurent Pinchart



_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 13/15] v4l: vsp1: Assign BRU and BRS to pipelines dynamically
  2018-04-04 16:00     ` Kieran Bingham
@ 2018-04-04 21:57       ` Laurent Pinchart
  -1 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-04-04 21:57 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: Laurent Pinchart, linux-media, dri-devel, linux-renesas-soc

Hi Kieran,

On Wednesday, 4 April 2018 19:00:10 EEST Kieran Bingham wrote:
> Hi Laurent,
> 
> Thank you for the patch.
> 
> I don't envy you on having to deal with this one ... it's a bit of a pain
> ...

Yes it was a bit painful :-/ The devil was both in the big picture and the 
details this time.

> On 26/02/18 21:45, Laurent Pinchart wrote:
> > The VSPDL variant drives two DU channels through two LIF and two
> > blenders, BRU and BRS. The DU channels thus share the five available
> > VSPDL inputs and expose them as five KMS planes.
> > 
> > The current implementation assigns the BRS to the second LIF and thus
> > artificially limits the number of planes for the second display channel
> > to two at most.
> > 
> > Lift this artificial limitation by assigning the BRU and BRS to the
> > display pipelines on demand based on the number of planes used by each
> > pipeline. When a display pipeline needs more than two inputs and the BRU
> > is already in use by the other pipeline, this requires reconfiguring the
> > other pipeline to free the BRU before processing, which can result in
> > frame drop on both pipelines.
> 
> So this is a hard one!
>  - Having to dynamically reconfigure "someone else's" pipes ...
> 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> Except for the recursion, which is unavoidable, and the lock handling across
> function calls which is ... unavoidable I think as well (at least for the
> moment), my only quibble is the naming of the 'notify' variable, which is
> not particularly clear in terms of who it notifies. (Internal, vs DRM)
> 
> I'll leave it up to you to decide whether or not to rename it though, and if
> you're happy with the naming then fine.

I agree with you, please see below.

> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> 
> > ---
> > 
> >  drivers/media/platform/vsp1/vsp1_drm.c | 160 ++++++++++++++++++++++------
> >  drivers/media/platform/vsp1/vsp1_drm.h |   9 ++
> >  2 files changed, 144 insertions(+), 25 deletions(-)
> > 
> > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c
> > b/drivers/media/platform/vsp1/vsp1_drm.c index 6c60b72b6f50..87e31ba0ddf5
> > 100644
> > --- a/drivers/media/platform/vsp1/vsp1_drm.c
> > +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> > @@ -39,7 +39,13 @@ static void vsp1_du_pipeline_frame_end(struct
> > vsp1_pipeline *pipe,> 
> >  	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
> >  	
> >  	if (drm_pipe->du_complete)
> > 
> > -		drm_pipe->du_complete(drm_pipe->du_private, completed);
> > +		drm_pipe->du_complete(drm_pipe->du_private,
> > +				      completed && !notify);
> > +
> > +	if (notify) {
> > +		drm_pipe->force_bru_release = false;
> > +		wake_up(&drm_pipe->wait_queue);
> > +	}
> 
> Notify seems such a nondescript verb to use here, and confuses me against
> who we are notifying  - and why (it's an internal notification, but notify
> makes me think we are 'notifying' the DU - which is exactly the opposite).
> 
> (Perhaps this is actually a comment for the previous patch, but I've gone
> out-of-order, due to the complexities here...)
> 
> Could this be 'internal', 'released' or 'reconfigured', or something to
> distinguish that this frame-end is not a normal frame-completion event ?

I think internal is a better name than notify. I'll pick that.

> >  }
> >  
> >  /* ----------------------------------------------------------------------
> > @@ -149,6 +155,10 @@ static int vsp1_du_pipeline_setup_rpf(struct
> > vsp1_device *vsp1,
> >  }
> >  
> >  /* Setup the BRU source pad. */
> > +static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
> > +					struct vsp1_pipeline *pipe);
> > +static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe);
> > +
> 
> Ohhh lovely, recursion...
> Ohhh lovely, recursion...

I wanted to avoid it but haven't found a better way.

> >  static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
> >  				      struct vsp1_pipeline *pipe)
> >  {
> > @@ -156,8 +166,93 @@ static int vsp1_du_pipeline_setup_bru(struct
> > vsp1_device *vsp1,
> >  	struct v4l2_subdev_format format = {
> >  		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
> >  	};
> > +	struct vsp1_entity *bru;
> >  	int ret;
> > 
> > +	/*
> > +	 * Pick a BRU:
> > +	 * - If we need more than two inputs, use the main BRU.
> > +	 * - Otherwise, if we are not forced to release our BRU, keep it.
> > +	 * - Else, use any free BRU (randomly starting with the main BRU).
> > +	 */
> > +	if (pipe->num_inputs > 2)
> > +		bru = &vsp1->bru->entity;
> > +	else if (pipe->bru && !drm_pipe->force_bru_release)
> > +		bru = pipe->bru;
> > +	else if (!vsp1->bru->entity.pipe)
> > +		bru = &vsp1->bru->entity;
> > +	else
> > +		bru = &vsp1->brs->entity;
> 
> Ok - that tooks some iterations to go through - but I think it covers all
> the bases.
> 
> > +
> > +	/* Switch BRU if needed. */
> > +	if (bru != pipe->bru) {
> > +		struct vsp1_entity *released_bru = NULL;
> > +
> > +		/* Release our BRU if we have one. */
> > +		if (pipe->bru) {
> > +			/*
> > +			 * The BRU might be acquired by the other pipeline in
> > +			 * the next step. We must thus remove it from the list
> > +			 * of entities for this pipeline. The other pipeline's
> > +			 * hardware configuration will reconfigure the BRU
> > +			 * routing.
> > +			 *
> > +			 * However, if the other pipeline doesn't acquire our
> > +			 * BRU, we need to keep it in the list, otherwise the
> > +			 * hardware configuration step won't disconnect it from
> > +			 * the pipeline. To solve this, store the released BRU
> > +			 * pointer to add it back to the list of entities later
> > +			 * if it isn't acquired by the other pipeline.
> > +			 */
> > +			released_bru = pipe->bru;
> > +
> > +			list_del(&pipe->bru->list_pipe);
> > +			pipe->bru->sink = NULL;
> > +			pipe->bru->pipe = NULL;
> > +			pipe->bru = NULL;
> > +		}
> > +
> > +		/*
> > +		 * If the BRU we need is in use, force the owner pipeline to
> > +		 * switch to the other BRU and wait until the switch completes.
> > +		 */
> > +		if (bru->pipe) {
> > +			struct vsp1_drm_pipeline *owner_pipe;
> > +
> > +			owner_pipe = to_vsp1_drm_pipeline(bru->pipe);
> > +			owner_pipe->force_bru_release = true;
> > +
> > +			vsp1_du_pipeline_setup_input(vsp1, &owner_pipe->pipe);
> > +			vsp1_du_pipeline_configure(&owner_pipe->pipe);
> > +
> > +			ret = wait_event_timeout(owner_pipe->wait_queue,
> > +						 !owner_pipe->force_bru_release,
> > +						 msecs_to_jiffies(500));
> > +			if (ret == 0)
> > +				dev_warn(vsp1->dev,
> > +					 "DRM pipeline %u reconfiguration timeout\n",
> > +					 owner_pipe->pipe.lif->index);
> > +		}
> > +
> > +		/*
> > +		 * If the BRU we have released previously hasn't been acquired
> > +		 * by the other pipeline, add it back to the entities list (with
> > +		 * the pipe pointer NULL) to let vsp1_du_pipeline_configure()
> > +		 * disconnect it from the hardware pipeline.
> > +		 */
> > +		if (released_bru && !released_bru->pipe)
> > +			list_add_tail(&released_bru->list_pipe,
> > +				      &pipe->entities);
> > +
> > +		/* Add the BRU to the pipeline. */
> > +		pipe->bru = bru;
> > +		pipe->bru->pipe = pipe;
> > +		pipe->bru->sink = &pipe->output->entity;
> > +		pipe->bru->sink_pad = 0;
> > +
> > +		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
> > +	}
> > +
> 
> Phew ... that's quite some chunk of interacting code ...
> 
> I've gone through it with the combinations of two pipes, 1 and 2, then
> swapping them around when say pipe 2 has 3 inputs.
> 
> It seems to scan through OK in my head ... but I think I've gone a bit
> cross-eyed now :D
> 
> Have we got some tests in place for the various combinations of paths
> through here ?

Maybe not for all combinations, but there's a kms-test-brxalloc.py test in the 
bru-brs branch of git://git.ideasonboard.com/renesas/kms-tests.git

> >  	/*
> >  	 * Configure the format on the BRU source and verify that it matches 
the
> >  	 * requested format. We don't set the media bus code as it is 
configured

[snip]

> > @@ -516,6 +623,9 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
> >   */
> >  
> >  void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index)
> >  {
> > +	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
> > +
> > +	mutex_lock(&vsp1->drm->lock);
> 
> Ouch ... we have to lock ...
> 
> >  }
> >  EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
> > 
> > @@ -629,6 +739,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned
> > int pipe_index)
> >  	vsp1_du_pipeline_setup_input(vsp1, pipe);
> >  	vsp1_du_pipeline_configure(pipe);
> > 
> > +	mutex_unlock(&vsp1->drm->lock);
> 
> And unlock in different functions ? :-(
> 
> (Yes, I see that we do - because we are crossing pipes...)

That's also something I would have liked to avoid :-/

> 
> >  }
> >  EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);

[snip]

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 13/15] v4l: vsp1: Assign BRU and BRS to pipelines dynamically
@ 2018-04-04 21:57       ` Laurent Pinchart
  0 siblings, 0 replies; 88+ messages in thread
From: Laurent Pinchart @ 2018-04-04 21:57 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: linux-renesas-soc, Laurent Pinchart, dri-devel, linux-media

Hi Kieran,

On Wednesday, 4 April 2018 19:00:10 EEST Kieran Bingham wrote:
> Hi Laurent,
> 
> Thank you for the patch.
> 
> I don't envy you on having to deal with this one ... it's a bit of a pain
> ...

Yes it was a bit painful :-/ The devil was both in the big picture and the 
details this time.

> On 26/02/18 21:45, Laurent Pinchart wrote:
> > The VSPDL variant drives two DU channels through two LIF and two
> > blenders, BRU and BRS. The DU channels thus share the five available
> > VSPDL inputs and expose them as five KMS planes.
> > 
> > The current implementation assigns the BRS to the second LIF and thus
> > artificially limits the number of planes for the second display channel
> > to two at most.
> > 
> > Lift this artificial limitation by assigning the BRU and BRS to the
> > display pipelines on demand based on the number of planes used by each
> > pipeline. When a display pipeline needs more than two inputs and the BRU
> > is already in use by the other pipeline, this requires reconfiguring the
> > other pipeline to free the BRU before processing, which can result in
> > frame drop on both pipelines.
> 
> So this is a hard one!
>  - Having to dynamically reconfigure "someone else's" pipes ...
> 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> Except for the recursion, which is unavoidable, and the lock handling across
> function calls which is ... unavoidable I think as well (at least for the
> moment), my only quibble is the naming of the 'notify' variable, which is
> not particularly clear in terms of who it notifies. (Internal, vs DRM)
> 
> I'll leave it up to you to decide whether or not to rename it though, and if
> you're happy with the naming then fine.

I agree with you, please see below.

> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> 
> > ---
> > 
> >  drivers/media/platform/vsp1/vsp1_drm.c | 160 ++++++++++++++++++++++------
> >  drivers/media/platform/vsp1/vsp1_drm.h |   9 ++
> >  2 files changed, 144 insertions(+), 25 deletions(-)
> > 
> > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c
> > b/drivers/media/platform/vsp1/vsp1_drm.c index 6c60b72b6f50..87e31ba0ddf5
> > 100644
> > --- a/drivers/media/platform/vsp1/vsp1_drm.c
> > +++ b/drivers/media/platform/vsp1/vsp1_drm.c
> > @@ -39,7 +39,13 @@ static void vsp1_du_pipeline_frame_end(struct
> > vsp1_pipeline *pipe,> 
> >  	struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe);
> >  	
> >  	if (drm_pipe->du_complete)
> > 
> > -		drm_pipe->du_complete(drm_pipe->du_private, completed);
> > +		drm_pipe->du_complete(drm_pipe->du_private,
> > +				      completed && !notify);
> > +
> > +	if (notify) {
> > +		drm_pipe->force_bru_release = false;
> > +		wake_up(&drm_pipe->wait_queue);
> > +	}
> 
> Notify seems such a nondescript verb to use here, and confuses me against
> who we are notifying  - and why (it's an internal notification, but notify
> makes me think we are 'notifying' the DU - which is exactly the opposite).
> 
> (Perhaps this is actually a comment for the previous patch, but I've gone
> out-of-order, due to the complexities here...)
> 
> Could this be 'internal', 'released' or 'reconfigured', or something to
> distinguish that this frame-end is not a normal frame-completion event ?

I think internal is a better name than notify. I'll pick that.

> >  }
> >  
> >  /* ----------------------------------------------------------------------
> > @@ -149,6 +155,10 @@ static int vsp1_du_pipeline_setup_rpf(struct
> > vsp1_device *vsp1,
> >  }
> >  
> >  /* Setup the BRU source pad. */
> > +static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1,
> > +					struct vsp1_pipeline *pipe);
> > +static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe);
> > +
> 
> Ohhh lovely, recursion...
> Ohhh lovely, recursion...

I wanted to avoid it but haven't found a better way.

> >  static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1,
> >  				      struct vsp1_pipeline *pipe)
> >  {
> > @@ -156,8 +166,93 @@ static int vsp1_du_pipeline_setup_bru(struct
> > vsp1_device *vsp1,
> >  	struct v4l2_subdev_format format = {
> >  		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
> >  	};
> > +	struct vsp1_entity *bru;
> >  	int ret;
> > 
> > +	/*
> > +	 * Pick a BRU:
> > +	 * - If we need more than two inputs, use the main BRU.
> > +	 * - Otherwise, if we are not forced to release our BRU, keep it.
> > +	 * - Else, use any free BRU (randomly starting with the main BRU).
> > +	 */
> > +	if (pipe->num_inputs > 2)
> > +		bru = &vsp1->bru->entity;
> > +	else if (pipe->bru && !drm_pipe->force_bru_release)
> > +		bru = pipe->bru;
> > +	else if (!vsp1->bru->entity.pipe)
> > +		bru = &vsp1->bru->entity;
> > +	else
> > +		bru = &vsp1->brs->entity;
> 
> Ok - that tooks some iterations to go through - but I think it covers all
> the bases.
> 
> > +
> > +	/* Switch BRU if needed. */
> > +	if (bru != pipe->bru) {
> > +		struct vsp1_entity *released_bru = NULL;
> > +
> > +		/* Release our BRU if we have one. */
> > +		if (pipe->bru) {
> > +			/*
> > +			 * The BRU might be acquired by the other pipeline in
> > +			 * the next step. We must thus remove it from the list
> > +			 * of entities for this pipeline. The other pipeline's
> > +			 * hardware configuration will reconfigure the BRU
> > +			 * routing.
> > +			 *
> > +			 * However, if the other pipeline doesn't acquire our
> > +			 * BRU, we need to keep it in the list, otherwise the
> > +			 * hardware configuration step won't disconnect it from
> > +			 * the pipeline. To solve this, store the released BRU
> > +			 * pointer to add it back to the list of entities later
> > +			 * if it isn't acquired by the other pipeline.
> > +			 */
> > +			released_bru = pipe->bru;
> > +
> > +			list_del(&pipe->bru->list_pipe);
> > +			pipe->bru->sink = NULL;
> > +			pipe->bru->pipe = NULL;
> > +			pipe->bru = NULL;
> > +		}
> > +
> > +		/*
> > +		 * If the BRU we need is in use, force the owner pipeline to
> > +		 * switch to the other BRU and wait until the switch completes.
> > +		 */
> > +		if (bru->pipe) {
> > +			struct vsp1_drm_pipeline *owner_pipe;
> > +
> > +			owner_pipe = to_vsp1_drm_pipeline(bru->pipe);
> > +			owner_pipe->force_bru_release = true;
> > +
> > +			vsp1_du_pipeline_setup_input(vsp1, &owner_pipe->pipe);
> > +			vsp1_du_pipeline_configure(&owner_pipe->pipe);
> > +
> > +			ret = wait_event_timeout(owner_pipe->wait_queue,
> > +						 !owner_pipe->force_bru_release,
> > +						 msecs_to_jiffies(500));
> > +			if (ret == 0)
> > +				dev_warn(vsp1->dev,
> > +					 "DRM pipeline %u reconfiguration timeout\n",
> > +					 owner_pipe->pipe.lif->index);
> > +		}
> > +
> > +		/*
> > +		 * If the BRU we have released previously hasn't been acquired
> > +		 * by the other pipeline, add it back to the entities list (with
> > +		 * the pipe pointer NULL) to let vsp1_du_pipeline_configure()
> > +		 * disconnect it from the hardware pipeline.
> > +		 */
> > +		if (released_bru && !released_bru->pipe)
> > +			list_add_tail(&released_bru->list_pipe,
> > +				      &pipe->entities);
> > +
> > +		/* Add the BRU to the pipeline. */
> > +		pipe->bru = bru;
> > +		pipe->bru->pipe = pipe;
> > +		pipe->bru->sink = &pipe->output->entity;
> > +		pipe->bru->sink_pad = 0;
> > +
> > +		list_add_tail(&pipe->bru->list_pipe, &pipe->entities);
> > +	}
> > +
> 
> Phew ... that's quite some chunk of interacting code ...
> 
> I've gone through it with the combinations of two pipes, 1 and 2, then
> swapping them around when say pipe 2 has 3 inputs.
> 
> It seems to scan through OK in my head ... but I think I've gone a bit
> cross-eyed now :D
> 
> Have we got some tests in place for the various combinations of paths
> through here ?

Maybe not for all combinations, but there's a kms-test-brxalloc.py test in the 
bru-brs branch of git://git.ideasonboard.com/renesas/kms-tests.git

> >  	/*
> >  	 * Configure the format on the BRU source and verify that it matches 
the
> >  	 * requested format. We don't set the media bus code as it is 
configured

[snip]

> > @@ -516,6 +623,9 @@ EXPORT_SYMBOL_GPL(vsp1_du_setup_lif);
> >   */
> >  
> >  void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index)
> >  {
> > +	struct vsp1_device *vsp1 = dev_get_drvdata(dev);
> > +
> > +	mutex_lock(&vsp1->drm->lock);
> 
> Ouch ... we have to lock ...
> 
> >  }
> >  EXPORT_SYMBOL_GPL(vsp1_du_atomic_begin);
> > 
> > @@ -629,6 +739,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned
> > int pipe_index)
> >  	vsp1_du_pipeline_setup_input(vsp1, pipe);
> >  	vsp1_du_pipeline_configure(pipe);
> > 
> > +	mutex_unlock(&vsp1->drm->lock);
> 
> And unlock in different functions ? :-(
> 
> (Yes, I see that we do - because we are crossing pipes...)

That's also something I would have liked to avoid :-/

> 
> >  }
> >  EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush);

[snip]

-- 
Regards,

Laurent Pinchart



_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 11/15] v4l: vsp1: Add per-display list completion notification support
  2018-04-04 21:43       ` Laurent Pinchart
@ 2018-04-05  8:46         ` Kieran Bingham
  -1 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-04-05  8:46 UTC (permalink / raw)
  To: Laurent Pinchart, Kieran Bingham
  Cc: Laurent Pinchart, linux-media, dri-devel, linux-renesas-soc

Hi Laurent,

On 04/04/18 22:43, Laurent Pinchart wrote:
> Hi Kieran,
> 
> On Wednesday, 4 April 2018 19:16:46 EEST Kieran Bingham wrote:
>> On 26/02/18 21:45, Laurent Pinchart wrote:

<snip>

>>>
>>> -void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
>>> +void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool notify)
>>
>> Rather than changing the vsp1_dl_list_commit() function - would it be nicer
>> to have an API to request or set the notify property? :
>>
>> @@..@@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
>> ...
>> +	/* The BRx will be released, without sending an update to DRM */
>> +	if (drm_pipe->force_bru_release)
>> +		vsp1_dl_list_request_internal_notify(dl);
>>
>> 	vsp1_dl_list_commit(dl);
>> ...
> 
> That's not a bad idea, but I wonder if it's worth it as we'll have to call an 
> extra function for what is essentially an internal API. On the other hand this 
> isn't a common case, so it's not a hot code path. We could also argue equally 
> that it is the commit that is internal or that it is the display list that is 

Aha, yes - it is more so that the commit is internal ...

> for internal purpose. Do you think an extra function call is better ? If you 
> do I'll change it.

so it could also instead be just a separate commit() function:


void vsp1_dl_list_commit_internal(struct vsp1_dl_list *dl)
{
	dl->internal = true;
	vsp1_dl_list_commit(dl);
}


...


{
	/* The BRx will be released, without sending an update to DRM */
	if (drm_pipe->force_bru_release)
		vsp1_dl_list_commit_internal(dl);
	else
 		vsp1_dl_list_commit(dl);
}

I'll leave the final implementation decision with you - I just thought that
extending the commit call with a notify flag seemed odd.

Of course - that could also have been due to the naming of the 'notify' - if it
was 'internal' as discussed in the other patches, then perhaps a flag on the
function call is still a sensible way. It just affects the other commit usages,
but there's only a total of three calls - so it's really not a big deal. If
there were 12 call locations perhaps the function wrapper would have more merit
- but probably not so much at 3 :D

--
Kieran

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

* Re: [PATCH 11/15] v4l: vsp1: Add per-display list completion notification support
@ 2018-04-05  8:46         ` Kieran Bingham
  0 siblings, 0 replies; 88+ messages in thread
From: Kieran Bingham @ 2018-04-05  8:46 UTC (permalink / raw)
  To: Laurent Pinchart, Kieran Bingham
  Cc: linux-renesas-soc, Laurent Pinchart, dri-devel, linux-media

Hi Laurent,

On 04/04/18 22:43, Laurent Pinchart wrote:
> Hi Kieran,
> 
> On Wednesday, 4 April 2018 19:16:46 EEST Kieran Bingham wrote:
>> On 26/02/18 21:45, Laurent Pinchart wrote:

<snip>

>>>
>>> -void vsp1_dl_list_commit(struct vsp1_dl_list *dl)
>>> +void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool notify)
>>
>> Rather than changing the vsp1_dl_list_commit() function - would it be nicer
>> to have an API to request or set the notify property? :
>>
>> @@..@@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe)
>> ...
>> +	/* The BRx will be released, without sending an update to DRM */
>> +	if (drm_pipe->force_bru_release)
>> +		vsp1_dl_list_request_internal_notify(dl);
>>
>> 	vsp1_dl_list_commit(dl);
>> ...
> 
> That's not a bad idea, but I wonder if it's worth it as we'll have to call an 
> extra function for what is essentially an internal API. On the other hand this 
> isn't a common case, so it's not a hot code path. We could also argue equally 
> that it is the commit that is internal or that it is the display list that is 

Aha, yes - it is more so that the commit is internal ...

> for internal purpose. Do you think an extra function call is better ? If you 
> do I'll change it.

so it could also instead be just a separate commit() function:


void vsp1_dl_list_commit_internal(struct vsp1_dl_list *dl)
{
	dl->internal = true;
	vsp1_dl_list_commit(dl);
}


...


{
	/* The BRx will be released, without sending an update to DRM */
	if (drm_pipe->force_bru_release)
		vsp1_dl_list_commit_internal(dl);
	else
 		vsp1_dl_list_commit(dl);
}

I'll leave the final implementation decision with you - I just thought that
extending the commit call with a notify flag seemed odd.

Of course - that could also have been due to the naming of the 'notify' - if it
was 'internal' as discussed in the other patches, then perhaps a flag on the
function call is still a sensible way. It just affects the other commit usages,
but there's only a total of three calls - so it's really not a big deal. If
there were 12 call locations perhaps the function wrapper would have more merit
- but probably not so much at 3 :D

--
Kieran
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

end of thread, other threads:[~2018-04-05  8:46 UTC | newest]

Thread overview: 88+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-26 21:45 [PATCH 00/15] R-Car VSP1: Dynamically assign blend units to display pipelines Laurent Pinchart
2018-02-26 21:45 ` Laurent Pinchart
2018-02-26 21:45 ` [PATCH 01/15] v4l: vsp1: Don't start/stop media pipeline for DRM Laurent Pinchart
2018-02-26 21:45   ` Laurent Pinchart
2018-04-04 15:35   ` Kieran Bingham
2018-04-04 15:35     ` Kieran Bingham
2018-02-26 21:45 ` [PATCH 02/15] v4l: vsp1: Remove outdated comment Laurent Pinchart
2018-02-26 21:45   ` Laurent Pinchart
2018-02-27  8:22   ` Sergei Shtylyov
2018-02-27  8:22     ` Sergei Shtylyov
2018-02-27  9:14     ` Laurent Pinchart
2018-02-27  9:14       ` Laurent Pinchart
2018-03-28 12:27   ` Kieran Bingham
2018-03-28 12:27     ` Kieran Bingham
2018-03-28 19:04     ` Kieran Bingham
2018-03-28 19:04       ` Kieran Bingham
2018-03-29  6:51       ` Laurent Pinchart
2018-03-29  6:51         ` Laurent Pinchart
2018-02-26 21:45 ` [PATCH 03/15] v4l: vsp1: Remove unused field from vsp1_drm_pipeline structure Laurent Pinchart
2018-02-26 21:45   ` Laurent Pinchart
2018-03-28 12:31   ` Kieran Bingham
2018-03-28 12:31     ` Kieran Bingham
2018-02-26 21:45 ` [PATCH 04/15] v4l: vsp1: Store pipeline pointer in vsp1_entity Laurent Pinchart
2018-02-26 21:45   ` Laurent Pinchart
2018-03-28 13:46   ` Kieran Bingham
2018-03-28 13:46     ` Kieran Bingham
2018-02-26 21:45 ` [PATCH 05/15] v4l: vsp1: Use vsp1_entity.pipe to check if entity belongs to a pipeline Laurent Pinchart
2018-02-26 21:45   ` Laurent Pinchart
2018-03-28 14:10   ` Kieran Bingham
2018-03-28 14:10     ` Kieran Bingham
2018-03-29  7:00     ` Laurent Pinchart
2018-03-29  7:00       ` Laurent Pinchart
2018-02-26 21:45 ` [PATCH 06/15] v4l: vsp1: Share duplicated DRM pipeline configuration code Laurent Pinchart
2018-02-26 21:45   ` Laurent Pinchart
2018-03-28 14:25   ` Kieran Bingham
2018-03-28 14:25     ` Kieran Bingham
2018-02-26 21:45 ` [PATCH 07/15] v4l: vsp1: Move DRM atomic commit pipeline setup to separate function Laurent Pinchart
2018-02-26 21:45   ` Laurent Pinchart
2018-03-28 14:43   ` Kieran Bingham
2018-03-28 14:43     ` Kieran Bingham
2018-03-29  7:08     ` Laurent Pinchart
2018-03-29  7:08       ` Laurent Pinchart
2018-02-26 21:45 ` [PATCH 08/15] v4l: vsp1: Setup BRU at atomic commit time Laurent Pinchart
2018-02-26 21:45   ` Laurent Pinchart
2018-03-28 19:01   ` Kieran Bingham
2018-03-28 19:01     ` Kieran Bingham
2018-02-26 21:45 ` [PATCH 09/15] v4l: vsp1: Replace manual DRM pipeline input setup in vsp1_du_setup_lif Laurent Pinchart
2018-02-26 21:45   ` Laurent Pinchart
2018-03-28 15:01   ` Kieran Bingham
2018-03-28 15:01     ` Kieran Bingham
2018-02-26 21:45 ` [PATCH 10/15] v4l: vsp1: Move DRM pipeline output setup code to a function Laurent Pinchart
2018-02-26 21:45   ` Laurent Pinchart
2018-03-29 11:49   ` Kieran Bingham
2018-03-29 11:49     ` Kieran Bingham
2018-04-02 12:35     ` Laurent Pinchart
2018-04-02 12:35       ` Laurent Pinchart
2018-04-04 16:15       ` Kieran Bingham
2018-04-04 16:15         ` Kieran Bingham
2018-04-04 21:05         ` Laurent Pinchart
2018-04-04 21:05           ` Laurent Pinchart
2018-02-26 21:45 ` [PATCH 11/15] v4l: vsp1: Add per-display list completion notification support Laurent Pinchart
2018-02-26 21:45   ` Laurent Pinchart
2018-04-04 16:16   ` Kieran Bingham
2018-04-04 16:16     ` Kieran Bingham
2018-04-04 21:43     ` Laurent Pinchart
2018-04-04 21:43       ` Laurent Pinchart
2018-04-05  8:46       ` Kieran Bingham
2018-04-05  8:46         ` Kieran Bingham
2018-02-26 21:45 ` [PATCH 12/15] v4l: vsp1: Generalize detection of entity removal from DRM pipeline Laurent Pinchart
2018-02-26 21:45   ` Laurent Pinchart
2018-03-29 11:37   ` Kieran Bingham
2018-03-29 11:37     ` Kieran Bingham
2018-04-02 12:57     ` Laurent Pinchart
2018-04-02 12:57       ` Laurent Pinchart
2018-02-26 21:45 ` [PATCH 13/15] v4l: vsp1: Assign BRU and BRS to pipelines dynamically Laurent Pinchart
2018-02-26 21:45   ` Laurent Pinchart
2018-04-04 16:00   ` Kieran Bingham
2018-04-04 16:00     ` Kieran Bingham
2018-04-04 21:57     ` Laurent Pinchart
2018-04-04 21:57       ` Laurent Pinchart
2018-02-26 21:45 ` [PATCH 14/15] v4l: vsp1: Add BRx dynamic assignment debugging messages Laurent Pinchart
2018-02-26 21:45   ` Laurent Pinchart
2018-04-04 16:17   ` Kieran Bingham
2018-04-04 16:17     ` Kieran Bingham
2018-02-26 21:45 ` [PATCH 15/15] v4l: vsp1: Rename BRU to BRx Laurent Pinchart
2018-02-26 21:45   ` Laurent Pinchart
2018-04-04 16:23   ` Kieran Bingham
2018-04-04 16:23     ` Kieran Bingham

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.