All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/22] R-Car DU: Add Gen3 support
@ 2015-09-13 22:50 ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

Hello,

This patch series adds support for the Display Unit found in the R-Car Gen3
SoC series.

The third generation differs significantly from the previous ones in that the
DU has lost its ability to source data from memory. It must instead use an
external hardware composer named VSP to read planes from memory and blend
them.

The VSP has a V4L2 driver in mainline that can be used in conjunction with the
DU through the live sources API (submitted previously as an RFC). However, as
VSP usage is mandatory in Gen3 and as no native DU planes are available, we
have decided that forcing userspace to use both KMS and V4L2 to display any
content wouldn't be very friendly. Instead the VSP driver has been extended to
make the device directly controllable by the DU driver ([1]) and this patch
series builds on top of it.

[1] http://www.spinics.net/lists/linux-media/msg93575.html

Koji Matsuoka (4):
  drm: rcar-du: Fix compile warning on 64-bit platforms
  drm: rcar-du: Enable compilation on ARM64
  drm: rcar-du: Support up to 4 CRTCs
  drm: rcar-du: lvds: Add R-Car Gen3 support

Laurent Pinchart (18):
  drm: rcar-du: Don't update planes on disabled CRTCs
  drm: rcar-du: Add support for the R8A7793 DU
  drm: rcar-du: Add support for the R8A7794 DU
  drm: rcar-du: Compute plane DDCR4 register value directly
  drm: rcar-du: Refactor plane setup
  drm: rcar-du: Add VSP1 support to the planes allocator
  drm: rcar-du: Add VSP1 compositor support
  drm: rcar-du: Restart the DU group when a plane source changes
  drm: rcar-du: Move plane allocator to rcar_du_plane.c
  drm: rcar-du: Expose the VSP1 compositor through KMS planes
  drm: rcar-du: Use the VSP atomic update API
  drm: rcar-du: Drop LVDS double dependency on OF
  drm: rcar-du: Output the DISP signal on the DISP pin
  drm: rcar-du: Output the DISP signal on the ODDF pin
  drm: rcar-du: Add R8A7795 device support
  drm: rcar-du: lvds: Avoid duplication of clock clamp code
  drm: rcar-du: lvds: Fix PLL frequency-related configuration
  drm: rcar-du: lvds: Rename PLLEN bit to PLLON

 .../devicetree/bindings/video/renesas,du.txt       |  22 +-
 drivers/gpu/drm/rcar-du/Kconfig                    |  15 +-
 drivers/gpu/drm/rcar-du/Makefile                   |   2 +
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c             |  63 ++-
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h             |   2 +
 drivers/gpu/drm/rcar-du/rcar_du_drv.c              |  58 ++-
 drivers/gpu/drm/rcar-du/rcar_du_drv.h              |  12 +-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c          |   6 +-
 drivers/gpu/drm/rcar-du/rcar_du_group.c            |  73 +++-
 drivers/gpu/drm/rcar-du/rcar_du_group.h            |   4 +
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |   7 +-
 drivers/gpu/drm/rcar-du/rcar_du_kms.c              | 273 ++----------
 drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c          | 142 +++++--
 drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h          |   6 +
 drivers/gpu/drm/rcar-du/rcar_du_plane.c            | 465 ++++++++++++++++++---
 drivers/gpu/drm/rcar-du/rcar_du_plane.h            |  21 +-
 drivers/gpu/drm/rcar-du/rcar_du_regs.h             |  21 +-
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c              | 373 +++++++++++++++++
 drivers/gpu/drm/rcar-du/rcar_du_vsp.h              |  76 ++++
 drivers/gpu/drm/rcar-du/rcar_lvds_regs.h           |  26 +-
 20 files changed, 1263 insertions(+), 404 deletions(-)
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vsp.c
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vsp.h

-- 
Regards,

Laurent Pinchart


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

* [PATCH 00/22] R-Car DU: Add Gen3 support
@ 2015-09-13 22:50 ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

Hello,

This patch series adds support for the Display Unit found in the R-Car Gen3
SoC series.

The third generation differs significantly from the previous ones in that the
DU has lost its ability to source data from memory. It must instead use an
external hardware composer named VSP to read planes from memory and blend
them.

The VSP has a V4L2 driver in mainline that can be used in conjunction with the
DU through the live sources API (submitted previously as an RFC). However, as
VSP usage is mandatory in Gen3 and as no native DU planes are available, we
have decided that forcing userspace to use both KMS and V4L2 to display any
content wouldn't be very friendly. Instead the VSP driver has been extended to
make the device directly controllable by the DU driver ([1]) and this patch
series builds on top of it.

[1] http://www.spinics.net/lists/linux-media/msg93575.html

Koji Matsuoka (4):
  drm: rcar-du: Fix compile warning on 64-bit platforms
  drm: rcar-du: Enable compilation on ARM64
  drm: rcar-du: Support up to 4 CRTCs
  drm: rcar-du: lvds: Add R-Car Gen3 support

Laurent Pinchart (18):
  drm: rcar-du: Don't update planes on disabled CRTCs
  drm: rcar-du: Add support for the R8A7793 DU
  drm: rcar-du: Add support for the R8A7794 DU
  drm: rcar-du: Compute plane DDCR4 register value directly
  drm: rcar-du: Refactor plane setup
  drm: rcar-du: Add VSP1 support to the planes allocator
  drm: rcar-du: Add VSP1 compositor support
  drm: rcar-du: Restart the DU group when a plane source changes
  drm: rcar-du: Move plane allocator to rcar_du_plane.c
  drm: rcar-du: Expose the VSP1 compositor through KMS planes
  drm: rcar-du: Use the VSP atomic update API
  drm: rcar-du: Drop LVDS double dependency on OF
  drm: rcar-du: Output the DISP signal on the DISP pin
  drm: rcar-du: Output the DISP signal on the ODDF pin
  drm: rcar-du: Add R8A7795 device support
  drm: rcar-du: lvds: Avoid duplication of clock clamp code
  drm: rcar-du: lvds: Fix PLL frequency-related configuration
  drm: rcar-du: lvds: Rename PLLEN bit to PLLON

 .../devicetree/bindings/video/renesas,du.txt       |  22 +-
 drivers/gpu/drm/rcar-du/Kconfig                    |  15 +-
 drivers/gpu/drm/rcar-du/Makefile                   |   2 +
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c             |  63 ++-
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h             |   2 +
 drivers/gpu/drm/rcar-du/rcar_du_drv.c              |  58 ++-
 drivers/gpu/drm/rcar-du/rcar_du_drv.h              |  12 +-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c          |   6 +-
 drivers/gpu/drm/rcar-du/rcar_du_group.c            |  73 +++-
 drivers/gpu/drm/rcar-du/rcar_du_group.h            |   4 +
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |   7 +-
 drivers/gpu/drm/rcar-du/rcar_du_kms.c              | 273 ++----------
 drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c          | 142 +++++--
 drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h          |   6 +
 drivers/gpu/drm/rcar-du/rcar_du_plane.c            | 465 ++++++++++++++++++---
 drivers/gpu/drm/rcar-du/rcar_du_plane.h            |  21 +-
 drivers/gpu/drm/rcar-du/rcar_du_regs.h             |  21 +-
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c              | 373 +++++++++++++++++
 drivers/gpu/drm/rcar-du/rcar_du_vsp.h              |  76 ++++
 drivers/gpu/drm/rcar-du/rcar_lvds_regs.h           |  26 +-
 20 files changed, 1263 insertions(+), 404 deletions(-)
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vsp.c
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vsp.h

-- 
Regards,

Laurent Pinchart


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

* [PATCH 01/22] drm: rcar-du: Don't update planes on disabled CRTCs
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:50   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

A disabled CRTC can't display planes, the driver shouldn't try to
configure it when updating planes. The DRM core will store the plane
state for us, and the plane will be configured appropriately the next
time the CRTC is enabled.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_kms.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index ca12e8ca5552..20813582fbf1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -456,7 +456,7 @@ static void rcar_du_atomic_complete(struct rcar_du_commit *commit)
 	/* Apply the atomic update. */
 	drm_atomic_helper_commit_modeset_disables(dev, old_state);
 	drm_atomic_helper_commit_modeset_enables(dev, old_state);
-	drm_atomic_helper_commit_planes(dev, old_state, false);
+	drm_atomic_helper_commit_planes(dev, old_state, true);
 
 	drm_atomic_helper_wait_for_vblanks(dev, old_state);
 
-- 
2.4.6


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

* [PATCH 01/22] drm: rcar-du: Don't update planes on disabled CRTCs
@ 2015-09-13 22:50   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

A disabled CRTC can't display planes, the driver shouldn't try to
configure it when updating planes. The DRM core will store the plane
state for us, and the plane will be configured appropriately the next
time the CRTC is enabled.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_kms.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index ca12e8ca5552..20813582fbf1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -456,7 +456,7 @@ static void rcar_du_atomic_complete(struct rcar_du_commit *commit)
 	/* Apply the atomic update. */
 	drm_atomic_helper_commit_modeset_disables(dev, old_state);
 	drm_atomic_helper_commit_modeset_enables(dev, old_state);
-	drm_atomic_helper_commit_planes(dev, old_state, false);
+	drm_atomic_helper_commit_planes(dev, old_state, true);
 
 	drm_atomic_helper_wait_for_vblanks(dev, old_state);
 
-- 
2.4.6


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

* [PATCH 02/22] drm: rcar-du: Add support for the R8A7793 DU
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:50   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: devicetree, linux-sh

The R8A7793 DU is identical to the R8A7791 and thus only requires a new
DT compatible string.

Cc: devicetree@vger.kernel.org
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 Documentation/devicetree/bindings/video/renesas,du.txt | 12 +++++++-----
 drivers/gpu/drm/rcar-du/rcar_du_drv.c                  |  4 +++-
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/renesas,du.txt b/Documentation/devicetree/bindings/video/renesas,du.txt
index c902323928f7..d05be121486f 100644
--- a/Documentation/devicetree/bindings/video/renesas,du.txt
+++ b/Documentation/devicetree/bindings/video/renesas,du.txt
@@ -5,7 +5,8 @@ Required Properties:
   - compatible: must be one of the following.
     - "renesas,du-r8a7779" for R8A7779 (R-Car H1) compatible DU
     - "renesas,du-r8a7790" for R8A7790 (R-Car H2) compatible DU
-    - "renesas,du-r8a7791" for R8A7791 (R-Car M2) compatible DU
+    - "renesas,du-r8a7791" for R8A7791 (R-Car M2-W) compatible DU
+    - "renesas,du-r8a7793" for R8A7793 (R-Car M2-N) compatible DU
 
   - reg: A list of base address and length of each memory resource, one for
     each entry in the reg-names property.
@@ -22,9 +23,9 @@ Required Properties:
   - clock-names: Name of the clocks. This property is model-dependent.
     - R8A7779 uses a single functional clock. The clock doesn't need to be
       named.
-    - R8A7790 and R8A7791 use one functional clock per channel and one clock
-      per LVDS encoder. The functional clocks must be named "du.x" with "x"
-      being the channel numerical index. The LVDS clocks must be named
+    - R8A779[013] use one functional clock per channel and one clock per LVDS
+      encoder (if available). The functional clocks must be named "du.x" with
+      "x" being the channel numerical index. The LVDS clocks must be named
       "lvds.x" with "x" being the LVDS encoder numerical index.
     - In addition to the functional and encoder clocks, all DU versions also
       support externally supplied pixel clocks. Those clocks are optional.
@@ -43,7 +44,8 @@ corresponding to each DU output.
 -----------------------------------------------------------------------------
  R8A7779 (H1)	DPAD 0		DPAD 1		-
  R8A7790 (H2)	DPAD		LVDS 0		LVDS 1
- R8A7791 (M2)	DPAD		LVDS 0		-
+ R8A7791 (M2-W)	DPAD		LVDS 0		-
+ R8A7793 (M2-N)	DPAD		LVDS 0		-
 
 
 Example: R8A7790 (R-Car H2) DU
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 44879136e933..90d19fb976ab 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -84,12 +84,13 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
 	.num_lvds = 2,
 };
 
+/* M2-W (r8a7791) and M2-N (r8a7793) are identical */
 static const struct rcar_du_device_info rcar_du_r8a7791_info = {
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS,
 	.num_crtcs = 2,
 	.routes = {
-		/* R8A7791 has one RGB output, one LVDS output and one
+		/* R8A779[13] has one RGB output, one LVDS output and one
 		 * (currently unsupported) TCON output.
 		 */
 		[RCAR_DU_OUTPUT_DPAD0] = {
@@ -110,6 +111,7 @@ static const struct of_device_id rcar_du_of_table[] = {
 	{ .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
 	{ .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
 	{ .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
+	{ .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
 	{ }
 };
 
-- 
2.4.6


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

* [PATCH 02/22] drm: rcar-du: Add support for the R8A7793 DU
@ 2015-09-13 22:50   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: devicetree, linux-sh

The R8A7793 DU is identical to the R8A7791 and thus only requires a new
DT compatible string.

Cc: devicetree@vger.kernel.org
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 Documentation/devicetree/bindings/video/renesas,du.txt | 12 +++++++-----
 drivers/gpu/drm/rcar-du/rcar_du_drv.c                  |  4 +++-
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/renesas,du.txt b/Documentation/devicetree/bindings/video/renesas,du.txt
index c902323928f7..d05be121486f 100644
--- a/Documentation/devicetree/bindings/video/renesas,du.txt
+++ b/Documentation/devicetree/bindings/video/renesas,du.txt
@@ -5,7 +5,8 @@ Required Properties:
   - compatible: must be one of the following.
     - "renesas,du-r8a7779" for R8A7779 (R-Car H1) compatible DU
     - "renesas,du-r8a7790" for R8A7790 (R-Car H2) compatible DU
-    - "renesas,du-r8a7791" for R8A7791 (R-Car M2) compatible DU
+    - "renesas,du-r8a7791" for R8A7791 (R-Car M2-W) compatible DU
+    - "renesas,du-r8a7793" for R8A7793 (R-Car M2-N) compatible DU
 
   - reg: A list of base address and length of each memory resource, one for
     each entry in the reg-names property.
@@ -22,9 +23,9 @@ Required Properties:
   - clock-names: Name of the clocks. This property is model-dependent.
     - R8A7779 uses a single functional clock. The clock doesn't need to be
       named.
-    - R8A7790 and R8A7791 use one functional clock per channel and one clock
-      per LVDS encoder. The functional clocks must be named "du.x" with "x"
-      being the channel numerical index. The LVDS clocks must be named
+    - R8A779[013] use one functional clock per channel and one clock per LVDS
+      encoder (if available). The functional clocks must be named "du.x" with
+      "x" being the channel numerical index. The LVDS clocks must be named
       "lvds.x" with "x" being the LVDS encoder numerical index.
     - In addition to the functional and encoder clocks, all DU versions also
       support externally supplied pixel clocks. Those clocks are optional.
@@ -43,7 +44,8 @@ corresponding to each DU output.
 -----------------------------------------------------------------------------
  R8A7779 (H1)	DPAD 0		DPAD 1		-
  R8A7790 (H2)	DPAD		LVDS 0		LVDS 1
- R8A7791 (M2)	DPAD		LVDS 0		-
+ R8A7791 (M2-W)	DPAD		LVDS 0		-
+ R8A7793 (M2-N)	DPAD		LVDS 0		-
 
 
 Example: R8A7790 (R-Car H2) DU
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 44879136e933..90d19fb976ab 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -84,12 +84,13 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
 	.num_lvds = 2,
 };
 
+/* M2-W (r8a7791) and M2-N (r8a7793) are identical */
 static const struct rcar_du_device_info rcar_du_r8a7791_info = {
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS,
 	.num_crtcs = 2,
 	.routes = {
-		/* R8A7791 has one RGB output, one LVDS output and one
+		/* R8A779[13] has one RGB output, one LVDS output and one
 		 * (currently unsupported) TCON output.
 		 */
 		[RCAR_DU_OUTPUT_DPAD0] = {
@@ -110,6 +111,7 @@ static const struct of_device_id rcar_du_of_table[] = {
 	{ .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
 	{ .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
 	{ .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
+	{ .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
 	{ }
 };
 
-- 
2.4.6

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

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

* [PATCH 03/22] drm: rcar-du: Add support for the R8A7794 DU
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:50   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh, devicetree

The R8A7794 DU has a fixed output routing configuration with one RGB
output per CRTC and thus lacks the RGB output routing register field.

Cc: devicetree@vger.kernel.org
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 .../devicetree/bindings/video/renesas,du.txt       |  4 +++-
 drivers/gpu/drm/rcar-du/rcar_du_drv.c              | 23 ++++++++++++++++++++++
 drivers/gpu/drm/rcar-du/rcar_du_group.c            |  5 +++--
 3 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/renesas,du.txt b/Documentation/devicetree/bindings/video/renesas,du.txt
index d05be121486f..eccd4f4867b2 100644
--- a/Documentation/devicetree/bindings/video/renesas,du.txt
+++ b/Documentation/devicetree/bindings/video/renesas,du.txt
@@ -7,6 +7,7 @@ Required Properties:
     - "renesas,du-r8a7790" for R8A7790 (R-Car H2) compatible DU
     - "renesas,du-r8a7791" for R8A7791 (R-Car M2-W) compatible DU
     - "renesas,du-r8a7793" for R8A7793 (R-Car M2-N) compatible DU
+    - "renesas,du-r8a7794" for R8A7794 (R-Car E2) compatible DU
 
   - reg: A list of base address and length of each memory resource, one for
     each entry in the reg-names property.
@@ -23,7 +24,7 @@ Required Properties:
   - clock-names: Name of the clocks. This property is model-dependent.
     - R8A7779 uses a single functional clock. The clock doesn't need to be
       named.
-    - R8A779[013] use one functional clock per channel and one clock per LVDS
+    - R8A779[0134] use one functional clock per channel and one clock per LVDS
       encoder (if available). The functional clocks must be named "du.x" with
       "x" being the channel numerical index. The LVDS clocks must be named
       "lvds.x" with "x" being the LVDS encoder numerical index.
@@ -46,6 +47,7 @@ corresponding to each DU output.
  R8A7790 (H2)	DPAD		LVDS 0		LVDS 1
  R8A7791 (M2-W)	DPAD		LVDS 0		-
  R8A7793 (M2-N)	DPAD		LVDS 0		-
+ R8A7794 (E2)	DPAD 0		DPAD 1		-
 
 
 Example: R8A7790 (R-Car H2) DU
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 90d19fb976ab..326d040515e4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -107,11 +107,34 @@ static const struct rcar_du_device_info rcar_du_r8a7791_info = {
 	.num_lvds = 1,
 };
 
+static const struct rcar_du_device_info rcar_du_r8a7794_info = {
+	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
+		  | RCAR_DU_FEATURE_EXT_CTRL_REGS,
+	.num_crtcs = 2,
+	.routes = {
+		/* R8A7794 has two RGB outputs and one (currently unsupported)
+		 * TCON output.
+		 */
+		[RCAR_DU_OUTPUT_DPAD0] = {
+			.possible_crtcs = BIT(0),
+			.encoder_type = DRM_MODE_ENCODER_NONE,
+			.port = 0,
+		},
+		[RCAR_DU_OUTPUT_DPAD1] = {
+			.possible_crtcs = BIT(1),
+			.encoder_type = DRM_MODE_ENCODER_NONE,
+			.port = 1,
+		},
+	},
+	.num_lvds = 0,
+};
+
 static const struct of_device_id rcar_du_of_table[] = {
 	{ .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
 	{ .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
 	{ .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
 	{ .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
+	{ .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
 	{ }
 };
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 7fd39a7d91c8..8e2ffe025153 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -49,9 +49,10 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 	u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;
 
 	/* The DEFR8 register for the first group also controls RGB output
-	 * routing to DPAD0
+	 * routing to DPAD0 for DU instances that support it.
 	 */
-	if (rgrp->index = 0)
+	if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1 &&
+	    rgrp->index = 0)
 		defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
 
 	rcar_du_group_write(rgrp, DEFR8, defr8);
-- 
2.4.6


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

* [PATCH 03/22] drm: rcar-du: Add support for the R8A7794 DU
@ 2015-09-13 22:50   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh, devicetree

The R8A7794 DU has a fixed output routing configuration with one RGB
output per CRTC and thus lacks the RGB output routing register field.

Cc: devicetree@vger.kernel.org
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 .../devicetree/bindings/video/renesas,du.txt       |  4 +++-
 drivers/gpu/drm/rcar-du/rcar_du_drv.c              | 23 ++++++++++++++++++++++
 drivers/gpu/drm/rcar-du/rcar_du_group.c            |  5 +++--
 3 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/renesas,du.txt b/Documentation/devicetree/bindings/video/renesas,du.txt
index d05be121486f..eccd4f4867b2 100644
--- a/Documentation/devicetree/bindings/video/renesas,du.txt
+++ b/Documentation/devicetree/bindings/video/renesas,du.txt
@@ -7,6 +7,7 @@ Required Properties:
     - "renesas,du-r8a7790" for R8A7790 (R-Car H2) compatible DU
     - "renesas,du-r8a7791" for R8A7791 (R-Car M2-W) compatible DU
     - "renesas,du-r8a7793" for R8A7793 (R-Car M2-N) compatible DU
+    - "renesas,du-r8a7794" for R8A7794 (R-Car E2) compatible DU
 
   - reg: A list of base address and length of each memory resource, one for
     each entry in the reg-names property.
@@ -23,7 +24,7 @@ Required Properties:
   - clock-names: Name of the clocks. This property is model-dependent.
     - R8A7779 uses a single functional clock. The clock doesn't need to be
       named.
-    - R8A779[013] use one functional clock per channel and one clock per LVDS
+    - R8A779[0134] use one functional clock per channel and one clock per LVDS
       encoder (if available). The functional clocks must be named "du.x" with
       "x" being the channel numerical index. The LVDS clocks must be named
       "lvds.x" with "x" being the LVDS encoder numerical index.
@@ -46,6 +47,7 @@ corresponding to each DU output.
  R8A7790 (H2)	DPAD		LVDS 0		LVDS 1
  R8A7791 (M2-W)	DPAD		LVDS 0		-
  R8A7793 (M2-N)	DPAD		LVDS 0		-
+ R8A7794 (E2)	DPAD 0		DPAD 1		-
 
 
 Example: R8A7790 (R-Car H2) DU
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 90d19fb976ab..326d040515e4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -107,11 +107,34 @@ static const struct rcar_du_device_info rcar_du_r8a7791_info = {
 	.num_lvds = 1,
 };
 
+static const struct rcar_du_device_info rcar_du_r8a7794_info = {
+	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
+		  | RCAR_DU_FEATURE_EXT_CTRL_REGS,
+	.num_crtcs = 2,
+	.routes = {
+		/* R8A7794 has two RGB outputs and one (currently unsupported)
+		 * TCON output.
+		 */
+		[RCAR_DU_OUTPUT_DPAD0] = {
+			.possible_crtcs = BIT(0),
+			.encoder_type = DRM_MODE_ENCODER_NONE,
+			.port = 0,
+		},
+		[RCAR_DU_OUTPUT_DPAD1] = {
+			.possible_crtcs = BIT(1),
+			.encoder_type = DRM_MODE_ENCODER_NONE,
+			.port = 1,
+		},
+	},
+	.num_lvds = 0,
+};
+
 static const struct of_device_id rcar_du_of_table[] = {
 	{ .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
 	{ .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
 	{ .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
 	{ .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
+	{ .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
 	{ }
 };
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 7fd39a7d91c8..8e2ffe025153 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -49,9 +49,10 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 	u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;
 
 	/* The DEFR8 register for the first group also controls RGB output
-	 * routing to DPAD0
+	 * routing to DPAD0 for DU instances that support it.
 	 */
-	if (rgrp->index == 0)
+	if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1 &&
+	    rgrp->index == 0)
 		defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
 
 	rcar_du_group_write(rgrp, DEFR8, defr8);
-- 
2.4.6


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

* [PATCH 04/22] drm: rcar-du: Compute plane DDCR4 register value directly
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:50   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

There's no need for a read-modify-write pattern, all register bits can
be set explicitly.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_plane.c | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index ffa583712cd9..b20f3ceb55e6 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -28,13 +28,6 @@
 #define RCAR_DU_COLORKEY_SOURCE		(1 << 24)
 #define RCAR_DU_COLORKEY_MASK		(1 << 24)
 
-static u32 rcar_du_plane_read(struct rcar_du_group *rgrp,
-			      unsigned int index, u32 reg)
-{
-	return rcar_du_read(rgrp->dev,
-			    rgrp->mmio_offset + index * PLANE_OFF + reg);
-}
-
 static void rcar_du_plane_write(struct rcar_du_group *rgrp,
 				unsigned int index, u32 reg, u32 data)
 {
@@ -182,9 +175,6 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
 	 * The data format is selected by the DDDF field in PnMR and the EDF
 	 * field in DDCR4.
 	 */
-	ddcr4 = rcar_du_plane_read(rgrp, index, PnDDCR4);
-	ddcr4 &= ~PnDDCR4_EDF_MASK;
-	ddcr4 |= state->format->edf | PnDDCR4_CODE;
 
 	rcar_du_plane_setup_mode(plane, index);
 
@@ -204,6 +194,9 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
 	}
 
 	rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);
+
+	ddcr4 = state->format->edf | PnDDCR4_CODE;
+
 	rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
 
 	/* Destination position and size */
-- 
2.4.6


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

* [PATCH 04/22] drm: rcar-du: Compute plane DDCR4 register value directly
@ 2015-09-13 22:50   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

There's no need for a read-modify-write pattern, all register bits can
be set explicitly.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_plane.c | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index ffa583712cd9..b20f3ceb55e6 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -28,13 +28,6 @@
 #define RCAR_DU_COLORKEY_SOURCE		(1 << 24)
 #define RCAR_DU_COLORKEY_MASK		(1 << 24)
 
-static u32 rcar_du_plane_read(struct rcar_du_group *rgrp,
-			      unsigned int index, u32 reg)
-{
-	return rcar_du_read(rgrp->dev,
-			    rgrp->mmio_offset + index * PLANE_OFF + reg);
-}
-
 static void rcar_du_plane_write(struct rcar_du_group *rgrp,
 				unsigned int index, u32 reg, u32 data)
 {
@@ -182,9 +175,6 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
 	 * The data format is selected by the DDDF field in PnMR and the EDF
 	 * field in DDCR4.
 	 */
-	ddcr4 = rcar_du_plane_read(rgrp, index, PnDDCR4);
-	ddcr4 &= ~PnDDCR4_EDF_MASK;
-	ddcr4 |= state->format->edf | PnDDCR4_CODE;
 
 	rcar_du_plane_setup_mode(plane, index);
 
@@ -204,6 +194,9 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
 	}
 
 	rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);
+
+	ddcr4 = state->format->edf | PnDDCR4_CODE;
+
 	rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
 
 	/* Destination position and size */
-- 
2.4.6


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

* [PATCH 05/22] drm: rcar-du: Refactor plane setup
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:50   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

Rename plane setup functions using more explicit names, and use local
variables to store intermediate values to increase readability. This
also prepares for VSP compositor support.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_plane.c | 39 ++++++++++++++++++---------------
 1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index b20f3ceb55e6..d64b23027749 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -35,7 +35,7 @@ static void rcar_du_plane_write(struct rcar_du_group *rgrp,
 		      data);
 }
 
-static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
+static void rcar_du_plane_setup_scanout(struct rcar_du_plane *plane)
 {
 	struct rcar_du_plane_state *state  		to_rcar_plane_state(plane->plane.state);
@@ -45,8 +45,10 @@ static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
 	unsigned int src_y = state->state.src_y >> 16;
 	unsigned int index = state->hwindex;
 	struct drm_gem_cma_object *gem;
+	unsigned int pitch;
 	bool interlaced;
-	u32 mwr;
+	unsigned int i;
+	u32 dma[2];
 
 	interlaced = state->state.crtc->state->adjusted_mode.flags
 		   & DRM_MODE_FLAG_INTERLACE;
@@ -55,14 +57,18 @@ static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
 	 * operation with 32bpp formats.
 	 */
 	if (state->format->planes = 2)
-		mwr = fb->pitches[0];
+		pitch = fb->pitches[0];
 	else
-		mwr = fb->pitches[0] * 8 / state->format->bpp;
+		pitch = fb->pitches[0] * 8 / state->format->bpp;
 
-	if (interlaced && state->format->bpp = 32)
-		mwr *= 2;
+	for (i = 0; i < state->format->planes; ++i) {
+		gem = drm_fb_cma_get_gem_obj(fb, i);
+		dma[i] = gem->paddr + fb->offsets[i];
+	}
 
-	rcar_du_plane_write(rgrp, index, PnMWR, mwr);
+	rcar_du_plane_write(rgrp, index, PnMWR,
+			    (interlaced && state->format->bpp = 32) ?
+			    pitch * 2 : pitch);
 
 	/* The Y position is expressed in raster line units and must be doubled
 	 * for 32bpp formats, according to the R8A7790 datasheet. No mention of
@@ -80,21 +86,18 @@ static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
 	rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
 			    (!interlaced && state->format->bpp = 32 ? 2 : 1));
 
-	gem = drm_fb_cma_get_gem_obj(fb, 0);
-	rcar_du_plane_write(rgrp, index, PnDSA0R, gem->paddr + fb->offsets[0]);
+	rcar_du_plane_write(rgrp, index, PnDSA0R, dma[0]);
 
 	if (state->format->planes = 2) {
 		index = (index + 1) % 8;
 
-		rcar_du_plane_write(rgrp, index, PnMWR, fb->pitches[0]);
+		rcar_du_plane_write(rgrp, index, PnMWR, pitch);
 
 		rcar_du_plane_write(rgrp, index, PnSPXR, src_x);
 		rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
 				    (state->format->bpp = 16 ? 2 : 1) / 2);
 
-		gem = drm_fb_cma_get_gem_obj(fb, 1);
-		rcar_du_plane_write(rgrp, index, PnDSA0R,
-				    gem->paddr + fb->offsets[1]);
+		rcar_du_plane_write(rgrp, index, PnDSA0R, dma[1]);
 	}
 }
 
@@ -161,8 +164,8 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
 	}
 }
 
-static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
-				  unsigned int index)
+static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
+				       unsigned int index)
 {
 	struct rcar_du_plane_state *state  		to_rcar_plane_state(plane->plane.state);
@@ -217,11 +220,11 @@ void rcar_du_plane_setup(struct rcar_du_plane *plane)
 	struct rcar_du_plane_state *state  		to_rcar_plane_state(plane->plane.state);
 
-	__rcar_du_plane_setup(plane, state->hwindex);
+	rcar_du_plane_setup_format(plane, state->hwindex);
 	if (state->format->planes = 2)
-		__rcar_du_plane_setup(plane, (state->hwindex + 1) % 8);
+		rcar_du_plane_setup_format(plane, (state->hwindex + 1) % 8);
 
-	rcar_du_plane_setup_fb(plane);
+	rcar_du_plane_setup_scanout(plane);
 }
 
 static int rcar_du_plane_atomic_check(struct drm_plane *plane,
-- 
2.4.6


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

* [PATCH 05/22] drm: rcar-du: Refactor plane setup
@ 2015-09-13 22:50   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

Rename plane setup functions using more explicit names, and use local
variables to store intermediate values to increase readability. This
also prepares for VSP compositor support.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_plane.c | 39 ++++++++++++++++++---------------
 1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index b20f3ceb55e6..d64b23027749 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -35,7 +35,7 @@ static void rcar_du_plane_write(struct rcar_du_group *rgrp,
 		      data);
 }
 
-static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
+static void rcar_du_plane_setup_scanout(struct rcar_du_plane *plane)
 {
 	struct rcar_du_plane_state *state =
 		to_rcar_plane_state(plane->plane.state);
@@ -45,8 +45,10 @@ static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
 	unsigned int src_y = state->state.src_y >> 16;
 	unsigned int index = state->hwindex;
 	struct drm_gem_cma_object *gem;
+	unsigned int pitch;
 	bool interlaced;
-	u32 mwr;
+	unsigned int i;
+	u32 dma[2];
 
 	interlaced = state->state.crtc->state->adjusted_mode.flags
 		   & DRM_MODE_FLAG_INTERLACE;
@@ -55,14 +57,18 @@ static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
 	 * operation with 32bpp formats.
 	 */
 	if (state->format->planes == 2)
-		mwr = fb->pitches[0];
+		pitch = fb->pitches[0];
 	else
-		mwr = fb->pitches[0] * 8 / state->format->bpp;
+		pitch = fb->pitches[0] * 8 / state->format->bpp;
 
-	if (interlaced && state->format->bpp == 32)
-		mwr *= 2;
+	for (i = 0; i < state->format->planes; ++i) {
+		gem = drm_fb_cma_get_gem_obj(fb, i);
+		dma[i] = gem->paddr + fb->offsets[i];
+	}
 
-	rcar_du_plane_write(rgrp, index, PnMWR, mwr);
+	rcar_du_plane_write(rgrp, index, PnMWR,
+			    (interlaced && state->format->bpp == 32) ?
+			    pitch * 2 : pitch);
 
 	/* The Y position is expressed in raster line units and must be doubled
 	 * for 32bpp formats, according to the R8A7790 datasheet. No mention of
@@ -80,21 +86,18 @@ static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
 	rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
 			    (!interlaced && state->format->bpp == 32 ? 2 : 1));
 
-	gem = drm_fb_cma_get_gem_obj(fb, 0);
-	rcar_du_plane_write(rgrp, index, PnDSA0R, gem->paddr + fb->offsets[0]);
+	rcar_du_plane_write(rgrp, index, PnDSA0R, dma[0]);
 
 	if (state->format->planes == 2) {
 		index = (index + 1) % 8;
 
-		rcar_du_plane_write(rgrp, index, PnMWR, fb->pitches[0]);
+		rcar_du_plane_write(rgrp, index, PnMWR, pitch);
 
 		rcar_du_plane_write(rgrp, index, PnSPXR, src_x);
 		rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
 				    (state->format->bpp == 16 ? 2 : 1) / 2);
 
-		gem = drm_fb_cma_get_gem_obj(fb, 1);
-		rcar_du_plane_write(rgrp, index, PnDSA0R,
-				    gem->paddr + fb->offsets[1]);
+		rcar_du_plane_write(rgrp, index, PnDSA0R, dma[1]);
 	}
 }
 
@@ -161,8 +164,8 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
 	}
 }
 
-static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
-				  unsigned int index)
+static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
+				       unsigned int index)
 {
 	struct rcar_du_plane_state *state =
 		to_rcar_plane_state(plane->plane.state);
@@ -217,11 +220,11 @@ void rcar_du_plane_setup(struct rcar_du_plane *plane)
 	struct rcar_du_plane_state *state =
 		to_rcar_plane_state(plane->plane.state);
 
-	__rcar_du_plane_setup(plane, state->hwindex);
+	rcar_du_plane_setup_format(plane, state->hwindex);
 	if (state->format->planes == 2)
-		__rcar_du_plane_setup(plane, (state->hwindex + 1) % 8);
+		rcar_du_plane_setup_format(plane, (state->hwindex + 1) % 8);
 
-	rcar_du_plane_setup_fb(plane);
+	rcar_du_plane_setup_scanout(plane);
 }
 
 static int rcar_du_plane_atomic_check(struct drm_plane *plane,
-- 
2.4.6

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

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

* [PATCH 06/22] drm: rcar-du: Add VSP1 support to the planes allocator
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:50   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

The R8A7790 DU can source frames directly from the VSP1 devices VSPD0
and VSPD1. VSPD0 feeds DU0/1 plane 0, and VSPD1 feeds either DU2 plane 0
or DU0/1 plane 1.

Allocate the correct fixed plane when sourcing frames from VSPD0 or
VSPD1, and allocate planes in reverse index order otherwise to ensure
maximum availability of planes 0 and 1.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_kms.c   | 42 ++++++++++++++++++++++++++++-----
 drivers/gpu/drm/rcar-du/rcar_du_plane.c |  1 +
 drivers/gpu/drm/rcar-du/rcar_du_plane.h |  7 ++++++
 3 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 20813582fbf1..455f7e466181 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -244,11 +244,41 @@ static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
 	return mask;
 }
 
-static int rcar_du_plane_hwalloc(unsigned int num_planes, unsigned int free)
+/*
+ * The R8A7790 DU can source frames directly from the VSP1 devices VSPD0 and
+ * VSPD1. VSPD0 feeds DU0/1 plane 0, and VSPD1 feeds either DU2 plane 0 or
+ * DU0/1 plane 1.
+ *
+ * Allocate the correct fixed plane when sourcing frames from VSPD0 or VSPD1,
+ * and allocate planes in reverse index order otherwise to ensure maximum
+ * availability of planes 0 and 1.
+ *
+ * The caller is responsible for ensuring that the requested source is
+ * compatible with the DU revision.
+ */
+static int rcar_du_plane_hwalloc(struct rcar_du_plane *plane,
+				 struct rcar_du_plane_state *state,
+				 unsigned int free)
 {
-	unsigned int i;
+	unsigned int num_planes = state->format->planes;
+	int fixed = -1;
+	int i;
+
+	if (state->source = RCAR_DU_PLANE_VSPD0) {
+		/* VSPD0 feeds plane 0 on DU0/1. */
+		if (plane->group->index != 0)
+			return -EINVAL;
+
+		fixed = 0;
+	} else if (state->source = RCAR_DU_PLANE_VSPD1) {
+		/* VSPD1 feeds plane 1 on DU0/1 or plane 0 on DU2. */
+		fixed = plane->group->index = 0 ? 1 : 0;
+	}
+
+	if (fixed >= 0)
+		return free & (1 << fixed) ? fixed : -EBUSY;
 
-	for (i = 0; i < RCAR_DU_NUM_HW_PLANES; ++i) {
+	for (i = RCAR_DU_NUM_HW_PLANES - 1; i >= 0; --i) {
 		if (!(free & (1 << i)))
 			continue;
 
@@ -256,7 +286,7 @@ static int rcar_du_plane_hwalloc(unsigned int num_planes, unsigned int free)
 			break;
 	}
 
-	return i = RCAR_DU_NUM_HW_PLANES ? -EBUSY : i;
+	return i < 0 ? -EBUSY : i;
 }
 
 static int rcar_du_atomic_check(struct drm_device *dev,
@@ -413,10 +443,10 @@ static int rcar_du_atomic_check(struct drm_device *dev,
 			    : ~plane->group->dptsr_planes;
 		free = group_free_planes[plane->group->index];
 
-		idx = rcar_du_plane_hwalloc(plane_state->format->planes,
+		idx = rcar_du_plane_hwalloc(plane, plane_state,
 					    free & crtc_planes);
 		if (idx < 0)
-			idx = rcar_du_plane_hwalloc(plane_state->format->planes,
+			idx = rcar_du_plane_hwalloc(plane, plane_state,
 						    free);
 		if (idx < 0) {
 			dev_dbg(rcdu->dev, "%s: no available hardware plane\n",
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index d64b23027749..f301c15934cc 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -309,6 +309,7 @@ static void rcar_du_plane_reset(struct drm_plane *plane)
 		return;
 
 	state->hwindex = -1;
+	state->source = RCAR_DU_PLANE_MEMORY;
 	state->alpha = 255;
 	state->colorkey = RCAR_DU_COLORKEY_NONE;
 	state->zpos = plane->type = DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 9732bff1911b..e24e45828d6a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -28,6 +28,12 @@ struct rcar_du_group;
 #define RCAR_DU_NUM_KMS_PLANES		9
 #define RCAR_DU_NUM_HW_PLANES		8
 
+enum rcar_du_plane_source {
+	RCAR_DU_PLANE_MEMORY,
+	RCAR_DU_PLANE_VSPD0,
+	RCAR_DU_PLANE_VSPD1,
+};
+
 struct rcar_du_plane {
 	struct drm_plane plane;
 	struct rcar_du_group *group;
@@ -52,6 +58,7 @@ struct rcar_du_plane_state {
 
 	const struct rcar_du_format_info *format;
 	int hwindex;
+	enum rcar_du_plane_source source;
 
 	unsigned int alpha;
 	unsigned int colorkey;
-- 
2.4.6


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

* [PATCH 06/22] drm: rcar-du: Add VSP1 support to the planes allocator
@ 2015-09-13 22:50   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

The R8A7790 DU can source frames directly from the VSP1 devices VSPD0
and VSPD1. VSPD0 feeds DU0/1 plane 0, and VSPD1 feeds either DU2 plane 0
or DU0/1 plane 1.

Allocate the correct fixed plane when sourcing frames from VSPD0 or
VSPD1, and allocate planes in reverse index order otherwise to ensure
maximum availability of planes 0 and 1.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_kms.c   | 42 ++++++++++++++++++++++++++++-----
 drivers/gpu/drm/rcar-du/rcar_du_plane.c |  1 +
 drivers/gpu/drm/rcar-du/rcar_du_plane.h |  7 ++++++
 3 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 20813582fbf1..455f7e466181 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -244,11 +244,41 @@ static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
 	return mask;
 }
 
-static int rcar_du_plane_hwalloc(unsigned int num_planes, unsigned int free)
+/*
+ * The R8A7790 DU can source frames directly from the VSP1 devices VSPD0 and
+ * VSPD1. VSPD0 feeds DU0/1 plane 0, and VSPD1 feeds either DU2 plane 0 or
+ * DU0/1 plane 1.
+ *
+ * Allocate the correct fixed plane when sourcing frames from VSPD0 or VSPD1,
+ * and allocate planes in reverse index order otherwise to ensure maximum
+ * availability of planes 0 and 1.
+ *
+ * The caller is responsible for ensuring that the requested source is
+ * compatible with the DU revision.
+ */
+static int rcar_du_plane_hwalloc(struct rcar_du_plane *plane,
+				 struct rcar_du_plane_state *state,
+				 unsigned int free)
 {
-	unsigned int i;
+	unsigned int num_planes = state->format->planes;
+	int fixed = -1;
+	int i;
+
+	if (state->source == RCAR_DU_PLANE_VSPD0) {
+		/* VSPD0 feeds plane 0 on DU0/1. */
+		if (plane->group->index != 0)
+			return -EINVAL;
+
+		fixed = 0;
+	} else if (state->source == RCAR_DU_PLANE_VSPD1) {
+		/* VSPD1 feeds plane 1 on DU0/1 or plane 0 on DU2. */
+		fixed = plane->group->index == 0 ? 1 : 0;
+	}
+
+	if (fixed >= 0)
+		return free & (1 << fixed) ? fixed : -EBUSY;
 
-	for (i = 0; i < RCAR_DU_NUM_HW_PLANES; ++i) {
+	for (i = RCAR_DU_NUM_HW_PLANES - 1; i >= 0; --i) {
 		if (!(free & (1 << i)))
 			continue;
 
@@ -256,7 +286,7 @@ static int rcar_du_plane_hwalloc(unsigned int num_planes, unsigned int free)
 			break;
 	}
 
-	return i == RCAR_DU_NUM_HW_PLANES ? -EBUSY : i;
+	return i < 0 ? -EBUSY : i;
 }
 
 static int rcar_du_atomic_check(struct drm_device *dev,
@@ -413,10 +443,10 @@ static int rcar_du_atomic_check(struct drm_device *dev,
 			    : ~plane->group->dptsr_planes;
 		free = group_free_planes[plane->group->index];
 
-		idx = rcar_du_plane_hwalloc(plane_state->format->planes,
+		idx = rcar_du_plane_hwalloc(plane, plane_state,
 					    free & crtc_planes);
 		if (idx < 0)
-			idx = rcar_du_plane_hwalloc(plane_state->format->planes,
+			idx = rcar_du_plane_hwalloc(plane, plane_state,
 						    free);
 		if (idx < 0) {
 			dev_dbg(rcdu->dev, "%s: no available hardware plane\n",
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index d64b23027749..f301c15934cc 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -309,6 +309,7 @@ static void rcar_du_plane_reset(struct drm_plane *plane)
 		return;
 
 	state->hwindex = -1;
+	state->source = RCAR_DU_PLANE_MEMORY;
 	state->alpha = 255;
 	state->colorkey = RCAR_DU_COLORKEY_NONE;
 	state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 9732bff1911b..e24e45828d6a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -28,6 +28,12 @@ struct rcar_du_group;
 #define RCAR_DU_NUM_KMS_PLANES		9
 #define RCAR_DU_NUM_HW_PLANES		8
 
+enum rcar_du_plane_source {
+	RCAR_DU_PLANE_MEMORY,
+	RCAR_DU_PLANE_VSPD0,
+	RCAR_DU_PLANE_VSPD1,
+};
+
 struct rcar_du_plane {
 	struct drm_plane plane;
 	struct rcar_du_group *group;
@@ -52,6 +58,7 @@ struct rcar_du_plane_state {
 
 	const struct rcar_du_format_info *format;
 	int hwindex;
+	enum rcar_du_plane_source source;
 
 	unsigned int alpha;
 	unsigned int colorkey;
-- 
2.4.6


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

* [PATCH 07/22] drm: rcar-du: Add VSP1 compositor support
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:50   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

Configure the plane source at plane setup time to source frames from
memory or from the VSP1.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_drv.h   |  2 +
 drivers/gpu/drm/rcar-du/rcar_du_group.c | 24 +++++----
 drivers/gpu/drm/rcar-du/rcar_du_group.h |  2 +
 drivers/gpu/drm/rcar-du/rcar_du_kms.c   | 16 ++++--
 drivers/gpu/drm/rcar-du/rcar_du_plane.c | 86 +++++++++++++++++++--------------
 drivers/gpu/drm/rcar-du/rcar_du_regs.h  |  1 +
 6 files changed, 82 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index 9f34fc86436a..e10b4f0d8f83 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -90,6 +90,8 @@ struct rcar_du_device {
 	} props;
 
 	unsigned int dpad0_source;
+	unsigned int vspd1_sink;
+
 	struct rcar_du_lvdsenc *lvds[RCAR_DU_MAX_LVDS];
 
 	struct {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 8e2ffe025153..4a44ddd51766 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -49,11 +49,15 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 	u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;
 
 	/* The DEFR8 register for the first group also controls RGB output
-	 * routing to DPAD0 for DU instances that support it.
+	 * routing to DPAD0 and VSPD1 routing to DU0/1/2 for DU instances that
+	 * support it.
 	 */
-	if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1 &&
-	    rgrp->index = 0)
-		defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
+	if (rgrp->index = 0) {
+		if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1)
+			defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
+		if (rgrp->dev->vspd1_sink = 2)
+			defr8 |= DEFR8_VSCS;
+	}
 
 	rcar_du_group_write(rgrp, DEFR8, defr8);
 }
@@ -162,17 +166,17 @@ void rcar_du_group_restart(struct rcar_du_group *rgrp)
 	__rcar_du_group_start_stop(rgrp, true);
 }
 
-static int rcar_du_set_dpad0_routing(struct rcar_du_device *rcdu)
+int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu)
 {
 	int ret;
 
 	if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_EXT_CTRL_REGS))
 		return 0;
 
-	/* RGB output routing to DPAD0 is configured in the DEFR8 register of
-	 * the first group. As this function can be called with the DU0 and DU1
-	 * CRTCs disabled, we need to enable the first group clock before
-	 * accessing the register.
+	/* RGB output routing to DPAD0 and VSP1D routing to DU0/1/2 are
+	 * configured in the DEFR8 register of the first group. As this function
+	 * can be called with the DU0 and DU1 CRTCs disabled, we need to enable
+	 * the first group clock before accessing the register.
 	 */
 	ret = clk_prepare_enable(rcdu->crtcs[0].clock);
 	if (ret < 0)
@@ -203,5 +207,5 @@ int rcar_du_group_set_routing(struct rcar_du_group *rgrp)
 
 	rcar_du_group_write(rgrp, DORCR, dorcr);
 
-	return rcar_du_set_dpad0_routing(rgrp->dev);
+	return rcar_du_set_dpad0_vsp1_routing(rgrp->dev);
 }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h
index d7318e1a6b00..4b1952fd4e7d 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
@@ -58,4 +58,6 @@ void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start);
 void rcar_du_group_restart(struct rcar_du_group *rgrp);
 int rcar_du_group_set_routing(struct rcar_du_group *rgrp);
 
+int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu);
+
 #endif /* __RCAR_DU_GROUP_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 455f7e466181..ba4e100e5b0f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -217,17 +217,25 @@ static void rcar_du_output_poll_changed(struct drm_device *dev)
  */
 
 static bool rcar_du_plane_needs_realloc(struct rcar_du_plane *plane,
-					struct rcar_du_plane_state *state)
+					struct rcar_du_plane_state *new_state)
 {
-	const struct rcar_du_format_info *cur_format;
+	struct rcar_du_plane_state *cur_state;
 
-	cur_format = to_rcar_plane_state(plane->plane.state)->format;
+	cur_state = to_rcar_plane_state(plane->plane.state);
 
 	/* Lowering the number of planes doesn't strictly require reallocation
 	 * as the extra hardware plane will be freed when committing, but doing
 	 * so could lead to more fragmentation.
 	 */
-	return !cur_format || cur_format->planes != state->format->planes;
+	if (!cur_state->format ||
+	    cur_state->format->planes != new_state->format->planes)
+		return true;
+
+	/* Reallocate hardware planes if the source has changed. */
+	if (cur_state->source != new_state->source)
+		return true;
+
+	return false;
 }
 
 static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index f301c15934cc..78ca353bfcf0 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -20,6 +20,7 @@
 #include <drm/drm_plane_helper.h>
 
 #include "rcar_du_drv.h"
+#include "rcar_du_group.h"
 #include "rcar_du_kms.h"
 #include "rcar_du_plane.h"
 #include "rcar_du_regs.h"
@@ -35,37 +36,42 @@ static void rcar_du_plane_write(struct rcar_du_group *rgrp,
 		      data);
 }
 
-static void rcar_du_plane_setup_scanout(struct rcar_du_plane *plane)
+static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp,
+					const struct rcar_du_plane_state *state)
 {
-	struct rcar_du_plane_state *state -		to_rcar_plane_state(plane->plane.state);
-	struct drm_framebuffer *fb = plane->plane.state->fb;
-	struct rcar_du_group *rgrp = plane->group;
 	unsigned int src_x = state->state.src_x >> 16;
 	unsigned int src_y = state->state.src_y >> 16;
 	unsigned int index = state->hwindex;
-	struct drm_gem_cma_object *gem;
 	unsigned int pitch;
 	bool interlaced;
-	unsigned int i;
 	u32 dma[2];
 
 	interlaced = state->state.crtc->state->adjusted_mode.flags
 		   & DRM_MODE_FLAG_INTERLACE;
 
-	/* Memory pitch (expressed in pixels). Must be doubled for interlaced
-	 * operation with 32bpp formats.
-	 */
-	if (state->format->planes = 2)
-		pitch = fb->pitches[0];
-	else
-		pitch = fb->pitches[0] * 8 / state->format->bpp;
+	if (state->source = RCAR_DU_PLANE_MEMORY) {
+		struct drm_framebuffer *fb = state->state.fb;
+		struct drm_gem_cma_object *gem;
+		unsigned int i;
+
+		if (state->format->planes = 2)
+			pitch = fb->pitches[0];
+		else
+			pitch = fb->pitches[0] * 8 / state->format->bpp;
 
-	for (i = 0; i < state->format->planes; ++i) {
-		gem = drm_fb_cma_get_gem_obj(fb, i);
-		dma[i] = gem->paddr + fb->offsets[i];
+		for (i = 0; i < state->format->planes; ++i) {
+			gem = drm_fb_cma_get_gem_obj(fb, i);
+			dma[i] = gem->paddr + fb->offsets[i];
+		}
+	} else {
+		pitch = state->state.src_w >> 16;
+		dma[0] = 0;
+		dma[1] = 0;
 	}
 
+	/* Memory pitch (expressed in pixels). Must be doubled for interlaced
+	 * operation with 32bpp formats.
+	 */
 	rcar_du_plane_write(rgrp, index, PnMWR,
 			    (interlaced && state->format->bpp = 32) ?
 			    pitch * 2 : pitch);
@@ -101,12 +107,10 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_plane *plane)
 	}
 }
 
-static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
-				     unsigned int index)
+static void rcar_du_plane_setup_mode(struct rcar_du_group *rgrp,
+				     unsigned int index,
+				     const struct rcar_du_plane_state *state)
 {
-	struct rcar_du_plane_state *state -		to_rcar_plane_state(plane->plane.state);
-	struct rcar_du_group *rgrp = plane->group;
 	u32 colorkey;
 	u32 pnmr;
 
@@ -164,12 +168,10 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
 	}
 }
 
-static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
-				       unsigned int index)
+static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
+				       unsigned int index,
+				       const struct rcar_du_plane_state *state)
 {
-	struct rcar_du_plane_state *state -		to_rcar_plane_state(plane->plane.state);
-	struct rcar_du_group *rgrp = plane->group;
 	u32 ddcr2 = PnDDCR2_CODE;
 	u32 ddcr4;
 
@@ -179,7 +181,7 @@ static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
 	 * field in DDCR4.
 	 */
 
-	rcar_du_plane_setup_mode(plane, index);
+	rcar_du_plane_setup_mode(rgrp, index, state);
 
 	if (state->format->planes = 2) {
 		if (state->hwindex != index) {
@@ -199,14 +201,16 @@ static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
 	rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);
 
 	ddcr4 = state->format->edf | PnDDCR4_CODE;
+	if (state->source != RCAR_DU_PLANE_MEMORY)
+		ddcr4 |= PnDDCR4_VSPS;
 
 	rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
 
 	/* Destination position and size */
-	rcar_du_plane_write(rgrp, index, PnDSXR, plane->plane.state->crtc_w);
-	rcar_du_plane_write(rgrp, index, PnDSYR, plane->plane.state->crtc_h);
-	rcar_du_plane_write(rgrp, index, PnDPXR, plane->plane.state->crtc_x);
-	rcar_du_plane_write(rgrp, index, PnDPYR, plane->plane.state->crtc_y);
+	rcar_du_plane_write(rgrp, index, PnDSXR, state->state.crtc_w);
+	rcar_du_plane_write(rgrp, index, PnDSYR, state->state.crtc_h);
+	rcar_du_plane_write(rgrp, index, PnDPXR, state->state.crtc_x);
+	rcar_du_plane_write(rgrp, index, PnDPYR, state->state.crtc_y);
 
 	/* Wrap-around and blinking, disabled */
 	rcar_du_plane_write(rgrp, index, PnWASPR, 0);
@@ -219,12 +223,24 @@ void rcar_du_plane_setup(struct rcar_du_plane *plane)
 {
 	struct rcar_du_plane_state *state  		to_rcar_plane_state(plane->plane.state);
+	struct rcar_du_group *rgrp = plane->group;
 
-	rcar_du_plane_setup_format(plane, state->hwindex);
+	rcar_du_plane_setup_format(rgrp, state->hwindex, state);
 	if (state->format->planes = 2)
-		rcar_du_plane_setup_format(plane, (state->hwindex + 1) % 8);
+		rcar_du_plane_setup_format(rgrp, (state->hwindex + 1) % 8,
+					   state);
+
+	rcar_du_plane_setup_scanout(rgrp, state);
 
-	rcar_du_plane_setup_scanout(plane);
+	if (state->source = RCAR_DU_PLANE_VSPD1) {
+		unsigned int vspd1_sink = rgrp->index ? 2 : 0;
+		struct rcar_du_device *rcdu = rgrp->dev;
+
+		if (rcdu->vspd1_sink != vspd1_sink) {
+			rcdu->vspd1_sink = vspd1_sink;
+			rcar_du_set_dpad0_vsp1_routing(rcdu);
+		}
+	}
 }
 
 static int rcar_du_plane_atomic_check(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
index 70fcbc471ebd..ac9c3e511e79 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
@@ -389,6 +389,7 @@
 
 #define PnDDCR4			0x00190
 #define PnDDCR4_CODE		(0x7766 << 16)
+#define PnDDCR4_VSPS		(1 << 13)
 #define PnDDCR4_SDFS_RGB	(0 << 4)
 #define PnDDCR4_SDFS_YC		(5 << 4)
 #define PnDDCR4_SDFS_MASK	(7 << 4)
-- 
2.4.6


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

* [PATCH 07/22] drm: rcar-du: Add VSP1 compositor support
@ 2015-09-13 22:50   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

Configure the plane source at plane setup time to source frames from
memory or from the VSP1.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_drv.h   |  2 +
 drivers/gpu/drm/rcar-du/rcar_du_group.c | 24 +++++----
 drivers/gpu/drm/rcar-du/rcar_du_group.h |  2 +
 drivers/gpu/drm/rcar-du/rcar_du_kms.c   | 16 ++++--
 drivers/gpu/drm/rcar-du/rcar_du_plane.c | 86 +++++++++++++++++++--------------
 drivers/gpu/drm/rcar-du/rcar_du_regs.h  |  1 +
 6 files changed, 82 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index 9f34fc86436a..e10b4f0d8f83 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -90,6 +90,8 @@ struct rcar_du_device {
 	} props;
 
 	unsigned int dpad0_source;
+	unsigned int vspd1_sink;
+
 	struct rcar_du_lvdsenc *lvds[RCAR_DU_MAX_LVDS];
 
 	struct {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 8e2ffe025153..4a44ddd51766 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -49,11 +49,15 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 	u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;
 
 	/* The DEFR8 register for the first group also controls RGB output
-	 * routing to DPAD0 for DU instances that support it.
+	 * routing to DPAD0 and VSPD1 routing to DU0/1/2 for DU instances that
+	 * support it.
 	 */
-	if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1 &&
-	    rgrp->index == 0)
-		defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
+	if (rgrp->index == 0) {
+		if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1)
+			defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
+		if (rgrp->dev->vspd1_sink == 2)
+			defr8 |= DEFR8_VSCS;
+	}
 
 	rcar_du_group_write(rgrp, DEFR8, defr8);
 }
@@ -162,17 +166,17 @@ void rcar_du_group_restart(struct rcar_du_group *rgrp)
 	__rcar_du_group_start_stop(rgrp, true);
 }
 
-static int rcar_du_set_dpad0_routing(struct rcar_du_device *rcdu)
+int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu)
 {
 	int ret;
 
 	if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_EXT_CTRL_REGS))
 		return 0;
 
-	/* RGB output routing to DPAD0 is configured in the DEFR8 register of
-	 * the first group. As this function can be called with the DU0 and DU1
-	 * CRTCs disabled, we need to enable the first group clock before
-	 * accessing the register.
+	/* RGB output routing to DPAD0 and VSP1D routing to DU0/1/2 are
+	 * configured in the DEFR8 register of the first group. As this function
+	 * can be called with the DU0 and DU1 CRTCs disabled, we need to enable
+	 * the first group clock before accessing the register.
 	 */
 	ret = clk_prepare_enable(rcdu->crtcs[0].clock);
 	if (ret < 0)
@@ -203,5 +207,5 @@ int rcar_du_group_set_routing(struct rcar_du_group *rgrp)
 
 	rcar_du_group_write(rgrp, DORCR, dorcr);
 
-	return rcar_du_set_dpad0_routing(rgrp->dev);
+	return rcar_du_set_dpad0_vsp1_routing(rgrp->dev);
 }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h
index d7318e1a6b00..4b1952fd4e7d 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
@@ -58,4 +58,6 @@ void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start);
 void rcar_du_group_restart(struct rcar_du_group *rgrp);
 int rcar_du_group_set_routing(struct rcar_du_group *rgrp);
 
+int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu);
+
 #endif /* __RCAR_DU_GROUP_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 455f7e466181..ba4e100e5b0f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -217,17 +217,25 @@ static void rcar_du_output_poll_changed(struct drm_device *dev)
  */
 
 static bool rcar_du_plane_needs_realloc(struct rcar_du_plane *plane,
-					struct rcar_du_plane_state *state)
+					struct rcar_du_plane_state *new_state)
 {
-	const struct rcar_du_format_info *cur_format;
+	struct rcar_du_plane_state *cur_state;
 
-	cur_format = to_rcar_plane_state(plane->plane.state)->format;
+	cur_state = to_rcar_plane_state(plane->plane.state);
 
 	/* Lowering the number of planes doesn't strictly require reallocation
 	 * as the extra hardware plane will be freed when committing, but doing
 	 * so could lead to more fragmentation.
 	 */
-	return !cur_format || cur_format->planes != state->format->planes;
+	if (!cur_state->format ||
+	    cur_state->format->planes != new_state->format->planes)
+		return true;
+
+	/* Reallocate hardware planes if the source has changed. */
+	if (cur_state->source != new_state->source)
+		return true;
+
+	return false;
 }
 
 static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index f301c15934cc..78ca353bfcf0 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -20,6 +20,7 @@
 #include <drm/drm_plane_helper.h>
 
 #include "rcar_du_drv.h"
+#include "rcar_du_group.h"
 #include "rcar_du_kms.h"
 #include "rcar_du_plane.h"
 #include "rcar_du_regs.h"
@@ -35,37 +36,42 @@ static void rcar_du_plane_write(struct rcar_du_group *rgrp,
 		      data);
 }
 
-static void rcar_du_plane_setup_scanout(struct rcar_du_plane *plane)
+static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp,
+					const struct rcar_du_plane_state *state)
 {
-	struct rcar_du_plane_state *state =
-		to_rcar_plane_state(plane->plane.state);
-	struct drm_framebuffer *fb = plane->plane.state->fb;
-	struct rcar_du_group *rgrp = plane->group;
 	unsigned int src_x = state->state.src_x >> 16;
 	unsigned int src_y = state->state.src_y >> 16;
 	unsigned int index = state->hwindex;
-	struct drm_gem_cma_object *gem;
 	unsigned int pitch;
 	bool interlaced;
-	unsigned int i;
 	u32 dma[2];
 
 	interlaced = state->state.crtc->state->adjusted_mode.flags
 		   & DRM_MODE_FLAG_INTERLACE;
 
-	/* Memory pitch (expressed in pixels). Must be doubled for interlaced
-	 * operation with 32bpp formats.
-	 */
-	if (state->format->planes == 2)
-		pitch = fb->pitches[0];
-	else
-		pitch = fb->pitches[0] * 8 / state->format->bpp;
+	if (state->source == RCAR_DU_PLANE_MEMORY) {
+		struct drm_framebuffer *fb = state->state.fb;
+		struct drm_gem_cma_object *gem;
+		unsigned int i;
+
+		if (state->format->planes == 2)
+			pitch = fb->pitches[0];
+		else
+			pitch = fb->pitches[0] * 8 / state->format->bpp;
 
-	for (i = 0; i < state->format->planes; ++i) {
-		gem = drm_fb_cma_get_gem_obj(fb, i);
-		dma[i] = gem->paddr + fb->offsets[i];
+		for (i = 0; i < state->format->planes; ++i) {
+			gem = drm_fb_cma_get_gem_obj(fb, i);
+			dma[i] = gem->paddr + fb->offsets[i];
+		}
+	} else {
+		pitch = state->state.src_w >> 16;
+		dma[0] = 0;
+		dma[1] = 0;
 	}
 
+	/* Memory pitch (expressed in pixels). Must be doubled for interlaced
+	 * operation with 32bpp formats.
+	 */
 	rcar_du_plane_write(rgrp, index, PnMWR,
 			    (interlaced && state->format->bpp == 32) ?
 			    pitch * 2 : pitch);
@@ -101,12 +107,10 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_plane *plane)
 	}
 }
 
-static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
-				     unsigned int index)
+static void rcar_du_plane_setup_mode(struct rcar_du_group *rgrp,
+				     unsigned int index,
+				     const struct rcar_du_plane_state *state)
 {
-	struct rcar_du_plane_state *state =
-		to_rcar_plane_state(plane->plane.state);
-	struct rcar_du_group *rgrp = plane->group;
 	u32 colorkey;
 	u32 pnmr;
 
@@ -164,12 +168,10 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
 	}
 }
 
-static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
-				       unsigned int index)
+static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
+				       unsigned int index,
+				       const struct rcar_du_plane_state *state)
 {
-	struct rcar_du_plane_state *state =
-		to_rcar_plane_state(plane->plane.state);
-	struct rcar_du_group *rgrp = plane->group;
 	u32 ddcr2 = PnDDCR2_CODE;
 	u32 ddcr4;
 
@@ -179,7 +181,7 @@ static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
 	 * field in DDCR4.
 	 */
 
-	rcar_du_plane_setup_mode(plane, index);
+	rcar_du_plane_setup_mode(rgrp, index, state);
 
 	if (state->format->planes == 2) {
 		if (state->hwindex != index) {
@@ -199,14 +201,16 @@ static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
 	rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);
 
 	ddcr4 = state->format->edf | PnDDCR4_CODE;
+	if (state->source != RCAR_DU_PLANE_MEMORY)
+		ddcr4 |= PnDDCR4_VSPS;
 
 	rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
 
 	/* Destination position and size */
-	rcar_du_plane_write(rgrp, index, PnDSXR, plane->plane.state->crtc_w);
-	rcar_du_plane_write(rgrp, index, PnDSYR, plane->plane.state->crtc_h);
-	rcar_du_plane_write(rgrp, index, PnDPXR, plane->plane.state->crtc_x);
-	rcar_du_plane_write(rgrp, index, PnDPYR, plane->plane.state->crtc_y);
+	rcar_du_plane_write(rgrp, index, PnDSXR, state->state.crtc_w);
+	rcar_du_plane_write(rgrp, index, PnDSYR, state->state.crtc_h);
+	rcar_du_plane_write(rgrp, index, PnDPXR, state->state.crtc_x);
+	rcar_du_plane_write(rgrp, index, PnDPYR, state->state.crtc_y);
 
 	/* Wrap-around and blinking, disabled */
 	rcar_du_plane_write(rgrp, index, PnWASPR, 0);
@@ -219,12 +223,24 @@ void rcar_du_plane_setup(struct rcar_du_plane *plane)
 {
 	struct rcar_du_plane_state *state =
 		to_rcar_plane_state(plane->plane.state);
+	struct rcar_du_group *rgrp = plane->group;
 
-	rcar_du_plane_setup_format(plane, state->hwindex);
+	rcar_du_plane_setup_format(rgrp, state->hwindex, state);
 	if (state->format->planes == 2)
-		rcar_du_plane_setup_format(plane, (state->hwindex + 1) % 8);
+		rcar_du_plane_setup_format(rgrp, (state->hwindex + 1) % 8,
+					   state);
+
+	rcar_du_plane_setup_scanout(rgrp, state);
 
-	rcar_du_plane_setup_scanout(plane);
+	if (state->source == RCAR_DU_PLANE_VSPD1) {
+		unsigned int vspd1_sink = rgrp->index ? 2 : 0;
+		struct rcar_du_device *rcdu = rgrp->dev;
+
+		if (rcdu->vspd1_sink != vspd1_sink) {
+			rcdu->vspd1_sink = vspd1_sink;
+			rcar_du_set_dpad0_vsp1_routing(rcdu);
+		}
+	}
 }
 
 static int rcar_du_plane_atomic_check(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
index 70fcbc471ebd..ac9c3e511e79 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
@@ -389,6 +389,7 @@
 
 #define PnDDCR4			0x00190
 #define PnDDCR4_CODE		(0x7766 << 16)
+#define PnDDCR4_VSPS		(1 << 13)
 #define PnDDCR4_SDFS_RGB	(0 << 4)
 #define PnDDCR4_SDFS_YC		(5 << 4)
 #define PnDDCR4_SDFS_MASK	(7 << 4)
-- 
2.4.6


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

* [PATCH 08/22] drm: rcar-du: Restart the DU group when a plane source changes
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:50   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

Plane sources are configured by the VSPS bit in the PnDDCR4 register.
Although the datasheet states that the bit is updated during vertical
blanking, it seems that updates only occur when the DU group is held in
reset through the DSYSR.DRES bit. Restart the group if the source
changes.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  4 ++++
 drivers/gpu/drm/rcar-du/rcar_du_group.c |  2 ++
 drivers/gpu/drm/rcar-du/rcar_du_group.h |  2 ++
 drivers/gpu/drm/rcar-du/rcar_du_plane.c | 22 ++++++++++++++++++++--
 4 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 48cb19949ca3..7e2f5c26d589 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -272,6 +272,10 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
 			rcar_du_group_restart(rcrtc->group);
 	}
 
+	/* Restart the group if plane sources have changed. */
+	if (rcrtc->group->need_restart)
+		rcar_du_group_restart(rcrtc->group);
+
 	mutex_unlock(&rcrtc->group->lock);
 
 	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 4a44ddd51766..0e2b46dce563 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -162,6 +162,8 @@ void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
 
 void rcar_du_group_restart(struct rcar_du_group *rgrp)
 {
+	rgrp->need_restart = false;
+
 	__rcar_du_group_start_stop(rgrp, false);
 	__rcar_du_group_start_stop(rgrp, true);
 }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h
index 4b1952fd4e7d..5e3adc6b31b5 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
@@ -32,6 +32,7 @@ struct rcar_du_device;
  * @dptsr_planes: bitmask of planes driven by dot-clock and timing generator 1
  * @num_planes: number of planes in the group
  * @planes: planes handled by the group
+ * @need_restart: the group needs to be restarted due to a configuration change
  */
 struct rcar_du_group {
 	struct rcar_du_device *dev;
@@ -47,6 +48,7 @@ struct rcar_du_group {
 
 	unsigned int num_planes;
 	struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
+	bool need_restart;
 };
 
 u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 78ca353bfcf0..c7e0535c0e77 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -275,9 +275,27 @@ static void rcar_du_plane_atomic_update(struct drm_plane *plane,
 					struct drm_plane_state *old_state)
 {
 	struct rcar_du_plane *rplane = to_rcar_plane(plane);
+	struct rcar_du_plane_state *old_rstate;
+	struct rcar_du_plane_state *new_rstate;
 
-	if (plane->state->crtc)
-		rcar_du_plane_setup(rplane);
+	if (!plane->state->crtc)
+		return;
+
+	rcar_du_plane_setup(rplane);
+
+	/* Check whether the source has changed from memory to live source or
+	 * from live source to memory. The source has been configured by the
+	 * VSPS bit in the PnDDCR4 register. Although the datasheet states that
+	 * the bit is updated during vertical blanking, it seems that updates
+	 * only occur when the DU group is held in reset through the DSYSR.DRES
+	 * bit. We thus need to restart the group if the source changes.
+	 */
+	old_rstate = to_rcar_plane_state(old_state);
+	new_rstate = to_rcar_plane_state(plane->state);
+
+	if ((old_rstate->source = RCAR_DU_PLANE_MEMORY) !+	    (new_rstate->source = RCAR_DU_PLANE_MEMORY))
+		rplane->group->need_restart = true;
 }
 
 static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = {
-- 
2.4.6


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

* [PATCH 08/22] drm: rcar-du: Restart the DU group when a plane source changes
@ 2015-09-13 22:50   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

Plane sources are configured by the VSPS bit in the PnDDCR4 register.
Although the datasheet states that the bit is updated during vertical
blanking, it seems that updates only occur when the DU group is held in
reset through the DSYSR.DRES bit. Restart the group if the source
changes.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  4 ++++
 drivers/gpu/drm/rcar-du/rcar_du_group.c |  2 ++
 drivers/gpu/drm/rcar-du/rcar_du_group.h |  2 ++
 drivers/gpu/drm/rcar-du/rcar_du_plane.c | 22 ++++++++++++++++++++--
 4 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 48cb19949ca3..7e2f5c26d589 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -272,6 +272,10 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
 			rcar_du_group_restart(rcrtc->group);
 	}
 
+	/* Restart the group if plane sources have changed. */
+	if (rcrtc->group->need_restart)
+		rcar_du_group_restart(rcrtc->group);
+
 	mutex_unlock(&rcrtc->group->lock);
 
 	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 4a44ddd51766..0e2b46dce563 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -162,6 +162,8 @@ void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
 
 void rcar_du_group_restart(struct rcar_du_group *rgrp)
 {
+	rgrp->need_restart = false;
+
 	__rcar_du_group_start_stop(rgrp, false);
 	__rcar_du_group_start_stop(rgrp, true);
 }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h
index 4b1952fd4e7d..5e3adc6b31b5 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
@@ -32,6 +32,7 @@ struct rcar_du_device;
  * @dptsr_planes: bitmask of planes driven by dot-clock and timing generator 1
  * @num_planes: number of planes in the group
  * @planes: planes handled by the group
+ * @need_restart: the group needs to be restarted due to a configuration change
  */
 struct rcar_du_group {
 	struct rcar_du_device *dev;
@@ -47,6 +48,7 @@ struct rcar_du_group {
 
 	unsigned int num_planes;
 	struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
+	bool need_restart;
 };
 
 u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 78ca353bfcf0..c7e0535c0e77 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -275,9 +275,27 @@ static void rcar_du_plane_atomic_update(struct drm_plane *plane,
 					struct drm_plane_state *old_state)
 {
 	struct rcar_du_plane *rplane = to_rcar_plane(plane);
+	struct rcar_du_plane_state *old_rstate;
+	struct rcar_du_plane_state *new_rstate;
 
-	if (plane->state->crtc)
-		rcar_du_plane_setup(rplane);
+	if (!plane->state->crtc)
+		return;
+
+	rcar_du_plane_setup(rplane);
+
+	/* Check whether the source has changed from memory to live source or
+	 * from live source to memory. The source has been configured by the
+	 * VSPS bit in the PnDDCR4 register. Although the datasheet states that
+	 * the bit is updated during vertical blanking, it seems that updates
+	 * only occur when the DU group is held in reset through the DSYSR.DRES
+	 * bit. We thus need to restart the group if the source changes.
+	 */
+	old_rstate = to_rcar_plane_state(old_state);
+	new_rstate = to_rcar_plane_state(plane->state);
+
+	if ((old_rstate->source == RCAR_DU_PLANE_MEMORY) !=
+	    (new_rstate->source == RCAR_DU_PLANE_MEMORY))
+		rplane->group->need_restart = true;
 }
 
 static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = {
-- 
2.4.6


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

* [PATCH 09/22] drm: rcar-du: Move plane allocator to rcar_du_plane.c
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:50   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

The plane allocator is specific to DU planes and won't be used for
VSP-based planes, move it with the rest of the DU planes code where it
belongs.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_kms.c   | 276 +-----------------------------
 drivers/gpu/drm/rcar-du/rcar_du_plane.c | 286 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/rcar-du/rcar_du_plane.h |   3 +
 3 files changed, 290 insertions(+), 275 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index ba4e100e5b0f..6196410b9e98 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -192,290 +192,16 @@ static void rcar_du_output_poll_changed(struct drm_device *dev)
  * Atomic Check and Update
  */
 
-/*
- * Atomic hardware plane allocator
- *
- * The hardware plane allocator is solely based on the atomic plane states
- * without keeping any external state to avoid races between .atomic_check()
- * and .atomic_commit().
- *
- * The core idea is to avoid using a free planes bitmask that would need to be
- * shared between check and commit handlers with a collective knowledge based on
- * the allocated hardware plane(s) for each KMS plane. The allocator then loops
- * over all plane states to compute the free planes bitmask, allocates hardware
- * planes based on that bitmask, and stores the result back in the plane states.
- *
- * For this to work we need to access the current state of planes not touched by
- * the atomic update. To ensure that it won't be modified, we need to lock all
- * planes using drm_atomic_get_plane_state(). This effectively serializes atomic
- * updates from .atomic_check() up to completion (when swapping the states if
- * the check step has succeeded) or rollback (when freeing the states if the
- * check step has failed).
- *
- * Allocation is performed in the .atomic_check() handler and applied
- * automatically when the core swaps the old and new states.
- */
-
-static bool rcar_du_plane_needs_realloc(struct rcar_du_plane *plane,
-					struct rcar_du_plane_state *new_state)
-{
-	struct rcar_du_plane_state *cur_state;
-
-	cur_state = to_rcar_plane_state(plane->plane.state);
-
-	/* Lowering the number of planes doesn't strictly require reallocation
-	 * as the extra hardware plane will be freed when committing, but doing
-	 * so could lead to more fragmentation.
-	 */
-	if (!cur_state->format ||
-	    cur_state->format->planes != new_state->format->planes)
-		return true;
-
-	/* Reallocate hardware planes if the source has changed. */
-	if (cur_state->source != new_state->source)
-		return true;
-
-	return false;
-}
-
-static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
-{
-	unsigned int mask;
-
-	if (state->hwindex = -1)
-		return 0;
-
-	mask = 1 << state->hwindex;
-	if (state->format->planes = 2)
-		mask |= 1 << ((state->hwindex + 1) % 8);
-
-	return mask;
-}
-
-/*
- * The R8A7790 DU can source frames directly from the VSP1 devices VSPD0 and
- * VSPD1. VSPD0 feeds DU0/1 plane 0, and VSPD1 feeds either DU2 plane 0 or
- * DU0/1 plane 1.
- *
- * Allocate the correct fixed plane when sourcing frames from VSPD0 or VSPD1,
- * and allocate planes in reverse index order otherwise to ensure maximum
- * availability of planes 0 and 1.
- *
- * The caller is responsible for ensuring that the requested source is
- * compatible with the DU revision.
- */
-static int rcar_du_plane_hwalloc(struct rcar_du_plane *plane,
-				 struct rcar_du_plane_state *state,
-				 unsigned int free)
-{
-	unsigned int num_planes = state->format->planes;
-	int fixed = -1;
-	int i;
-
-	if (state->source = RCAR_DU_PLANE_VSPD0) {
-		/* VSPD0 feeds plane 0 on DU0/1. */
-		if (plane->group->index != 0)
-			return -EINVAL;
-
-		fixed = 0;
-	} else if (state->source = RCAR_DU_PLANE_VSPD1) {
-		/* VSPD1 feeds plane 1 on DU0/1 or plane 0 on DU2. */
-		fixed = plane->group->index = 0 ? 1 : 0;
-	}
-
-	if (fixed >= 0)
-		return free & (1 << fixed) ? fixed : -EBUSY;
-
-	for (i = RCAR_DU_NUM_HW_PLANES - 1; i >= 0; --i) {
-		if (!(free & (1 << i)))
-			continue;
-
-		if (num_planes = 1 || free & (1 << ((i + 1) % 8)))
-			break;
-	}
-
-	return i < 0 ? -EBUSY : i;
-}
-
 static int rcar_du_atomic_check(struct drm_device *dev,
 				struct drm_atomic_state *state)
 {
-	struct rcar_du_device *rcdu = dev->dev_private;
-	unsigned int group_freed_planes[RCAR_DU_MAX_GROUPS] = { 0, };
-	unsigned int group_free_planes[RCAR_DU_MAX_GROUPS] = { 0, };
-	bool needs_realloc = false;
-	unsigned int groups = 0;
-	unsigned int i;
 	int ret;
 
 	ret = drm_atomic_helper_check(dev, state);
 	if (ret < 0)
 		return ret;
 
-	/* Check if hardware planes need to be reallocated. */
-	for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
-		struct rcar_du_plane_state *plane_state;
-		struct rcar_du_plane *plane;
-		unsigned int index;
-
-		if (!state->planes[i])
-			continue;
-
-		plane = to_rcar_plane(state->planes[i]);
-		plane_state = to_rcar_plane_state(state->plane_states[i]);
-
-		dev_dbg(rcdu->dev, "%s: checking plane (%u,%u)\n", __func__,
-			plane->group->index, plane - plane->group->planes);
-
-		/* If the plane is being disabled we don't need to go through
-		 * the full reallocation procedure. Just mark the hardware
-		 * plane(s) as freed.
-		 */
-		if (!plane_state->format) {
-			dev_dbg(rcdu->dev, "%s: plane is being disabled\n",
-				__func__);
-			index = plane - plane->group->planes;
-			group_freed_planes[plane->group->index] |= 1 << index;
-			plane_state->hwindex = -1;
-			continue;
-		}
-
-		/* If the plane needs to be reallocated mark it as such, and
-		 * mark the hardware plane(s) as free.
-		 */
-		if (rcar_du_plane_needs_realloc(plane, plane_state)) {
-			dev_dbg(rcdu->dev, "%s: plane needs reallocation\n",
-				__func__);
-			groups |= 1 << plane->group->index;
-			needs_realloc = true;
-
-			index = plane - plane->group->planes;
-			group_freed_planes[plane->group->index] |= 1 << index;
-			plane_state->hwindex = -1;
-		}
-	}
-
-	if (!needs_realloc)
-		return 0;
-
-	/* Grab all plane states for the groups that need reallocation to ensure
-	 * locking and avoid racy updates. This serializes the update operation,
-	 * but there's not much we can do about it as that's the hardware
-	 * design.
-	 *
-	 * Compute the used planes mask for each group at the same time to avoid
-	 * looping over the planes separately later.
-	 */
-	while (groups) {
-		unsigned int index = ffs(groups) - 1;
-		struct rcar_du_group *group = &rcdu->groups[index];
-		unsigned int used_planes = 0;
-
-		dev_dbg(rcdu->dev, "%s: finding free planes for group %u\n",
-			__func__, index);
-
-		for (i = 0; i < group->num_planes; ++i) {
-			struct rcar_du_plane *plane = &group->planes[i];
-			struct rcar_du_plane_state *plane_state;
-			struct drm_plane_state *s;
-
-			s = drm_atomic_get_plane_state(state, &plane->plane);
-			if (IS_ERR(s))
-				return PTR_ERR(s);
-
-			/* If the plane has been freed in the above loop its
-			 * hardware planes must not be added to the used planes
-			 * bitmask. However, the current state doesn't reflect
-			 * the free state yet, as we've modified the new state
-			 * above. Use the local freed planes list to check for
-			 * that condition instead.
-			 */
-			if (group_freed_planes[index] & (1 << i)) {
-				dev_dbg(rcdu->dev,
-					"%s: plane (%u,%u) has been freed, skipping\n",
-					__func__, plane->group->index,
-					plane - plane->group->planes);
-				continue;
-			}
-
-			plane_state = to_rcar_plane_state(plane->plane.state);
-			used_planes |= rcar_du_plane_hwmask(plane_state);
-
-			dev_dbg(rcdu->dev,
-				"%s: plane (%u,%u) uses %u hwplanes (index %d)\n",
-				__func__, plane->group->index,
-				plane - plane->group->planes,
-				plane_state->format ?
-				plane_state->format->planes : 0,
-				plane_state->hwindex);
-		}
-
-		group_free_planes[index] = 0xff & ~used_planes;
-		groups &= ~(1 << index);
-
-		dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
-			__func__, index, group_free_planes[index]);
-	}
-
-	/* Reallocate hardware planes for each plane that needs it. */
-	for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
-		struct rcar_du_plane_state *plane_state;
-		struct rcar_du_plane *plane;
-		unsigned int crtc_planes;
-		unsigned int free;
-		int idx;
-
-		if (!state->planes[i])
-			continue;
-
-		plane = to_rcar_plane(state->planes[i]);
-		plane_state = to_rcar_plane_state(state->plane_states[i]);
-
-		dev_dbg(rcdu->dev, "%s: allocating plane (%u,%u)\n", __func__,
-			plane->group->index, plane - plane->group->planes);
-
-		/* Skip planes that are being disabled or don't need to be
-		 * reallocated.
-		 */
-		if (!plane_state->format ||
-		    !rcar_du_plane_needs_realloc(plane, plane_state))
-			continue;
-
-		/* Try to allocate the plane from the free planes currently
-		 * associated with the target CRTC to avoid restarting the CRTC
-		 * group and thus minimize flicker. If it fails fall back to
-		 * allocating from all free planes.
-		 */
-		crtc_planes = to_rcar_crtc(plane_state->state.crtc)->index % 2
-			    ? plane->group->dptsr_planes
-			    : ~plane->group->dptsr_planes;
-		free = group_free_planes[plane->group->index];
-
-		idx = rcar_du_plane_hwalloc(plane, plane_state,
-					    free & crtc_planes);
-		if (idx < 0)
-			idx = rcar_du_plane_hwalloc(plane, plane_state,
-						    free);
-		if (idx < 0) {
-			dev_dbg(rcdu->dev, "%s: no available hardware plane\n",
-				__func__);
-			return idx;
-		}
-
-		dev_dbg(rcdu->dev, "%s: allocated %u hwplanes (index %u)\n",
-			__func__, plane_state->format->planes, idx);
-
-		plane_state->hwindex = idx;
-
-		group_free_planes[plane->group->index] &-			~rcar_du_plane_hwmask(plane_state);
-
-		dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
-			__func__, plane->group->index,
-			group_free_planes[plane->group->index]);
-	}
-
-	return 0;
+	return rcar_du_atomic_check_planes(dev, state);
 }
 
 struct rcar_du_commit {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index c7e0535c0e77..b868184e8385 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -12,6 +12,7 @@
  */
 
 #include <drm/drmP.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
@@ -25,6 +26,291 @@
 #include "rcar_du_plane.h"
 #include "rcar_du_regs.h"
 
+/* -----------------------------------------------------------------------------
+ * Atomic hardware plane allocator
+ *
+ * The hardware plane allocator is solely based on the atomic plane states
+ * without keeping any external state to avoid races between .atomic_check()
+ * and .atomic_commit().
+ *
+ * The core idea is to avoid using a free planes bitmask that would need to be
+ * shared between check and commit handlers with a collective knowledge based on
+ * the allocated hardware plane(s) for each KMS plane. The allocator then loops
+ * over all plane states to compute the free planes bitmask, allocates hardware
+ * planes based on that bitmask, and stores the result back in the plane states.
+ *
+ * For this to work we need to access the current state of planes not touched by
+ * the atomic update. To ensure that it won't be modified, we need to lock all
+ * planes using drm_atomic_get_plane_state(). This effectively serializes atomic
+ * updates from .atomic_check() up to completion (when swapping the states if
+ * the check step has succeeded) or rollback (when freeing the states if the
+ * check step has failed).
+ *
+ * Allocation is performed in the .atomic_check() handler and applied
+ * automatically when the core swaps the old and new states.
+ */
+
+static bool rcar_du_plane_needs_realloc(struct rcar_du_plane *plane,
+					struct rcar_du_plane_state *new_state)
+{
+	struct rcar_du_plane_state *cur_state;
+
+	cur_state = to_rcar_plane_state(plane->plane.state);
+
+	/* Lowering the number of planes doesn't strictly require reallocation
+	 * as the extra hardware plane will be freed when committing, but doing
+	 * so could lead to more fragmentation.
+	 */
+	if (!cur_state->format ||
+	    cur_state->format->planes != new_state->format->planes)
+		return true;
+
+	/* Reallocate hardware planes if the source has changed. */
+	if (cur_state->source != new_state->source)
+		return true;
+
+	return false;
+}
+
+static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
+{
+	unsigned int mask;
+
+	if (state->hwindex = -1)
+		return 0;
+
+	mask = 1 << state->hwindex;
+	if (state->format->planes = 2)
+		mask |= 1 << ((state->hwindex + 1) % 8);
+
+	return mask;
+}
+
+/*
+ * The R8A7790 DU can source frames directly from the VSP1 devices VSPD0 and
+ * VSPD1. VSPD0 feeds DU0/1 plane 0, and VSPD1 feeds either DU2 plane 0 or
+ * DU0/1 plane 1.
+ *
+ * Allocate the correct fixed plane when sourcing frames from VSPD0 or VSPD1,
+ * and allocate planes in reverse index order otherwise to ensure maximum
+ * availability of planes 0 and 1.
+ *
+ * The caller is responsible for ensuring that the requested source is
+ * compatible with the DU revision.
+ */
+static int rcar_du_plane_hwalloc(struct rcar_du_plane *plane,
+				 struct rcar_du_plane_state *state,
+				 unsigned int free)
+{
+	unsigned int num_planes = state->format->planes;
+	int fixed = -1;
+	int i;
+
+	if (state->source = RCAR_DU_PLANE_VSPD0) {
+		/* VSPD0 feeds plane 0 on DU0/1. */
+		if (plane->group->index != 0)
+			return -EINVAL;
+
+		fixed = 0;
+	} else if (state->source = RCAR_DU_PLANE_VSPD1) {
+		/* VSPD1 feeds plane 1 on DU0/1 or plane 0 on DU2. */
+		fixed = plane->group->index = 0 ? 1 : 0;
+	}
+
+	if (fixed >= 0)
+		return free & (1 << fixed) ? fixed : -EBUSY;
+
+	for (i = RCAR_DU_NUM_HW_PLANES - 1; i >= 0; --i) {
+		if (!(free & (1 << i)))
+			continue;
+
+		if (num_planes = 1 || free & (1 << ((i + 1) % 8)))
+			break;
+	}
+
+	return i < 0 ? -EBUSY : i;
+}
+
+int rcar_du_atomic_check_planes(struct drm_device *dev,
+				struct drm_atomic_state *state)
+{
+	struct rcar_du_device *rcdu = dev->dev_private;
+	unsigned int group_freed_planes[RCAR_DU_MAX_GROUPS] = { 0, };
+	unsigned int group_free_planes[RCAR_DU_MAX_GROUPS] = { 0, };
+	bool needs_realloc = false;
+	unsigned int groups = 0;
+	unsigned int i;
+
+	/* Check if hardware planes need to be reallocated. */
+	for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
+		struct rcar_du_plane_state *plane_state;
+		struct rcar_du_plane *plane;
+		unsigned int index;
+
+		if (!state->planes[i])
+			continue;
+
+		plane = to_rcar_plane(state->planes[i]);
+		plane_state = to_rcar_plane_state(state->plane_states[i]);
+
+		dev_dbg(rcdu->dev, "%s: checking plane (%u,%u)\n", __func__,
+			plane->group->index, plane - plane->group->planes);
+
+		/* If the plane is being disabled we don't need to go through
+		 * the full reallocation procedure. Just mark the hardware
+		 * plane(s) as freed.
+		 */
+		if (!plane_state->format) {
+			dev_dbg(rcdu->dev, "%s: plane is being disabled\n",
+				__func__);
+			index = plane - plane->group->planes;
+			group_freed_planes[plane->group->index] |= 1 << index;
+			plane_state->hwindex = -1;
+			continue;
+		}
+
+		/* If the plane needs to be reallocated mark it as such, and
+		 * mark the hardware plane(s) as free.
+		 */
+		if (rcar_du_plane_needs_realloc(plane, plane_state)) {
+			dev_dbg(rcdu->dev, "%s: plane needs reallocation\n",
+				__func__);
+			groups |= 1 << plane->group->index;
+			needs_realloc = true;
+
+			index = plane - plane->group->planes;
+			group_freed_planes[plane->group->index] |= 1 << index;
+			plane_state->hwindex = -1;
+		}
+	}
+
+	if (!needs_realloc)
+		return 0;
+
+	/* Grab all plane states for the groups that need reallocation to ensure
+	 * locking and avoid racy updates. This serializes the update operation,
+	 * but there's not much we can do about it as that's the hardware
+	 * design.
+	 *
+	 * Compute the used planes mask for each group at the same time to avoid
+	 * looping over the planes separately later.
+	 */
+	while (groups) {
+		unsigned int index = ffs(groups) - 1;
+		struct rcar_du_group *group = &rcdu->groups[index];
+		unsigned int used_planes = 0;
+
+		dev_dbg(rcdu->dev, "%s: finding free planes for group %u\n",
+			__func__, index);
+
+		for (i = 0; i < group->num_planes; ++i) {
+			struct rcar_du_plane *plane = &group->planes[i];
+			struct rcar_du_plane_state *plane_state;
+			struct drm_plane_state *s;
+
+			s = drm_atomic_get_plane_state(state, &plane->plane);
+			if (IS_ERR(s))
+				return PTR_ERR(s);
+
+			/* If the plane has been freed in the above loop its
+			 * hardware planes must not be added to the used planes
+			 * bitmask. However, the current state doesn't reflect
+			 * the free state yet, as we've modified the new state
+			 * above. Use the local freed planes list to check for
+			 * that condition instead.
+			 */
+			if (group_freed_planes[index] & (1 << i)) {
+				dev_dbg(rcdu->dev,
+					"%s: plane (%u,%u) has been freed, skipping\n",
+					__func__, plane->group->index,
+					plane - plane->group->planes);
+				continue;
+			}
+
+			plane_state = to_rcar_plane_state(plane->plane.state);
+			used_planes |= rcar_du_plane_hwmask(plane_state);
+
+			dev_dbg(rcdu->dev,
+				"%s: plane (%u,%u) uses %u hwplanes (index %d)\n",
+				__func__, plane->group->index,
+				plane - plane->group->planes,
+				plane_state->format ?
+				plane_state->format->planes : 0,
+				plane_state->hwindex);
+		}
+
+		group_free_planes[index] = 0xff & ~used_planes;
+		groups &= ~(1 << index);
+
+		dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
+			__func__, index, group_free_planes[index]);
+	}
+
+	/* Reallocate hardware planes for each plane that needs it. */
+	for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
+		struct rcar_du_plane_state *plane_state;
+		struct rcar_du_plane *plane;
+		unsigned int crtc_planes;
+		unsigned int free;
+		int idx;
+
+		if (!state->planes[i])
+			continue;
+
+		plane = to_rcar_plane(state->planes[i]);
+		plane_state = to_rcar_plane_state(state->plane_states[i]);
+
+		dev_dbg(rcdu->dev, "%s: allocating plane (%u,%u)\n", __func__,
+			plane->group->index, plane - plane->group->planes);
+
+		/* Skip planes that are being disabled or don't need to be
+		 * reallocated.
+		 */
+		if (!plane_state->format ||
+		    !rcar_du_plane_needs_realloc(plane, plane_state))
+			continue;
+
+		/* Try to allocate the plane from the free planes currently
+		 * associated with the target CRTC to avoid restarting the CRTC
+		 * group and thus minimize flicker. If it fails fall back to
+		 * allocating from all free planes.
+		 */
+		crtc_planes = to_rcar_crtc(plane_state->state.crtc)->index % 2
+			    ? plane->group->dptsr_planes
+			    : ~plane->group->dptsr_planes;
+		free = group_free_planes[plane->group->index];
+
+		idx = rcar_du_plane_hwalloc(plane, plane_state,
+					    free & crtc_planes);
+		if (idx < 0)
+			idx = rcar_du_plane_hwalloc(plane, plane_state,
+						    free);
+		if (idx < 0) {
+			dev_dbg(rcdu->dev, "%s: no available hardware plane\n",
+				__func__);
+			return idx;
+		}
+
+		dev_dbg(rcdu->dev, "%s: allocated %u hwplanes (index %u)\n",
+			__func__, plane_state->format->planes, idx);
+
+		plane_state->hwindex = idx;
+
+		group_free_planes[plane->group->index] &+			~rcar_du_plane_hwmask(plane_state);
+
+		dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
+			__func__, plane->group->index,
+			group_free_planes[plane->group->index]);
+	}
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Plane Setup
+ */
+
 #define RCAR_DU_COLORKEY_NONE		(0 << 24)
 #define RCAR_DU_COLORKEY_SOURCE		(1 << 24)
 #define RCAR_DU_COLORKEY_MASK		(1 << 24)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index e24e45828d6a..6a6460dffae4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -71,6 +71,9 @@ to_rcar_plane_state(struct drm_plane_state *state)
 	return container_of(state, struct rcar_du_plane_state, state);
 }
 
+int rcar_du_atomic_check_planes(struct drm_device *dev,
+				struct drm_atomic_state *state);
+
 int rcar_du_planes_init(struct rcar_du_group *rgrp);
 
 void rcar_du_plane_setup(struct rcar_du_plane *plane);
-- 
2.4.6


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

* [PATCH 09/22] drm: rcar-du: Move plane allocator to rcar_du_plane.c
@ 2015-09-13 22:50   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

The plane allocator is specific to DU planes and won't be used for
VSP-based planes, move it with the rest of the DU planes code where it
belongs.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_kms.c   | 276 +-----------------------------
 drivers/gpu/drm/rcar-du/rcar_du_plane.c | 286 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/rcar-du/rcar_du_plane.h |   3 +
 3 files changed, 290 insertions(+), 275 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index ba4e100e5b0f..6196410b9e98 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -192,290 +192,16 @@ static void rcar_du_output_poll_changed(struct drm_device *dev)
  * Atomic Check and Update
  */
 
-/*
- * Atomic hardware plane allocator
- *
- * The hardware plane allocator is solely based on the atomic plane states
- * without keeping any external state to avoid races between .atomic_check()
- * and .atomic_commit().
- *
- * The core idea is to avoid using a free planes bitmask that would need to be
- * shared between check and commit handlers with a collective knowledge based on
- * the allocated hardware plane(s) for each KMS plane. The allocator then loops
- * over all plane states to compute the free planes bitmask, allocates hardware
- * planes based on that bitmask, and stores the result back in the plane states.
- *
- * For this to work we need to access the current state of planes not touched by
- * the atomic update. To ensure that it won't be modified, we need to lock all
- * planes using drm_atomic_get_plane_state(). This effectively serializes atomic
- * updates from .atomic_check() up to completion (when swapping the states if
- * the check step has succeeded) or rollback (when freeing the states if the
- * check step has failed).
- *
- * Allocation is performed in the .atomic_check() handler and applied
- * automatically when the core swaps the old and new states.
- */
-
-static bool rcar_du_plane_needs_realloc(struct rcar_du_plane *plane,
-					struct rcar_du_plane_state *new_state)
-{
-	struct rcar_du_plane_state *cur_state;
-
-	cur_state = to_rcar_plane_state(plane->plane.state);
-
-	/* Lowering the number of planes doesn't strictly require reallocation
-	 * as the extra hardware plane will be freed when committing, but doing
-	 * so could lead to more fragmentation.
-	 */
-	if (!cur_state->format ||
-	    cur_state->format->planes != new_state->format->planes)
-		return true;
-
-	/* Reallocate hardware planes if the source has changed. */
-	if (cur_state->source != new_state->source)
-		return true;
-
-	return false;
-}
-
-static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
-{
-	unsigned int mask;
-
-	if (state->hwindex == -1)
-		return 0;
-
-	mask = 1 << state->hwindex;
-	if (state->format->planes == 2)
-		mask |= 1 << ((state->hwindex + 1) % 8);
-
-	return mask;
-}
-
-/*
- * The R8A7790 DU can source frames directly from the VSP1 devices VSPD0 and
- * VSPD1. VSPD0 feeds DU0/1 plane 0, and VSPD1 feeds either DU2 plane 0 or
- * DU0/1 plane 1.
- *
- * Allocate the correct fixed plane when sourcing frames from VSPD0 or VSPD1,
- * and allocate planes in reverse index order otherwise to ensure maximum
- * availability of planes 0 and 1.
- *
- * The caller is responsible for ensuring that the requested source is
- * compatible with the DU revision.
- */
-static int rcar_du_plane_hwalloc(struct rcar_du_plane *plane,
-				 struct rcar_du_plane_state *state,
-				 unsigned int free)
-{
-	unsigned int num_planes = state->format->planes;
-	int fixed = -1;
-	int i;
-
-	if (state->source == RCAR_DU_PLANE_VSPD0) {
-		/* VSPD0 feeds plane 0 on DU0/1. */
-		if (plane->group->index != 0)
-			return -EINVAL;
-
-		fixed = 0;
-	} else if (state->source == RCAR_DU_PLANE_VSPD1) {
-		/* VSPD1 feeds plane 1 on DU0/1 or plane 0 on DU2. */
-		fixed = plane->group->index == 0 ? 1 : 0;
-	}
-
-	if (fixed >= 0)
-		return free & (1 << fixed) ? fixed : -EBUSY;
-
-	for (i = RCAR_DU_NUM_HW_PLANES - 1; i >= 0; --i) {
-		if (!(free & (1 << i)))
-			continue;
-
-		if (num_planes == 1 || free & (1 << ((i + 1) % 8)))
-			break;
-	}
-
-	return i < 0 ? -EBUSY : i;
-}
-
 static int rcar_du_atomic_check(struct drm_device *dev,
 				struct drm_atomic_state *state)
 {
-	struct rcar_du_device *rcdu = dev->dev_private;
-	unsigned int group_freed_planes[RCAR_DU_MAX_GROUPS] = { 0, };
-	unsigned int group_free_planes[RCAR_DU_MAX_GROUPS] = { 0, };
-	bool needs_realloc = false;
-	unsigned int groups = 0;
-	unsigned int i;
 	int ret;
 
 	ret = drm_atomic_helper_check(dev, state);
 	if (ret < 0)
 		return ret;
 
-	/* Check if hardware planes need to be reallocated. */
-	for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
-		struct rcar_du_plane_state *plane_state;
-		struct rcar_du_plane *plane;
-		unsigned int index;
-
-		if (!state->planes[i])
-			continue;
-
-		plane = to_rcar_plane(state->planes[i]);
-		plane_state = to_rcar_plane_state(state->plane_states[i]);
-
-		dev_dbg(rcdu->dev, "%s: checking plane (%u,%u)\n", __func__,
-			plane->group->index, plane - plane->group->planes);
-
-		/* If the plane is being disabled we don't need to go through
-		 * the full reallocation procedure. Just mark the hardware
-		 * plane(s) as freed.
-		 */
-		if (!plane_state->format) {
-			dev_dbg(rcdu->dev, "%s: plane is being disabled\n",
-				__func__);
-			index = plane - plane->group->planes;
-			group_freed_planes[plane->group->index] |= 1 << index;
-			plane_state->hwindex = -1;
-			continue;
-		}
-
-		/* If the plane needs to be reallocated mark it as such, and
-		 * mark the hardware plane(s) as free.
-		 */
-		if (rcar_du_plane_needs_realloc(plane, plane_state)) {
-			dev_dbg(rcdu->dev, "%s: plane needs reallocation\n",
-				__func__);
-			groups |= 1 << plane->group->index;
-			needs_realloc = true;
-
-			index = plane - plane->group->planes;
-			group_freed_planes[plane->group->index] |= 1 << index;
-			plane_state->hwindex = -1;
-		}
-	}
-
-	if (!needs_realloc)
-		return 0;
-
-	/* Grab all plane states for the groups that need reallocation to ensure
-	 * locking and avoid racy updates. This serializes the update operation,
-	 * but there's not much we can do about it as that's the hardware
-	 * design.
-	 *
-	 * Compute the used planes mask for each group at the same time to avoid
-	 * looping over the planes separately later.
-	 */
-	while (groups) {
-		unsigned int index = ffs(groups) - 1;
-		struct rcar_du_group *group = &rcdu->groups[index];
-		unsigned int used_planes = 0;
-
-		dev_dbg(rcdu->dev, "%s: finding free planes for group %u\n",
-			__func__, index);
-
-		for (i = 0; i < group->num_planes; ++i) {
-			struct rcar_du_plane *plane = &group->planes[i];
-			struct rcar_du_plane_state *plane_state;
-			struct drm_plane_state *s;
-
-			s = drm_atomic_get_plane_state(state, &plane->plane);
-			if (IS_ERR(s))
-				return PTR_ERR(s);
-
-			/* If the plane has been freed in the above loop its
-			 * hardware planes must not be added to the used planes
-			 * bitmask. However, the current state doesn't reflect
-			 * the free state yet, as we've modified the new state
-			 * above. Use the local freed planes list to check for
-			 * that condition instead.
-			 */
-			if (group_freed_planes[index] & (1 << i)) {
-				dev_dbg(rcdu->dev,
-					"%s: plane (%u,%u) has been freed, skipping\n",
-					__func__, plane->group->index,
-					plane - plane->group->planes);
-				continue;
-			}
-
-			plane_state = to_rcar_plane_state(plane->plane.state);
-			used_planes |= rcar_du_plane_hwmask(plane_state);
-
-			dev_dbg(rcdu->dev,
-				"%s: plane (%u,%u) uses %u hwplanes (index %d)\n",
-				__func__, plane->group->index,
-				plane - plane->group->planes,
-				plane_state->format ?
-				plane_state->format->planes : 0,
-				plane_state->hwindex);
-		}
-
-		group_free_planes[index] = 0xff & ~used_planes;
-		groups &= ~(1 << index);
-
-		dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
-			__func__, index, group_free_planes[index]);
-	}
-
-	/* Reallocate hardware planes for each plane that needs it. */
-	for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
-		struct rcar_du_plane_state *plane_state;
-		struct rcar_du_plane *plane;
-		unsigned int crtc_planes;
-		unsigned int free;
-		int idx;
-
-		if (!state->planes[i])
-			continue;
-
-		plane = to_rcar_plane(state->planes[i]);
-		plane_state = to_rcar_plane_state(state->plane_states[i]);
-
-		dev_dbg(rcdu->dev, "%s: allocating plane (%u,%u)\n", __func__,
-			plane->group->index, plane - plane->group->planes);
-
-		/* Skip planes that are being disabled or don't need to be
-		 * reallocated.
-		 */
-		if (!plane_state->format ||
-		    !rcar_du_plane_needs_realloc(plane, plane_state))
-			continue;
-
-		/* Try to allocate the plane from the free planes currently
-		 * associated with the target CRTC to avoid restarting the CRTC
-		 * group and thus minimize flicker. If it fails fall back to
-		 * allocating from all free planes.
-		 */
-		crtc_planes = to_rcar_crtc(plane_state->state.crtc)->index % 2
-			    ? plane->group->dptsr_planes
-			    : ~plane->group->dptsr_planes;
-		free = group_free_planes[plane->group->index];
-
-		idx = rcar_du_plane_hwalloc(plane, plane_state,
-					    free & crtc_planes);
-		if (idx < 0)
-			idx = rcar_du_plane_hwalloc(plane, plane_state,
-						    free);
-		if (idx < 0) {
-			dev_dbg(rcdu->dev, "%s: no available hardware plane\n",
-				__func__);
-			return idx;
-		}
-
-		dev_dbg(rcdu->dev, "%s: allocated %u hwplanes (index %u)\n",
-			__func__, plane_state->format->planes, idx);
-
-		plane_state->hwindex = idx;
-
-		group_free_planes[plane->group->index] &=
-			~rcar_du_plane_hwmask(plane_state);
-
-		dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
-			__func__, plane->group->index,
-			group_free_planes[plane->group->index]);
-	}
-
-	return 0;
+	return rcar_du_atomic_check_planes(dev, state);
 }
 
 struct rcar_du_commit {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index c7e0535c0e77..b868184e8385 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -12,6 +12,7 @@
  */
 
 #include <drm/drmP.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
@@ -25,6 +26,291 @@
 #include "rcar_du_plane.h"
 #include "rcar_du_regs.h"
 
+/* -----------------------------------------------------------------------------
+ * Atomic hardware plane allocator
+ *
+ * The hardware plane allocator is solely based on the atomic plane states
+ * without keeping any external state to avoid races between .atomic_check()
+ * and .atomic_commit().
+ *
+ * The core idea is to avoid using a free planes bitmask that would need to be
+ * shared between check and commit handlers with a collective knowledge based on
+ * the allocated hardware plane(s) for each KMS plane. The allocator then loops
+ * over all plane states to compute the free planes bitmask, allocates hardware
+ * planes based on that bitmask, and stores the result back in the plane states.
+ *
+ * For this to work we need to access the current state of planes not touched by
+ * the atomic update. To ensure that it won't be modified, we need to lock all
+ * planes using drm_atomic_get_plane_state(). This effectively serializes atomic
+ * updates from .atomic_check() up to completion (when swapping the states if
+ * the check step has succeeded) or rollback (when freeing the states if the
+ * check step has failed).
+ *
+ * Allocation is performed in the .atomic_check() handler and applied
+ * automatically when the core swaps the old and new states.
+ */
+
+static bool rcar_du_plane_needs_realloc(struct rcar_du_plane *plane,
+					struct rcar_du_plane_state *new_state)
+{
+	struct rcar_du_plane_state *cur_state;
+
+	cur_state = to_rcar_plane_state(plane->plane.state);
+
+	/* Lowering the number of planes doesn't strictly require reallocation
+	 * as the extra hardware plane will be freed when committing, but doing
+	 * so could lead to more fragmentation.
+	 */
+	if (!cur_state->format ||
+	    cur_state->format->planes != new_state->format->planes)
+		return true;
+
+	/* Reallocate hardware planes if the source has changed. */
+	if (cur_state->source != new_state->source)
+		return true;
+
+	return false;
+}
+
+static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
+{
+	unsigned int mask;
+
+	if (state->hwindex == -1)
+		return 0;
+
+	mask = 1 << state->hwindex;
+	if (state->format->planes == 2)
+		mask |= 1 << ((state->hwindex + 1) % 8);
+
+	return mask;
+}
+
+/*
+ * The R8A7790 DU can source frames directly from the VSP1 devices VSPD0 and
+ * VSPD1. VSPD0 feeds DU0/1 plane 0, and VSPD1 feeds either DU2 plane 0 or
+ * DU0/1 plane 1.
+ *
+ * Allocate the correct fixed plane when sourcing frames from VSPD0 or VSPD1,
+ * and allocate planes in reverse index order otherwise to ensure maximum
+ * availability of planes 0 and 1.
+ *
+ * The caller is responsible for ensuring that the requested source is
+ * compatible with the DU revision.
+ */
+static int rcar_du_plane_hwalloc(struct rcar_du_plane *plane,
+				 struct rcar_du_plane_state *state,
+				 unsigned int free)
+{
+	unsigned int num_planes = state->format->planes;
+	int fixed = -1;
+	int i;
+
+	if (state->source == RCAR_DU_PLANE_VSPD0) {
+		/* VSPD0 feeds plane 0 on DU0/1. */
+		if (plane->group->index != 0)
+			return -EINVAL;
+
+		fixed = 0;
+	} else if (state->source == RCAR_DU_PLANE_VSPD1) {
+		/* VSPD1 feeds plane 1 on DU0/1 or plane 0 on DU2. */
+		fixed = plane->group->index == 0 ? 1 : 0;
+	}
+
+	if (fixed >= 0)
+		return free & (1 << fixed) ? fixed : -EBUSY;
+
+	for (i = RCAR_DU_NUM_HW_PLANES - 1; i >= 0; --i) {
+		if (!(free & (1 << i)))
+			continue;
+
+		if (num_planes == 1 || free & (1 << ((i + 1) % 8)))
+			break;
+	}
+
+	return i < 0 ? -EBUSY : i;
+}
+
+int rcar_du_atomic_check_planes(struct drm_device *dev,
+				struct drm_atomic_state *state)
+{
+	struct rcar_du_device *rcdu = dev->dev_private;
+	unsigned int group_freed_planes[RCAR_DU_MAX_GROUPS] = { 0, };
+	unsigned int group_free_planes[RCAR_DU_MAX_GROUPS] = { 0, };
+	bool needs_realloc = false;
+	unsigned int groups = 0;
+	unsigned int i;
+
+	/* Check if hardware planes need to be reallocated. */
+	for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
+		struct rcar_du_plane_state *plane_state;
+		struct rcar_du_plane *plane;
+		unsigned int index;
+
+		if (!state->planes[i])
+			continue;
+
+		plane = to_rcar_plane(state->planes[i]);
+		plane_state = to_rcar_plane_state(state->plane_states[i]);
+
+		dev_dbg(rcdu->dev, "%s: checking plane (%u,%u)\n", __func__,
+			plane->group->index, plane - plane->group->planes);
+
+		/* If the plane is being disabled we don't need to go through
+		 * the full reallocation procedure. Just mark the hardware
+		 * plane(s) as freed.
+		 */
+		if (!plane_state->format) {
+			dev_dbg(rcdu->dev, "%s: plane is being disabled\n",
+				__func__);
+			index = plane - plane->group->planes;
+			group_freed_planes[plane->group->index] |= 1 << index;
+			plane_state->hwindex = -1;
+			continue;
+		}
+
+		/* If the plane needs to be reallocated mark it as such, and
+		 * mark the hardware plane(s) as free.
+		 */
+		if (rcar_du_plane_needs_realloc(plane, plane_state)) {
+			dev_dbg(rcdu->dev, "%s: plane needs reallocation\n",
+				__func__);
+			groups |= 1 << plane->group->index;
+			needs_realloc = true;
+
+			index = plane - plane->group->planes;
+			group_freed_planes[plane->group->index] |= 1 << index;
+			plane_state->hwindex = -1;
+		}
+	}
+
+	if (!needs_realloc)
+		return 0;
+
+	/* Grab all plane states for the groups that need reallocation to ensure
+	 * locking and avoid racy updates. This serializes the update operation,
+	 * but there's not much we can do about it as that's the hardware
+	 * design.
+	 *
+	 * Compute the used planes mask for each group at the same time to avoid
+	 * looping over the planes separately later.
+	 */
+	while (groups) {
+		unsigned int index = ffs(groups) - 1;
+		struct rcar_du_group *group = &rcdu->groups[index];
+		unsigned int used_planes = 0;
+
+		dev_dbg(rcdu->dev, "%s: finding free planes for group %u\n",
+			__func__, index);
+
+		for (i = 0; i < group->num_planes; ++i) {
+			struct rcar_du_plane *plane = &group->planes[i];
+			struct rcar_du_plane_state *plane_state;
+			struct drm_plane_state *s;
+
+			s = drm_atomic_get_plane_state(state, &plane->plane);
+			if (IS_ERR(s))
+				return PTR_ERR(s);
+
+			/* If the plane has been freed in the above loop its
+			 * hardware planes must not be added to the used planes
+			 * bitmask. However, the current state doesn't reflect
+			 * the free state yet, as we've modified the new state
+			 * above. Use the local freed planes list to check for
+			 * that condition instead.
+			 */
+			if (group_freed_planes[index] & (1 << i)) {
+				dev_dbg(rcdu->dev,
+					"%s: plane (%u,%u) has been freed, skipping\n",
+					__func__, plane->group->index,
+					plane - plane->group->planes);
+				continue;
+			}
+
+			plane_state = to_rcar_plane_state(plane->plane.state);
+			used_planes |= rcar_du_plane_hwmask(plane_state);
+
+			dev_dbg(rcdu->dev,
+				"%s: plane (%u,%u) uses %u hwplanes (index %d)\n",
+				__func__, plane->group->index,
+				plane - plane->group->planes,
+				plane_state->format ?
+				plane_state->format->planes : 0,
+				plane_state->hwindex);
+		}
+
+		group_free_planes[index] = 0xff & ~used_planes;
+		groups &= ~(1 << index);
+
+		dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
+			__func__, index, group_free_planes[index]);
+	}
+
+	/* Reallocate hardware planes for each plane that needs it. */
+	for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
+		struct rcar_du_plane_state *plane_state;
+		struct rcar_du_plane *plane;
+		unsigned int crtc_planes;
+		unsigned int free;
+		int idx;
+
+		if (!state->planes[i])
+			continue;
+
+		plane = to_rcar_plane(state->planes[i]);
+		plane_state = to_rcar_plane_state(state->plane_states[i]);
+
+		dev_dbg(rcdu->dev, "%s: allocating plane (%u,%u)\n", __func__,
+			plane->group->index, plane - plane->group->planes);
+
+		/* Skip planes that are being disabled or don't need to be
+		 * reallocated.
+		 */
+		if (!plane_state->format ||
+		    !rcar_du_plane_needs_realloc(plane, plane_state))
+			continue;
+
+		/* Try to allocate the plane from the free planes currently
+		 * associated with the target CRTC to avoid restarting the CRTC
+		 * group and thus minimize flicker. If it fails fall back to
+		 * allocating from all free planes.
+		 */
+		crtc_planes = to_rcar_crtc(plane_state->state.crtc)->index % 2
+			    ? plane->group->dptsr_planes
+			    : ~plane->group->dptsr_planes;
+		free = group_free_planes[plane->group->index];
+
+		idx = rcar_du_plane_hwalloc(plane, plane_state,
+					    free & crtc_planes);
+		if (idx < 0)
+			idx = rcar_du_plane_hwalloc(plane, plane_state,
+						    free);
+		if (idx < 0) {
+			dev_dbg(rcdu->dev, "%s: no available hardware plane\n",
+				__func__);
+			return idx;
+		}
+
+		dev_dbg(rcdu->dev, "%s: allocated %u hwplanes (index %u)\n",
+			__func__, plane_state->format->planes, idx);
+
+		plane_state->hwindex = idx;
+
+		group_free_planes[plane->group->index] &=
+			~rcar_du_plane_hwmask(plane_state);
+
+		dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
+			__func__, plane->group->index,
+			group_free_planes[plane->group->index]);
+	}
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Plane Setup
+ */
+
 #define RCAR_DU_COLORKEY_NONE		(0 << 24)
 #define RCAR_DU_COLORKEY_SOURCE		(1 << 24)
 #define RCAR_DU_COLORKEY_MASK		(1 << 24)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index e24e45828d6a..6a6460dffae4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -71,6 +71,9 @@ to_rcar_plane_state(struct drm_plane_state *state)
 	return container_of(state, struct rcar_du_plane_state, state);
 }
 
+int rcar_du_atomic_check_planes(struct drm_device *dev,
+				struct drm_atomic_state *state);
+
 int rcar_du_planes_init(struct rcar_du_group *rgrp);
 
 void rcar_du_plane_setup(struct rcar_du_plane *plane);
-- 
2.4.6


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

* [PATCH 10/22] drm: rcar-du: Expose the VSP1 compositor through KMS planes
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:50   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

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

---
 drivers/gpu/drm/rcar-du/Kconfig         |   7 +
 drivers/gpu/drm/rcar-du/Makefile        |   2 +
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  42 +++-
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h  |   2 +
 drivers/gpu/drm/rcar-du/rcar_du_drv.h   |   4 +
 drivers/gpu/drm/rcar-du/rcar_du_kms.c   |  28 ++-
 drivers/gpu/drm/rcar-du/rcar_du_plane.c |   7 +-
 drivers/gpu/drm/rcar-du/rcar_du_plane.h |  11 +-
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c   | 359 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/rcar-du/rcar_du_vsp.h   |  72 +++++++
 10 files changed, 518 insertions(+), 16 deletions(-)
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vsp.c
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vsp.h

diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index d4e0a39568f6..62650abc3120 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -25,3 +25,10 @@ config DRM_RCAR_LVDS
 	help
 	  Enable support for the R-Car Display Unit embedded LVDS encoders
 	  (currently only on R8A7790 and R8A7791).
+
+config DRM_RCAR_VSP
+	bool "R-Car DU VSP Compositor Support"
+	depends on DRM_RCAR_DU
+	depends on VIDEO_RENESAS_VSP1
+	help
+	  Enable support to expose the R-Car VSP Compositor as KMS planes.
diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
index 05de1c4097af..827711e28226 100644
--- a/drivers/gpu/drm/rcar-du/Makefile
+++ b/drivers/gpu/drm/rcar-du/Makefile
@@ -11,4 +11,6 @@ rcar-du-drm-$(CONFIG_DRM_RCAR_HDMI)	+= rcar_du_hdmicon.o \
 					   rcar_du_hdmienc.o
 rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS)	+= rcar_du_lvdsenc.o
 
+rcar-du-drm-$(CONFIG_DRM_RCAR_VSP)	+= rcar_du_vsp.o
+
 obj-$(CONFIG_DRM_RCAR_DU)		+= rcar-du-drm.o
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 7e2f5c26d589..196b940ea8d7 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -28,6 +28,7 @@
 #include "rcar_du_kms.h"
 #include "rcar_du_plane.h"
 #include "rcar_du_regs.h"
+#include "rcar_du_vsp.h"
 
 static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg)
 {
@@ -207,6 +208,7 @@ plane_format(struct rcar_du_plane *plane)
 static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
 {
 	struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES];
+	struct rcar_du_device *rcdu = rcrtc->group->dev;
 	unsigned int num_planes = 0;
 	unsigned int dptsr_planes;
 	unsigned int hwplanes = 0;
@@ -250,6 +252,12 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
 		}
 	}
 
+	/* If VSP+DU integration is enabled the plane assignment is fixed. */
+	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
+		dspr = (rcrtc->index % 2) + 1;
+		hwplanes = 1 << (rcrtc->index % 2);
+	}
+
 	/* Update the planes to display timing and dot clock generator
 	 * associations.
 	 *
@@ -389,6 +397,10 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
 
 	rcar_du_group_start_stop(rcrtc->group, true);
 
+	/* Enable the VSP compositor. */
+	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
+		rcar_du_vsp_enable(rcrtc);
+
 	/* Turn vertical blanking interrupt reporting back on. */
 	drm_crtc_vblank_on(crtc);
 
@@ -422,6 +434,10 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
 	rcar_du_crtc_wait_page_flip(rcrtc);
 	drm_crtc_vblank_off(crtc);
 
+	/* Disable the VSP compositor. */
+	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
+		rcar_du_vsp_disable(rcrtc);
+
 	/* Select switch sync mode. This stops display operation and configures
 	 * the HSYNC and VSYNC signals as inputs.
 	 */
@@ -434,6 +450,9 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
 
 void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc)
 {
+	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
+		rcar_du_vsp_disable(rcrtc);
+
 	rcar_du_crtc_stop(rcrtc);
 	rcar_du_crtc_put(rcrtc);
 }
@@ -449,13 +468,17 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc)
 	rcar_du_crtc_start(rcrtc);
 
 	/* Commit the planes state. */
-	for (i = 0; i < rcrtc->group->num_planes; ++i) {
-		struct rcar_du_plane *plane = &rcrtc->group->planes[i];
+	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) {
+		rcar_du_vsp_enable(rcrtc);
+	} else {
+		for (i = 0; i < rcrtc->group->num_planes; ++i) {
+			struct rcar_du_plane *plane = &rcrtc->group->planes[i];
 
-		if (plane->plane.state->crtc != &rcrtc->crtc)
-			continue;
+			if (plane->plane.state->crtc != &rcrtc->crtc)
+				continue;
 
-		rcar_du_plane_setup(plane);
+			rcar_du_plane_setup(plane);
+		}
 	}
 
 	rcar_du_crtc_update_planes(rcrtc);
@@ -578,6 +601,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
 	struct platform_device *pdev = to_platform_device(rcdu->dev);
 	struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index];
 	struct drm_crtc *crtc = &rcrtc->crtc;
+	struct drm_plane *primary;
 	unsigned int irqflags;
 	struct clk *clk;
 	char clk_name[9];
@@ -615,8 +639,12 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
 	rcrtc->index = index;
 	rcrtc->enabled = false;
 
-	ret = drm_crtc_init_with_planes(rcdu->ddev, crtc,
-					&rgrp->planes[index % 2].plane,
+	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
+		primary = &rcrtc->vsp->planes[0].plane;
+	else
+		primary = &rgrp->planes[index % 2].plane;
+
+	ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary,
 					NULL, &crtc_funcs);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index 4b95d9d08c49..c7ab46702b1d 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -21,6 +21,7 @@
 #include <drm/drm_crtc.h>
 
 struct rcar_du_group;
+struct rcar_du_vsp;
 
 /**
  * struct rcar_du_crtc - the CRTC, representing a DU superposition processor
@@ -52,6 +53,7 @@ struct rcar_du_crtc {
 	bool enabled;
 
 	struct rcar_du_group *group;
+	struct rcar_du_vsp *vsp;
 };
 
 #define to_rcar_crtc(c)	container_of(c, struct rcar_du_crtc, crtc)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index e10b4f0d8f83..a81eb3281e7f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -19,6 +19,7 @@
 
 #include "rcar_du_crtc.h"
 #include "rcar_du_group.h"
+#include "rcar_du_vsp.h"
 
 struct clk;
 struct device;
@@ -29,6 +30,7 @@ struct rcar_du_lvdsenc;
 
 #define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK	(1 << 0)	/* Per-CRTC IRQ and clock */
 #define RCAR_DU_FEATURE_EXT_CTRL_REGS	(1 << 1)	/* Has extended control registers */
+#define RCAR_DU_FEATURE_VSP1_SOURCE	(1 << 2)	/* Has inputs from VSP1 */
 
 #define RCAR_DU_QUIRK_ALIGN_128B	(1 << 0)	/* Align pitches to 128 bytes */
 #define RCAR_DU_QUIRK_LVDS_LANES	(1 << 1)	/* LVDS lanes 1 and 3 inverted */
@@ -68,6 +70,7 @@ struct rcar_du_device_info {
 #define RCAR_DU_MAX_CRTCS		3
 #define RCAR_DU_MAX_GROUPS		DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2)
 #define RCAR_DU_MAX_LVDS		2
+#define RCAR_DU_MAX_VSPS		4
 
 struct rcar_du_device {
 	struct device *dev;
@@ -82,6 +85,7 @@ struct rcar_du_device {
 	unsigned int num_crtcs;
 
 	struct rcar_du_group groups[RCAR_DU_MAX_GROUPS];
+	struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS];
 
 	struct {
 		struct drm_property *alpha;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 6196410b9e98..3f3d93dcbf64 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -28,6 +28,7 @@
 #include "rcar_du_kms.h"
 #include "rcar_du_lvdsenc.h"
 #include "rcar_du_regs.h"
+#include "rcar_du_vsp.h"
 
 /* -----------------------------------------------------------------------------
  * Format helpers
@@ -195,12 +196,16 @@ static void rcar_du_output_poll_changed(struct drm_device *dev)
 static int rcar_du_atomic_check(struct drm_device *dev,
 				struct drm_atomic_state *state)
 {
+	struct rcar_du_device *rcdu = dev->dev_private;
 	int ret;
 
 	ret = drm_atomic_helper_check(dev, state);
 	if (ret < 0)
 		return ret;
 
+	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
+		return 0;
+
 	return rcar_du_atomic_check_planes(dev, state);
 }
 
@@ -544,9 +549,26 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 		 */
 		rgrp->dptsr_planes = rgrp->num_crtcs > 1 ? 0xf0 : 0;
 
-		ret = rcar_du_planes_init(rgrp);
-		if (ret < 0)
-			return ret;
+		if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
+			ret = rcar_du_planes_init(rgrp);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	/* Initialize the compositors. */
+	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
+		for (i = 0; i < rcdu->num_crtcs; ++i) {
+			struct rcar_du_vsp *vsp = &rcdu->vsps[i];
+
+			vsp->index = i;
+			vsp->dev = rcdu;
+			rcdu->crtcs[i].vsp = vsp;
+
+			ret = rcar_du_vsp_init(vsp);
+			if (ret < 0)
+				return ret;
+		}
 	}
 
 	/* Create the CRTCs. */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index b868184e8385..4a38ced4b952 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -505,12 +505,9 @@ static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
 	rcar_du_plane_write(rgrp, index, PnMLR, 0);
 }
 
-void rcar_du_plane_setup(struct rcar_du_plane *plane)
+void __rcar_du_plane_setup(struct rcar_du_group *rgrp,
+			   const struct rcar_du_plane_state *state)
 {
-	struct rcar_du_plane_state *state -		to_rcar_plane_state(plane->plane.state);
-	struct rcar_du_group *rgrp = plane->group;
-
 	rcar_du_plane_setup_format(rgrp, state->hwindex, state);
 	if (state->format->planes = 2)
 		rcar_du_plane_setup_format(rgrp, (state->hwindex + 1) % 8,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 6a6460dffae4..b18b7b25dbfa 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -76,6 +76,15 @@ int rcar_du_atomic_check_planes(struct drm_device *dev,
 
 int rcar_du_planes_init(struct rcar_du_group *rgrp);
 
-void rcar_du_plane_setup(struct rcar_du_plane *plane);
+void __rcar_du_plane_setup(struct rcar_du_group *rgrp,
+			   const struct rcar_du_plane_state *state);
+
+static inline void rcar_du_plane_setup(struct rcar_du_plane *plane)
+{
+	struct rcar_du_plane_state *state +		to_rcar_plane_state(plane->plane.state);
+
+	return __rcar_du_plane_setup(plane->group, state);
+}
 
 #endif /* __RCAR_DU_PLANE_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
new file mode 100644
index 000000000000..6e34dfd0ef42
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -0,0 +1,359 @@
+/*
+ * rcar_du_vsp.h  --  R-Car Display Unit VSP-Based Compositor
+ *
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include <linux/of_platform.h>
+#include <linux/videodev2.h>
+
+#include <media/vsp1.h>
+
+#include "rcar_du_drv.h"
+#include "rcar_du_kms.h"
+#include "rcar_du_vsp.h"
+
+void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
+{
+	const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode;
+	struct rcar_du_plane_state state = {
+		.state = {
+			.crtc = &crtc->crtc,
+			.crtc_x = 0,
+			.crtc_y = 0,
+			.crtc_w = mode->hdisplay,
+			.crtc_h = mode->vdisplay,
+			.src_x = 0,
+			.src_y = 0,
+			.src_w = mode->hdisplay << 16,
+			.src_h = mode->vdisplay << 16,
+		},
+		.format = rcar_du_format_info(DRM_FORMAT_ARGB8888),
+		.hwindex = crtc->index % 2,
+		.source = RCAR_DU_PLANE_VSPD1,
+		.alpha = 255,
+		.colorkey = 0,
+		.zpos = 0,
+	};
+
+	__rcar_du_plane_setup(crtc->group, &state);
+
+	/* Ensure that the plane source configuration takes effect by requesting
+	 * a restart of the group. See rcar_du_plane_atomic_update() for a more
+	 * detailed explanation.
+	 *
+	 * TODO: Check whether this is still needed on Gen3.
+	 */
+	crtc->group->need_restart = true;
+
+	vsp1_du_setup_lif(crtc->vsp->vsp, mode->hdisplay, mode->vdisplay);
+}
+
+void rcar_du_vsp_disable(struct rcar_du_crtc *crtc)
+{
+	vsp1_du_setup_lif(crtc->vsp->vsp, 0, 0);
+}
+
+/* Keep the two tables in sync. */
+static const u32 formats_kms[] = {
+	DRM_FORMAT_RGB332,
+	DRM_FORMAT_ARGB4444,
+	DRM_FORMAT_XRGB4444,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_XRGB1555,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGRA8888,
+	DRM_FORMAT_BGRX8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_VYUY,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV21,
+	DRM_FORMAT_NV16,
+	DRM_FORMAT_NV61,
+};
+
+static const u32 formats_v4l2[] = {
+	V4L2_PIX_FMT_RGB332,
+	V4L2_PIX_FMT_ARGB444,
+	V4L2_PIX_FMT_XRGB444,
+	V4L2_PIX_FMT_ARGB555,
+	V4L2_PIX_FMT_XRGB555,
+	V4L2_PIX_FMT_RGB565,
+	V4L2_PIX_FMT_RGB24,
+	V4L2_PIX_FMT_BGR24,
+	V4L2_PIX_FMT_ARGB32,
+	V4L2_PIX_FMT_XRGB32,
+	V4L2_PIX_FMT_ABGR32,
+	V4L2_PIX_FMT_XBGR32,
+	V4L2_PIX_FMT_UYVY,
+	V4L2_PIX_FMT_VYUY,
+	V4L2_PIX_FMT_YUYV,
+	V4L2_PIX_FMT_YVYU,
+	V4L2_PIX_FMT_NV12M,
+	V4L2_PIX_FMT_NV21M,
+	V4L2_PIX_FMT_NV16M,
+	V4L2_PIX_FMT_NV61M,
+};
+
+static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
+{
+	struct rcar_du_vsp_plane_state *state +		to_rcar_vsp_plane_state(plane->plane.state);
+	struct drm_framebuffer *fb = plane->plane.state->fb;
+	struct drm_gem_cma_object *gem;
+	struct v4l2_rect src;
+	struct v4l2_rect dst;
+	dma_addr_t paddr[2] = { 0, };
+	u32 pixelformat = 0;
+	unsigned int i;
+
+	src.left = state->state.src_x >> 16;
+	src.top = state->state.src_y >> 16;
+	src.width = state->state.src_w >> 16;
+	src.height = state->state.src_h >> 16;
+
+	dst.left = state->state.crtc_x;
+	dst.top = state->state.crtc_y;
+	dst.width = state->state.crtc_w;
+	dst.height = state->state.crtc_h;
+
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+	paddr[0] = gem->paddr + fb->offsets[0];
+
+	if (state->format->planes = 2) {
+		gem = drm_fb_cma_get_gem_obj(fb, 1);
+		paddr[1] = gem->paddr + fb->offsets[1];
+	}
+
+	for (i = 0; i < ARRAY_SIZE(formats_kms); ++i) {
+		if (formats_kms[i] = state->format->fourcc) {
+			pixelformat = formats_v4l2[i];
+			break;
+		}
+	}
+
+	WARN_ON(!pixelformat);
+
+	vsp1_du_setup_rpf(plane->vsp->vsp, plane->index, pixelformat,
+			  fb->pitches[0], paddr, &src, &dst);
+}
+
+static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane,
+					  struct drm_plane_state *state)
+{
+	struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state);
+	struct rcar_du_vsp_plane *rplane = to_rcar_vsp_plane(plane);
+	struct rcar_du_device *rcdu = rplane->vsp->dev;
+
+	if (!state->fb || !state->crtc) {
+		rstate->format = NULL;
+		return 0;
+	}
+
+	if (state->src_w >> 16 != state->crtc_w ||
+	    state->src_h >> 16 != state->crtc_h) {
+		dev_dbg(rcdu->dev, "%s: scaling not supported\n", __func__);
+		return -EINVAL;
+	}
+
+	rstate->format = rcar_du_format_info(state->fb->pixel_format);
+	if (rstate->format = NULL) {
+		dev_dbg(rcdu->dev, "%s: unsupported format %08x\n", __func__,
+			state->fb->pixel_format);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void rcar_du_vsp_plane_atomic_update(struct drm_plane *plane,
+					struct drm_plane_state *old_state)
+{
+	struct rcar_du_vsp_plane *rplane = to_rcar_vsp_plane(plane);
+
+	if (plane->state->crtc)
+		rcar_du_vsp_plane_setup(rplane);
+	else
+		vsp1_du_setup_rpf(rplane->vsp->vsp, rplane->index, 0, 0, 0,
+				  NULL, NULL);
+}
+
+static const struct drm_plane_helper_funcs rcar_du_vsp_plane_helper_funcs = {
+	.atomic_check = rcar_du_vsp_plane_atomic_check,
+	.atomic_update = rcar_du_vsp_plane_atomic_update,
+};
+
+static struct drm_plane_state *
+rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane)
+{
+	struct rcar_du_vsp_plane_state *state;
+	struct rcar_du_vsp_plane_state *copy;
+
+	if (WARN_ON(!plane->state))
+		return NULL;
+
+	state = to_rcar_vsp_plane_state(plane->state);
+	copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
+	if (copy = NULL)
+		return NULL;
+
+	__drm_atomic_helper_plane_duplicate_state(plane, &copy->state);
+
+	return &copy->state;
+}
+
+static void rcar_du_vsp_plane_atomic_destroy_state(struct drm_plane *plane,
+						   struct drm_plane_state *state)
+{
+	__drm_atomic_helper_plane_destroy_state(plane, state);
+	kfree(to_rcar_vsp_plane_state(state));
+}
+
+static void rcar_du_vsp_plane_reset(struct drm_plane *plane)
+{
+	struct rcar_du_vsp_plane_state *state;
+
+	if (plane->state) {
+		rcar_du_vsp_plane_atomic_destroy_state(plane, plane->state);
+		plane->state = NULL;
+	}
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (state = NULL)
+		return;
+
+	state->alpha = 255;
+
+	plane->state = &state->state;
+	plane->state->plane = plane;
+}
+
+static int rcar_du_vsp_plane_atomic_set_property(struct drm_plane *plane,
+	struct drm_plane_state *state, struct drm_property *property,
+	uint64_t val)
+{
+	struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state);
+	struct rcar_du_device *rcdu = to_rcar_vsp_plane(plane)->vsp->dev;
+
+	if (property = rcdu->props.alpha)
+		rstate->alpha = val;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int rcar_du_vsp_plane_atomic_get_property(struct drm_plane *plane,
+	const struct drm_plane_state *state, struct drm_property *property,
+	uint64_t *val)
+{
+	const struct rcar_du_vsp_plane_state *rstate +		container_of(state, const struct rcar_du_vsp_plane_state, state);
+	struct rcar_du_device *rcdu = to_rcar_vsp_plane(plane)->vsp->dev;
+
+	if (property = rcdu->props.alpha)
+		*val = rstate->alpha;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct drm_plane_funcs rcar_du_vsp_plane_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.reset = rcar_du_vsp_plane_reset,
+	.set_property = drm_atomic_helper_plane_set_property,
+	.destroy = drm_plane_cleanup,
+	.atomic_duplicate_state = rcar_du_vsp_plane_atomic_duplicate_state,
+	.atomic_destroy_state = rcar_du_vsp_plane_atomic_destroy_state,
+	.atomic_set_property = rcar_du_vsp_plane_atomic_set_property,
+	.atomic_get_property = rcar_du_vsp_plane_atomic_get_property,
+};
+
+int rcar_du_vsp_init(struct rcar_du_vsp *vsp)
+{
+	struct rcar_du_device *rcdu = vsp->dev;
+	struct platform_device *pdev;
+	struct device_node *np;
+	unsigned int i;
+	int ret;
+
+	/* Find the VSP device and initialize it. */
+	np = of_parse_phandle(rcdu->dev->of_node, "vsps", vsp->index);
+	if (!np) {
+		dev_err(rcdu->dev, "vsps node not found\n");
+		return -ENXIO;
+	}
+
+	pdev = of_find_device_by_node(np);
+	of_node_put(np);
+	if (!pdev)
+		return -ENXIO;
+
+	vsp->vsp = &pdev->dev;
+
+	ret = vsp1_du_init(vsp->vsp);
+	if (ret < 0)
+		return ret;
+
+	 /* The VSP2D (Gen3) has 5 RPFs, but the VSP1D (Gen2) is limited to
+	  * 4 RPFs. Hardcode the number of planes to 4 as Gen3 isn't supported
+	  * yet.
+	  */
+	vsp->num_planes = 4;
+
+	vsp->planes = devm_kcalloc(rcdu->dev, vsp->num_planes,
+				   sizeof(*vsp->planes), GFP_KERNEL);
+	if (!vsp->planes)
+		return -ENOMEM;
+
+	for (i = 0; i < vsp->num_planes; ++i) {
+		enum drm_plane_type type = i ? DRM_PLANE_TYPE_OVERLAY
+					 : DRM_PLANE_TYPE_PRIMARY;
+		struct rcar_du_vsp_plane *plane = &vsp->planes[i];
+
+		plane->vsp = vsp;
+		plane->index = i;
+
+		ret = drm_universal_plane_init(rcdu->ddev, &plane->plane,
+					       1 << vsp->index,
+					       &rcar_du_vsp_plane_funcs,
+					       formats_kms,
+					       ARRAY_SIZE(formats_kms), type);
+		if (ret < 0)
+			return ret;
+
+		drm_plane_helper_add(&plane->plane,
+				     &rcar_du_vsp_plane_helper_funcs);
+
+		if (type = DRM_PLANE_TYPE_PRIMARY)
+			continue;
+
+		drm_object_attach_property(&plane->plane.base,
+					   rcdu->props.alpha, 255);
+	}
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
new file mode 100644
index 000000000000..7a6ed21ebcd3
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
@@ -0,0 +1,72 @@
+/*
+ * rcar_du_vsp.h  --  R-Car Display Unit VSP-Based Compositor
+ *
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __RCAR_DU_VSP_H__
+#define __RCAR_DU_VSP_H__
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+
+struct rcar_du_format_info;
+struct rcar_du_vsp;
+
+struct rcar_du_vsp_plane {
+	struct drm_plane plane;
+	struct rcar_du_vsp *vsp;
+	unsigned int index;
+};
+
+struct rcar_du_vsp {
+	unsigned int index;
+	struct device *vsp;
+	struct rcar_du_device *dev;
+	struct rcar_du_vsp_plane *planes;
+	unsigned int num_planes;
+};
+
+static inline struct rcar_du_vsp_plane *to_rcar_vsp_plane(struct drm_plane *p)
+{
+	return container_of(p, struct rcar_du_vsp_plane, plane);
+}
+
+/**
+ * struct rcar_du_vsp_plane_state - Driver-specific plane state
+ * @state: base DRM plane state
+ * @format: information about the pixel format used by the plane
+ * @alpha: value of the plane alpha property
+ */
+struct rcar_du_vsp_plane_state {
+	struct drm_plane_state state;
+
+	const struct rcar_du_format_info *format;
+
+	unsigned int alpha;
+};
+
+static inline struct rcar_du_vsp_plane_state *
+to_rcar_vsp_plane_state(struct drm_plane_state *state)
+{
+	return container_of(state, struct rcar_du_vsp_plane_state, state);
+}
+
+#ifdef CONFIG_DRM_RCAR_VSP
+int rcar_du_vsp_init(struct rcar_du_vsp *vsp);
+void rcar_du_vsp_enable(struct rcar_du_crtc *crtc);
+void rcar_du_vsp_disable(struct rcar_du_crtc *crtc);
+#else
+static inline int rcar_du_vsp_init(struct rcar_du_vsp *vsp) { return 0; };
+static inline void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) { };
+static inline void rcar_du_vsp_disable(struct rcar_du_crtc *crtc) { };
+#endif
+
+#endif /* __RCAR_DU_VSP_H__ */
-- 
2.4.6


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

* [PATCH 10/22] drm: rcar-du: Expose the VSP1 compositor through KMS planes
@ 2015-09-13 22:50   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

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

---
 drivers/gpu/drm/rcar-du/Kconfig         |   7 +
 drivers/gpu/drm/rcar-du/Makefile        |   2 +
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  42 +++-
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h  |   2 +
 drivers/gpu/drm/rcar-du/rcar_du_drv.h   |   4 +
 drivers/gpu/drm/rcar-du/rcar_du_kms.c   |  28 ++-
 drivers/gpu/drm/rcar-du/rcar_du_plane.c |   7 +-
 drivers/gpu/drm/rcar-du/rcar_du_plane.h |  11 +-
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c   | 359 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/rcar-du/rcar_du_vsp.h   |  72 +++++++
 10 files changed, 518 insertions(+), 16 deletions(-)
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vsp.c
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vsp.h

diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index d4e0a39568f6..62650abc3120 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -25,3 +25,10 @@ config DRM_RCAR_LVDS
 	help
 	  Enable support for the R-Car Display Unit embedded LVDS encoders
 	  (currently only on R8A7790 and R8A7791).
+
+config DRM_RCAR_VSP
+	bool "R-Car DU VSP Compositor Support"
+	depends on DRM_RCAR_DU
+	depends on VIDEO_RENESAS_VSP1
+	help
+	  Enable support to expose the R-Car VSP Compositor as KMS planes.
diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
index 05de1c4097af..827711e28226 100644
--- a/drivers/gpu/drm/rcar-du/Makefile
+++ b/drivers/gpu/drm/rcar-du/Makefile
@@ -11,4 +11,6 @@ rcar-du-drm-$(CONFIG_DRM_RCAR_HDMI)	+= rcar_du_hdmicon.o \
 					   rcar_du_hdmienc.o
 rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS)	+= rcar_du_lvdsenc.o
 
+rcar-du-drm-$(CONFIG_DRM_RCAR_VSP)	+= rcar_du_vsp.o
+
 obj-$(CONFIG_DRM_RCAR_DU)		+= rcar-du-drm.o
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 7e2f5c26d589..196b940ea8d7 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -28,6 +28,7 @@
 #include "rcar_du_kms.h"
 #include "rcar_du_plane.h"
 #include "rcar_du_regs.h"
+#include "rcar_du_vsp.h"
 
 static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg)
 {
@@ -207,6 +208,7 @@ plane_format(struct rcar_du_plane *plane)
 static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
 {
 	struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES];
+	struct rcar_du_device *rcdu = rcrtc->group->dev;
 	unsigned int num_planes = 0;
 	unsigned int dptsr_planes;
 	unsigned int hwplanes = 0;
@@ -250,6 +252,12 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
 		}
 	}
 
+	/* If VSP+DU integration is enabled the plane assignment is fixed. */
+	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
+		dspr = (rcrtc->index % 2) + 1;
+		hwplanes = 1 << (rcrtc->index % 2);
+	}
+
 	/* Update the planes to display timing and dot clock generator
 	 * associations.
 	 *
@@ -389,6 +397,10 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
 
 	rcar_du_group_start_stop(rcrtc->group, true);
 
+	/* Enable the VSP compositor. */
+	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
+		rcar_du_vsp_enable(rcrtc);
+
 	/* Turn vertical blanking interrupt reporting back on. */
 	drm_crtc_vblank_on(crtc);
 
@@ -422,6 +434,10 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
 	rcar_du_crtc_wait_page_flip(rcrtc);
 	drm_crtc_vblank_off(crtc);
 
+	/* Disable the VSP compositor. */
+	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
+		rcar_du_vsp_disable(rcrtc);
+
 	/* Select switch sync mode. This stops display operation and configures
 	 * the HSYNC and VSYNC signals as inputs.
 	 */
@@ -434,6 +450,9 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
 
 void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc)
 {
+	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
+		rcar_du_vsp_disable(rcrtc);
+
 	rcar_du_crtc_stop(rcrtc);
 	rcar_du_crtc_put(rcrtc);
 }
@@ -449,13 +468,17 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc)
 	rcar_du_crtc_start(rcrtc);
 
 	/* Commit the planes state. */
-	for (i = 0; i < rcrtc->group->num_planes; ++i) {
-		struct rcar_du_plane *plane = &rcrtc->group->planes[i];
+	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) {
+		rcar_du_vsp_enable(rcrtc);
+	} else {
+		for (i = 0; i < rcrtc->group->num_planes; ++i) {
+			struct rcar_du_plane *plane = &rcrtc->group->planes[i];
 
-		if (plane->plane.state->crtc != &rcrtc->crtc)
-			continue;
+			if (plane->plane.state->crtc != &rcrtc->crtc)
+				continue;
 
-		rcar_du_plane_setup(plane);
+			rcar_du_plane_setup(plane);
+		}
 	}
 
 	rcar_du_crtc_update_planes(rcrtc);
@@ -578,6 +601,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
 	struct platform_device *pdev = to_platform_device(rcdu->dev);
 	struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index];
 	struct drm_crtc *crtc = &rcrtc->crtc;
+	struct drm_plane *primary;
 	unsigned int irqflags;
 	struct clk *clk;
 	char clk_name[9];
@@ -615,8 +639,12 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
 	rcrtc->index = index;
 	rcrtc->enabled = false;
 
-	ret = drm_crtc_init_with_planes(rcdu->ddev, crtc,
-					&rgrp->planes[index % 2].plane,
+	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
+		primary = &rcrtc->vsp->planes[0].plane;
+	else
+		primary = &rgrp->planes[index % 2].plane;
+
+	ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary,
 					NULL, &crtc_funcs);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index 4b95d9d08c49..c7ab46702b1d 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -21,6 +21,7 @@
 #include <drm/drm_crtc.h>
 
 struct rcar_du_group;
+struct rcar_du_vsp;
 
 /**
  * struct rcar_du_crtc - the CRTC, representing a DU superposition processor
@@ -52,6 +53,7 @@ struct rcar_du_crtc {
 	bool enabled;
 
 	struct rcar_du_group *group;
+	struct rcar_du_vsp *vsp;
 };
 
 #define to_rcar_crtc(c)	container_of(c, struct rcar_du_crtc, crtc)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index e10b4f0d8f83..a81eb3281e7f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -19,6 +19,7 @@
 
 #include "rcar_du_crtc.h"
 #include "rcar_du_group.h"
+#include "rcar_du_vsp.h"
 
 struct clk;
 struct device;
@@ -29,6 +30,7 @@ struct rcar_du_lvdsenc;
 
 #define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK	(1 << 0)	/* Per-CRTC IRQ and clock */
 #define RCAR_DU_FEATURE_EXT_CTRL_REGS	(1 << 1)	/* Has extended control registers */
+#define RCAR_DU_FEATURE_VSP1_SOURCE	(1 << 2)	/* Has inputs from VSP1 */
 
 #define RCAR_DU_QUIRK_ALIGN_128B	(1 << 0)	/* Align pitches to 128 bytes */
 #define RCAR_DU_QUIRK_LVDS_LANES	(1 << 1)	/* LVDS lanes 1 and 3 inverted */
@@ -68,6 +70,7 @@ struct rcar_du_device_info {
 #define RCAR_DU_MAX_CRTCS		3
 #define RCAR_DU_MAX_GROUPS		DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2)
 #define RCAR_DU_MAX_LVDS		2
+#define RCAR_DU_MAX_VSPS		4
 
 struct rcar_du_device {
 	struct device *dev;
@@ -82,6 +85,7 @@ struct rcar_du_device {
 	unsigned int num_crtcs;
 
 	struct rcar_du_group groups[RCAR_DU_MAX_GROUPS];
+	struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS];
 
 	struct {
 		struct drm_property *alpha;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 6196410b9e98..3f3d93dcbf64 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -28,6 +28,7 @@
 #include "rcar_du_kms.h"
 #include "rcar_du_lvdsenc.h"
 #include "rcar_du_regs.h"
+#include "rcar_du_vsp.h"
 
 /* -----------------------------------------------------------------------------
  * Format helpers
@@ -195,12 +196,16 @@ static void rcar_du_output_poll_changed(struct drm_device *dev)
 static int rcar_du_atomic_check(struct drm_device *dev,
 				struct drm_atomic_state *state)
 {
+	struct rcar_du_device *rcdu = dev->dev_private;
 	int ret;
 
 	ret = drm_atomic_helper_check(dev, state);
 	if (ret < 0)
 		return ret;
 
+	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
+		return 0;
+
 	return rcar_du_atomic_check_planes(dev, state);
 }
 
@@ -544,9 +549,26 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 		 */
 		rgrp->dptsr_planes = rgrp->num_crtcs > 1 ? 0xf0 : 0;
 
-		ret = rcar_du_planes_init(rgrp);
-		if (ret < 0)
-			return ret;
+		if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
+			ret = rcar_du_planes_init(rgrp);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	/* Initialize the compositors. */
+	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
+		for (i = 0; i < rcdu->num_crtcs; ++i) {
+			struct rcar_du_vsp *vsp = &rcdu->vsps[i];
+
+			vsp->index = i;
+			vsp->dev = rcdu;
+			rcdu->crtcs[i].vsp = vsp;
+
+			ret = rcar_du_vsp_init(vsp);
+			if (ret < 0)
+				return ret;
+		}
 	}
 
 	/* Create the CRTCs. */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index b868184e8385..4a38ced4b952 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -505,12 +505,9 @@ static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
 	rcar_du_plane_write(rgrp, index, PnMLR, 0);
 }
 
-void rcar_du_plane_setup(struct rcar_du_plane *plane)
+void __rcar_du_plane_setup(struct rcar_du_group *rgrp,
+			   const struct rcar_du_plane_state *state)
 {
-	struct rcar_du_plane_state *state =
-		to_rcar_plane_state(plane->plane.state);
-	struct rcar_du_group *rgrp = plane->group;
-
 	rcar_du_plane_setup_format(rgrp, state->hwindex, state);
 	if (state->format->planes == 2)
 		rcar_du_plane_setup_format(rgrp, (state->hwindex + 1) % 8,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 6a6460dffae4..b18b7b25dbfa 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -76,6 +76,15 @@ int rcar_du_atomic_check_planes(struct drm_device *dev,
 
 int rcar_du_planes_init(struct rcar_du_group *rgrp);
 
-void rcar_du_plane_setup(struct rcar_du_plane *plane);
+void __rcar_du_plane_setup(struct rcar_du_group *rgrp,
+			   const struct rcar_du_plane_state *state);
+
+static inline void rcar_du_plane_setup(struct rcar_du_plane *plane)
+{
+	struct rcar_du_plane_state *state =
+		to_rcar_plane_state(plane->plane.state);
+
+	return __rcar_du_plane_setup(plane->group, state);
+}
 
 #endif /* __RCAR_DU_PLANE_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
new file mode 100644
index 000000000000..6e34dfd0ef42
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -0,0 +1,359 @@
+/*
+ * rcar_du_vsp.h  --  R-Car Display Unit VSP-Based Compositor
+ *
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include <linux/of_platform.h>
+#include <linux/videodev2.h>
+
+#include <media/vsp1.h>
+
+#include "rcar_du_drv.h"
+#include "rcar_du_kms.h"
+#include "rcar_du_vsp.h"
+
+void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
+{
+	const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode;
+	struct rcar_du_plane_state state = {
+		.state = {
+			.crtc = &crtc->crtc,
+			.crtc_x = 0,
+			.crtc_y = 0,
+			.crtc_w = mode->hdisplay,
+			.crtc_h = mode->vdisplay,
+			.src_x = 0,
+			.src_y = 0,
+			.src_w = mode->hdisplay << 16,
+			.src_h = mode->vdisplay << 16,
+		},
+		.format = rcar_du_format_info(DRM_FORMAT_ARGB8888),
+		.hwindex = crtc->index % 2,
+		.source = RCAR_DU_PLANE_VSPD1,
+		.alpha = 255,
+		.colorkey = 0,
+		.zpos = 0,
+	};
+
+	__rcar_du_plane_setup(crtc->group, &state);
+
+	/* Ensure that the plane source configuration takes effect by requesting
+	 * a restart of the group. See rcar_du_plane_atomic_update() for a more
+	 * detailed explanation.
+	 *
+	 * TODO: Check whether this is still needed on Gen3.
+	 */
+	crtc->group->need_restart = true;
+
+	vsp1_du_setup_lif(crtc->vsp->vsp, mode->hdisplay, mode->vdisplay);
+}
+
+void rcar_du_vsp_disable(struct rcar_du_crtc *crtc)
+{
+	vsp1_du_setup_lif(crtc->vsp->vsp, 0, 0);
+}
+
+/* Keep the two tables in sync. */
+static const u32 formats_kms[] = {
+	DRM_FORMAT_RGB332,
+	DRM_FORMAT_ARGB4444,
+	DRM_FORMAT_XRGB4444,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_XRGB1555,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGRA8888,
+	DRM_FORMAT_BGRX8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_VYUY,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV21,
+	DRM_FORMAT_NV16,
+	DRM_FORMAT_NV61,
+};
+
+static const u32 formats_v4l2[] = {
+	V4L2_PIX_FMT_RGB332,
+	V4L2_PIX_FMT_ARGB444,
+	V4L2_PIX_FMT_XRGB444,
+	V4L2_PIX_FMT_ARGB555,
+	V4L2_PIX_FMT_XRGB555,
+	V4L2_PIX_FMT_RGB565,
+	V4L2_PIX_FMT_RGB24,
+	V4L2_PIX_FMT_BGR24,
+	V4L2_PIX_FMT_ARGB32,
+	V4L2_PIX_FMT_XRGB32,
+	V4L2_PIX_FMT_ABGR32,
+	V4L2_PIX_FMT_XBGR32,
+	V4L2_PIX_FMT_UYVY,
+	V4L2_PIX_FMT_VYUY,
+	V4L2_PIX_FMT_YUYV,
+	V4L2_PIX_FMT_YVYU,
+	V4L2_PIX_FMT_NV12M,
+	V4L2_PIX_FMT_NV21M,
+	V4L2_PIX_FMT_NV16M,
+	V4L2_PIX_FMT_NV61M,
+};
+
+static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
+{
+	struct rcar_du_vsp_plane_state *state =
+		to_rcar_vsp_plane_state(plane->plane.state);
+	struct drm_framebuffer *fb = plane->plane.state->fb;
+	struct drm_gem_cma_object *gem;
+	struct v4l2_rect src;
+	struct v4l2_rect dst;
+	dma_addr_t paddr[2] = { 0, };
+	u32 pixelformat = 0;
+	unsigned int i;
+
+	src.left = state->state.src_x >> 16;
+	src.top = state->state.src_y >> 16;
+	src.width = state->state.src_w >> 16;
+	src.height = state->state.src_h >> 16;
+
+	dst.left = state->state.crtc_x;
+	dst.top = state->state.crtc_y;
+	dst.width = state->state.crtc_w;
+	dst.height = state->state.crtc_h;
+
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+	paddr[0] = gem->paddr + fb->offsets[0];
+
+	if (state->format->planes == 2) {
+		gem = drm_fb_cma_get_gem_obj(fb, 1);
+		paddr[1] = gem->paddr + fb->offsets[1];
+	}
+
+	for (i = 0; i < ARRAY_SIZE(formats_kms); ++i) {
+		if (formats_kms[i] == state->format->fourcc) {
+			pixelformat = formats_v4l2[i];
+			break;
+		}
+	}
+
+	WARN_ON(!pixelformat);
+
+	vsp1_du_setup_rpf(plane->vsp->vsp, plane->index, pixelformat,
+			  fb->pitches[0], paddr, &src, &dst);
+}
+
+static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane,
+					  struct drm_plane_state *state)
+{
+	struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state);
+	struct rcar_du_vsp_plane *rplane = to_rcar_vsp_plane(plane);
+	struct rcar_du_device *rcdu = rplane->vsp->dev;
+
+	if (!state->fb || !state->crtc) {
+		rstate->format = NULL;
+		return 0;
+	}
+
+	if (state->src_w >> 16 != state->crtc_w ||
+	    state->src_h >> 16 != state->crtc_h) {
+		dev_dbg(rcdu->dev, "%s: scaling not supported\n", __func__);
+		return -EINVAL;
+	}
+
+	rstate->format = rcar_du_format_info(state->fb->pixel_format);
+	if (rstate->format == NULL) {
+		dev_dbg(rcdu->dev, "%s: unsupported format %08x\n", __func__,
+			state->fb->pixel_format);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void rcar_du_vsp_plane_atomic_update(struct drm_plane *plane,
+					struct drm_plane_state *old_state)
+{
+	struct rcar_du_vsp_plane *rplane = to_rcar_vsp_plane(plane);
+
+	if (plane->state->crtc)
+		rcar_du_vsp_plane_setup(rplane);
+	else
+		vsp1_du_setup_rpf(rplane->vsp->vsp, rplane->index, 0, 0, 0,
+				  NULL, NULL);
+}
+
+static const struct drm_plane_helper_funcs rcar_du_vsp_plane_helper_funcs = {
+	.atomic_check = rcar_du_vsp_plane_atomic_check,
+	.atomic_update = rcar_du_vsp_plane_atomic_update,
+};
+
+static struct drm_plane_state *
+rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane)
+{
+	struct rcar_du_vsp_plane_state *state;
+	struct rcar_du_vsp_plane_state *copy;
+
+	if (WARN_ON(!plane->state))
+		return NULL;
+
+	state = to_rcar_vsp_plane_state(plane->state);
+	copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
+	if (copy == NULL)
+		return NULL;
+
+	__drm_atomic_helper_plane_duplicate_state(plane, &copy->state);
+
+	return &copy->state;
+}
+
+static void rcar_du_vsp_plane_atomic_destroy_state(struct drm_plane *plane,
+						   struct drm_plane_state *state)
+{
+	__drm_atomic_helper_plane_destroy_state(plane, state);
+	kfree(to_rcar_vsp_plane_state(state));
+}
+
+static void rcar_du_vsp_plane_reset(struct drm_plane *plane)
+{
+	struct rcar_du_vsp_plane_state *state;
+
+	if (plane->state) {
+		rcar_du_vsp_plane_atomic_destroy_state(plane, plane->state);
+		plane->state = NULL;
+	}
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (state == NULL)
+		return;
+
+	state->alpha = 255;
+
+	plane->state = &state->state;
+	plane->state->plane = plane;
+}
+
+static int rcar_du_vsp_plane_atomic_set_property(struct drm_plane *plane,
+	struct drm_plane_state *state, struct drm_property *property,
+	uint64_t val)
+{
+	struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state);
+	struct rcar_du_device *rcdu = to_rcar_vsp_plane(plane)->vsp->dev;
+
+	if (property == rcdu->props.alpha)
+		rstate->alpha = val;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int rcar_du_vsp_plane_atomic_get_property(struct drm_plane *plane,
+	const struct drm_plane_state *state, struct drm_property *property,
+	uint64_t *val)
+{
+	const struct rcar_du_vsp_plane_state *rstate =
+		container_of(state, const struct rcar_du_vsp_plane_state, state);
+	struct rcar_du_device *rcdu = to_rcar_vsp_plane(plane)->vsp->dev;
+
+	if (property == rcdu->props.alpha)
+		*val = rstate->alpha;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct drm_plane_funcs rcar_du_vsp_plane_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.reset = rcar_du_vsp_plane_reset,
+	.set_property = drm_atomic_helper_plane_set_property,
+	.destroy = drm_plane_cleanup,
+	.atomic_duplicate_state = rcar_du_vsp_plane_atomic_duplicate_state,
+	.atomic_destroy_state = rcar_du_vsp_plane_atomic_destroy_state,
+	.atomic_set_property = rcar_du_vsp_plane_atomic_set_property,
+	.atomic_get_property = rcar_du_vsp_plane_atomic_get_property,
+};
+
+int rcar_du_vsp_init(struct rcar_du_vsp *vsp)
+{
+	struct rcar_du_device *rcdu = vsp->dev;
+	struct platform_device *pdev;
+	struct device_node *np;
+	unsigned int i;
+	int ret;
+
+	/* Find the VSP device and initialize it. */
+	np = of_parse_phandle(rcdu->dev->of_node, "vsps", vsp->index);
+	if (!np) {
+		dev_err(rcdu->dev, "vsps node not found\n");
+		return -ENXIO;
+	}
+
+	pdev = of_find_device_by_node(np);
+	of_node_put(np);
+	if (!pdev)
+		return -ENXIO;
+
+	vsp->vsp = &pdev->dev;
+
+	ret = vsp1_du_init(vsp->vsp);
+	if (ret < 0)
+		return ret;
+
+	 /* The VSP2D (Gen3) has 5 RPFs, but the VSP1D (Gen2) is limited to
+	  * 4 RPFs. Hardcode the number of planes to 4 as Gen3 isn't supported
+	  * yet.
+	  */
+	vsp->num_planes = 4;
+
+	vsp->planes = devm_kcalloc(rcdu->dev, vsp->num_planes,
+				   sizeof(*vsp->planes), GFP_KERNEL);
+	if (!vsp->planes)
+		return -ENOMEM;
+
+	for (i = 0; i < vsp->num_planes; ++i) {
+		enum drm_plane_type type = i ? DRM_PLANE_TYPE_OVERLAY
+					 : DRM_PLANE_TYPE_PRIMARY;
+		struct rcar_du_vsp_plane *plane = &vsp->planes[i];
+
+		plane->vsp = vsp;
+		plane->index = i;
+
+		ret = drm_universal_plane_init(rcdu->ddev, &plane->plane,
+					       1 << vsp->index,
+					       &rcar_du_vsp_plane_funcs,
+					       formats_kms,
+					       ARRAY_SIZE(formats_kms), type);
+		if (ret < 0)
+			return ret;
+
+		drm_plane_helper_add(&plane->plane,
+				     &rcar_du_vsp_plane_helper_funcs);
+
+		if (type == DRM_PLANE_TYPE_PRIMARY)
+			continue;
+
+		drm_object_attach_property(&plane->plane.base,
+					   rcdu->props.alpha, 255);
+	}
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
new file mode 100644
index 000000000000..7a6ed21ebcd3
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
@@ -0,0 +1,72 @@
+/*
+ * rcar_du_vsp.h  --  R-Car Display Unit VSP-Based Compositor
+ *
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __RCAR_DU_VSP_H__
+#define __RCAR_DU_VSP_H__
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+
+struct rcar_du_format_info;
+struct rcar_du_vsp;
+
+struct rcar_du_vsp_plane {
+	struct drm_plane plane;
+	struct rcar_du_vsp *vsp;
+	unsigned int index;
+};
+
+struct rcar_du_vsp {
+	unsigned int index;
+	struct device *vsp;
+	struct rcar_du_device *dev;
+	struct rcar_du_vsp_plane *planes;
+	unsigned int num_planes;
+};
+
+static inline struct rcar_du_vsp_plane *to_rcar_vsp_plane(struct drm_plane *p)
+{
+	return container_of(p, struct rcar_du_vsp_plane, plane);
+}
+
+/**
+ * struct rcar_du_vsp_plane_state - Driver-specific plane state
+ * @state: base DRM plane state
+ * @format: information about the pixel format used by the plane
+ * @alpha: value of the plane alpha property
+ */
+struct rcar_du_vsp_plane_state {
+	struct drm_plane_state state;
+
+	const struct rcar_du_format_info *format;
+
+	unsigned int alpha;
+};
+
+static inline struct rcar_du_vsp_plane_state *
+to_rcar_vsp_plane_state(struct drm_plane_state *state)
+{
+	return container_of(state, struct rcar_du_vsp_plane_state, state);
+}
+
+#ifdef CONFIG_DRM_RCAR_VSP
+int rcar_du_vsp_init(struct rcar_du_vsp *vsp);
+void rcar_du_vsp_enable(struct rcar_du_crtc *crtc);
+void rcar_du_vsp_disable(struct rcar_du_crtc *crtc);
+#else
+static inline int rcar_du_vsp_init(struct rcar_du_vsp *vsp) { return 0; };
+static inline void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) { };
+static inline void rcar_du_vsp_disable(struct rcar_du_crtc *crtc) { };
+#endif
+
+#endif /* __RCAR_DU_VSP_H__ */
-- 
2.4.6

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

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

* [PATCH 11/22] drm: rcar-du: Use the VSP atomic update API
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:50   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c |  6 ++++++
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c  | 18 ++++++++++++++----
 drivers/gpu/drm/rcar-du/rcar_du_vsp.h  |  4 ++++
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 196b940ea8d7..b63bdd12609e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -538,6 +538,9 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
 		rcrtc->event = event;
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 	}
+
+	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
+		rcar_du_vsp_atomic_begin(rcrtc);
 }
 
 static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc,
@@ -546,6 +549,9 @@ static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc,
 	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
 
 	rcar_du_crtc_update_planes(rcrtc);
+
+	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
+		rcar_du_vsp_atomic_flush(rcrtc);
 }
 
 static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index 6e34dfd0ef42..f01c089881e0 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -69,6 +69,16 @@ void rcar_du_vsp_disable(struct rcar_du_crtc *crtc)
 	vsp1_du_setup_lif(crtc->vsp->vsp, 0, 0);
 }
 
+void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc)
+{
+	vsp1_du_atomic_begin(crtc->vsp->vsp);
+}
+
+void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc)
+{
+	vsp1_du_atomic_flush(crtc->vsp->vsp);
+}
+
 /* Keep the two tables in sync. */
 static const u32 formats_kms[] = {
 	DRM_FORMAT_RGB332,
@@ -155,8 +165,8 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
 
 	WARN_ON(!pixelformat);
 
-	vsp1_du_setup_rpf(plane->vsp->vsp, plane->index, pixelformat,
-			  fb->pitches[0], paddr, &src, &dst);
+	vsp1_du_atomic_update(plane->vsp->vsp, plane->index, pixelformat,
+			      fb->pitches[0], paddr, &src, &dst);
 }
 
 static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane,
@@ -195,8 +205,8 @@ static void rcar_du_vsp_plane_atomic_update(struct drm_plane *plane,
 	if (plane->state->crtc)
 		rcar_du_vsp_plane_setup(rplane);
 	else
-		vsp1_du_setup_rpf(rplane->vsp->vsp, rplane->index, 0, 0, 0,
-				  NULL, NULL);
+		vsp1_du_atomic_update(rplane->vsp->vsp, rplane->index, 0, 0, 0,
+				      NULL, NULL);
 }
 
 static const struct drm_plane_helper_funcs rcar_du_vsp_plane_helper_funcs = {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
index 7a6ed21ebcd3..df3bf3805c69 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
@@ -63,10 +63,14 @@ to_rcar_vsp_plane_state(struct drm_plane_state *state)
 int rcar_du_vsp_init(struct rcar_du_vsp *vsp);
 void rcar_du_vsp_enable(struct rcar_du_crtc *crtc);
 void rcar_du_vsp_disable(struct rcar_du_crtc *crtc);
+void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc);
+void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc);
 #else
 static inline int rcar_du_vsp_init(struct rcar_du_vsp *vsp) { return 0; };
 static inline void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) { };
 static inline void rcar_du_vsp_disable(struct rcar_du_crtc *crtc) { };
+static inline void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc) { };
+static inline void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc) { };
 #endif
 
 #endif /* __RCAR_DU_VSP_H__ */
-- 
2.4.6


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

* [PATCH 11/22] drm: rcar-du: Use the VSP atomic update API
@ 2015-09-13 22:50   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c |  6 ++++++
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c  | 18 ++++++++++++++----
 drivers/gpu/drm/rcar-du/rcar_du_vsp.h  |  4 ++++
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 196b940ea8d7..b63bdd12609e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -538,6 +538,9 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
 		rcrtc->event = event;
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 	}
+
+	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
+		rcar_du_vsp_atomic_begin(rcrtc);
 }
 
 static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc,
@@ -546,6 +549,9 @@ static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc,
 	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
 
 	rcar_du_crtc_update_planes(rcrtc);
+
+	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
+		rcar_du_vsp_atomic_flush(rcrtc);
 }
 
 static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index 6e34dfd0ef42..f01c089881e0 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -69,6 +69,16 @@ void rcar_du_vsp_disable(struct rcar_du_crtc *crtc)
 	vsp1_du_setup_lif(crtc->vsp->vsp, 0, 0);
 }
 
+void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc)
+{
+	vsp1_du_atomic_begin(crtc->vsp->vsp);
+}
+
+void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc)
+{
+	vsp1_du_atomic_flush(crtc->vsp->vsp);
+}
+
 /* Keep the two tables in sync. */
 static const u32 formats_kms[] = {
 	DRM_FORMAT_RGB332,
@@ -155,8 +165,8 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
 
 	WARN_ON(!pixelformat);
 
-	vsp1_du_setup_rpf(plane->vsp->vsp, plane->index, pixelformat,
-			  fb->pitches[0], paddr, &src, &dst);
+	vsp1_du_atomic_update(plane->vsp->vsp, plane->index, pixelformat,
+			      fb->pitches[0], paddr, &src, &dst);
 }
 
 static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane,
@@ -195,8 +205,8 @@ static void rcar_du_vsp_plane_atomic_update(struct drm_plane *plane,
 	if (plane->state->crtc)
 		rcar_du_vsp_plane_setup(rplane);
 	else
-		vsp1_du_setup_rpf(rplane->vsp->vsp, rplane->index, 0, 0, 0,
-				  NULL, NULL);
+		vsp1_du_atomic_update(rplane->vsp->vsp, rplane->index, 0, 0, 0,
+				      NULL, NULL);
 }
 
 static const struct drm_plane_helper_funcs rcar_du_vsp_plane_helper_funcs = {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
index 7a6ed21ebcd3..df3bf3805c69 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h
@@ -63,10 +63,14 @@ to_rcar_vsp_plane_state(struct drm_plane_state *state)
 int rcar_du_vsp_init(struct rcar_du_vsp *vsp);
 void rcar_du_vsp_enable(struct rcar_du_crtc *crtc);
 void rcar_du_vsp_disable(struct rcar_du_crtc *crtc);
+void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc);
+void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc);
 #else
 static inline int rcar_du_vsp_init(struct rcar_du_vsp *vsp) { return 0; };
 static inline void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) { };
 static inline void rcar_du_vsp_disable(struct rcar_du_crtc *crtc) { };
+static inline void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc) { };
+static inline void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc) { };
 #endif
 
 #endif /* __RCAR_DU_VSP_H__ */
-- 
2.4.6

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

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

* [PATCH 12/22] drm: rcar-du: Fix compile warning on 64-bit platforms
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:50   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

From: Koji Matsuoka <koji.matsuoka.xm@renesas.com>

Use %tu instead of %u to print difference between pointers.

Signed-off-by: Koji Matsuoka <koji.matsuoka.xm@renesas.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_plane.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 4a38ced4b952..7d2e301df042 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -153,7 +153,7 @@ int rcar_du_atomic_check_planes(struct drm_device *dev,
 		plane = to_rcar_plane(state->planes[i]);
 		plane_state = to_rcar_plane_state(state->plane_states[i]);
 
-		dev_dbg(rcdu->dev, "%s: checking plane (%u,%u)\n", __func__,
+		dev_dbg(rcdu->dev, "%s: checking plane (%u,%tu)\n", __func__,
 			plane->group->index, plane - plane->group->planes);
 
 		/* If the plane is being disabled we don't need to go through
@@ -221,7 +221,7 @@ int rcar_du_atomic_check_planes(struct drm_device *dev,
 			 */
 			if (group_freed_planes[index] & (1 << i)) {
 				dev_dbg(rcdu->dev,
-					"%s: plane (%u,%u) has been freed, skipping\n",
+					"%s: plane (%u,%tu) has been freed, skipping\n",
 					__func__, plane->group->index,
 					plane - plane->group->planes);
 				continue;
@@ -231,7 +231,7 @@ int rcar_du_atomic_check_planes(struct drm_device *dev,
 			used_planes |= rcar_du_plane_hwmask(plane_state);
 
 			dev_dbg(rcdu->dev,
-				"%s: plane (%u,%u) uses %u hwplanes (index %d)\n",
+				"%s: plane (%u,%tu) uses %u hwplanes (index %d)\n",
 				__func__, plane->group->index,
 				plane - plane->group->planes,
 				plane_state->format ?
@@ -260,7 +260,7 @@ int rcar_du_atomic_check_planes(struct drm_device *dev,
 		plane = to_rcar_plane(state->planes[i]);
 		plane_state = to_rcar_plane_state(state->plane_states[i]);
 
-		dev_dbg(rcdu->dev, "%s: allocating plane (%u,%u)\n", __func__,
+		dev_dbg(rcdu->dev, "%s: allocating plane (%u,%tu)\n", __func__,
 			plane->group->index, plane - plane->group->planes);
 
 		/* Skip planes that are being disabled or don't need to be
-- 
2.4.6


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

* [PATCH 12/22] drm: rcar-du: Fix compile warning on 64-bit platforms
@ 2015-09-13 22:50   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:50 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

From: Koji Matsuoka <koji.matsuoka.xm@renesas.com>

Use %tu instead of %u to print difference between pointers.

Signed-off-by: Koji Matsuoka <koji.matsuoka.xm@renesas.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_plane.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 4a38ced4b952..7d2e301df042 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -153,7 +153,7 @@ int rcar_du_atomic_check_planes(struct drm_device *dev,
 		plane = to_rcar_plane(state->planes[i]);
 		plane_state = to_rcar_plane_state(state->plane_states[i]);
 
-		dev_dbg(rcdu->dev, "%s: checking plane (%u,%u)\n", __func__,
+		dev_dbg(rcdu->dev, "%s: checking plane (%u,%tu)\n", __func__,
 			plane->group->index, plane - plane->group->planes);
 
 		/* If the plane is being disabled we don't need to go through
@@ -221,7 +221,7 @@ int rcar_du_atomic_check_planes(struct drm_device *dev,
 			 */
 			if (group_freed_planes[index] & (1 << i)) {
 				dev_dbg(rcdu->dev,
-					"%s: plane (%u,%u) has been freed, skipping\n",
+					"%s: plane (%u,%tu) has been freed, skipping\n",
 					__func__, plane->group->index,
 					plane - plane->group->planes);
 				continue;
@@ -231,7 +231,7 @@ int rcar_du_atomic_check_planes(struct drm_device *dev,
 			used_planes |= rcar_du_plane_hwmask(plane_state);
 
 			dev_dbg(rcdu->dev,
-				"%s: plane (%u,%u) uses %u hwplanes (index %d)\n",
+				"%s: plane (%u,%tu) uses %u hwplanes (index %d)\n",
 				__func__, plane->group->index,
 				plane - plane->group->planes,
 				plane_state->format ?
@@ -260,7 +260,7 @@ int rcar_du_atomic_check_planes(struct drm_device *dev,
 		plane = to_rcar_plane(state->planes[i]);
 		plane_state = to_rcar_plane_state(state->plane_states[i]);
 
-		dev_dbg(rcdu->dev, "%s: allocating plane (%u,%u)\n", __func__,
+		dev_dbg(rcdu->dev, "%s: allocating plane (%u,%tu)\n", __func__,
 			plane->group->index, plane - plane->group->planes);
 
 		/* Skip planes that are being disabled or don't need to be
-- 
2.4.6


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

* [PATCH 13/22] drm: rcar-du: Enable compilation on ARM64
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:51   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

From: Koji Matsuoka <koji.matsuoka.xm@renesas.com>

The R8A7795 SoC is ARM64-based and include a DU. Enable driver
compilation on ARM64.

Signed-off-by: Koji Matsuoka <koji.matsuoka.xm@renesas.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/Kconfig | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index 62650abc3120..7c465ee7aec3 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -1,6 +1,7 @@
 config DRM_RCAR_DU
 	tristate "DRM Support for R-Car Display Unit"
-	depends on DRM && ARM && HAVE_DMA_ATTRS && OF
+	depends on DRM && HAVE_DMA_ATTRS && OF
+	depends on ARM || ARM64
 	depends on ARCH_SHMOBILE || COMPILE_TEST
 	select DRM_KMS_HELPER
 	select DRM_KMS_CMA_HELPER
-- 
2.4.6


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

* [PATCH 13/22] drm: rcar-du: Enable compilation on ARM64
@ 2015-09-13 22:51   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

From: Koji Matsuoka <koji.matsuoka.xm@renesas.com>

The R8A7795 SoC is ARM64-based and include a DU. Enable driver
compilation on ARM64.

Signed-off-by: Koji Matsuoka <koji.matsuoka.xm@renesas.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/Kconfig | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index 62650abc3120..7c465ee7aec3 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -1,6 +1,7 @@
 config DRM_RCAR_DU
 	tristate "DRM Support for R-Car Display Unit"
-	depends on DRM && ARM && HAVE_DMA_ATTRS && OF
+	depends on DRM && HAVE_DMA_ATTRS && OF
+	depends on ARM || ARM64
 	depends on ARCH_SHMOBILE || COMPILE_TEST
 	select DRM_KMS_HELPER
 	select DRM_KMS_CMA_HELPER
-- 
2.4.6


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

* [PATCH 14/22] drm: rcar-du: Drop LVDS double dependency on OF
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:51   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

LVDS support depends on DRM_RCAR_DU which already depends on OF. Drop
the explicit dependency.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index 7c465ee7aec3..6c3e49e9e290 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -15,7 +15,6 @@ config DRM_RCAR_DU
 config DRM_RCAR_HDMI
 	bool "R-Car DU HDMI Encoder Support"
 	depends on DRM_RCAR_DU
-	depends on OF
 	help
 	  Enable support for external HDMI encoders.
 
-- 
2.4.6


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

* [PATCH 14/22] drm: rcar-du: Drop LVDS double dependency on OF
@ 2015-09-13 22:51   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

LVDS support depends on DRM_RCAR_DU which already depends on OF. Drop
the explicit dependency.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index 7c465ee7aec3..6c3e49e9e290 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -15,7 +15,6 @@ config DRM_RCAR_DU
 config DRM_RCAR_HDMI
 	bool "R-Car DU HDMI Encoder Support"
 	depends on DRM_RCAR_DU
-	depends on OF
 	help
 	  Enable support for external HDMI encoders.
 
-- 
2.4.6

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

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

* [PATCH 15/22] drm: rcar-du: Support up to 4 CRTCs
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:51   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

From: Koji Matsuoka <koji.matsuoka.xm@renesas.com>

The Gen3 R8A7795 DU has 4 CRTCs, support them all.

Signed-off-by: Koji Matsuoka <koji.matsuoka.xm@renesas.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_drv.h  | 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_regs.h | 1 +
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index b63bdd12609e..9f0d94b3ec10 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -600,7 +600,7 @@ static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
 int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
 {
 	static const unsigned int mmio_offsets[] = {
-		DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET
+		DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET, DU3_REG_OFFSET
 	};
 
 	struct rcar_du_device *rcdu = rgrp->dev;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index a81eb3281e7f..ce359edc9ab9 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -67,7 +67,7 @@ struct rcar_du_device_info {
 	unsigned int num_lvds;
 };
 
-#define RCAR_DU_MAX_CRTCS		3
+#define RCAR_DU_MAX_CRTCS		4
 #define RCAR_DU_MAX_GROUPS		DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2)
 #define RCAR_DU_MAX_LVDS		2
 #define RCAR_DU_MAX_VSPS		4
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
index ac9c3e511e79..95add71a33c8 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
@@ -16,6 +16,7 @@
 #define DU0_REG_OFFSET		0x00000
 #define DU1_REG_OFFSET		0x30000
 #define DU2_REG_OFFSET		0x40000
+#define DU3_REG_OFFSET		0x70000
 
 /* -----------------------------------------------------------------------------
  * Display Control Registers
-- 
2.4.6


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

* [PATCH 15/22] drm: rcar-du: Support up to 4 CRTCs
@ 2015-09-13 22:51   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

From: Koji Matsuoka <koji.matsuoka.xm@renesas.com>

The Gen3 R8A7795 DU has 4 CRTCs, support them all.

Signed-off-by: Koji Matsuoka <koji.matsuoka.xm@renesas.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_drv.h  | 2 +-
 drivers/gpu/drm/rcar-du/rcar_du_regs.h | 1 +
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index b63bdd12609e..9f0d94b3ec10 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -600,7 +600,7 @@ static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
 int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
 {
 	static const unsigned int mmio_offsets[] = {
-		DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET
+		DU0_REG_OFFSET, DU1_REG_OFFSET, DU2_REG_OFFSET, DU3_REG_OFFSET
 	};
 
 	struct rcar_du_device *rcdu = rgrp->dev;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index a81eb3281e7f..ce359edc9ab9 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -67,7 +67,7 @@ struct rcar_du_device_info {
 	unsigned int num_lvds;
 };
 
-#define RCAR_DU_MAX_CRTCS		3
+#define RCAR_DU_MAX_CRTCS		4
 #define RCAR_DU_MAX_GROUPS		DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2)
 #define RCAR_DU_MAX_LVDS		2
 #define RCAR_DU_MAX_VSPS		4
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
index ac9c3e511e79..95add71a33c8 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
@@ -16,6 +16,7 @@
 #define DU0_REG_OFFSET		0x00000
 #define DU1_REG_OFFSET		0x30000
 #define DU2_REG_OFFSET		0x40000
+#define DU3_REG_OFFSET		0x70000
 
 /* -----------------------------------------------------------------------------
  * Display Control Registers
-- 
2.4.6

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

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

* [PATCH 16/22] drm: rcar-du: Output the DISP signal on the DISP pin
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:51   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

The DE signal is currently configured to be identical to the DISP
signal and is used for the same purpose. To make it clearer that the
DISP pin outputs the DISP signal, select it explicitly.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 9f0d94b3ec10..15bf57de106b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -151,7 +151,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
 	/* Signal polarities */
 	value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : DSMR_VSL)
 	      | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : DSMR_HSL)
-	      | DSMR_DIPM_DE | DSMR_CSPM;
+	      | DSMR_DIPM_DISP | DSMR_CSPM;
 	rcar_du_crtc_write(rcrtc, DSMR, value);
 
 	/* Display timings */
-- 
2.4.6


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

* [PATCH 16/22] drm: rcar-du: Output the DISP signal on the DISP pin
@ 2015-09-13 22:51   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

The DE signal is currently configured to be identical to the DISP
signal and is used for the same purpose. To make it clearer that the
DISP pin outputs the DISP signal, select it explicitly.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 9f0d94b3ec10..15bf57de106b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -151,7 +151,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
 	/* Signal polarities */
 	value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : DSMR_VSL)
 	      | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : DSMR_HSL)
-	      | DSMR_DIPM_DE | DSMR_CSPM;
+	      | DSMR_DIPM_DISP | DSMR_CSPM;
 	rcar_du_crtc_write(rcrtc, DSMR, value);
 
 	/* Display timings */
-- 
2.4.6


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

* [PATCH 17/22] drm: rcar-du: Output the DISP signal on the ODDF pin
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:51   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

The ODDF signal, output by default on the ODDF pin, isn't used on any
board supported in the kernel. As the Gen3 Salvator-X board uses the
ODDF pin as a DISP signal, hardcode that configuration in the driver.

Use of the ODDF signal will be implemented later through proper DT-based
configuration of the DU pins.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_group.c | 12 ++++++++++++
 drivers/gpu/drm/rcar-du/rcar_du_regs.h  |  2 +-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 0e2b46dce563..144d1e0a7a4a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -44,6 +44,16 @@ void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data)
 	rcar_du_write(rgrp->dev, rgrp->mmio_offset + reg, data);
 }
 
+static void rcar_du_group_setup_pins(struct rcar_du_group *rgrp)
+{
+	u32 defr6 = DEFR6_CODE | DEFR6_ODPM12_DISP;
+
+	if (rgrp->num_crtcs > 1)
+		defr6 |= DEFR6_ODPM22_DISP;
+
+	rcar_du_group_write(rgrp, DEFR6, defr6);
+}
+
 static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 {
 	u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;
@@ -71,6 +81,8 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
 	rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE);
 	rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5);
 
+	rcar_du_group_setup_pins(rgrp);
+
 	if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) {
 		rcar_du_group_setup_defr8(rgrp);
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
index 95add71a33c8..2ccb1a241fc4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
@@ -187,7 +187,7 @@
 
 #define DEFR6			0x000e8
 #define DEFR6_CODE		(0x7778 << 16)
-#define DEFR6_ODPM22_D2SMR	(0 << 10)
+#define DEFR6_ODPM22_DSMR	(0 << 10)
 #define DEFR6_ODPM22_DISP	(2 << 10)
 #define DEFR6_ODPM22_CDE	(3 << 10)
 #define DEFR6_ODPM22_MASK	(3 << 10)
-- 
2.4.6


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

* [PATCH 17/22] drm: rcar-du: Output the DISP signal on the ODDF pin
@ 2015-09-13 22:51   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

The ODDF signal, output by default on the ODDF pin, isn't used on any
board supported in the kernel. As the Gen3 Salvator-X board uses the
ODDF pin as a DISP signal, hardcode that configuration in the driver.

Use of the ODDF signal will be implemented later through proper DT-based
configuration of the DU pins.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_group.c | 12 ++++++++++++
 drivers/gpu/drm/rcar-du/rcar_du_regs.h  |  2 +-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 0e2b46dce563..144d1e0a7a4a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -44,6 +44,16 @@ void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data)
 	rcar_du_write(rgrp->dev, rgrp->mmio_offset + reg, data);
 }
 
+static void rcar_du_group_setup_pins(struct rcar_du_group *rgrp)
+{
+	u32 defr6 = DEFR6_CODE | DEFR6_ODPM12_DISP;
+
+	if (rgrp->num_crtcs > 1)
+		defr6 |= DEFR6_ODPM22_DISP;
+
+	rcar_du_group_write(rgrp, DEFR6, defr6);
+}
+
 static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 {
 	u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;
@@ -71,6 +81,8 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
 	rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE);
 	rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5);
 
+	rcar_du_group_setup_pins(rgrp);
+
 	if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) {
 		rcar_du_group_setup_defr8(rgrp);
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
index 95add71a33c8..2ccb1a241fc4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
@@ -187,7 +187,7 @@
 
 #define DEFR6			0x000e8
 #define DEFR6_CODE		(0x7778 << 16)
-#define DEFR6_ODPM22_D2SMR	(0 << 10)
+#define DEFR6_ODPM22_DSMR	(0 << 10)
 #define DEFR6_ODPM22_DISP	(2 << 10)
 #define DEFR6_ODPM22_CDE	(3 << 10)
 #define DEFR6_ODPM22_MASK	(3 << 10)
-- 
2.4.6


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

* [PATCH 18/22] drm: rcar-du: Add R8A7795 device support
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:51   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh, devicetree

Document the R8A7795-specific DT bindings and support them in the
driver. The HDMI and LVDS outputs are currently not supported.

Cc: devicetree@vger.kernel.org
Signed-off-by: Koji Matsuoka <koji.matsuoka.xm@renesas.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 .../devicetree/bindings/video/renesas,du.txt       | 16 ++++---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c             | 11 +++--
 drivers/gpu/drm/rcar-du/rcar_du_drv.c              | 25 ++++++++++-
 drivers/gpu/drm/rcar-du/rcar_du_drv.h              |  4 +-
 drivers/gpu/drm/rcar-du/rcar_du_group.c            | 50 ++++++++++++++++------
 drivers/gpu/drm/rcar-du/rcar_du_kms.c              | 11 +++--
 drivers/gpu/drm/rcar-du/rcar_du_plane.c            | 49 ++++++++++++++++-----
 drivers/gpu/drm/rcar-du/rcar_du_regs.h             | 17 +++++++-
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c              | 12 ++++--
 9 files changed, 149 insertions(+), 46 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/renesas,du.txt b/Documentation/devicetree/bindings/video/renesas,du.txt
index eccd4f4867b2..0d30e42e40be 100644
--- a/Documentation/devicetree/bindings/video/renesas,du.txt
+++ b/Documentation/devicetree/bindings/video/renesas,du.txt
@@ -8,6 +8,7 @@ Required Properties:
     - "renesas,du-r8a7791" for R8A7791 (R-Car M2-W) compatible DU
     - "renesas,du-r8a7793" for R8A7793 (R-Car M2-N) compatible DU
     - "renesas,du-r8a7794" for R8A7794 (R-Car E2) compatible DU
+    - "renesas,du-r8a7795" for R8A7795 (R-Car H3) compatible DU
 
   - reg: A list of base address and length of each memory resource, one for
     each entry in the reg-names property.
@@ -24,7 +25,7 @@ Required Properties:
   - clock-names: Name of the clocks. This property is model-dependent.
     - R8A7779 uses a single functional clock. The clock doesn't need to be
       named.
-    - R8A779[0134] use one functional clock per channel and one clock per LVDS
+    - R8A779[01345] use one functional clock per channel and one clock per LVDS
       encoder (if available). The functional clocks must be named "du.x" with
       "x" being the channel numerical index. The LVDS clocks must be named
       "lvds.x" with "x" being the LVDS encoder numerical index.
@@ -41,13 +42,14 @@ bindings specified in Documentation/devicetree/bindings/graph.txt.
 The following table lists for each supported model the port number
 corresponding to each DU output.
 
-		Port 0		Port1		Port2
+		Port 0		Port1		Port2		Port3
 -----------------------------------------------------------------------------
- R8A7779 (H1)	DPAD 0		DPAD 1		-
- R8A7790 (H2)	DPAD		LVDS 0		LVDS 1
- R8A7791 (M2-W)	DPAD		LVDS 0		-
- R8A7793 (M2-N)	DPAD		LVDS 0		-
- R8A7794 (E2)	DPAD 0		DPAD 1		-
+ R8A7779 (H1)	DPAD 0		DPAD 1		-		-
+ R8A7790 (H2)	DPAD		LVDS 0		LVDS 1		-
+ R8A7791 (M2-W)	DPAD		LVDS 0		-		-
+ R8A7793 (M2-N)	DPAD		LVDS 0		-		-
+ R8A7794 (E2)	DPAD 0		DPAD 1		-		-
+ R8A7795 (H3)	DPAD		HDMI 0		HDMI 1		LVDS
 
 
 Example: R8A7790 (R-Car H2) DU
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 15bf57de106b..ed71d1dc0790 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -1,7 +1,7 @@
 /*
  * rcar_du_crtc.c  --  R-Car Display Unit CRTCs
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -254,8 +254,13 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
 
 	/* If VSP+DU integration is enabled the plane assignment is fixed. */
 	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
-		dspr = (rcrtc->index % 2) + 1;
-		hwplanes = 1 << (rcrtc->index % 2);
+		if (rcdu->info->gen < 3) {
+			dspr = (rcrtc->index % 2) + 1;
+			hwplanes = 1 << (rcrtc->index % 2);
+		} else {
+			dspr = (rcrtc->index % 2) ? 3 : 1;
+			hwplanes = 1 << ((rcrtc->index % 2) ? 2 : 0);
+		}
 	}
 
 	/* Update the planes to display timing and dot clock generator
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 326d040515e4..4909db60971a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -1,7 +1,7 @@
 /*
  * rcar_du_drv.c  --  R-Car Display Unit DRM driver
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -36,6 +36,7 @@
  */
 
 static const struct rcar_du_device_info rcar_du_r8a7779_info = {
+	.gen = 2,
 	.features = 0,
 	.num_crtcs = 2,
 	.routes = {
@@ -57,6 +58,7 @@ static const struct rcar_du_device_info rcar_du_r8a7779_info = {
 };
 
 static const struct rcar_du_device_info rcar_du_r8a7790_info = {
+	.gen = 2,
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS,
 	.quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES,
@@ -86,6 +88,7 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
 
 /* M2-W (r8a7791) and M2-N (r8a7793) are identical */
 static const struct rcar_du_device_info rcar_du_r8a7791_info = {
+	.gen = 2,
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS,
 	.num_crtcs = 2,
@@ -108,6 +111,7 @@ static const struct rcar_du_device_info rcar_du_r8a7791_info = {
 };
 
 static const struct rcar_du_device_info rcar_du_r8a7794_info = {
+	.gen = 2,
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS,
 	.num_crtcs = 2,
@@ -129,12 +133,31 @@ static const struct rcar_du_device_info rcar_du_r8a7794_info = {
 	.num_lvds = 0,
 };
 
+static const struct rcar_du_device_info rcar_du_r8a7795_info = {
+	.gen = 3,
+	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
+		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
+		  | RCAR_DU_FEATURE_VSP1_SOURCE,
+	.num_crtcs = 4,
+	.routes = {
+		/* R8A7795 has one RGB output, and two HDMI and one LVDS
+		 * (currently unsupported) outputs
+		 */
+		[RCAR_DU_OUTPUT_DPAD0] = {
+			.possible_crtcs = BIT(3),
+			.encoder_type = DRM_MODE_ENCODER_NONE,
+			.port = 0,
+		},
+	},
+};
+
 static const struct of_device_id rcar_du_of_table[] = {
 	{ .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
 	{ .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
 	{ .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
 	{ .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
 	{ .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
+	{ .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info },
 	{ }
 };
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index ce359edc9ab9..ed35467d96cf 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -1,7 +1,7 @@
 /*
  * rcar_du_drv.h  --  R-Car Display Unit DRM driver
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -53,6 +53,7 @@ struct rcar_du_output_routing {
 
 /*
  * struct rcar_du_device_info - DU model-specific information
+ * @gen: device generation (2 or 3)
  * @features: device features (RCAR_DU_FEATURE_*)
  * @quirks: device quirks (RCAR_DU_QUIRK_*)
  * @num_crtcs: total number of CRTCs
@@ -60,6 +61,7 @@ struct rcar_du_output_routing {
  * @num_lvds: number of internal LVDS encoders
  */
 struct rcar_du_device_info {
+	unsigned int gen;
 	unsigned int features;
 	unsigned int quirks;
 	unsigned int num_crtcs;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 144d1e0a7a4a..33b2fc53da3e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -1,7 +1,7 @@
 /*
  * rcar_du_group.c  --  R-Car Display Unit Channels Pair
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -56,17 +56,32 @@ static void rcar_du_group_setup_pins(struct rcar_du_group *rgrp)
 
 static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 {
-	u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;
+	struct rcar_du_device *rcdu = rgrp->dev;
+	unsigned int possible_crtcs +		rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;
+	u32 defr8 = DEFR8_CODE;
 
-	/* The DEFR8 register for the first group also controls RGB output
-	 * routing to DPAD0 and VSPD1 routing to DU0/1/2 for DU instances that
-	 * support it.
-	 */
-	if (rgrp->index = 0) {
-		if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1)
-			defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
-		if (rgrp->dev->vspd1_sink = 2)
-			defr8 |= DEFR8_VSCS;
+	if (rcdu->info->gen < 3) {
+		defr8 |= DEFR8_DEFE8;
+
+		/* On Gen2 the DEFR8 register for the first group also controls
+		 * RGB output routing to DPAD0 and VSPD1 routing to DU0/1/2 for
+		 * DU instances that support it.
+		 */
+		if (rgrp->index = 0) {
+			if (possible_crtcs > 1)
+				defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source);
+			if (rgrp->dev->vspd1_sink = 2)
+				defr8 |= DEFR8_VSCS;
+		}
+	} else {
+		/* On Gen3 VSPD routing can't be configured, but DPAD routing
+		 * needs to be set despite having a single option available.
+		 */
+		u32 crtc = ffs(possible_crtcs) - 1;
+
+		if (crtc / 2 = rgrp->index)
+			defr8 |= DEFR8_DRGBS_DU(crtc);
 	}
 
 	rcar_du_group_write(rgrp, DEFR8, defr8);
@@ -74,11 +89,15 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 
 static void rcar_du_group_setup(struct rcar_du_group *rgrp)
 {
+	struct rcar_du_device *rcdu = rgrp->dev;
+
 	/* Enable extended features */
 	rcar_du_group_write(rgrp, DEFR, DEFR_CODE | DEFR_DEFE);
-	rcar_du_group_write(rgrp, DEFR2, DEFR2_CODE | DEFR2_DEFE2G);
-	rcar_du_group_write(rgrp, DEFR3, DEFR3_CODE | DEFR3_DEFE3);
-	rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE);
+	if (rcdu->info->gen < 3) {
+		rcar_du_group_write(rgrp, DEFR2, DEFR2_CODE | DEFR2_DEFE2G);
+		rcar_du_group_write(rgrp, DEFR3, DEFR3_CODE | DEFR3_DEFE3);
+		rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE);
+	}
 	rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5);
 
 	rcar_du_group_setup_pins(rgrp);
@@ -98,6 +117,9 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
 				    DIDSR_PDCS_CLK(0, 0));
 	}
 
+	if (rcdu->info->gen >= 3)
+		rcar_du_group_write(rgrp, DEFR10, DEFR10_CODE | DEFR10_DEFE10);
+
 	/* Use DS1PR and DS2PR to configure planes priorities and connects the
 	 * superposition 0 to DU0 pins. DU1 pins will be configured dynamically.
 	 */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 3f3d93dcbf64..4ef1be751df4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -1,7 +1,7 @@
 /*
  * rcar_du_kms.c  --  R-Car Display Unit Mode Setting
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -544,10 +544,13 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 		rgrp->num_crtcs = min(rcdu->num_crtcs - 2 * i, 2U);
 
 		/* If we have more than one CRTCs in this group pre-associate
-		 * planes 0-3 with CRTC 0 and planes 4-7 with CRTC 1 to minimize
-		 * flicker occurring when the association is changed.
+		 * the low-order planes with CRTC 0 and the high-order planes
+		 * with CRTC 1 to minimize flicker occurring when the
+		 * association is changed.
 		 */
-		rgrp->dptsr_planes = rgrp->num_crtcs > 1 ? 0xf0 : 0;
+		rgrp->dptsr_planes = rgrp->num_crtcs > 1
+				   ? (rcdu->info->gen >= 3 ? 0x04 : 0xf0)
+				   : 0;
 
 		if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
 			ret = rcar_du_planes_init(rgrp);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 7d2e301df042..eaed240cdaa8 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -1,7 +1,7 @@
 /*
  * rcar_du_plane.c  --  R-Car Display Unit Planes
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -454,9 +454,9 @@ static void rcar_du_plane_setup_mode(struct rcar_du_group *rgrp,
 	}
 }
 
-static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
-				       unsigned int index,
-				       const struct rcar_du_plane_state *state)
+static void rcar_du_plane_setup_format_gen2(struct rcar_du_group *rgrp,
+					    unsigned int index,
+					    const struct rcar_du_plane_state *state)
 {
 	u32 ddcr2 = PnDDCR2_CODE;
 	u32 ddcr4;
@@ -491,6 +491,29 @@ static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
 		ddcr4 |= PnDDCR4_VSPS;
 
 	rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
+}
+
+static void rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp,
+					    unsigned int index,
+					    const struct rcar_du_plane_state *state)
+{
+	rcar_du_plane_write(rgrp, index, PnMR,
+			    PnMR_SPIM_TP_OFF | state->format->pnmr);
+
+	rcar_du_plane_write(rgrp, index, PnDDCR4,
+			    state->format->edf | PnDDCR4_CODE);
+}
+
+static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
+				       unsigned int index,
+				       const struct rcar_du_plane_state *state)
+{
+	struct rcar_du_device *rcdu = rgrp->dev;
+
+	if (rcdu->info->gen < 3)
+		rcar_du_plane_setup_format_gen2(rgrp, index, state);
+	else
+		rcar_du_plane_setup_format_gen3(rgrp, index, state);
 
 	/* Destination position and size */
 	rcar_du_plane_write(rgrp, index, PnDSXR, state->state.crtc_w);
@@ -498,26 +521,30 @@ static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
 	rcar_du_plane_write(rgrp, index, PnDPXR, state->state.crtc_x);
 	rcar_du_plane_write(rgrp, index, PnDPYR, state->state.crtc_y);
 
-	/* Wrap-around and blinking, disabled */
-	rcar_du_plane_write(rgrp, index, PnWASPR, 0);
-	rcar_du_plane_write(rgrp, index, PnWAMWR, 4095);
-	rcar_du_plane_write(rgrp, index, PnBTR, 0);
-	rcar_du_plane_write(rgrp, index, PnMLR, 0);
+	if (rcdu->info->gen < 3) {
+		/* Wrap-around and blinking, disabled */
+		rcar_du_plane_write(rgrp, index, PnWASPR, 0);
+		rcar_du_plane_write(rgrp, index, PnWAMWR, 4095);
+		rcar_du_plane_write(rgrp, index, PnBTR, 0);
+		rcar_du_plane_write(rgrp, index, PnMLR, 0);
+	}
 }
 
 void __rcar_du_plane_setup(struct rcar_du_group *rgrp,
 			   const struct rcar_du_plane_state *state)
 {
+	struct rcar_du_device *rcdu = rgrp->dev;
+
 	rcar_du_plane_setup_format(rgrp, state->hwindex, state);
 	if (state->format->planes = 2)
 		rcar_du_plane_setup_format(rgrp, (state->hwindex + 1) % 8,
 					   state);
 
-	rcar_du_plane_setup_scanout(rgrp, state);
+	if (rcdu->info->gen < 3)
+		rcar_du_plane_setup_scanout(rgrp, state);
 
 	if (state->source = RCAR_DU_PLANE_VSPD1) {
 		unsigned int vspd1_sink = rgrp->index ? 2 : 0;
-		struct rcar_du_device *rcdu = rgrp->dev;
 
 		if (rcdu->vspd1_sink != vspd1_sink) {
 			rcdu->vspd1_sink = vspd1_sink;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
index 2ccb1a241fc4..d2f66068e52c 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
@@ -1,7 +1,7 @@
 /*
  * rcar_du_regs.h  --  R-Car Display Unit Registers Definitions
  *
- * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -261,6 +261,21 @@
 #define DIDSR_PDCS_CLK(n, clk)	(clk << ((n) * 2))
 #define DIDSR_PDCS_MASK(n)	(3 << ((n) * 2))
 
+#define DEFR10			0x20038
+#define DEFR10_CODE		(0x7795 << 16)
+#define DEFR10_VSPF1_RGB	(0 << 14)
+#define DEFR10_VSPF1_YC		(1 << 14)
+#define DEFR10_DOCF1_RGB	(0 << 12)
+#define DEFR10_DOCF1_YC		(1 << 12)
+#define DEFR10_YCDF0_YCBCR444	(0 << 11)
+#define DEFR10_YCDF0_YCBCR422	(1 << 11)
+#define DEFR10_VSPF0_RGB	(0 << 10)
+#define DEFR10_VSPF0_YC		(1 << 10)
+#define DEFR10_DOCF0_RGB	(0 << 8)
+#define DEFR10_DOCF0_YC		(1 << 8)
+#define DEFR10_TSEL_H3_TCON1	(0 << 1) /* DEFR102 register only (DU2/DU3) */
+#define DEFR10_DEFE10		(1 << 0)
+
 /* -----------------------------------------------------------------------------
  * Display Timing Generation Registers
  */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index f01c089881e0..b5e7d96d3604 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -31,6 +31,7 @@
 void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
 {
 	const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode;
+	struct rcar_du_device *rcdu = crtc->group->dev;
 	struct rcar_du_plane_state state = {
 		.state = {
 			.crtc = &crtc->crtc,
@@ -44,13 +45,17 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
 			.src_h = mode->vdisplay << 16,
 		},
 		.format = rcar_du_format_info(DRM_FORMAT_ARGB8888),
-		.hwindex = crtc->index % 2,
 		.source = RCAR_DU_PLANE_VSPD1,
 		.alpha = 255,
 		.colorkey = 0,
 		.zpos = 0,
 	};
 
+	if (rcdu->info->gen >= 3)
+		state.hwindex = (crtc->index % 2) ? 2 : 0;
+	else
+		state.hwindex = crtc->index % 2;
+
 	__rcar_du_plane_setup(crtc->group, &state);
 
 	/* Ensure that the plane source configuration takes effect by requesting
@@ -329,10 +334,9 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp)
 		return ret;
 
 	 /* The VSP2D (Gen3) has 5 RPFs, but the VSP1D (Gen2) is limited to
-	  * 4 RPFs. Hardcode the number of planes to 4 as Gen3 isn't supported
-	  * yet.
+	  * 4 RPFs.
 	  */
-	vsp->num_planes = 4;
+	vsp->num_planes = rcdu->info->gen >= 3 ? 5 : 4;
 
 	vsp->planes = devm_kcalloc(rcdu->dev, vsp->num_planes,
 				   sizeof(*vsp->planes), GFP_KERNEL);
-- 
2.4.6


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

* [PATCH 18/22] drm: rcar-du: Add R8A7795 device support
@ 2015-09-13 22:51   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh, devicetree

Document the R8A7795-specific DT bindings and support them in the
driver. The HDMI and LVDS outputs are currently not supported.

Cc: devicetree@vger.kernel.org
Signed-off-by: Koji Matsuoka <koji.matsuoka.xm@renesas.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 .../devicetree/bindings/video/renesas,du.txt       | 16 ++++---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c             | 11 +++--
 drivers/gpu/drm/rcar-du/rcar_du_drv.c              | 25 ++++++++++-
 drivers/gpu/drm/rcar-du/rcar_du_drv.h              |  4 +-
 drivers/gpu/drm/rcar-du/rcar_du_group.c            | 50 ++++++++++++++++------
 drivers/gpu/drm/rcar-du/rcar_du_kms.c              | 11 +++--
 drivers/gpu/drm/rcar-du/rcar_du_plane.c            | 49 ++++++++++++++++-----
 drivers/gpu/drm/rcar-du/rcar_du_regs.h             | 17 +++++++-
 drivers/gpu/drm/rcar-du/rcar_du_vsp.c              | 12 ++++--
 9 files changed, 149 insertions(+), 46 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/renesas,du.txt b/Documentation/devicetree/bindings/video/renesas,du.txt
index eccd4f4867b2..0d30e42e40be 100644
--- a/Documentation/devicetree/bindings/video/renesas,du.txt
+++ b/Documentation/devicetree/bindings/video/renesas,du.txt
@@ -8,6 +8,7 @@ Required Properties:
     - "renesas,du-r8a7791" for R8A7791 (R-Car M2-W) compatible DU
     - "renesas,du-r8a7793" for R8A7793 (R-Car M2-N) compatible DU
     - "renesas,du-r8a7794" for R8A7794 (R-Car E2) compatible DU
+    - "renesas,du-r8a7795" for R8A7795 (R-Car H3) compatible DU
 
   - reg: A list of base address and length of each memory resource, one for
     each entry in the reg-names property.
@@ -24,7 +25,7 @@ Required Properties:
   - clock-names: Name of the clocks. This property is model-dependent.
     - R8A7779 uses a single functional clock. The clock doesn't need to be
       named.
-    - R8A779[0134] use one functional clock per channel and one clock per LVDS
+    - R8A779[01345] use one functional clock per channel and one clock per LVDS
       encoder (if available). The functional clocks must be named "du.x" with
       "x" being the channel numerical index. The LVDS clocks must be named
       "lvds.x" with "x" being the LVDS encoder numerical index.
@@ -41,13 +42,14 @@ bindings specified in Documentation/devicetree/bindings/graph.txt.
 The following table lists for each supported model the port number
 corresponding to each DU output.
 
-		Port 0		Port1		Port2
+		Port 0		Port1		Port2		Port3
 -----------------------------------------------------------------------------
- R8A7779 (H1)	DPAD 0		DPAD 1		-
- R8A7790 (H2)	DPAD		LVDS 0		LVDS 1
- R8A7791 (M2-W)	DPAD		LVDS 0		-
- R8A7793 (M2-N)	DPAD		LVDS 0		-
- R8A7794 (E2)	DPAD 0		DPAD 1		-
+ R8A7779 (H1)	DPAD 0		DPAD 1		-		-
+ R8A7790 (H2)	DPAD		LVDS 0		LVDS 1		-
+ R8A7791 (M2-W)	DPAD		LVDS 0		-		-
+ R8A7793 (M2-N)	DPAD		LVDS 0		-		-
+ R8A7794 (E2)	DPAD 0		DPAD 1		-		-
+ R8A7795 (H3)	DPAD		HDMI 0		HDMI 1		LVDS
 
 
 Example: R8A7790 (R-Car H2) DU
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 15bf57de106b..ed71d1dc0790 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -1,7 +1,7 @@
 /*
  * rcar_du_crtc.c  --  R-Car Display Unit CRTCs
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -254,8 +254,13 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
 
 	/* If VSP+DU integration is enabled the plane assignment is fixed. */
 	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
-		dspr = (rcrtc->index % 2) + 1;
-		hwplanes = 1 << (rcrtc->index % 2);
+		if (rcdu->info->gen < 3) {
+			dspr = (rcrtc->index % 2) + 1;
+			hwplanes = 1 << (rcrtc->index % 2);
+		} else {
+			dspr = (rcrtc->index % 2) ? 3 : 1;
+			hwplanes = 1 << ((rcrtc->index % 2) ? 2 : 0);
+		}
 	}
 
 	/* Update the planes to display timing and dot clock generator
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 326d040515e4..4909db60971a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -1,7 +1,7 @@
 /*
  * rcar_du_drv.c  --  R-Car Display Unit DRM driver
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -36,6 +36,7 @@
  */
 
 static const struct rcar_du_device_info rcar_du_r8a7779_info = {
+	.gen = 2,
 	.features = 0,
 	.num_crtcs = 2,
 	.routes = {
@@ -57,6 +58,7 @@ static const struct rcar_du_device_info rcar_du_r8a7779_info = {
 };
 
 static const struct rcar_du_device_info rcar_du_r8a7790_info = {
+	.gen = 2,
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS,
 	.quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES,
@@ -86,6 +88,7 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
 
 /* M2-W (r8a7791) and M2-N (r8a7793) are identical */
 static const struct rcar_du_device_info rcar_du_r8a7791_info = {
+	.gen = 2,
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS,
 	.num_crtcs = 2,
@@ -108,6 +111,7 @@ static const struct rcar_du_device_info rcar_du_r8a7791_info = {
 };
 
 static const struct rcar_du_device_info rcar_du_r8a7794_info = {
+	.gen = 2,
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS,
 	.num_crtcs = 2,
@@ -129,12 +133,31 @@ static const struct rcar_du_device_info rcar_du_r8a7794_info = {
 	.num_lvds = 0,
 };
 
+static const struct rcar_du_device_info rcar_du_r8a7795_info = {
+	.gen = 3,
+	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
+		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
+		  | RCAR_DU_FEATURE_VSP1_SOURCE,
+	.num_crtcs = 4,
+	.routes = {
+		/* R8A7795 has one RGB output, and two HDMI and one LVDS
+		 * (currently unsupported) outputs
+		 */
+		[RCAR_DU_OUTPUT_DPAD0] = {
+			.possible_crtcs = BIT(3),
+			.encoder_type = DRM_MODE_ENCODER_NONE,
+			.port = 0,
+		},
+	},
+};
+
 static const struct of_device_id rcar_du_of_table[] = {
 	{ .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
 	{ .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
 	{ .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
 	{ .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
 	{ .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
+	{ .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info },
 	{ }
 };
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index ce359edc9ab9..ed35467d96cf 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -1,7 +1,7 @@
 /*
  * rcar_du_drv.h  --  R-Car Display Unit DRM driver
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -53,6 +53,7 @@ struct rcar_du_output_routing {
 
 /*
  * struct rcar_du_device_info - DU model-specific information
+ * @gen: device generation (2 or 3)
  * @features: device features (RCAR_DU_FEATURE_*)
  * @quirks: device quirks (RCAR_DU_QUIRK_*)
  * @num_crtcs: total number of CRTCs
@@ -60,6 +61,7 @@ struct rcar_du_output_routing {
  * @num_lvds: number of internal LVDS encoders
  */
 struct rcar_du_device_info {
+	unsigned int gen;
 	unsigned int features;
 	unsigned int quirks;
 	unsigned int num_crtcs;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 144d1e0a7a4a..33b2fc53da3e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -1,7 +1,7 @@
 /*
  * rcar_du_group.c  --  R-Car Display Unit Channels Pair
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -56,17 +56,32 @@ static void rcar_du_group_setup_pins(struct rcar_du_group *rgrp)
 
 static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 {
-	u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;
+	struct rcar_du_device *rcdu = rgrp->dev;
+	unsigned int possible_crtcs =
+		rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;
+	u32 defr8 = DEFR8_CODE;
 
-	/* The DEFR8 register for the first group also controls RGB output
-	 * routing to DPAD0 and VSPD1 routing to DU0/1/2 for DU instances that
-	 * support it.
-	 */
-	if (rgrp->index == 0) {
-		if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1)
-			defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
-		if (rgrp->dev->vspd1_sink == 2)
-			defr8 |= DEFR8_VSCS;
+	if (rcdu->info->gen < 3) {
+		defr8 |= DEFR8_DEFE8;
+
+		/* On Gen2 the DEFR8 register for the first group also controls
+		 * RGB output routing to DPAD0 and VSPD1 routing to DU0/1/2 for
+		 * DU instances that support it.
+		 */
+		if (rgrp->index == 0) {
+			if (possible_crtcs > 1)
+				defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source);
+			if (rgrp->dev->vspd1_sink == 2)
+				defr8 |= DEFR8_VSCS;
+		}
+	} else {
+		/* On Gen3 VSPD routing can't be configured, but DPAD routing
+		 * needs to be set despite having a single option available.
+		 */
+		u32 crtc = ffs(possible_crtcs) - 1;
+
+		if (crtc / 2 == rgrp->index)
+			defr8 |= DEFR8_DRGBS_DU(crtc);
 	}
 
 	rcar_du_group_write(rgrp, DEFR8, defr8);
@@ -74,11 +89,15 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 
 static void rcar_du_group_setup(struct rcar_du_group *rgrp)
 {
+	struct rcar_du_device *rcdu = rgrp->dev;
+
 	/* Enable extended features */
 	rcar_du_group_write(rgrp, DEFR, DEFR_CODE | DEFR_DEFE);
-	rcar_du_group_write(rgrp, DEFR2, DEFR2_CODE | DEFR2_DEFE2G);
-	rcar_du_group_write(rgrp, DEFR3, DEFR3_CODE | DEFR3_DEFE3);
-	rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE);
+	if (rcdu->info->gen < 3) {
+		rcar_du_group_write(rgrp, DEFR2, DEFR2_CODE | DEFR2_DEFE2G);
+		rcar_du_group_write(rgrp, DEFR3, DEFR3_CODE | DEFR3_DEFE3);
+		rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE);
+	}
 	rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5);
 
 	rcar_du_group_setup_pins(rgrp);
@@ -98,6 +117,9 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
 				    DIDSR_PDCS_CLK(0, 0));
 	}
 
+	if (rcdu->info->gen >= 3)
+		rcar_du_group_write(rgrp, DEFR10, DEFR10_CODE | DEFR10_DEFE10);
+
 	/* Use DS1PR and DS2PR to configure planes priorities and connects the
 	 * superposition 0 to DU0 pins. DU1 pins will be configured dynamically.
 	 */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 3f3d93dcbf64..4ef1be751df4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -1,7 +1,7 @@
 /*
  * rcar_du_kms.c  --  R-Car Display Unit Mode Setting
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -544,10 +544,13 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 		rgrp->num_crtcs = min(rcdu->num_crtcs - 2 * i, 2U);
 
 		/* If we have more than one CRTCs in this group pre-associate
-		 * planes 0-3 with CRTC 0 and planes 4-7 with CRTC 1 to minimize
-		 * flicker occurring when the association is changed.
+		 * the low-order planes with CRTC 0 and the high-order planes
+		 * with CRTC 1 to minimize flicker occurring when the
+		 * association is changed.
 		 */
-		rgrp->dptsr_planes = rgrp->num_crtcs > 1 ? 0xf0 : 0;
+		rgrp->dptsr_planes = rgrp->num_crtcs > 1
+				   ? (rcdu->info->gen >= 3 ? 0x04 : 0xf0)
+				   : 0;
 
 		if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
 			ret = rcar_du_planes_init(rgrp);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 7d2e301df042..eaed240cdaa8 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -1,7 +1,7 @@
 /*
  * rcar_du_plane.c  --  R-Car Display Unit Planes
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -454,9 +454,9 @@ static void rcar_du_plane_setup_mode(struct rcar_du_group *rgrp,
 	}
 }
 
-static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
-				       unsigned int index,
-				       const struct rcar_du_plane_state *state)
+static void rcar_du_plane_setup_format_gen2(struct rcar_du_group *rgrp,
+					    unsigned int index,
+					    const struct rcar_du_plane_state *state)
 {
 	u32 ddcr2 = PnDDCR2_CODE;
 	u32 ddcr4;
@@ -491,6 +491,29 @@ static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
 		ddcr4 |= PnDDCR4_VSPS;
 
 	rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
+}
+
+static void rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp,
+					    unsigned int index,
+					    const struct rcar_du_plane_state *state)
+{
+	rcar_du_plane_write(rgrp, index, PnMR,
+			    PnMR_SPIM_TP_OFF | state->format->pnmr);
+
+	rcar_du_plane_write(rgrp, index, PnDDCR4,
+			    state->format->edf | PnDDCR4_CODE);
+}
+
+static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
+				       unsigned int index,
+				       const struct rcar_du_plane_state *state)
+{
+	struct rcar_du_device *rcdu = rgrp->dev;
+
+	if (rcdu->info->gen < 3)
+		rcar_du_plane_setup_format_gen2(rgrp, index, state);
+	else
+		rcar_du_plane_setup_format_gen3(rgrp, index, state);
 
 	/* Destination position and size */
 	rcar_du_plane_write(rgrp, index, PnDSXR, state->state.crtc_w);
@@ -498,26 +521,30 @@ static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
 	rcar_du_plane_write(rgrp, index, PnDPXR, state->state.crtc_x);
 	rcar_du_plane_write(rgrp, index, PnDPYR, state->state.crtc_y);
 
-	/* Wrap-around and blinking, disabled */
-	rcar_du_plane_write(rgrp, index, PnWASPR, 0);
-	rcar_du_plane_write(rgrp, index, PnWAMWR, 4095);
-	rcar_du_plane_write(rgrp, index, PnBTR, 0);
-	rcar_du_plane_write(rgrp, index, PnMLR, 0);
+	if (rcdu->info->gen < 3) {
+		/* Wrap-around and blinking, disabled */
+		rcar_du_plane_write(rgrp, index, PnWASPR, 0);
+		rcar_du_plane_write(rgrp, index, PnWAMWR, 4095);
+		rcar_du_plane_write(rgrp, index, PnBTR, 0);
+		rcar_du_plane_write(rgrp, index, PnMLR, 0);
+	}
 }
 
 void __rcar_du_plane_setup(struct rcar_du_group *rgrp,
 			   const struct rcar_du_plane_state *state)
 {
+	struct rcar_du_device *rcdu = rgrp->dev;
+
 	rcar_du_plane_setup_format(rgrp, state->hwindex, state);
 	if (state->format->planes == 2)
 		rcar_du_plane_setup_format(rgrp, (state->hwindex + 1) % 8,
 					   state);
 
-	rcar_du_plane_setup_scanout(rgrp, state);
+	if (rcdu->info->gen < 3)
+		rcar_du_plane_setup_scanout(rgrp, state);
 
 	if (state->source == RCAR_DU_PLANE_VSPD1) {
 		unsigned int vspd1_sink = rgrp->index ? 2 : 0;
-		struct rcar_du_device *rcdu = rgrp->dev;
 
 		if (rcdu->vspd1_sink != vspd1_sink) {
 			rcdu->vspd1_sink = vspd1_sink;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
index 2ccb1a241fc4..d2f66068e52c 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
@@ -1,7 +1,7 @@
 /*
  * rcar_du_regs.h  --  R-Car Display Unit Registers Definitions
  *
- * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -261,6 +261,21 @@
 #define DIDSR_PDCS_CLK(n, clk)	(clk << ((n) * 2))
 #define DIDSR_PDCS_MASK(n)	(3 << ((n) * 2))
 
+#define DEFR10			0x20038
+#define DEFR10_CODE		(0x7795 << 16)
+#define DEFR10_VSPF1_RGB	(0 << 14)
+#define DEFR10_VSPF1_YC		(1 << 14)
+#define DEFR10_DOCF1_RGB	(0 << 12)
+#define DEFR10_DOCF1_YC		(1 << 12)
+#define DEFR10_YCDF0_YCBCR444	(0 << 11)
+#define DEFR10_YCDF0_YCBCR422	(1 << 11)
+#define DEFR10_VSPF0_RGB	(0 << 10)
+#define DEFR10_VSPF0_YC		(1 << 10)
+#define DEFR10_DOCF0_RGB	(0 << 8)
+#define DEFR10_DOCF0_YC		(1 << 8)
+#define DEFR10_TSEL_H3_TCON1	(0 << 1) /* DEFR102 register only (DU2/DU3) */
+#define DEFR10_DEFE10		(1 << 0)
+
 /* -----------------------------------------------------------------------------
  * Display Timing Generation Registers
  */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index f01c089881e0..b5e7d96d3604 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -31,6 +31,7 @@
 void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
 {
 	const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode;
+	struct rcar_du_device *rcdu = crtc->group->dev;
 	struct rcar_du_plane_state state = {
 		.state = {
 			.crtc = &crtc->crtc,
@@ -44,13 +45,17 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
 			.src_h = mode->vdisplay << 16,
 		},
 		.format = rcar_du_format_info(DRM_FORMAT_ARGB8888),
-		.hwindex = crtc->index % 2,
 		.source = RCAR_DU_PLANE_VSPD1,
 		.alpha = 255,
 		.colorkey = 0,
 		.zpos = 0,
 	};
 
+	if (rcdu->info->gen >= 3)
+		state.hwindex = (crtc->index % 2) ? 2 : 0;
+	else
+		state.hwindex = crtc->index % 2;
+
 	__rcar_du_plane_setup(crtc->group, &state);
 
 	/* Ensure that the plane source configuration takes effect by requesting
@@ -329,10 +334,9 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp)
 		return ret;
 
 	 /* The VSP2D (Gen3) has 5 RPFs, but the VSP1D (Gen2) is limited to
-	  * 4 RPFs. Hardcode the number of planes to 4 as Gen3 isn't supported
-	  * yet.
+	  * 4 RPFs.
 	  */
-	vsp->num_planes = 4;
+	vsp->num_planes = rcdu->info->gen >= 3 ? 5 : 4;
 
 	vsp->planes = devm_kcalloc(rcdu->dev, vsp->num_planes,
 				   sizeof(*vsp->planes), GFP_KERNEL);
-- 
2.4.6


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

* [PATCH 19/22] drm: rcar-du: lvds: Avoid duplication of clock clamp code
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:51   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

Replace the duplicate code by a single central function.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 6 +-----
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 7 ++-----
 drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 9 +++++++++
 drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h | 6 ++++++
 4 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index d0ae1e8009c6..b7d64336fb3b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -89,12 +89,8 @@ static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder,
 	/* The flat panel mode is fixed, just copy it to the adjusted mode. */
 	drm_mode_copy(adjusted_mode, panel_mode);
 
-	/* The internal LVDS encoder has a clock frequency operating range of
-	 * 30MHz to 150MHz. Clamp the clock accordingly.
-	 */
 	if (renc->lvds)
-		adjusted_mode->clock = clamp(adjusted_mode->clock,
-					     30000, 150000);
+		rcar_du_lvdsenc_atomic_check(renc->lvds, adjusted_mode);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
index 81da8419282b..c45b626c7d66 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
@@ -71,12 +71,9 @@ static int rcar_du_hdmienc_atomic_check(struct drm_encoder *encoder,
 	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
 	const struct drm_display_mode *mode = &crtc_state->mode;
 
-	/* The internal LVDS encoder has a clock frequency operating range of
-	 * 30MHz to 150MHz. Clamp the clock accordingly.
-	 */
 	if (hdmienc->renc->lvds)
-		adjusted_mode->clock = clamp(adjusted_mode->clock,
-					     30000, 150000);
+		rcar_du_lvdsenc_atomic_check(hdmienc->renc->lvds,
+					     adjusted_mode);
 
 	if (sfuncs->mode_fixup = NULL)
 		return 0;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
index 85043c5bad03..937b2da98814 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
@@ -140,6 +140,15 @@ int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds, struct drm_crtc *crtc,
 		return -EINVAL;
 }
 
+void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
+				  struct drm_display_mode *mode)
+{
+	/* The internal LVDS encoder has a clock frequency operating range of
+	 * 30MHz to 150MHz. Clamp the clock accordingly.
+	 */
+	mode->clock = clamp(mode->clock, 30000, 150000);
+}
+
 static int rcar_du_lvdsenc_get_resources(struct rcar_du_lvdsenc *lvds,
 					 struct platform_device *pdev)
 {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h
index 9a6001c07303..dfdba746edf4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h
@@ -30,6 +30,8 @@ enum rcar_lvds_input {
 int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu);
 int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds,
 			   struct drm_crtc *crtc, bool enable);
+void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
+				  struct drm_display_mode *mode);
 #else
 static inline int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu)
 {
@@ -40,6 +42,10 @@ static inline int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds,
 {
 	return 0;
 }
+static inline void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
+						struct drm_display_mode *mode)
+{
+}
 #endif
 
 #endif /* __RCAR_DU_LVDSENC_H__ */
-- 
2.4.6


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

* [PATCH 19/22] drm: rcar-du: lvds: Avoid duplication of clock clamp code
@ 2015-09-13 22:51   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

Replace the duplicate code by a single central function.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 6 +-----
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 7 ++-----
 drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 9 +++++++++
 drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h | 6 ++++++
 4 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index d0ae1e8009c6..b7d64336fb3b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -89,12 +89,8 @@ static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder,
 	/* The flat panel mode is fixed, just copy it to the adjusted mode. */
 	drm_mode_copy(adjusted_mode, panel_mode);
 
-	/* The internal LVDS encoder has a clock frequency operating range of
-	 * 30MHz to 150MHz. Clamp the clock accordingly.
-	 */
 	if (renc->lvds)
-		adjusted_mode->clock = clamp(adjusted_mode->clock,
-					     30000, 150000);
+		rcar_du_lvdsenc_atomic_check(renc->lvds, adjusted_mode);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
index 81da8419282b..c45b626c7d66 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
@@ -71,12 +71,9 @@ static int rcar_du_hdmienc_atomic_check(struct drm_encoder *encoder,
 	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
 	const struct drm_display_mode *mode = &crtc_state->mode;
 
-	/* The internal LVDS encoder has a clock frequency operating range of
-	 * 30MHz to 150MHz. Clamp the clock accordingly.
-	 */
 	if (hdmienc->renc->lvds)
-		adjusted_mode->clock = clamp(adjusted_mode->clock,
-					     30000, 150000);
+		rcar_du_lvdsenc_atomic_check(hdmienc->renc->lvds,
+					     adjusted_mode);
 
 	if (sfuncs->mode_fixup == NULL)
 		return 0;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
index 85043c5bad03..937b2da98814 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
@@ -140,6 +140,15 @@ int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds, struct drm_crtc *crtc,
 		return -EINVAL;
 }
 
+void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
+				  struct drm_display_mode *mode)
+{
+	/* The internal LVDS encoder has a clock frequency operating range of
+	 * 30MHz to 150MHz. Clamp the clock accordingly.
+	 */
+	mode->clock = clamp(mode->clock, 30000, 150000);
+}
+
 static int rcar_du_lvdsenc_get_resources(struct rcar_du_lvdsenc *lvds,
 					 struct platform_device *pdev)
 {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h
index 9a6001c07303..dfdba746edf4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h
@@ -30,6 +30,8 @@ enum rcar_lvds_input {
 int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu);
 int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds,
 			   struct drm_crtc *crtc, bool enable);
+void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
+				  struct drm_display_mode *mode);
 #else
 static inline int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu)
 {
@@ -40,6 +42,10 @@ static inline int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds,
 {
 	return 0;
 }
+static inline void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
+						struct drm_display_mode *mode)
+{
+}
 #endif
 
 #endif /* __RCAR_DU_LVDSENC_H__ */
-- 
2.4.6

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

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

* [PATCH 20/22] drm: rcar-du: lvds: Fix PLL frequency-related configuration
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:51   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

The frequency checks don't match the datasheet, fix them.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
index 937b2da98814..e044a17a2a2f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
@@ -56,11 +56,11 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
 		return ret;
 
 	/* PLL clock configuration */
-	if (freq <= 38000)
+	if (freq < 39000)
 		pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
-	else if (freq <= 60000)
+	else if (freq < 61000)
 		pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
-	else if (freq <= 121000)
+	else if (freq < 121000)
 		pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
 	else
 		pllcr = LVDPLLCR_PLLDLYCNT_150M;
-- 
2.4.6


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

* [PATCH 20/22] drm: rcar-du: lvds: Fix PLL frequency-related configuration
@ 2015-09-13 22:51   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

The frequency checks don't match the datasheet, fix them.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
index 937b2da98814..e044a17a2a2f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
@@ -56,11 +56,11 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
 		return ret;
 
 	/* PLL clock configuration */
-	if (freq <= 38000)
+	if (freq < 39000)
 		pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
-	else if (freq <= 60000)
+	else if (freq < 61000)
 		pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
-	else if (freq <= 121000)
+	else if (freq < 121000)
 		pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
 	else
 		pllcr = LVDPLLCR_PLLDLYCNT_150M;
-- 
2.4.6


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

* [PATCH 21/22] drm: rcar-du: lvds: Rename PLLEN bit to PLLON
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:51   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

The bit is named PLLON in the datasheet, rename it.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 2 +-
 drivers/gpu/drm/rcar-du/rcar_lvds_regs.h  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
index e044a17a2a2f..02acebadf7d6 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
@@ -102,7 +102,7 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
 	/* Turn the PLL on, wait for the startup delay, and turn the output
 	 * on.
 	 */
-	lvdcr0 |= LVDCR0_PLLEN;
+	lvdcr0 |= LVDCR0_PLLON;
 	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
 
 	usleep_range(100, 150);
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
index 77cf9289ab65..b1eafd097a79 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
@@ -18,7 +18,7 @@
 #define LVDCR0_DMD			(1 << 12)
 #define LVDCR0_LVMD_MASK		(0xf << 8)
 #define LVDCR0_LVMD_SHIFT		8
-#define LVDCR0_PLLEN			(1 << 4)
+#define LVDCR0_PLLON			(1 << 4)
 #define LVDCR0_BEN			(1 << 2)
 #define LVDCR0_LVEN			(1 << 1)
 #define LVDCR0_LVRES			(1 << 0)
-- 
2.4.6


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

* [PATCH 21/22] drm: rcar-du: lvds: Rename PLLEN bit to PLLON
@ 2015-09-13 22:51   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

The bit is named PLLON in the datasheet, rename it.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 2 +-
 drivers/gpu/drm/rcar-du/rcar_lvds_regs.h  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
index e044a17a2a2f..02acebadf7d6 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
@@ -102,7 +102,7 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
 	/* Turn the PLL on, wait for the startup delay, and turn the output
 	 * on.
 	 */
-	lvdcr0 |= LVDCR0_PLLEN;
+	lvdcr0 |= LVDCR0_PLLON;
 	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
 
 	usleep_range(100, 150);
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
index 77cf9289ab65..b1eafd097a79 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
@@ -18,7 +18,7 @@
 #define LVDCR0_DMD			(1 << 12)
 #define LVDCR0_LVMD_MASK		(0xf << 8)
 #define LVDCR0_LVMD_SHIFT		8
-#define LVDCR0_PLLEN			(1 << 4)
+#define LVDCR0_PLLON			(1 << 4)
 #define LVDCR0_BEN			(1 << 2)
 #define LVDCR0_LVEN			(1 << 1)
 #define LVDCR0_LVRES			(1 << 0)
-- 
2.4.6

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

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

* [PATCH 22/22] drm: rcar-du: lvds: Add R-Car Gen3 support
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-13 22:51   ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

From: Koji Matsuoka <koji.matsuoka.xm@renesas.com>

The LVDS encoder differs slightly in Gen3 SoCs in its PLL configuration.
Add support for the Gen3 LVDS PLL parameters and startup procedure.

Signed-off-by: Koji Matsuoka <koji.matsuoka.xm@renesas.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/Kconfig           |   4 +-
 drivers/gpu/drm/rcar-du/rcar_du_drv.c     |  10 ++-
 drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 133 ++++++++++++++++++++++--------
 drivers/gpu/drm/rcar-du/rcar_lvds_regs.h  |  24 ++++--
 4 files changed, 123 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index 6c3e49e9e290..971ab014eee5 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -21,10 +21,8 @@ config DRM_RCAR_HDMI
 config DRM_RCAR_LVDS
 	bool "R-Car DU LVDS Encoder Support"
 	depends on DRM_RCAR_DU
-	depends on ARCH_R8A7790 || ARCH_R8A7791 || COMPILE_TEST
 	help
-	  Enable support for the R-Car Display Unit embedded LVDS encoders
-	  (currently only on R8A7790 and R8A7791).
+	  Enable support for the R-Car Display Unit embedded LVDS encoders.
 
 config DRM_RCAR_VSP
 	bool "R-Car DU VSP Compositor Support"
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 4909db60971a..87eedb7fee28 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -140,15 +140,21 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = {
 		  | RCAR_DU_FEATURE_VSP1_SOURCE,
 	.num_crtcs = 4,
 	.routes = {
-		/* R8A7795 has one RGB output, and two HDMI and one LVDS
-		 * (currently unsupported) outputs
+		/* R8A7795 has one RGB output, one LVDS output and two
+		 * (currently unsupported) HDMI outputs.
 		 */
 		[RCAR_DU_OUTPUT_DPAD0] = {
 			.possible_crtcs = BIT(3),
 			.encoder_type = DRM_MODE_ENCODER_NONE,
 			.port = 0,
 		},
+		[RCAR_DU_OUTPUT_LVDS0] = {
+			.possible_crtcs = BIT(0),
+			.encoder_type = DRM_MODE_ENCODER_LVDS,
+			.port = 3,
+		},
 	},
+	.num_lvds = 1,
 };
 
 static const struct of_device_id rcar_du_of_table[] = {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
index 02acebadf7d6..ef3a50321ecc 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
@@ -38,22 +38,13 @@ static void rcar_lvds_write(struct rcar_du_lvdsenc *lvds, u32 reg, u32 data)
 	iowrite32(data, lvds->mmio + reg);
 }
 
-static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
-				 struct rcar_du_crtc *rcrtc)
+static void rcar_du_lvdsenc_start_gen2(struct rcar_du_lvdsenc *lvds,
+				       struct rcar_du_crtc *rcrtc)
 {
 	const struct drm_display_mode *mode = &rcrtc->crtc.mode;
 	unsigned int freq = mode->clock;
 	u32 lvdcr0;
-	u32 lvdhcr;
 	u32 pllcr;
-	int ret;
-
-	if (lvds->enabled)
-		return 0;
-
-	ret = clk_prepare_enable(lvds->clock);
-	if (ret < 0)
-		return ret;
 
 	/* PLL clock configuration */
 	if (freq < 39000)
@@ -67,26 +58,6 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
 
 	rcar_lvds_write(lvds, LVDPLLCR, pllcr);
 
-	/* Hardcode the channels and control signals routing for now.
-	 *
-	 * HSYNC -> CTRL0
-	 * VSYNC -> CTRL1
-	 * DISP  -> CTRL2
-	 * 0     -> CTRL3
-	 */
-	rcar_lvds_write(lvds, LVDCTRCR, LVDCTRCR_CTR3SEL_ZERO |
-			LVDCTRCR_CTR2SEL_DISP | LVDCTRCR_CTR1SEL_VSYNC |
-			LVDCTRCR_CTR0SEL_HSYNC);
-
-	if (rcar_du_needs(lvds->dev, RCAR_DU_QUIRK_LVDS_LANES))
-		lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3)
-		       | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1);
-	else
-		lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 1)
-		       | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 3);
-
-	rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
-
 	/* Select the input, hardcode mode 0, enable LVDS operation and turn
 	 * bias circuitry on.
 	 */
@@ -96,8 +67,10 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
 	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
 
 	/* Turn all the channels on. */
-	rcar_lvds_write(lvds, LVDCR1, LVDCR1_CHSTBY(3) | LVDCR1_CHSTBY(2) |
-			LVDCR1_CHSTBY(1) | LVDCR1_CHSTBY(0) | LVDCR1_CLKSTBY);
+	rcar_lvds_write(lvds, LVDCR1,
+			LVDCR1_CHSTBY_GEN2(3) | LVDCR1_CHSTBY_GEN2(2) |
+			LVDCR1_CHSTBY_GEN2(1) | LVDCR1_CHSTBY_GEN2(0) |
+			LVDCR1_CLKSTBY_GEN2);
 
 	/* Turn the PLL on, wait for the startup delay, and turn the output
 	 * on.
@@ -109,8 +82,90 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
 
 	lvdcr0 |= LVDCR0_LVRES;
 	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
+}
+
+static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds,
+				       struct rcar_du_crtc *rcrtc)
+{
+	const struct drm_display_mode *mode = &rcrtc->crtc.mode;
+	unsigned int freq = mode->clock;
+	u32 lvdcr0;
+	u32 pllcr;
+
+	/* PLL clock configuration */
+	if (freq < 42000)
+		pllcr = LVDPLLCR_PLLDIVCNT_42M;
+	else if (freq < 85000)
+		pllcr = LVDPLLCR_PLLDIVCNT_85M;
+	else if (freq < 128000)
+		pllcr = LVDPLLCR_PLLDIVCNT_128M;
+	else
+		pllcr = LVDPLLCR_PLLDIVCNT_148M;
+
+	rcar_lvds_write(lvds, LVDPLLCR, pllcr);
+
+	/* Turn the PLL on, set it to LVDS normal mode, wait for the startup
+	 * delay and turn the output on.
+	 */
+	lvdcr0 = LVDCR0_PLLON;
+	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
+
+	lvdcr0 |= LVDCR0_PWD;
+	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
+
+	usleep_range(100, 150);
+
+	lvdcr0 |= LVDCR0_LVRES;
+	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
+
+	/* Turn all the channels on. */
+	rcar_lvds_write(lvds, LVDCR1,
+			LVDCR1_CHSTBY_GEN3(3) | LVDCR1_CHSTBY_GEN3(2) |
+			LVDCR1_CHSTBY_GEN3(1) | LVDCR1_CHSTBY_GEN3(0) |
+			LVDCR1_CLKSTBY_GEN3);
+}
+
+static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
+				 struct rcar_du_crtc *rcrtc)
+{
+	u32 lvdhcr;
+	int ret;
+
+	if (lvds->enabled)
+		return 0;
+
+	ret = clk_prepare_enable(lvds->clock);
+	if (ret < 0)
+		return ret;
+
+	/* Hardcode the channels and control signals routing for now.
+	 *
+	 * HSYNC -> CTRL0
+	 * VSYNC -> CTRL1
+	 * DISP  -> CTRL2
+	 * 0     -> CTRL3
+	 */
+	rcar_lvds_write(lvds, LVDCTRCR, LVDCTRCR_CTR3SEL_ZERO |
+			LVDCTRCR_CTR2SEL_DISP | LVDCTRCR_CTR1SEL_VSYNC |
+			LVDCTRCR_CTR0SEL_HSYNC);
+
+	if (rcar_du_needs(lvds->dev, RCAR_DU_QUIRK_LVDS_LANES))
+		lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3)
+		       | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1);
+	else
+		lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 1)
+		       | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 3);
+
+	rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
+
+	/* Perform generation-specific initialization. */
+	if (lvds->dev->info->gen < 3)
+		rcar_du_lvdsenc_start_gen2(lvds, rcrtc);
+	else
+		rcar_du_lvdsenc_start_gen3(lvds, rcrtc);
 
 	lvds->enabled = true;
+
 	return 0;
 }
 
@@ -143,10 +198,16 @@ int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds, struct drm_crtc *crtc,
 void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
 				  struct drm_display_mode *mode)
 {
-	/* The internal LVDS encoder has a clock frequency operating range of
-	 * 30MHz to 150MHz. Clamp the clock accordingly.
+	struct rcar_du_device *rcdu = lvds->dev;
+
+	/* The internal LVDS encoder has a restricted clock frequency operating
+	 * range (30MHz to 150MHz on Gen2, 25.175MHz to 148.5MHz on Gen3). Clamp
+	 * the clock accordingly.
 	 */
-	mode->clock = clamp(mode->clock, 30000, 150000);
+	if (rcdu->info->gen < 3)
+		mode->clock = clamp(mode->clock, 30000, 150000);
+	else
+		mode->clock = clamp(mode->clock, 25175, 148500);
 }
 
 static int rcar_du_lvdsenc_get_resources(struct rcar_du_lvdsenc *lvds,
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
index b1eafd097a79..d7d294ba2dbe 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
@@ -1,7 +1,7 @@
 /*
  * rcar_lvds_regs.h  --  R-Car LVDS Interface Registers Definitions
  *
- * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -15,28 +15,38 @@
 
 #define LVDCR0				0x0000
 #define LVDCR0_DUSEL			(1 << 15)
-#define LVDCR0_DMD			(1 << 12)
+#define LVDCR0_DMD			(1 << 12)		/* Gen2 only */
 #define LVDCR0_LVMD_MASK		(0xf << 8)
 #define LVDCR0_LVMD_SHIFT		8
 #define LVDCR0_PLLON			(1 << 4)
-#define LVDCR0_BEN			(1 << 2)
-#define LVDCR0_LVEN			(1 << 1)
+#define LVDCR0_PWD			(1 << 2)		/* Gen3 only */
+#define LVDCR0_BEN			(1 << 2)		/* Gen2 only */
+#define LVDCR0_LVEN			(1 << 1)		/* Gen2 only */
 #define LVDCR0_LVRES			(1 << 0)
 
 #define LVDCR1				0x0004
-#define LVDCR1_CKSEL			(1 << 15)
-#define LVDCR1_CHSTBY(n)		(3 << (2 + (n) * 2))
-#define LVDCR1_CLKSTBY			(3 << 0)
+#define LVDCR1_CKSEL			(1 << 15)		/* Gen2 only */
+#define LVDCR1_CHSTBY_GEN2(n)		(3 << (2 + (n) * 2))	/* Gen2 only */
+#define LVDCR1_CHSTBY_GEN3(n)		(1 << (2 + (n) * 2))	/* Gen3 only */
+#define LVDCR1_CLKSTBY_GEN2		(3 << 0)		/* Gen2 only */
+#define LVDCR1_CLKSTBY_GEN3		(1 << 0)		/* Gen3 only */
 
 #define LVDPLLCR			0x0008
 #define LVDPLLCR_CEEN			(1 << 14)
 #define LVDPLLCR_FBEN			(1 << 13)
 #define LVDPLLCR_COSEL			(1 << 12)
+/* Gen2 */
 #define LVDPLLCR_PLLDLYCNT_150M		(0x1bf << 0)
 #define LVDPLLCR_PLLDLYCNT_121M		(0x22c << 0)
 #define LVDPLLCR_PLLDLYCNT_60M		(0x77b << 0)
 #define LVDPLLCR_PLLDLYCNT_38M		(0x69a << 0)
 #define LVDPLLCR_PLLDLYCNT_MASK		(0x7ff << 0)
+/* Gen3 */
+#define LVDPLLCR_PLLDIVCNT_42M		(0x014cb << 0)
+#define LVDPLLCR_PLLDIVCNT_85M		(0x00a45 << 0)
+#define LVDPLLCR_PLLDIVCNT_128M		(0x006c3 << 0)
+#define LVDPLLCR_PLLDIVCNT_148M		(0x046c1 << 0)
+#define LVDPLLCR_PLLDIVCNT_MASK		(0x7ffff << 0)
 
 #define LVDCTRCR			0x000c
 #define LVDCTRCR_CTR3SEL_ZERO		(0 << 12)
-- 
2.4.6


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

* [PATCH 22/22] drm: rcar-du: lvds: Add R-Car Gen3 support
@ 2015-09-13 22:51   ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-09-13 22:51 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-sh

From: Koji Matsuoka <koji.matsuoka.xm@renesas.com>

The LVDS encoder differs slightly in Gen3 SoCs in its PLL configuration.
Add support for the Gen3 LVDS PLL parameters and startup procedure.

Signed-off-by: Koji Matsuoka <koji.matsuoka.xm@renesas.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/Kconfig           |   4 +-
 drivers/gpu/drm/rcar-du/rcar_du_drv.c     |  10 ++-
 drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 133 ++++++++++++++++++++++--------
 drivers/gpu/drm/rcar-du/rcar_lvds_regs.h  |  24 ++++--
 4 files changed, 123 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index 6c3e49e9e290..971ab014eee5 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -21,10 +21,8 @@ config DRM_RCAR_HDMI
 config DRM_RCAR_LVDS
 	bool "R-Car DU LVDS Encoder Support"
 	depends on DRM_RCAR_DU
-	depends on ARCH_R8A7790 || ARCH_R8A7791 || COMPILE_TEST
 	help
-	  Enable support for the R-Car Display Unit embedded LVDS encoders
-	  (currently only on R8A7790 and R8A7791).
+	  Enable support for the R-Car Display Unit embedded LVDS encoders.
 
 config DRM_RCAR_VSP
 	bool "R-Car DU VSP Compositor Support"
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 4909db60971a..87eedb7fee28 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -140,15 +140,21 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = {
 		  | RCAR_DU_FEATURE_VSP1_SOURCE,
 	.num_crtcs = 4,
 	.routes = {
-		/* R8A7795 has one RGB output, and two HDMI and one LVDS
-		 * (currently unsupported) outputs
+		/* R8A7795 has one RGB output, one LVDS output and two
+		 * (currently unsupported) HDMI outputs.
 		 */
 		[RCAR_DU_OUTPUT_DPAD0] = {
 			.possible_crtcs = BIT(3),
 			.encoder_type = DRM_MODE_ENCODER_NONE,
 			.port = 0,
 		},
+		[RCAR_DU_OUTPUT_LVDS0] = {
+			.possible_crtcs = BIT(0),
+			.encoder_type = DRM_MODE_ENCODER_LVDS,
+			.port = 3,
+		},
 	},
+	.num_lvds = 1,
 };
 
 static const struct of_device_id rcar_du_of_table[] = {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
index 02acebadf7d6..ef3a50321ecc 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
@@ -38,22 +38,13 @@ static void rcar_lvds_write(struct rcar_du_lvdsenc *lvds, u32 reg, u32 data)
 	iowrite32(data, lvds->mmio + reg);
 }
 
-static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
-				 struct rcar_du_crtc *rcrtc)
+static void rcar_du_lvdsenc_start_gen2(struct rcar_du_lvdsenc *lvds,
+				       struct rcar_du_crtc *rcrtc)
 {
 	const struct drm_display_mode *mode = &rcrtc->crtc.mode;
 	unsigned int freq = mode->clock;
 	u32 lvdcr0;
-	u32 lvdhcr;
 	u32 pllcr;
-	int ret;
-
-	if (lvds->enabled)
-		return 0;
-
-	ret = clk_prepare_enable(lvds->clock);
-	if (ret < 0)
-		return ret;
 
 	/* PLL clock configuration */
 	if (freq < 39000)
@@ -67,26 +58,6 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
 
 	rcar_lvds_write(lvds, LVDPLLCR, pllcr);
 
-	/* Hardcode the channels and control signals routing for now.
-	 *
-	 * HSYNC -> CTRL0
-	 * VSYNC -> CTRL1
-	 * DISP  -> CTRL2
-	 * 0     -> CTRL3
-	 */
-	rcar_lvds_write(lvds, LVDCTRCR, LVDCTRCR_CTR3SEL_ZERO |
-			LVDCTRCR_CTR2SEL_DISP | LVDCTRCR_CTR1SEL_VSYNC |
-			LVDCTRCR_CTR0SEL_HSYNC);
-
-	if (rcar_du_needs(lvds->dev, RCAR_DU_QUIRK_LVDS_LANES))
-		lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3)
-		       | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1);
-	else
-		lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 1)
-		       | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 3);
-
-	rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
-
 	/* Select the input, hardcode mode 0, enable LVDS operation and turn
 	 * bias circuitry on.
 	 */
@@ -96,8 +67,10 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
 	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
 
 	/* Turn all the channels on. */
-	rcar_lvds_write(lvds, LVDCR1, LVDCR1_CHSTBY(3) | LVDCR1_CHSTBY(2) |
-			LVDCR1_CHSTBY(1) | LVDCR1_CHSTBY(0) | LVDCR1_CLKSTBY);
+	rcar_lvds_write(lvds, LVDCR1,
+			LVDCR1_CHSTBY_GEN2(3) | LVDCR1_CHSTBY_GEN2(2) |
+			LVDCR1_CHSTBY_GEN2(1) | LVDCR1_CHSTBY_GEN2(0) |
+			LVDCR1_CLKSTBY_GEN2);
 
 	/* Turn the PLL on, wait for the startup delay, and turn the output
 	 * on.
@@ -109,8 +82,90 @@ static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
 
 	lvdcr0 |= LVDCR0_LVRES;
 	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
+}
+
+static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds,
+				       struct rcar_du_crtc *rcrtc)
+{
+	const struct drm_display_mode *mode = &rcrtc->crtc.mode;
+	unsigned int freq = mode->clock;
+	u32 lvdcr0;
+	u32 pllcr;
+
+	/* PLL clock configuration */
+	if (freq < 42000)
+		pllcr = LVDPLLCR_PLLDIVCNT_42M;
+	else if (freq < 85000)
+		pllcr = LVDPLLCR_PLLDIVCNT_85M;
+	else if (freq < 128000)
+		pllcr = LVDPLLCR_PLLDIVCNT_128M;
+	else
+		pllcr = LVDPLLCR_PLLDIVCNT_148M;
+
+	rcar_lvds_write(lvds, LVDPLLCR, pllcr);
+
+	/* Turn the PLL on, set it to LVDS normal mode, wait for the startup
+	 * delay and turn the output on.
+	 */
+	lvdcr0 = LVDCR0_PLLON;
+	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
+
+	lvdcr0 |= LVDCR0_PWD;
+	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
+
+	usleep_range(100, 150);
+
+	lvdcr0 |= LVDCR0_LVRES;
+	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
+
+	/* Turn all the channels on. */
+	rcar_lvds_write(lvds, LVDCR1,
+			LVDCR1_CHSTBY_GEN3(3) | LVDCR1_CHSTBY_GEN3(2) |
+			LVDCR1_CHSTBY_GEN3(1) | LVDCR1_CHSTBY_GEN3(0) |
+			LVDCR1_CLKSTBY_GEN3);
+}
+
+static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
+				 struct rcar_du_crtc *rcrtc)
+{
+	u32 lvdhcr;
+	int ret;
+
+	if (lvds->enabled)
+		return 0;
+
+	ret = clk_prepare_enable(lvds->clock);
+	if (ret < 0)
+		return ret;
+
+	/* Hardcode the channels and control signals routing for now.
+	 *
+	 * HSYNC -> CTRL0
+	 * VSYNC -> CTRL1
+	 * DISP  -> CTRL2
+	 * 0     -> CTRL3
+	 */
+	rcar_lvds_write(lvds, LVDCTRCR, LVDCTRCR_CTR3SEL_ZERO |
+			LVDCTRCR_CTR2SEL_DISP | LVDCTRCR_CTR1SEL_VSYNC |
+			LVDCTRCR_CTR0SEL_HSYNC);
+
+	if (rcar_du_needs(lvds->dev, RCAR_DU_QUIRK_LVDS_LANES))
+		lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3)
+		       | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1);
+	else
+		lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 1)
+		       | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 3);
+
+	rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
+
+	/* Perform generation-specific initialization. */
+	if (lvds->dev->info->gen < 3)
+		rcar_du_lvdsenc_start_gen2(lvds, rcrtc);
+	else
+		rcar_du_lvdsenc_start_gen3(lvds, rcrtc);
 
 	lvds->enabled = true;
+
 	return 0;
 }
 
@@ -143,10 +198,16 @@ int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds, struct drm_crtc *crtc,
 void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
 				  struct drm_display_mode *mode)
 {
-	/* The internal LVDS encoder has a clock frequency operating range of
-	 * 30MHz to 150MHz. Clamp the clock accordingly.
+	struct rcar_du_device *rcdu = lvds->dev;
+
+	/* The internal LVDS encoder has a restricted clock frequency operating
+	 * range (30MHz to 150MHz on Gen2, 25.175MHz to 148.5MHz on Gen3). Clamp
+	 * the clock accordingly.
 	 */
-	mode->clock = clamp(mode->clock, 30000, 150000);
+	if (rcdu->info->gen < 3)
+		mode->clock = clamp(mode->clock, 30000, 150000);
+	else
+		mode->clock = clamp(mode->clock, 25175, 148500);
 }
 
 static int rcar_du_lvdsenc_get_resources(struct rcar_du_lvdsenc *lvds,
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
index b1eafd097a79..d7d294ba2dbe 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
@@ -1,7 +1,7 @@
 /*
  * rcar_lvds_regs.h  --  R-Car LVDS Interface Registers Definitions
  *
- * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  *
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  *
@@ -15,28 +15,38 @@
 
 #define LVDCR0				0x0000
 #define LVDCR0_DUSEL			(1 << 15)
-#define LVDCR0_DMD			(1 << 12)
+#define LVDCR0_DMD			(1 << 12)		/* Gen2 only */
 #define LVDCR0_LVMD_MASK		(0xf << 8)
 #define LVDCR0_LVMD_SHIFT		8
 #define LVDCR0_PLLON			(1 << 4)
-#define LVDCR0_BEN			(1 << 2)
-#define LVDCR0_LVEN			(1 << 1)
+#define LVDCR0_PWD			(1 << 2)		/* Gen3 only */
+#define LVDCR0_BEN			(1 << 2)		/* Gen2 only */
+#define LVDCR0_LVEN			(1 << 1)		/* Gen2 only */
 #define LVDCR0_LVRES			(1 << 0)
 
 #define LVDCR1				0x0004
-#define LVDCR1_CKSEL			(1 << 15)
-#define LVDCR1_CHSTBY(n)		(3 << (2 + (n) * 2))
-#define LVDCR1_CLKSTBY			(3 << 0)
+#define LVDCR1_CKSEL			(1 << 15)		/* Gen2 only */
+#define LVDCR1_CHSTBY_GEN2(n)		(3 << (2 + (n) * 2))	/* Gen2 only */
+#define LVDCR1_CHSTBY_GEN3(n)		(1 << (2 + (n) * 2))	/* Gen3 only */
+#define LVDCR1_CLKSTBY_GEN2		(3 << 0)		/* Gen2 only */
+#define LVDCR1_CLKSTBY_GEN3		(1 << 0)		/* Gen3 only */
 
 #define LVDPLLCR			0x0008
 #define LVDPLLCR_CEEN			(1 << 14)
 #define LVDPLLCR_FBEN			(1 << 13)
 #define LVDPLLCR_COSEL			(1 << 12)
+/* Gen2 */
 #define LVDPLLCR_PLLDLYCNT_150M		(0x1bf << 0)
 #define LVDPLLCR_PLLDLYCNT_121M		(0x22c << 0)
 #define LVDPLLCR_PLLDLYCNT_60M		(0x77b << 0)
 #define LVDPLLCR_PLLDLYCNT_38M		(0x69a << 0)
 #define LVDPLLCR_PLLDLYCNT_MASK		(0x7ff << 0)
+/* Gen3 */
+#define LVDPLLCR_PLLDIVCNT_42M		(0x014cb << 0)
+#define LVDPLLCR_PLLDIVCNT_85M		(0x00a45 << 0)
+#define LVDPLLCR_PLLDIVCNT_128M		(0x006c3 << 0)
+#define LVDPLLCR_PLLDIVCNT_148M		(0x046c1 << 0)
+#define LVDPLLCR_PLLDIVCNT_MASK		(0x7ffff << 0)
 
 #define LVDCTRCR			0x000c
 #define LVDCTRCR_CTR3SEL_ZERO		(0 << 12)
-- 
2.4.6


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

* Re: [PATCH 08/22] drm: rcar-du: Restart the DU group when a plane source changes
  2015-09-13 22:50   ` Laurent Pinchart
@ 2015-09-14  7:22     ` Daniel Vetter
  -1 siblings, 0 replies; 58+ messages in thread
From: Daniel Vetter @ 2015-09-14  7:22 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel, linux-sh

On Mon, Sep 14, 2015 at 01:50:55AM +0300, Laurent Pinchart wrote:
> Plane sources are configured by the VSPS bit in the PnDDCR4 register.
> Although the datasheet states that the bit is updated during vertical
> blanking, it seems that updates only occur when the DU group is held in
> reset through the DSYSR.DRES bit. Restart the group if the source
> changes.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  4 ++++
>  drivers/gpu/drm/rcar-du/rcar_du_group.c |  2 ++
>  drivers/gpu/drm/rcar-du/rcar_du_group.h |  2 ++
>  drivers/gpu/drm/rcar-du/rcar_du_plane.c | 22 ++++++++++++++++++++--
>  4 files changed, 28 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> index 48cb19949ca3..7e2f5c26d589 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> @@ -272,6 +272,10 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
>  			rcar_du_group_restart(rcrtc->group);
>  	}
>  
> +	/* Restart the group if plane sources have changed. */
> +	if (rcrtc->group->need_restart)
> +		rcar_du_group_restart(rcrtc->group);
> +
>  	mutex_unlock(&rcrtc->group->lock);
>  
>  	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> index 4a44ddd51766..0e2b46dce563 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> @@ -162,6 +162,8 @@ void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
>  
>  void rcar_du_group_restart(struct rcar_du_group *rgrp)
>  {
> +	rgrp->need_restart = false;
> +
>  	__rcar_du_group_start_stop(rgrp, false);
>  	__rcar_du_group_start_stop(rgrp, true);
>  }
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h
> index 4b1952fd4e7d..5e3adc6b31b5 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
> @@ -32,6 +32,7 @@ struct rcar_du_device;
>   * @dptsr_planes: bitmask of planes driven by dot-clock and timing generator 1
>   * @num_planes: number of planes in the group
>   * @planes: planes handled by the group
> + * @need_restart: the group needs to be restarted due to a configuration change
>   */
>  struct rcar_du_group {
>  	struct rcar_du_device *dev;
> @@ -47,6 +48,7 @@ struct rcar_du_group {
>  
>  	unsigned int num_planes;
>  	struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
> +	bool need_restart;

My recommendation is to keep any of these intermediate values in state
objects too. The reason is that eventually we want to also support real
queues of atomic commits, and then anything stored globally (well, outside
of the state objects) won't work. And yes it's ok to push that kind of
stuff into helper, this isn't really any different than e.g.
crtc_state->active_changed and similar booleans indicating that something
special needs to be done when committing.

Cheers, Daniel

>  };
>  
>  u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg);
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> index 78ca353bfcf0..c7e0535c0e77 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> @@ -275,9 +275,27 @@ static void rcar_du_plane_atomic_update(struct drm_plane *plane,
>  					struct drm_plane_state *old_state)
>  {
>  	struct rcar_du_plane *rplane = to_rcar_plane(plane);
> +	struct rcar_du_plane_state *old_rstate;
> +	struct rcar_du_plane_state *new_rstate;
>  
> -	if (plane->state->crtc)
> -		rcar_du_plane_setup(rplane);
> +	if (!plane->state->crtc)
> +		return;
> +
> +	rcar_du_plane_setup(rplane);
> +
> +	/* Check whether the source has changed from memory to live source or
> +	 * from live source to memory. The source has been configured by the
> +	 * VSPS bit in the PnDDCR4 register. Although the datasheet states that
> +	 * the bit is updated during vertical blanking, it seems that updates
> +	 * only occur when the DU group is held in reset through the DSYSR.DRES
> +	 * bit. We thus need to restart the group if the source changes.
> +	 */
> +	old_rstate = to_rcar_plane_state(old_state);
> +	new_rstate = to_rcar_plane_state(plane->state);
> +
> +	if ((old_rstate->source = RCAR_DU_PLANE_MEMORY) !> +	    (new_rstate->source = RCAR_DU_PLANE_MEMORY))
> +		rplane->group->need_restart = true;
>  }
>  
>  static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = {
> -- 
> 2.4.6
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [PATCH 08/22] drm: rcar-du: Restart the DU group when a plane source changes
@ 2015-09-14  7:22     ` Daniel Vetter
  0 siblings, 0 replies; 58+ messages in thread
From: Daniel Vetter @ 2015-09-14  7:22 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel, linux-sh

On Mon, Sep 14, 2015 at 01:50:55AM +0300, Laurent Pinchart wrote:
> Plane sources are configured by the VSPS bit in the PnDDCR4 register.
> Although the datasheet states that the bit is updated during vertical
> blanking, it seems that updates only occur when the DU group is held in
> reset through the DSYSR.DRES bit. Restart the group if the source
> changes.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  4 ++++
>  drivers/gpu/drm/rcar-du/rcar_du_group.c |  2 ++
>  drivers/gpu/drm/rcar-du/rcar_du_group.h |  2 ++
>  drivers/gpu/drm/rcar-du/rcar_du_plane.c | 22 ++++++++++++++++++++--
>  4 files changed, 28 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> index 48cb19949ca3..7e2f5c26d589 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> @@ -272,6 +272,10 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
>  			rcar_du_group_restart(rcrtc->group);
>  	}
>  
> +	/* Restart the group if plane sources have changed. */
> +	if (rcrtc->group->need_restart)
> +		rcar_du_group_restart(rcrtc->group);
> +
>  	mutex_unlock(&rcrtc->group->lock);
>  
>  	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> index 4a44ddd51766..0e2b46dce563 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> @@ -162,6 +162,8 @@ void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
>  
>  void rcar_du_group_restart(struct rcar_du_group *rgrp)
>  {
> +	rgrp->need_restart = false;
> +
>  	__rcar_du_group_start_stop(rgrp, false);
>  	__rcar_du_group_start_stop(rgrp, true);
>  }
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h
> index 4b1952fd4e7d..5e3adc6b31b5 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
> @@ -32,6 +32,7 @@ struct rcar_du_device;
>   * @dptsr_planes: bitmask of planes driven by dot-clock and timing generator 1
>   * @num_planes: number of planes in the group
>   * @planes: planes handled by the group
> + * @need_restart: the group needs to be restarted due to a configuration change
>   */
>  struct rcar_du_group {
>  	struct rcar_du_device *dev;
> @@ -47,6 +48,7 @@ struct rcar_du_group {
>  
>  	unsigned int num_planes;
>  	struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
> +	bool need_restart;

My recommendation is to keep any of these intermediate values in state
objects too. The reason is that eventually we want to also support real
queues of atomic commits, and then anything stored globally (well, outside
of the state objects) won't work. And yes it's ok to push that kind of
stuff into helper, this isn't really any different than e.g.
crtc_state->active_changed and similar booleans indicating that something
special needs to be done when committing.

Cheers, Daniel

>  };
>  
>  u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg);
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> index 78ca353bfcf0..c7e0535c0e77 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> @@ -275,9 +275,27 @@ static void rcar_du_plane_atomic_update(struct drm_plane *plane,
>  					struct drm_plane_state *old_state)
>  {
>  	struct rcar_du_plane *rplane = to_rcar_plane(plane);
> +	struct rcar_du_plane_state *old_rstate;
> +	struct rcar_du_plane_state *new_rstate;
>  
> -	if (plane->state->crtc)
> -		rcar_du_plane_setup(rplane);
> +	if (!plane->state->crtc)
> +		return;
> +
> +	rcar_du_plane_setup(rplane);
> +
> +	/* Check whether the source has changed from memory to live source or
> +	 * from live source to memory. The source has been configured by the
> +	 * VSPS bit in the PnDDCR4 register. Although the datasheet states that
> +	 * the bit is updated during vertical blanking, it seems that updates
> +	 * only occur when the DU group is held in reset through the DSYSR.DRES
> +	 * bit. We thus need to restart the group if the source changes.
> +	 */
> +	old_rstate = to_rcar_plane_state(old_state);
> +	new_rstate = to_rcar_plane_state(plane->state);
> +
> +	if ((old_rstate->source == RCAR_DU_PLANE_MEMORY) !=
> +	    (new_rstate->source == RCAR_DU_PLANE_MEMORY))
> +		rplane->group->need_restart = true;
>  }
>  
>  static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = {
> -- 
> 2.4.6
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [PATCH 00/22] R-Car DU: Add Gen3 support
  2015-09-13 22:50 ` Laurent Pinchart
@ 2015-09-14  7:52   ` Geert Uytterhoeven
  -1 siblings, 0 replies; 58+ messages in thread
From: Geert Uytterhoeven @ 2015-09-14  7:52 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: DRI Development, Linux-sh list

Hi Laurent,

On Mon, Sep 14, 2015 at 12:50 AM, Laurent Pinchart
<laurent.pinchart+renesas@ideasonboard.com> wrote:
> This patch series adds support for the Display Unit found in the R-Car Gen3
> SoC series.
>
> The third generation differs significantly from the previous ones in that the
> DU has lost its ability to source data from memory. It must instead use an
> external hardware composer named VSP to read planes from memory and blend
> them.
>
> The VSP has a V4L2 driver in mainline that can be used in conjunction with the
> DU through the live sources API (submitted previously as an RFC). However, as
> VSP usage is mandatory in Gen3 and as no native DU planes are available, we
> have decided that forcing userspace to use both KMS and V4L2 to display any
> content wouldn't be very friendly. Instead the VSP driver has been extended to
> make the device directly controllable by the DU driver ([1]) and this patch
> series builds on top of it.
>
> [1] http://www.spinics.net/lists/linux-media/msg93575.html

Against which tree is this series?

From patch 1, I derived it's against drm-misc
(git://anongit.freedesktop.org/drm-intel#topic/drm-misc), but later patches
have other requirements.
E.g. patch 13 assumes DRM_RCAR_DU has a dependency on OF, but that's nowhere
to be found in -next.
It is in git://linuxtv.org/pinchartl/media#vsp1-kms-gen3-20150909.2, but that
conflicts badly with your R-Car Gen3 VSP series.

Thanks!

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 00/22] R-Car DU: Add Gen3 support
@ 2015-09-14  7:52   ` Geert Uytterhoeven
  0 siblings, 0 replies; 58+ messages in thread
From: Geert Uytterhoeven @ 2015-09-14  7:52 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: DRI Development, Linux-sh list

Hi Laurent,

On Mon, Sep 14, 2015 at 12:50 AM, Laurent Pinchart
<laurent.pinchart+renesas@ideasonboard.com> wrote:
> This patch series adds support for the Display Unit found in the R-Car Gen3
> SoC series.
>
> The third generation differs significantly from the previous ones in that the
> DU has lost its ability to source data from memory. It must instead use an
> external hardware composer named VSP to read planes from memory and blend
> them.
>
> The VSP has a V4L2 driver in mainline that can be used in conjunction with the
> DU through the live sources API (submitted previously as an RFC). However, as
> VSP usage is mandatory in Gen3 and as no native DU planes are available, we
> have decided that forcing userspace to use both KMS and V4L2 to display any
> content wouldn't be very friendly. Instead the VSP driver has been extended to
> make the device directly controllable by the DU driver ([1]) and this patch
> series builds on top of it.
>
> [1] http://www.spinics.net/lists/linux-media/msg93575.html

Against which tree is this series?

From patch 1, I derived it's against drm-misc
(git://anongit.freedesktop.org/drm-intel#topic/drm-misc), but later patches
have other requirements.
E.g. patch 13 assumes DRM_RCAR_DU has a dependency on OF, but that's nowhere
to be found in -next.
It is in git://linuxtv.org/pinchartl/media#vsp1-kms-gen3-20150909.2, but that
conflicts badly with your R-Car Gen3 VSP series.

Thanks!

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 00/22] R-Car DU: Add Gen3 support
  2015-09-14  7:52   ` Geert Uytterhoeven
@ 2015-09-14  8:07     ` Geert Uytterhoeven
  -1 siblings, 0 replies; 58+ messages in thread
From: Geert Uytterhoeven @ 2015-09-14  8:07 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: DRI Development, Linux-sh list

On Mon, Sep 14, 2015 at 9:52 AM, Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> On Mon, Sep 14, 2015 at 12:50 AM, Laurent Pinchart
> <laurent.pinchart+renesas@ideasonboard.com> wrote:
>> This patch series adds support for the Display Unit found in the R-Car Gen3
>> SoC series.
>>
>> The third generation differs significantly from the previous ones in that the
>> DU has lost its ability to source data from memory. It must instead use an
>> external hardware composer named VSP to read planes from memory and blend
>> them.
>>
>> The VSP has a V4L2 driver in mainline that can be used in conjunction with the
>> DU through the live sources API (submitted previously as an RFC). However, as
>> VSP usage is mandatory in Gen3 and as no native DU planes are available, we
>> have decided that forcing userspace to use both KMS and V4L2 to display any
>> content wouldn't be very friendly. Instead the VSP driver has been extended to
>> make the device directly controllable by the DU driver ([1]) and this patch
>> series builds on top of it.
>>
>> [1] http://www.spinics.net/lists/linux-media/msg93575.html
>
> Against which tree is this series?
>
> From patch 1, I derived it's against drm-misc
> (git://anongit.freedesktop.org/drm-intel#topic/drm-misc), but later patches
> have other requirements.
> E.g. patch 13 assumes DRM_RCAR_DU has a dependency on OF, but that's nowhere
> to be found in -next.
> It is in git://linuxtv.org/pinchartl/media#vsp1-kms-gen3-20150909.2, but that
> conflicts badly with your R-Car Gen3 VSP series.

Or shall I just use vsp1-kms-gen3-20150913?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 00/22] R-Car DU: Add Gen3 support
@ 2015-09-14  8:07     ` Geert Uytterhoeven
  0 siblings, 0 replies; 58+ messages in thread
From: Geert Uytterhoeven @ 2015-09-14  8:07 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: DRI Development, Linux-sh list

On Mon, Sep 14, 2015 at 9:52 AM, Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> On Mon, Sep 14, 2015 at 12:50 AM, Laurent Pinchart
> <laurent.pinchart+renesas@ideasonboard.com> wrote:
>> This patch series adds support for the Display Unit found in the R-Car Gen3
>> SoC series.
>>
>> The third generation differs significantly from the previous ones in that the
>> DU has lost its ability to source data from memory. It must instead use an
>> external hardware composer named VSP to read planes from memory and blend
>> them.
>>
>> The VSP has a V4L2 driver in mainline that can be used in conjunction with the
>> DU through the live sources API (submitted previously as an RFC). However, as
>> VSP usage is mandatory in Gen3 and as no native DU planes are available, we
>> have decided that forcing userspace to use both KMS and V4L2 to display any
>> content wouldn't be very friendly. Instead the VSP driver has been extended to
>> make the device directly controllable by the DU driver ([1]) and this patch
>> series builds on top of it.
>>
>> [1] http://www.spinics.net/lists/linux-media/msg93575.html
>
> Against which tree is this series?
>
> From patch 1, I derived it's against drm-misc
> (git://anongit.freedesktop.org/drm-intel#topic/drm-misc), but later patches
> have other requirements.
> E.g. patch 13 assumes DRM_RCAR_DU has a dependency on OF, but that's nowhere
> to be found in -next.
> It is in git://linuxtv.org/pinchartl/media#vsp1-kms-gen3-20150909.2, but that
> conflicts badly with your R-Car Gen3 VSP series.

Or shall I just use vsp1-kms-gen3-20150913?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 08/22] drm: rcar-du: Restart the DU group when a plane source changes
  2015-09-14  7:22     ` Daniel Vetter
@ 2015-12-17  7:11       ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-12-17  7:11 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Laurent Pinchart, dri-devel, linux-sh

Hi Daniel,

On Monday 14 September 2015 09:22:13 Daniel Vetter wrote:
> On Mon, Sep 14, 2015 at 01:50:55AM +0300, Laurent Pinchart wrote:
> > Plane sources are configured by the VSPS bit in the PnDDCR4 register.
> > Although the datasheet states that the bit is updated during vertical
> > blanking, it seems that updates only occur when the DU group is held in
> > reset through the DSYSR.DRES bit. Restart the group if the source
> > changes.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  4 ++++
> >  drivers/gpu/drm/rcar-du/rcar_du_group.c |  2 ++
> >  drivers/gpu/drm/rcar-du/rcar_du_group.h |  2 ++
> >  drivers/gpu/drm/rcar-du/rcar_du_plane.c | 22 ++++++++++++++++++++--
> >  4 files changed, 28 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 48cb19949ca3..7e2f5c26d589
> > 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > @@ -272,6 +272,10 @@ static void rcar_du_crtc_update_planes(struct
> > rcar_du_crtc *rcrtc)
> >  			rcar_du_group_restart(rcrtc->group);
> >  	}
> > 
> > +	/* Restart the group if plane sources have changed. */
> > +	if (rcrtc->group->need_restart)
> > +		rcar_du_group_restart(rcrtc->group);
> > +
> >  	mutex_unlock(&rcrtc->group->lock);
> >  	
> >  	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_group.c index
> > 4a44ddd51766..0e2b46dce563 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > @@ -162,6 +162,8 @@ void rcar_du_group_start_stop(struct rcar_du_group
> > *rgrp, bool start)
> > 
> >  void rcar_du_group_restart(struct rcar_du_group *rgrp)
> >  {
> > +	rgrp->need_restart = false;
> > +
> >  	__rcar_du_group_start_stop(rgrp, false);
> >  	__rcar_du_group_start_stop(rgrp, true);
> >  }
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h
> > b/drivers/gpu/drm/rcar-du/rcar_du_group.h index
> > 4b1952fd4e7d..5e3adc6b31b5 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
> > @@ -32,6 +32,7 @@ struct rcar_du_device;
> >   * @dptsr_planes: bitmask of planes driven by dot-clock and timing
> >   generator 1
> >   * @num_planes: number of planes in the group
> >   * @planes: planes handled by the group
> > + * @need_restart: the group needs to be restarted due to a configuration
> > change
> >   */
> >  struct rcar_du_group {
> >  	struct rcar_du_device *dev;
> > @@ -47,6 +48,7 @@ struct rcar_du_group {
> >  	unsigned int num_planes;
> >  	struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
> > 
> > +	bool need_restart;
> 
> My recommendation is to keep any of these intermediate values in state
> objects too. The reason is that eventually we want to also support real
> queues of atomic commits,

I like the idea :-)

> and then anything stored globally (well, outside of the state objects) won't
> work. And yes it's ok to push that kind of stuff into helper, this isn't
> really any different than e.g. crtc_state->active_changed and similar
> booleans indicating that something special needs to be done when committing.

I agree with you. There's still a couple of state variables I need to remove 
in the driver structures, and that's on my todo list (although not very high 
I'm afraid).

The group state is a bit of an oddball. The DU groups CRTCs by two and shares 
resources inside a group. Implementing that resource sharing requires storing 
group state, which is very difficult without an atomic state object for the 
group.

Am I missing an easy way to fix that ? And would it be fine to upstream this 
patch as-is in the meantime ? I'd like to get it in v4.6, it's been out for 
long enough and is blocking other people.

> >  };
> >  
> >  u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg);
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index
> > 78ca353bfcf0..c7e0535c0e77 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> > @@ -275,9 +275,27 @@ static void rcar_du_plane_atomic_update(struct
> > drm_plane *plane,
> >  					struct drm_plane_state *old_state)
> >  {
> >  	struct rcar_du_plane *rplane = to_rcar_plane(plane);
> > +	struct rcar_du_plane_state *old_rstate;
> > +	struct rcar_du_plane_state *new_rstate;
> > 
> > -	if (plane->state->crtc)
> > -		rcar_du_plane_setup(rplane);
> > +	if (!plane->state->crtc)
> > +		return;
> > +
> > +	rcar_du_plane_setup(rplane);
> > +
> > +	/* Check whether the source has changed from memory to live source or
> > +	 * from live source to memory. The source has been configured by the
> > +	 * VSPS bit in the PnDDCR4 register. Although the datasheet states
> > that
> > +	 * the bit is updated during vertical blanking, it seems that updates
> > +	 * only occur when the DU group is held in reset through the
> > DSYSR.DRES
> > +	 * bit. We thus need to restart the group if the source changes.
> > +	 */
> > +	old_rstate = to_rcar_plane_state(old_state);
> > +	new_rstate = to_rcar_plane_state(plane->state);
> > +
> > +	if ((old_rstate->source = RCAR_DU_PLANE_MEMORY) !> > +	    (new_rstate->source = RCAR_DU_PLANE_MEMORY))
> > +		rplane->group->need_restart = true;
> >  }
> >  
> >  static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = {

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 08/22] drm: rcar-du: Restart the DU group when a plane source changes
@ 2015-12-17  7:11       ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-12-17  7:11 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Laurent Pinchart, dri-devel, linux-sh

Hi Daniel,

On Monday 14 September 2015 09:22:13 Daniel Vetter wrote:
> On Mon, Sep 14, 2015 at 01:50:55AM +0300, Laurent Pinchart wrote:
> > Plane sources are configured by the VSPS bit in the PnDDCR4 register.
> > Although the datasheet states that the bit is updated during vertical
> > blanking, it seems that updates only occur when the DU group is held in
> > reset through the DSYSR.DRES bit. Restart the group if the source
> > changes.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  4 ++++
> >  drivers/gpu/drm/rcar-du/rcar_du_group.c |  2 ++
> >  drivers/gpu/drm/rcar-du/rcar_du_group.h |  2 ++
> >  drivers/gpu/drm/rcar-du/rcar_du_plane.c | 22 ++++++++++++++++++++--
> >  4 files changed, 28 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 48cb19949ca3..7e2f5c26d589
> > 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > @@ -272,6 +272,10 @@ static void rcar_du_crtc_update_planes(struct
> > rcar_du_crtc *rcrtc)
> >  			rcar_du_group_restart(rcrtc->group);
> >  	}
> > 
> > +	/* Restart the group if plane sources have changed. */
> > +	if (rcrtc->group->need_restart)
> > +		rcar_du_group_restart(rcrtc->group);
> > +
> >  	mutex_unlock(&rcrtc->group->lock);
> >  	
> >  	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_group.c index
> > 4a44ddd51766..0e2b46dce563 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > @@ -162,6 +162,8 @@ void rcar_du_group_start_stop(struct rcar_du_group
> > *rgrp, bool start)
> > 
> >  void rcar_du_group_restart(struct rcar_du_group *rgrp)
> >  {
> > +	rgrp->need_restart = false;
> > +
> >  	__rcar_du_group_start_stop(rgrp, false);
> >  	__rcar_du_group_start_stop(rgrp, true);
> >  }
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h
> > b/drivers/gpu/drm/rcar-du/rcar_du_group.h index
> > 4b1952fd4e7d..5e3adc6b31b5 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
> > @@ -32,6 +32,7 @@ struct rcar_du_device;
> >   * @dptsr_planes: bitmask of planes driven by dot-clock and timing
> >   generator 1
> >   * @num_planes: number of planes in the group
> >   * @planes: planes handled by the group
> > + * @need_restart: the group needs to be restarted due to a configuration
> > change
> >   */
> >  struct rcar_du_group {
> >  	struct rcar_du_device *dev;
> > @@ -47,6 +48,7 @@ struct rcar_du_group {
> >  	unsigned int num_planes;
> >  	struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
> > 
> > +	bool need_restart;
> 
> My recommendation is to keep any of these intermediate values in state
> objects too. The reason is that eventually we want to also support real
> queues of atomic commits,

I like the idea :-)

> and then anything stored globally (well, outside of the state objects) won't
> work. And yes it's ok to push that kind of stuff into helper, this isn't
> really any different than e.g. crtc_state->active_changed and similar
> booleans indicating that something special needs to be done when committing.

I agree with you. There's still a couple of state variables I need to remove 
in the driver structures, and that's on my todo list (although not very high 
I'm afraid).

The group state is a bit of an oddball. The DU groups CRTCs by two and shares 
resources inside a group. Implementing that resource sharing requires storing 
group state, which is very difficult without an atomic state object for the 
group.

Am I missing an easy way to fix that ? And would it be fine to upstream this 
patch as-is in the meantime ? I'd like to get it in v4.6, it's been out for 
long enough and is blocking other people.

> >  };
> >  
> >  u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg);
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index
> > 78ca353bfcf0..c7e0535c0e77 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
> > @@ -275,9 +275,27 @@ static void rcar_du_plane_atomic_update(struct
> > drm_plane *plane,
> >  					struct drm_plane_state *old_state)
> >  {
> >  	struct rcar_du_plane *rplane = to_rcar_plane(plane);
> > +	struct rcar_du_plane_state *old_rstate;
> > +	struct rcar_du_plane_state *new_rstate;
> > 
> > -	if (plane->state->crtc)
> > -		rcar_du_plane_setup(rplane);
> > +	if (!plane->state->crtc)
> > +		return;
> > +
> > +	rcar_du_plane_setup(rplane);
> > +
> > +	/* Check whether the source has changed from memory to live source or
> > +	 * from live source to memory. The source has been configured by the
> > +	 * VSPS bit in the PnDDCR4 register. Although the datasheet states
> > that
> > +	 * the bit is updated during vertical blanking, it seems that updates
> > +	 * only occur when the DU group is held in reset through the
> > DSYSR.DRES
> > +	 * bit. We thus need to restart the group if the source changes.
> > +	 */
> > +	old_rstate = to_rcar_plane_state(old_state);
> > +	new_rstate = to_rcar_plane_state(plane->state);
> > +
> > +	if ((old_rstate->source == RCAR_DU_PLANE_MEMORY) !=
> > +	    (new_rstate->source == RCAR_DU_PLANE_MEMORY))
> > +		rplane->group->need_restart = true;
> >  }
> >  
> >  static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = {

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 08/22] drm: rcar-du: Restart the DU group when a plane source changes
  2015-12-17  7:11       ` Laurent Pinchart
@ 2015-12-17  9:41         ` Daniel Vetter
  -1 siblings, 0 replies; 58+ messages in thread
From: Daniel Vetter @ 2015-12-17  9:41 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Laurent Pinchart, dri-devel, linux-sh

On Thu, Dec 17, 2015 at 09:11:49AM +0200, Laurent Pinchart wrote:
> Hi Daniel,
> 
> On Monday 14 September 2015 09:22:13 Daniel Vetter wrote:
> > On Mon, Sep 14, 2015 at 01:50:55AM +0300, Laurent Pinchart wrote:
> > > Plane sources are configured by the VSPS bit in the PnDDCR4 register.
> > > Although the datasheet states that the bit is updated during vertical
> > > blanking, it seems that updates only occur when the DU group is held in
> > > reset through the DSYSR.DRES bit. Restart the group if the source
> > > changes.
> > > 
> > > Signed-off-by: Laurent Pinchart
> > > <laurent.pinchart+renesas@ideasonboard.com>
> > > ---
> > > 
> > >  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  4 ++++
> > >  drivers/gpu/drm/rcar-du/rcar_du_group.c |  2 ++
> > >  drivers/gpu/drm/rcar-du/rcar_du_group.h |  2 ++
> > >  drivers/gpu/drm/rcar-du/rcar_du_plane.c | 22 ++++++++++++++++++++--
> > >  4 files changed, 28 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > > b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 48cb19949ca3..7e2f5c26d589
> > > 100644
> > > --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > > +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > > @@ -272,6 +272,10 @@ static void rcar_du_crtc_update_planes(struct
> > > rcar_du_crtc *rcrtc)
> > >  			rcar_du_group_restart(rcrtc->group);
> > >  	}
> > > 
> > > +	/* Restart the group if plane sources have changed. */
> > > +	if (rcrtc->group->need_restart)
> > > +		rcar_du_group_restart(rcrtc->group);
> > > +
> > >  	mutex_unlock(&rcrtc->group->lock);
> > >  	
> > >  	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
> > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > > b/drivers/gpu/drm/rcar-du/rcar_du_group.c index
> > > 4a44ddd51766..0e2b46dce563 100644
> > > --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > > +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > > @@ -162,6 +162,8 @@ void rcar_du_group_start_stop(struct rcar_du_group
> > > *rgrp, bool start)
> > > 
> > >  void rcar_du_group_restart(struct rcar_du_group *rgrp)
> > >  {
> > > +	rgrp->need_restart = false;
> > > +
> > >  	__rcar_du_group_start_stop(rgrp, false);
> > >  	__rcar_du_group_start_stop(rgrp, true);
> > >  }
> > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h
> > > b/drivers/gpu/drm/rcar-du/rcar_du_group.h index
> > > 4b1952fd4e7d..5e3adc6b31b5 100644
> > > --- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
> > > +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
> > > @@ -32,6 +32,7 @@ struct rcar_du_device;
> > >   * @dptsr_planes: bitmask of planes driven by dot-clock and timing
> > >   generator 1
> > >   * @num_planes: number of planes in the group
> > >   * @planes: planes handled by the group
> > > + * @need_restart: the group needs to be restarted due to a configuration
> > > change
> > >   */
> > >  struct rcar_du_group {
> > >  	struct rcar_du_device *dev;
> > > @@ -47,6 +48,7 @@ struct rcar_du_group {
> > >  	unsigned int num_planes;
> > >  	struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
> > > 
> > > +	bool need_restart;
> > 
> > My recommendation is to keep any of these intermediate values in state
> > objects too. The reason is that eventually we want to also support real
> > queues of atomic commits,
> 
> I like the idea :-)
> 
> > and then anything stored globally (well, outside of the state objects) won't
> > work. And yes it's ok to push that kind of stuff into helper, this isn't
> > really any different than e.g. crtc_state->active_changed and similar
> > booleans indicating that something special needs to be done when committing.
> 
> I agree with you. There's still a couple of state variables I need to remove 
> in the driver structures, and that's on my todo list (although not very high 
> I'm afraid).
> 
> The group state is a bit of an oddball. The DU groups CRTCs by two and shares 
> resources inside a group. Implementing that resource sharing requires storing 
> group state, which is very difficult without an atomic state object for the 
> group.
> 
> Am I missing an easy way to fix that ? And would it be fine to upstream this 
> patch as-is in the meantime ? I'd like to get it in v4.6, it's been out for 
> long enough and is blocking other people.

Involves a bit of typing, but we allow drivers to subclass
drm_atomic_state and add whatever they want. The important part is to make
sure you get the locking right, i.e. only ever duplicate anything when you
hold the right locks. For that you have about 3 options:
- protect all group state with mode_config->connection_lock. Might
  unecessarily serialize updates.
- create a per-group ww_mutex (atomic allows you to throw as many
  additional ww_mutex locks encapsulated within a drm_modeset_lock as you
  want).
- just grab the crtc states (plus locks) for all the crtcs in a group when
  duplicating a group state

I highly recommend you follow the patterns laid out in drm_atomic.c and
only allow your driver to get at the group state through a get_group_state
helper, like we have for plane/crtc/connector states. That can then take
care of the locking and everything.

i915 uses this to keep track of shared resources like dpll and display
core clock.

There should be kerneldoc for the individual functions, but I think we
lack an overview/example section ... hint, hint ;-)

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [PATCH 08/22] drm: rcar-du: Restart the DU group when a plane source changes
@ 2015-12-17  9:41         ` Daniel Vetter
  0 siblings, 0 replies; 58+ messages in thread
From: Daniel Vetter @ 2015-12-17  9:41 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Laurent Pinchart, dri-devel, linux-sh

On Thu, Dec 17, 2015 at 09:11:49AM +0200, Laurent Pinchart wrote:
> Hi Daniel,
> 
> On Monday 14 September 2015 09:22:13 Daniel Vetter wrote:
> > On Mon, Sep 14, 2015 at 01:50:55AM +0300, Laurent Pinchart wrote:
> > > Plane sources are configured by the VSPS bit in the PnDDCR4 register.
> > > Although the datasheet states that the bit is updated during vertical
> > > blanking, it seems that updates only occur when the DU group is held in
> > > reset through the DSYSR.DRES bit. Restart the group if the source
> > > changes.
> > > 
> > > Signed-off-by: Laurent Pinchart
> > > <laurent.pinchart+renesas@ideasonboard.com>
> > > ---
> > > 
> > >  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  4 ++++
> > >  drivers/gpu/drm/rcar-du/rcar_du_group.c |  2 ++
> > >  drivers/gpu/drm/rcar-du/rcar_du_group.h |  2 ++
> > >  drivers/gpu/drm/rcar-du/rcar_du_plane.c | 22 ++++++++++++++++++++--
> > >  4 files changed, 28 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > > b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 48cb19949ca3..7e2f5c26d589
> > > 100644
> > > --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > > +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > > @@ -272,6 +272,10 @@ static void rcar_du_crtc_update_planes(struct
> > > rcar_du_crtc *rcrtc)
> > >  			rcar_du_group_restart(rcrtc->group);
> > >  	}
> > > 
> > > +	/* Restart the group if plane sources have changed. */
> > > +	if (rcrtc->group->need_restart)
> > > +		rcar_du_group_restart(rcrtc->group);
> > > +
> > >  	mutex_unlock(&rcrtc->group->lock);
> > >  	
> > >  	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
> > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > > b/drivers/gpu/drm/rcar-du/rcar_du_group.c index
> > > 4a44ddd51766..0e2b46dce563 100644
> > > --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > > +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > > @@ -162,6 +162,8 @@ void rcar_du_group_start_stop(struct rcar_du_group
> > > *rgrp, bool start)
> > > 
> > >  void rcar_du_group_restart(struct rcar_du_group *rgrp)
> > >  {
> > > +	rgrp->need_restart = false;
> > > +
> > >  	__rcar_du_group_start_stop(rgrp, false);
> > >  	__rcar_du_group_start_stop(rgrp, true);
> > >  }
> > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h
> > > b/drivers/gpu/drm/rcar-du/rcar_du_group.h index
> > > 4b1952fd4e7d..5e3adc6b31b5 100644
> > > --- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
> > > +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
> > > @@ -32,6 +32,7 @@ struct rcar_du_device;
> > >   * @dptsr_planes: bitmask of planes driven by dot-clock and timing
> > >   generator 1
> > >   * @num_planes: number of planes in the group
> > >   * @planes: planes handled by the group
> > > + * @need_restart: the group needs to be restarted due to a configuration
> > > change
> > >   */
> > >  struct rcar_du_group {
> > >  	struct rcar_du_device *dev;
> > > @@ -47,6 +48,7 @@ struct rcar_du_group {
> > >  	unsigned int num_planes;
> > >  	struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
> > > 
> > > +	bool need_restart;
> > 
> > My recommendation is to keep any of these intermediate values in state
> > objects too. The reason is that eventually we want to also support real
> > queues of atomic commits,
> 
> I like the idea :-)
> 
> > and then anything stored globally (well, outside of the state objects) won't
> > work. And yes it's ok to push that kind of stuff into helper, this isn't
> > really any different than e.g. crtc_state->active_changed and similar
> > booleans indicating that something special needs to be done when committing.
> 
> I agree with you. There's still a couple of state variables I need to remove 
> in the driver structures, and that's on my todo list (although not very high 
> I'm afraid).
> 
> The group state is a bit of an oddball. The DU groups CRTCs by two and shares 
> resources inside a group. Implementing that resource sharing requires storing 
> group state, which is very difficult without an atomic state object for the 
> group.
> 
> Am I missing an easy way to fix that ? And would it be fine to upstream this 
> patch as-is in the meantime ? I'd like to get it in v4.6, it's been out for 
> long enough and is blocking other people.

Involves a bit of typing, but we allow drivers to subclass
drm_atomic_state and add whatever they want. The important part is to make
sure you get the locking right, i.e. only ever duplicate anything when you
hold the right locks. For that you have about 3 options:
- protect all group state with mode_config->connection_lock. Might
  unecessarily serialize updates.
- create a per-group ww_mutex (atomic allows you to throw as many
  additional ww_mutex locks encapsulated within a drm_modeset_lock as you
  want).
- just grab the crtc states (plus locks) for all the crtcs in a group when
  duplicating a group state

I highly recommend you follow the patterns laid out in drm_atomic.c and
only allow your driver to get at the group state through a get_group_state
helper, like we have for plane/crtc/connector states. That can then take
care of the locking and everything.

i915 uses this to keep track of shared resources like dpll and display
core clock.

There should be kerneldoc for the individual functions, but I think we
lack an overview/example section ... hint, hint ;-)

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 08/22] drm: rcar-du: Restart the DU group when a plane source changes
  2015-12-17  9:41         ` Daniel Vetter
@ 2015-12-27  9:00           ` Laurent Pinchart
  -1 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-12-27  9:00 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Laurent Pinchart, dri-devel, linux-sh

Hi Daniel,

On Thursday 17 December 2015 10:41:51 Daniel Vetter wrote:
> On Thu, Dec 17, 2015 at 09:11:49AM +0200, Laurent Pinchart wrote:
> > On Monday 14 September 2015 09:22:13 Daniel Vetter wrote:
> >> On Mon, Sep 14, 2015 at 01:50:55AM +0300, Laurent Pinchart wrote:
> >>> Plane sources are configured by the VSPS bit in the PnDDCR4 register.
> >>> Although the datasheet states that the bit is updated during vertical
> >>> blanking, it seems that updates only occur when the DU group is held
> >>> in reset through the DSYSR.DRES bit. Restart the group if the source
> >>> changes.
> >>> 
> >>> Signed-off-by: Laurent Pinchart
> >>> <laurent.pinchart+renesas@ideasonboard.com>
> >>> ---
> >>> 
> >>>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  4 ++++
> >>>  drivers/gpu/drm/rcar-du/rcar_du_group.c |  2 ++
> >>>  drivers/gpu/drm/rcar-du/rcar_du_group.h |  2 ++
> >>>  drivers/gpu/drm/rcar-du/rcar_du_plane.c | 22 ++++++++++++++++++++--
> >>>  4 files changed, 28 insertions(+), 2 deletions(-)
> >>> 
> >>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> >>> b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index
> >>> 48cb19949ca3..7e2f5c26d589
> >>> 100644
> >>> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> >>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> >>> @@ -272,6 +272,10 @@ static void rcar_du_crtc_update_planes(struct
> >>> rcar_du_crtc *rcrtc)
> >>>  			rcar_du_group_restart(rcrtc->group);
> >>>  	}
> >>> 
> >>> +	/* Restart the group if plane sources have changed. */
> >>> +	if (rcrtc->group->need_restart)
> >>> +		rcar_du_group_restart(rcrtc->group);
> >>> +
> >>>  	mutex_unlock(&rcrtc->group->lock);
> >>>  	
> >>>  	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
> >>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> >>> b/drivers/gpu/drm/rcar-du/rcar_du_group.c index
> >>> 4a44ddd51766..0e2b46dce563 100644
> >>> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> >>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> >>> @@ -162,6 +162,8 @@ void rcar_du_group_start_stop(struct rcar_du_group
> >>> *rgrp, bool start)
> >>> 
> >>>  void rcar_du_group_restart(struct rcar_du_group *rgrp)
> >>>  {
> >>> +	rgrp->need_restart = false;
> >>> +
> >>>  	__rcar_du_group_start_stop(rgrp, false);
> >>>  	__rcar_du_group_start_stop(rgrp, true);
> >>>  }
> >>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h
> >>> b/drivers/gpu/drm/rcar-du/rcar_du_group.h index
> >>> 4b1952fd4e7d..5e3adc6b31b5 100644
> >>> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
> >>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
> >>> @@ -32,6 +32,7 @@ struct rcar_du_device;
> >>>   * @dptsr_planes: bitmask of planes driven by dot-clock and timing
> >>>   generator 1
> >>>   * @num_planes: number of planes in the group
> >>>   * @planes: planes handled by the group
> >>> + * @need_restart: the group needs to be restarted due to a
> >>> configuration change
> >>>   */
> >>>  struct rcar_du_group {
> >>>  	struct rcar_du_device *dev;
> >>> @@ -47,6 +48,7 @@ struct rcar_du_group {
> >>>  	unsigned int num_planes;
> >>>  	struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
> >>> 
> >>> +	bool need_restart;
> >> 
> >> My recommendation is to keep any of these intermediate values in state
> >> objects too. The reason is that eventually we want to also support real
> >> queues of atomic commits,
> > 
> > I like the idea :-)
> > 
> >> and then anything stored globally (well, outside of the state objects)
> >> won't work. And yes it's ok to push that kind of stuff into helper,
> >> this isn't really any different than e.g. crtc_state->active_changed
> >> and similar booleans indicating that something special needs to be done
> >> when committing.
> >
> > I agree with you. There's still a couple of state variables I need to
> > remove in the driver structures, and that's on my todo list (although not
> > very high I'm afraid).
> > 
> > The group state is a bit of an oddball. The DU groups CRTCs by two and
> > shares resources inside a group. Implementing that resource sharing
> > requires storing group state, which is very difficult without an atomic
> > state object for the group.
> > 
> > Am I missing an easy way to fix that ? And would it be fine to upstream
> > this patch as-is in the meantime ? I'd like to get it in v4.6, it's been
> > out for long enough and is blocking other people.
> 
> Involves a bit of typing, but we allow drivers to subclass
> drm_atomic_state and add whatever they want.

I hadn't noticed it had been introduced, that's very nice.

> The important part is to make sure you get the locking right, i.e. only ever
> duplicate anything when you hold the right locks. For that you have about 3
> options:
> - protect all group state with mode_config->connection_lock. Might
>   unecessarily serialize updates.
> - create a per-group ww_mutex (atomic allows you to throw as many
>   additional ww_mutex locks encapsulated within a drm_modeset_lock as you
>   want).
> - just grab the crtc states (plus locks) for all the crtcs in a group when
>   duplicating a group state
> 
> I highly recommend you follow the patterns laid out in drm_atomic.c and
> only allow your driver to get at the group state through a get_group_state
> helper, like we have for plane/crtc/connector states. That can then take
> care of the locking and everything.

Thanks for the tip, I'll give it a try.

> i915 uses this to keep track of shared resources like dpll and display
> core clock.
> 
> There should be kerneldoc for the individual functions, but I think we
> lack an overview/example section ... hint, hint ;-)

I'll first try to understand it by using it :-)

-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 08/22] drm: rcar-du: Restart the DU group when a plane source changes
@ 2015-12-27  9:00           ` Laurent Pinchart
  0 siblings, 0 replies; 58+ messages in thread
From: Laurent Pinchart @ 2015-12-27  9:00 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Laurent Pinchart, dri-devel, linux-sh

Hi Daniel,

On Thursday 17 December 2015 10:41:51 Daniel Vetter wrote:
> On Thu, Dec 17, 2015 at 09:11:49AM +0200, Laurent Pinchart wrote:
> > On Monday 14 September 2015 09:22:13 Daniel Vetter wrote:
> >> On Mon, Sep 14, 2015 at 01:50:55AM +0300, Laurent Pinchart wrote:
> >>> Plane sources are configured by the VSPS bit in the PnDDCR4 register.
> >>> Although the datasheet states that the bit is updated during vertical
> >>> blanking, it seems that updates only occur when the DU group is held
> >>> in reset through the DSYSR.DRES bit. Restart the group if the source
> >>> changes.
> >>> 
> >>> Signed-off-by: Laurent Pinchart
> >>> <laurent.pinchart+renesas@ideasonboard.com>
> >>> ---
> >>> 
> >>>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  4 ++++
> >>>  drivers/gpu/drm/rcar-du/rcar_du_group.c |  2 ++
> >>>  drivers/gpu/drm/rcar-du/rcar_du_group.h |  2 ++
> >>>  drivers/gpu/drm/rcar-du/rcar_du_plane.c | 22 ++++++++++++++++++++--
> >>>  4 files changed, 28 insertions(+), 2 deletions(-)
> >>> 
> >>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> >>> b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index
> >>> 48cb19949ca3..7e2f5c26d589
> >>> 100644
> >>> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> >>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> >>> @@ -272,6 +272,10 @@ static void rcar_du_crtc_update_planes(struct
> >>> rcar_du_crtc *rcrtc)
> >>>  			rcar_du_group_restart(rcrtc->group);
> >>>  	}
> >>> 
> >>> +	/* Restart the group if plane sources have changed. */
> >>> +	if (rcrtc->group->need_restart)
> >>> +		rcar_du_group_restart(rcrtc->group);
> >>> +
> >>>  	mutex_unlock(&rcrtc->group->lock);
> >>>  	
> >>>  	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
> >>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> >>> b/drivers/gpu/drm/rcar-du/rcar_du_group.c index
> >>> 4a44ddd51766..0e2b46dce563 100644
> >>> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> >>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> >>> @@ -162,6 +162,8 @@ void rcar_du_group_start_stop(struct rcar_du_group
> >>> *rgrp, bool start)
> >>> 
> >>>  void rcar_du_group_restart(struct rcar_du_group *rgrp)
> >>>  {
> >>> +	rgrp->need_restart = false;
> >>> +
> >>>  	__rcar_du_group_start_stop(rgrp, false);
> >>>  	__rcar_du_group_start_stop(rgrp, true);
> >>>  }
> >>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h
> >>> b/drivers/gpu/drm/rcar-du/rcar_du_group.h index
> >>> 4b1952fd4e7d..5e3adc6b31b5 100644
> >>> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
> >>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
> >>> @@ -32,6 +32,7 @@ struct rcar_du_device;
> >>>   * @dptsr_planes: bitmask of planes driven by dot-clock and timing
> >>>   generator 1
> >>>   * @num_planes: number of planes in the group
> >>>   * @planes: planes handled by the group
> >>> + * @need_restart: the group needs to be restarted due to a
> >>> configuration change
> >>>   */
> >>>  struct rcar_du_group {
> >>>  	struct rcar_du_device *dev;
> >>> @@ -47,6 +48,7 @@ struct rcar_du_group {
> >>>  	unsigned int num_planes;
> >>>  	struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
> >>> 
> >>> +	bool need_restart;
> >> 
> >> My recommendation is to keep any of these intermediate values in state
> >> objects too. The reason is that eventually we want to also support real
> >> queues of atomic commits,
> > 
> > I like the idea :-)
> > 
> >> and then anything stored globally (well, outside of the state objects)
> >> won't work. And yes it's ok to push that kind of stuff into helper,
> >> this isn't really any different than e.g. crtc_state->active_changed
> >> and similar booleans indicating that something special needs to be done
> >> when committing.
> >
> > I agree with you. There's still a couple of state variables I need to
> > remove in the driver structures, and that's on my todo list (although not
> > very high I'm afraid).
> > 
> > The group state is a bit of an oddball. The DU groups CRTCs by two and
> > shares resources inside a group. Implementing that resource sharing
> > requires storing group state, which is very difficult without an atomic
> > state object for the group.
> > 
> > Am I missing an easy way to fix that ? And would it be fine to upstream
> > this patch as-is in the meantime ? I'd like to get it in v4.6, it's been
> > out for long enough and is blocking other people.
> 
> Involves a bit of typing, but we allow drivers to subclass
> drm_atomic_state and add whatever they want.

I hadn't noticed it had been introduced, that's very nice.

> The important part is to make sure you get the locking right, i.e. only ever
> duplicate anything when you hold the right locks. For that you have about 3
> options:
> - protect all group state with mode_config->connection_lock. Might
>   unecessarily serialize updates.
> - create a per-group ww_mutex (atomic allows you to throw as many
>   additional ww_mutex locks encapsulated within a drm_modeset_lock as you
>   want).
> - just grab the crtc states (plus locks) for all the crtcs in a group when
>   duplicating a group state
> 
> I highly recommend you follow the patterns laid out in drm_atomic.c and
> only allow your driver to get at the group state through a get_group_state
> helper, like we have for plane/crtc/connector states. That can then take
> care of the locking and everything.

Thanks for the tip, I'll give it a try.

> i915 uses this to keep track of shared resources like dpll and display
> core clock.
> 
> There should be kerneldoc for the individual functions, but I think we
> lack an overview/example section ... hint, hint ;-)

I'll first try to understand it by using it :-)

-- 
Regards,

Laurent Pinchart

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

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

end of thread, other threads:[~2015-12-27  9:00 UTC | newest]

Thread overview: 58+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-13 22:50 [PATCH 00/22] R-Car DU: Add Gen3 support Laurent Pinchart
2015-09-13 22:50 ` Laurent Pinchart
2015-09-13 22:50 ` [PATCH 01/22] drm: rcar-du: Don't update planes on disabled CRTCs Laurent Pinchart
2015-09-13 22:50   ` Laurent Pinchart
2015-09-13 22:50 ` [PATCH 02/22] drm: rcar-du: Add support for the R8A7793 DU Laurent Pinchart
2015-09-13 22:50   ` Laurent Pinchart
2015-09-13 22:50 ` [PATCH 03/22] drm: rcar-du: Add support for the R8A7794 DU Laurent Pinchart
2015-09-13 22:50   ` Laurent Pinchart
2015-09-13 22:50 ` [PATCH 04/22] drm: rcar-du: Compute plane DDCR4 register value directly Laurent Pinchart
2015-09-13 22:50   ` Laurent Pinchart
2015-09-13 22:50 ` [PATCH 05/22] drm: rcar-du: Refactor plane setup Laurent Pinchart
2015-09-13 22:50   ` Laurent Pinchart
2015-09-13 22:50 ` [PATCH 06/22] drm: rcar-du: Add VSP1 support to the planes allocator Laurent Pinchart
2015-09-13 22:50   ` Laurent Pinchart
2015-09-13 22:50 ` [PATCH 07/22] drm: rcar-du: Add VSP1 compositor support Laurent Pinchart
2015-09-13 22:50   ` Laurent Pinchart
2015-09-13 22:50 ` [PATCH 08/22] drm: rcar-du: Restart the DU group when a plane source changes Laurent Pinchart
2015-09-13 22:50   ` Laurent Pinchart
2015-09-14  7:22   ` Daniel Vetter
2015-09-14  7:22     ` Daniel Vetter
2015-12-17  7:11     ` Laurent Pinchart
2015-12-17  7:11       ` Laurent Pinchart
2015-12-17  9:41       ` Daniel Vetter
2015-12-17  9:41         ` Daniel Vetter
2015-12-27  9:00         ` Laurent Pinchart
2015-12-27  9:00           ` Laurent Pinchart
2015-09-13 22:50 ` [PATCH 09/22] drm: rcar-du: Move plane allocator to rcar_du_plane.c Laurent Pinchart
2015-09-13 22:50   ` Laurent Pinchart
2015-09-13 22:50 ` [PATCH 10/22] drm: rcar-du: Expose the VSP1 compositor through KMS planes Laurent Pinchart
2015-09-13 22:50   ` Laurent Pinchart
2015-09-13 22:50 ` [PATCH 11/22] drm: rcar-du: Use the VSP atomic update API Laurent Pinchart
2015-09-13 22:50   ` Laurent Pinchart
2015-09-13 22:50 ` [PATCH 12/22] drm: rcar-du: Fix compile warning on 64-bit platforms Laurent Pinchart
2015-09-13 22:50   ` Laurent Pinchart
2015-09-13 22:51 ` [PATCH 13/22] drm: rcar-du: Enable compilation on ARM64 Laurent Pinchart
2015-09-13 22:51   ` Laurent Pinchart
2015-09-13 22:51 ` [PATCH 14/22] drm: rcar-du: Drop LVDS double dependency on OF Laurent Pinchart
2015-09-13 22:51   ` Laurent Pinchart
2015-09-13 22:51 ` [PATCH 15/22] drm: rcar-du: Support up to 4 CRTCs Laurent Pinchart
2015-09-13 22:51   ` Laurent Pinchart
2015-09-13 22:51 ` [PATCH 16/22] drm: rcar-du: Output the DISP signal on the DISP pin Laurent Pinchart
2015-09-13 22:51   ` Laurent Pinchart
2015-09-13 22:51 ` [PATCH 17/22] drm: rcar-du: Output the DISP signal on the ODDF pin Laurent Pinchart
2015-09-13 22:51   ` Laurent Pinchart
2015-09-13 22:51 ` [PATCH 18/22] drm: rcar-du: Add R8A7795 device support Laurent Pinchart
2015-09-13 22:51   ` Laurent Pinchart
2015-09-13 22:51 ` [PATCH 19/22] drm: rcar-du: lvds: Avoid duplication of clock clamp code Laurent Pinchart
2015-09-13 22:51   ` Laurent Pinchart
2015-09-13 22:51 ` [PATCH 20/22] drm: rcar-du: lvds: Fix PLL frequency-related configuration Laurent Pinchart
2015-09-13 22:51   ` Laurent Pinchart
2015-09-13 22:51 ` [PATCH 21/22] drm: rcar-du: lvds: Rename PLLEN bit to PLLON Laurent Pinchart
2015-09-13 22:51   ` Laurent Pinchart
2015-09-13 22:51 ` [PATCH 22/22] drm: rcar-du: lvds: Add R-Car Gen3 support Laurent Pinchart
2015-09-13 22:51   ` Laurent Pinchart
2015-09-14  7:52 ` [PATCH 00/22] R-Car DU: Add " Geert Uytterhoeven
2015-09-14  7:52   ` Geert Uytterhoeven
2015-09-14  8:07   ` Geert Uytterhoeven
2015-09-14  8:07     ` Geert Uytterhoeven

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.