All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/16] R-Car D3/E3 display support (with LVDS PLL)
@ 2018-09-04 12:10 ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: devicetree, Ulrich Hecht, Jacopo Mondi, linux-renesas-soc

Hello everybody,

This patch series adds display support for the D3 and E3 SoCs, and in
particular the Draak and Ebisu boards.

The code is based on Ulrich's "[PROTO][PATCH 00/10] R-Car D3 LVDS/HDMI support
(with PLL)" series previously posted to the dri-devel and linux-renesas-soc
mailing lists. It has been extensively reworked and partly rewritten, and
support for E3 and Ebisu has been added.

The DU in the D3 and E3 SoCs has no internal PLL. In order to achieve precise
pixel clock rates (required, among other use cases, for HDMI operation), the
PLL from the internal LVDS encoder must be programmed and its output clock
routed back to the DU.

The series starts with update to the DU and LVDS encoder DT bindings to add E3
(R8A77990) support (patches 01/16 and 02/16) and new clock sources for the
LVDS encoder (patch 03/16).

The next patch (04/16) adds a .mode_valid() operation to the thc63lvd1024
driver, to reject modes outside of the LVDS decoder's pixel clock operating
range (8 MHz to 135 MHz). The patch can be merged on its own separately from
this series.

Patch (05/16) adds support for D3 and E3 to the LVDS encoder driver. Compared
to the already supported SoCs, D3 and E3 use a different initialization
sequence and have a different PLL architecture, with more options for the
input clock.

The next five patches (06/16 to 10/16) perform small reworks or add support
for miscellaneous missing features and limitations of the DU, to be followed
by patch 11/16 that adds support for the D3 and E3 to the DU driver.

Finally patches 12/16 to 16/16 enable display for the D3 and E3 boards in DT.
Patch 12/16 adds support for the I2C controllers in the E3 DT, and will likely
be merged separately from this series. Patch 13/16 adds all the display IP
cores (FCP, VSP, DU and LVDS encoders) to the E3 DT, while patch 14/16 adds
(and wires up) the missing LVDS encoders to the D3 DT. Patches 15/16 and 16/16
then enable display output for the Ebisu and Draak boards respectively.

I believe the patch series to be ready for upstreaming (after fixing the
issues found during review of course). There is no big hack in the code, and I
haven't noticed any regression. A few issues are still unsolved, such as how
to disable display outputs independently on D3 and E3, and usage of the LVDS
PLL for the RGB output, but those are not regressions and shouldn't in my
opinion be considered as show stoppers.

The patches are available from

	git://linuxtv.org/pinchartl/media.git drm/du/lvds-pll

with an additional patch for E3 pinctrl that is required for testing and has
been queued by Geert for v4.20 already.

I have successfully tested the series with the HDMI output of the Ebisu board.
Ulrich, Jacopo, could you test it on D3 if you have time ? You only need to
run kmstest or modetest to display an image on the HDMI output.

Kieran Bingham (1):
  arm64: dts: renesas: r8a77995: Add LVDS support

Laurent Pinchart (12):
  dt-bindings: display: renesas: du: Document r8a77990 bindings
  dt-bindings: display: renesas: lvds: Document r8a77990 bindings
  dt-bindings: display: renesas: lvds: Add EXTAL and DU_DOTCLKIN clocks
  drm: bridge: thc63: Restrict modes based on hardware operating
    frequency
  drm: rcar-du: lvds: D3/E3 support
  drm: rcar-du: Perform the initial CRTC setup from rcar_du_crtc_get()
  drm: rcar-du: Use LVDS PLL clock as dot clock when possible
  drm: rcar-du: Enable configurable DPAD0 routing on Gen3
  drm: rcar-du: Cache DSYSR value to ensure known initial value
  drm: rcar-du: Don't use TV sync mode when not supported by the
    hardware
  arm64: dts: renesas: r8a77990: Add display output support
  arm64: dts: renesas: r8a77990: ebisu: Enable VGA and HDMI outputs

Takeshi Kihara (1):
  arm64: dts: renesas: r8a77990: Add I2C device nodes

Ulrich Hecht (2):
  drm: rcar-du: Add r8a77990 and r8a77995 device support
  arm64: dts: renesas: r8a77995: draak: Enable HDMI display output

 .../bindings/display/bridge/renesas,lvds.txt       |  13 +-
 .../devicetree/bindings/display/renesas,du.txt     |   2 +
 arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts     | 166 ++++++++++
 arch/arm64/boot/dts/renesas/r8a77990.dtsi          | 290 ++++++++++++++++
 arch/arm64/boot/dts/renesas/r8a77995-draak.dts     |  98 +++++-
 arch/arm64/boot/dts/renesas/r8a77995.dtsi          |  56 ++++
 drivers/gpu/drm/bridge/thc63lvd1024.c              |  18 +
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c             | 136 ++++----
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h             |   5 +
 drivers/gpu/drm/rcar-du/rcar_du_drv.c              |  63 +++-
 drivers/gpu/drm/rcar-du/rcar_du_drv.h              |   3 +
 drivers/gpu/drm/rcar-du/rcar_du_group.c            |  88 +++--
 drivers/gpu/drm/rcar-du/rcar_du_kms.c              |  12 +
 drivers/gpu/drm/rcar-du/rcar_lvds.c                | 365 ++++++++++++++++++---
 drivers/gpu/drm/rcar-du/rcar_lvds_regs.h           |  43 ++-
 15 files changed, 1210 insertions(+), 148 deletions(-)

-- 
Regards,

Laurent Pinchart

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

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

* [PATCH 00/16] R-Car D3/E3 display support (with LVDS PLL)
@ 2018-09-04 12:10 ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-renesas-soc, devicetree, Archit Taneja, Andrzej Hajda,
	Jacopo Mondi, Ulrich Hecht

Hello everybody,

This patch series adds display support for the D3 and E3 SoCs, and in
particular the Draak and Ebisu boards.

The code is based on Ulrich's "[PROTO][PATCH 00/10] R-Car D3 LVDS/HDMI support
(with PLL)" series previously posted to the dri-devel and linux-renesas-soc
mailing lists. It has been extensively reworked and partly rewritten, and
support for E3 and Ebisu has been added.

The DU in the D3 and E3 SoCs has no internal PLL. In order to achieve precise
pixel clock rates (required, among other use cases, for HDMI operation), the
PLL from the internal LVDS encoder must be programmed and its output clock
routed back to the DU.

The series starts with update to the DU and LVDS encoder DT bindings to add E3
(R8A77990) support (patches 01/16 and 02/16) and new clock sources for the
LVDS encoder (patch 03/16).

The next patch (04/16) adds a .mode_valid() operation to the thc63lvd1024
driver, to reject modes outside of the LVDS decoder's pixel clock operating
range (8 MHz to 135 MHz). The patch can be merged on its own separately from
this series.

Patch (05/16) adds support for D3 and E3 to the LVDS encoder driver. Compared
to the already supported SoCs, D3 and E3 use a different initialization
sequence and have a different PLL architecture, with more options for the
input clock.

The next five patches (06/16 to 10/16) perform small reworks or add support
for miscellaneous missing features and limitations of the DU, to be followed
by patch 11/16 that adds support for the D3 and E3 to the DU driver.

Finally patches 12/16 to 16/16 enable display for the D3 and E3 boards in DT.
Patch 12/16 adds support for the I2C controllers in the E3 DT, and will likely
be merged separately from this series. Patch 13/16 adds all the display IP
cores (FCP, VSP, DU and LVDS encoders) to the E3 DT, while patch 14/16 adds
(and wires up) the missing LVDS encoders to the D3 DT. Patches 15/16 and 16/16
then enable display output for the Ebisu and Draak boards respectively.

I believe the patch series to be ready for upstreaming (after fixing the
issues found during review of course). There is no big hack in the code, and I
haven't noticed any regression. A few issues are still unsolved, such as how
to disable display outputs independently on D3 and E3, and usage of the LVDS
PLL for the RGB output, but those are not regressions and shouldn't in my
opinion be considered as show stoppers.

The patches are available from

	git://linuxtv.org/pinchartl/media.git drm/du/lvds-pll

with an additional patch for E3 pinctrl that is required for testing and has
been queued by Geert for v4.20 already.

I have successfully tested the series with the HDMI output of the Ebisu board.
Ulrich, Jacopo, could you test it on D3 if you have time ? You only need to
run kmstest or modetest to display an image on the HDMI output.

Kieran Bingham (1):
  arm64: dts: renesas: r8a77995: Add LVDS support

Laurent Pinchart (12):
  dt-bindings: display: renesas: du: Document r8a77990 bindings
  dt-bindings: display: renesas: lvds: Document r8a77990 bindings
  dt-bindings: display: renesas: lvds: Add EXTAL and DU_DOTCLKIN clocks
  drm: bridge: thc63: Restrict modes based on hardware operating
    frequency
  drm: rcar-du: lvds: D3/E3 support
  drm: rcar-du: Perform the initial CRTC setup from rcar_du_crtc_get()
  drm: rcar-du: Use LVDS PLL clock as dot clock when possible
  drm: rcar-du: Enable configurable DPAD0 routing on Gen3
  drm: rcar-du: Cache DSYSR value to ensure known initial value
  drm: rcar-du: Don't use TV sync mode when not supported by the
    hardware
  arm64: dts: renesas: r8a77990: Add display output support
  arm64: dts: renesas: r8a77990: ebisu: Enable VGA and HDMI outputs

Takeshi Kihara (1):
  arm64: dts: renesas: r8a77990: Add I2C device nodes

Ulrich Hecht (2):
  drm: rcar-du: Add r8a77990 and r8a77995 device support
  arm64: dts: renesas: r8a77995: draak: Enable HDMI display output

 .../bindings/display/bridge/renesas,lvds.txt       |  13 +-
 .../devicetree/bindings/display/renesas,du.txt     |   2 +
 arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts     | 166 ++++++++++
 arch/arm64/boot/dts/renesas/r8a77990.dtsi          | 290 ++++++++++++++++
 arch/arm64/boot/dts/renesas/r8a77995-draak.dts     |  98 +++++-
 arch/arm64/boot/dts/renesas/r8a77995.dtsi          |  56 ++++
 drivers/gpu/drm/bridge/thc63lvd1024.c              |  18 +
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c             | 136 ++++----
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h             |   5 +
 drivers/gpu/drm/rcar-du/rcar_du_drv.c              |  63 +++-
 drivers/gpu/drm/rcar-du/rcar_du_drv.h              |   3 +
 drivers/gpu/drm/rcar-du/rcar_du_group.c            |  88 +++--
 drivers/gpu/drm/rcar-du/rcar_du_kms.c              |  12 +
 drivers/gpu/drm/rcar-du/rcar_lvds.c                | 365 ++++++++++++++++++---
 drivers/gpu/drm/rcar-du/rcar_lvds_regs.h           |  43 ++-
 15 files changed, 1210 insertions(+), 148 deletions(-)

-- 
Regards,

Laurent Pinchart

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

* [PATCH 01/16] dt-bindings: display: renesas: du: Document r8a77990 bindings
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-04 12:10   ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, devicetree

Document the E3 (r8a77990) SoC in the R-Car DU bindings.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 Documentation/devicetree/bindings/display/renesas,du.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt
index caae2348a292..9de67be632d1 100644
--- a/Documentation/devicetree/bindings/display/renesas,du.txt
+++ b/Documentation/devicetree/bindings/display/renesas,du.txt
@@ -16,6 +16,7 @@ Required Properties:
     - "renesas,du-r8a77965" for R8A77965 (R-Car M3-N) compatible DU
     - "renesas,du-r8a77970" for R8A77970 (R-Car V3M) compatible DU
     - "renesas,du-r8a77980" for R8A77980 (R-Car V3H) compatible DU
+    - "renesas,du-r8a77990" for R8A77990 (R-Car E3) compatible DU
     - "renesas,du-r8a77995" for R8A77995 (R-Car D3) compatible DU
 
   - reg: the memory-mapped I/O registers base address and length
@@ -63,6 +64,7 @@ corresponding to each DU output.
  R8A77965 (R-Car M3-N)  DPAD 0         HDMI 0         LVDS 0         -
  R8A77970 (R-Car V3M)   DPAD 0         LVDS 0         -              -
  R8A77980 (R-Car V3H)   DPAD 0         LVDS 0         -              -
+ R8A77990 (R-Car E3)    DPAD 0         LVDS 0         LVDS 1         -
  R8A77995 (R-Car D3)    DPAD 0         LVDS 0         LVDS 1         -
 
 
-- 
Regards,

Laurent Pinchart

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

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

* [PATCH 01/16] dt-bindings: display: renesas: du: Document r8a77990 bindings
@ 2018-09-04 12:10   ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, devicetree

Document the E3 (r8a77990) SoC in the R-Car DU bindings.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 Documentation/devicetree/bindings/display/renesas,du.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt
index caae2348a292..9de67be632d1 100644
--- a/Documentation/devicetree/bindings/display/renesas,du.txt
+++ b/Documentation/devicetree/bindings/display/renesas,du.txt
@@ -16,6 +16,7 @@ Required Properties:
     - "renesas,du-r8a77965" for R8A77965 (R-Car M3-N) compatible DU
     - "renesas,du-r8a77970" for R8A77970 (R-Car V3M) compatible DU
     - "renesas,du-r8a77980" for R8A77980 (R-Car V3H) compatible DU
+    - "renesas,du-r8a77990" for R8A77990 (R-Car E3) compatible DU
     - "renesas,du-r8a77995" for R8A77995 (R-Car D3) compatible DU
 
   - reg: the memory-mapped I/O registers base address and length
@@ -63,6 +64,7 @@ corresponding to each DU output.
  R8A77965 (R-Car M3-N)  DPAD 0         HDMI 0         LVDS 0         -
  R8A77970 (R-Car V3M)   DPAD 0         LVDS 0         -              -
  R8A77980 (R-Car V3H)   DPAD 0         LVDS 0         -              -
+ R8A77990 (R-Car E3)    DPAD 0         LVDS 0         LVDS 1         -
  R8A77995 (R-Car D3)    DPAD 0         LVDS 0         LVDS 1         -
 
 
-- 
Regards,

Laurent Pinchart

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

* [PATCH 02/16] dt-bindings: display: renesas: lvds: Document r8a77990 bindings
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-04 12:10   ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, devicetree

The E3 (r8a77990) supports two LVDS channels. Extend the binding to
support them.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
index 5a4e379bb414..13af7e2ac7e8 100644
--- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
+++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
@@ -15,6 +15,7 @@ Required properties:
   - "renesas,r8a7796-lvds" for R8A7796 (R-Car M3-W) compatible LVDS encoders
   - "renesas,r8a77970-lvds" for R8A77970 (R-Car V3M) compatible LVDS encoders
   - "renesas,r8a77980-lvds" for R8A77980 (R-Car V3H) compatible LVDS encoders
+  - "renesas,r8a77990-lvds" for R8A77990 (R-Car E3) compatible LVDS encoders
   - "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS encoders
 
 - reg: Base address and length for the memory-mapped registers
-- 
Regards,

Laurent Pinchart

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

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

* [PATCH 02/16] dt-bindings: display: renesas: lvds: Document r8a77990 bindings
@ 2018-09-04 12:10   ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, devicetree

The E3 (r8a77990) supports two LVDS channels. Extend the binding to
support them.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
index 5a4e379bb414..13af7e2ac7e8 100644
--- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
+++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
@@ -15,6 +15,7 @@ Required properties:
   - "renesas,r8a7796-lvds" for R8A7796 (R-Car M3-W) compatible LVDS encoders
   - "renesas,r8a77970-lvds" for R8A77970 (R-Car V3M) compatible LVDS encoders
   - "renesas,r8a77980-lvds" for R8A77980 (R-Car V3H) compatible LVDS encoders
+  - "renesas,r8a77990-lvds" for R8A77990 (R-Car E3) compatible LVDS encoders
   - "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS encoders
 
 - reg: Base address and length for the memory-mapped registers
-- 
Regards,

Laurent Pinchart

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

* [PATCH 03/16] dt-bindings: display: renesas: lvds: Add EXTAL and DU_DOTCLKIN clocks
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-04 12:10   ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, devicetree

On the D3 and E3 SoCs, the LVDS encoder can derive its internal pixel
clock from an externally supplied clock, either through the EXTAL pin or
through one of the DU_DOTCLKINx pins. Add corresponding clocks to the DT
bindings.

To retain backward compatibility with DT that don't specify the
clock-names property, the functional clock must always be specified
first, and the clock-names property is optional when only the functional
clock is specified.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 .../devicetree/bindings/display/bridge/renesas,lvds.txt      | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
index 13af7e2ac7e8..9e3913f6a643 100644
--- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
+++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
@@ -19,7 +19,17 @@ Required properties:
   - "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS encoders
 
 - reg: Base address and length for the memory-mapped registers
-- clocks: A phandle + clock-specifier pair for the functional clock
+- clocks: A list of phandles + clock-specifier pairs, one for each entry in
+  the clock-names property.
+- clock-names: Name of the clocks. This property is model-dependent.
+  - The functional clock is mandatory for all models, shall be listed first,
+    and shall be named "fck".
+  - On R8A77990 and R8A77995, the LVDS encoder can use the EXTAL or
+    DU_DOTCLKINx clocks. Those clocks are optional. When supplied they must be
+    named "extal" and "dclkin.x" respectively, with "x" being the DU_DOTCLKIN
+    numerical index.
+  - When the clocks property only contains the functional clock, the
+    clock-names property may be omitted.
 - resets: A phandle + reset specifier for the module reset
 
 Required nodes:
-- 
Regards,

Laurent Pinchart

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

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

* [PATCH 03/16] dt-bindings: display: renesas: lvds: Add EXTAL and DU_DOTCLKIN clocks
@ 2018-09-04 12:10   ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, devicetree

On the D3 and E3 SoCs, the LVDS encoder can derive its internal pixel
clock from an externally supplied clock, either through the EXTAL pin or
through one of the DU_DOTCLKINx pins. Add corresponding clocks to the DT
bindings.

To retain backward compatibility with DT that don't specify the
clock-names property, the functional clock must always be specified
first, and the clock-names property is optional when only the functional
clock is specified.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 .../devicetree/bindings/display/bridge/renesas,lvds.txt      | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
index 13af7e2ac7e8..9e3913f6a643 100644
--- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
+++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
@@ -19,7 +19,17 @@ Required properties:
   - "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS encoders
 
 - reg: Base address and length for the memory-mapped registers
-- clocks: A phandle + clock-specifier pair for the functional clock
+- clocks: A list of phandles + clock-specifier pairs, one for each entry in
+  the clock-names property.
+- clock-names: Name of the clocks. This property is model-dependent.
+  - The functional clock is mandatory for all models, shall be listed first,
+    and shall be named "fck".
+  - On R8A77990 and R8A77995, the LVDS encoder can use the EXTAL or
+    DU_DOTCLKINx clocks. Those clocks are optional. When supplied they must be
+    named "extal" and "dclkin.x" respectively, with "x" being the DU_DOTCLKIN
+    numerical index.
+  - When the clocks property only contains the functional clock, the
+    clock-names property may be omitted.
 - resets: A phandle + reset specifier for the module reset
 
 Required nodes:
-- 
Regards,

Laurent Pinchart

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

* [PATCH 04/16] drm: bridge: thc63: Restrict modes based on hardware operating frequency
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-04 12:10   ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Archit Taneja, Andrzej Hajda, Jacopo Mondi

The THC63LVD1024 is restricted to a pixel clock frequency in the range
of 8 to 135 MHz. Implement the bridge .mode_valid() operation
accordingly.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/bridge/thc63lvd1024.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c b/drivers/gpu/drm/bridge/thc63lvd1024.c
index c8b9edd5a7f4..63609ba16b6d 100644
--- a/drivers/gpu/drm/bridge/thc63lvd1024.c
+++ b/drivers/gpu/drm/bridge/thc63lvd1024.c
@@ -45,6 +45,23 @@ static int thc63_attach(struct drm_bridge *bridge)
 	return drm_bridge_attach(bridge->encoder, thc63->next, bridge);
 }
 
+static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge,
+					const struct drm_display_mode *mode)
+{
+	/*
+	 * The THC63LVD0124 clock frequency range is 8 to 135 MHz in single-in,
+	 * single-out mode. Note that the limits depends on the mode and will
+	 * need to be adjusted accordingly.
+	 */
+	if (mode->clock < 8000)
+		return MODE_CLOCK_LOW;
+
+	if (mode->clock > 135000)
+		return MODE_CLOCK_HIGH;
+
+	return MODE_OK;
+}
+
 static void thc63_enable(struct drm_bridge *bridge)
 {
 	struct thc63_dev *thc63 = to_thc63(bridge);
@@ -77,6 +94,7 @@ static void thc63_disable(struct drm_bridge *bridge)
 
 static const struct drm_bridge_funcs thc63_bridge_func = {
 	.attach	= thc63_attach,
+	.mode_valid = thc63_mode_valid,
 	.enable = thc63_enable,
 	.disable = thc63_disable,
 };
-- 
Regards,

Laurent Pinchart

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

* [PATCH 04/16] drm: bridge: thc63: Restrict modes based on hardware operating frequency
@ 2018-09-04 12:10   ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Jacopo Mondi

The THC63LVD1024 is restricted to a pixel clock frequency in the range
of 8 to 135 MHz. Implement the bridge .mode_valid() operation
accordingly.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/bridge/thc63lvd1024.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c b/drivers/gpu/drm/bridge/thc63lvd1024.c
index c8b9edd5a7f4..63609ba16b6d 100644
--- a/drivers/gpu/drm/bridge/thc63lvd1024.c
+++ b/drivers/gpu/drm/bridge/thc63lvd1024.c
@@ -45,6 +45,23 @@ static int thc63_attach(struct drm_bridge *bridge)
 	return drm_bridge_attach(bridge->encoder, thc63->next, bridge);
 }
 
+static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge,
+					const struct drm_display_mode *mode)
+{
+	/*
+	 * The THC63LVD0124 clock frequency range is 8 to 135 MHz in single-in,
+	 * single-out mode. Note that the limits depends on the mode and will
+	 * need to be adjusted accordingly.
+	 */
+	if (mode->clock < 8000)
+		return MODE_CLOCK_LOW;
+
+	if (mode->clock > 135000)
+		return MODE_CLOCK_HIGH;
+
+	return MODE_OK;
+}
+
 static void thc63_enable(struct drm_bridge *bridge)
 {
 	struct thc63_dev *thc63 = to_thc63(bridge);
@@ -77,6 +94,7 @@ static void thc63_disable(struct drm_bridge *bridge)
 
 static const struct drm_bridge_funcs thc63_bridge_func = {
 	.attach	= thc63_attach,
+	.mode_valid = thc63_mode_valid,
 	.enable = thc63_enable,
 	.disable = thc63_disable,
 };
-- 
Regards,

Laurent Pinchart

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

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

* [PATCH 05/16] drm: rcar-du: lvds: D3/E3 support
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-04 12:10   ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

The LVDS encoders in the D3 and E3 SoCs differ significantly from those
in the other R-Car Gen3 family members:

- The LVDS PLL architecture is more complex and requires computing PLL
  parameters manually.
- The PLL uses external clocks as inputs, which need to be retrieved
  from DT.
- In addition to the different PLL setup, the startup sequence has
  changed *again* (seems someone had trouble making his/her mind).

Supporting all this requires DT bindings extensions for external clocks,
brand new PLL setup code, and a few quirks to handle the differences in
the startup sequence.

The implementation doesn't support all hardware features yet, namely

- Using the LV[01] clocks generated by the CPG as PLL input.
- Providing the LVDS PLL clock to the DU for use with the RGB output.

Those features can be added later when the need will arise.

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

diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
index ce0eb68c3416..aac4acbcfbfc 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
@@ -24,6 +24,8 @@
 
 #include "rcar_lvds_regs.h"
 
+struct rcar_lvds;
+
 /* Keep in sync with the LVDCR0.LVMD hardware register values. */
 enum rcar_lvds_mode {
 	RCAR_LVDS_MODE_JEIDA = 0,
@@ -31,14 +33,16 @@ enum rcar_lvds_mode {
 	RCAR_LVDS_MODE_VESA = 4,
 };
 
-#define RCAR_LVDS_QUIRK_LANES	(1 << 0)	/* LVDS lanes 1 and 3 inverted */
-#define RCAR_LVDS_QUIRK_GEN2_PLLCR (1 << 1)	/* LVDPLLCR has gen2 layout */
-#define RCAR_LVDS_QUIRK_GEN3_LVEN (1 << 2)	/* LVEN bit needs to be set */
-						/* on R8A77970/R8A7799x */
+#define RCAR_LVDS_QUIRK_LANES		BIT(0)	/* LVDS lanes 1 and 3 inverted */
+#define RCAR_LVDS_QUIRK_GEN3_LVEN	BIT(1)	/* LVEN bit needs to be set on R8A77970/R8A7799x */
+#define RCAR_LVDS_QUIRK_PWD		BIT(2)	/* PWD bit available (all of Gen3 but E3) */
+#define RCAR_LVDS_QUIRK_EXT_PLL		BIT(3)	/* Has extended PLL */
+#define RCAR_LVDS_QUIRK_DUAL_LINK	BIT(4)	/* Supports dual-link operation */
 
 struct rcar_lvds_device_info {
 	unsigned int gen;
 	unsigned int quirks;
+	void (*pll_setup)(struct rcar_lvds *lvds, unsigned int freq);
 };
 
 struct rcar_lvds {
@@ -52,7 +56,11 @@ struct rcar_lvds {
 	struct drm_panel *panel;
 
 	void __iomem *mmio;
-	struct clk *clock;
+	struct {
+		struct clk *mod;		/* CPG module clock */
+		struct clk *extal;		/* External clock */
+		struct clk *dotclkin[2];	/* External DU clocks */
+	} clocks;
 	bool enabled;
 
 	struct drm_display_mode display_mode;
@@ -128,33 +136,222 @@ static const struct drm_connector_funcs rcar_lvds_conn_funcs = {
 };
 
 /* -----------------------------------------------------------------------------
- * Bridge
+ * PLL Setup
  */
 
-static u32 rcar_lvds_lvdpllcr_gen2(unsigned int freq)
+static void rcar_lvds_pll_setup_gen2(struct rcar_lvds *lvds, unsigned int freq)
+{
+	u32 val;
+
+	if (freq < 39000000)
+		val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
+	else if (freq < 61000000)
+		val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
+	else if (freq < 121000000)
+		val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
+	else
+		val = LVDPLLCR_PLLDLYCNT_150M;
+
+	rcar_lvds_write(lvds, LVDPLLCR, val);
+}
+
+static void rcar_lvds_pll_setup_gen3(struct rcar_lvds *lvds, unsigned int freq)
 {
-	if (freq < 39000)
-		return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
-	else if (freq < 61000)
-		return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
-	else if (freq < 121000)
-		return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
+	u32 val;
+
+	if (freq < 42000000)
+		val = LVDPLLCR_PLLDIVCNT_42M;
+	else if (freq < 85000000)
+		val = LVDPLLCR_PLLDIVCNT_85M;
+	else if (freq < 128000000)
+		val = LVDPLLCR_PLLDIVCNT_128M;
 	else
-		return LVDPLLCR_PLLDLYCNT_150M;
+		val = LVDPLLCR_PLLDIVCNT_148M;
+
+	rcar_lvds_write(lvds, LVDPLLCR, val);
+}
+
+struct pll_info {
+	struct clk *clk;
+	unsigned long diff;
+	unsigned int pll_m;
+	unsigned int pll_n;
+	unsigned int pll_e;
+	unsigned int div;
+};
+
+static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk,
+				     unsigned long target, struct pll_info *pll)
+{
+	unsigned long fin;
+	unsigned int m_min;
+	unsigned int m_max;
+	unsigned int m;
+
+	if (!clk)
+		return;
+
+	/*
+	 * The LVDS PLL is made of a pre-divider and a multiplier (strangerly
+	 * enough called M and N respectively), followed by a post-divider E.
+	 *
+	 *         ,-----.         ,-----.     ,-----.         ,-----.
+	 * Fin --> | 1/M | -Fpdf-> | PFD | --> | VCO | -Fvco-> | 1/E | --> Fout
+	 *         `-----'     ,-> |     |     `-----'   |     `-----'
+	 *                     |   `-----'               |
+	 *                     |         ,-----.         |
+	 *                     `-------- | 1/N | <-------'
+	 *                               `-----'
+	 *
+	 * The clock output by the PLL is then further divided by a programmable
+	 * divider DIV to achieve the desired target frequency. Finally, an
+	 * optional fixed /7 divider is used to convert the bit clock to a pixel
+	 * clock (as LVDS transmits 7 bits per lane per clock sample).
+	 *
+	 *          ,-------.     ,-----.     |\
+	 * Fout --> | 1/DIV | --> | 1/7 | --> | |
+	 *          `-------'  |  `-----'     | | --> dot clock
+	 *                     `------------> | |
+	 *                                    |/
+	 *
+	 * The /7 divider is optional when the LVDS PLL is used to generate a
+	 * dot clock for the DU RGB output, without using the LVDS encoder. We
+	 * don't support this configuration yet.
+	 *
+	 * The PLL allowed input frequency range is 12 MHz to 192 MHz.
+	 */
+
+	fin = clk_get_rate(clk);
+	if (fin < 12000000 || fin > 192000000)
+		return;
+
+	/*
+	 * The comparison frequency range is 12 MHz to 24 MHz, which limits the
+	 * allowed values for the pre-divider M (normal range 1-8).
+	 *
+	 * Fpfd = Fin / M
+	 */
+	m_min = max_t(unsigned int, 1, DIV_ROUND_UP(fin, 24000000));
+	m_max = min_t(unsigned int, 8, fin / 12000000);
+
+	for (m = m_min; m <= m_max; ++m) {
+		unsigned long fpfd;
+		unsigned int n_min;
+		unsigned int n_max;
+		unsigned int n;
+
+		/*
+		 * The VCO operating range is 900 Mhz to 1800 MHz, which limits
+		 * the allowed values for the multiplier N (normal range
+		 * 60-120).
+		 *
+		 * Fvco = Fin * N / M
+		 */
+		fpfd = fin / m;
+		n_min = max_t(unsigned int, 60, DIV_ROUND_UP(900000000, fpfd));
+		n_max = min_t(unsigned int, 120, 1800000000 / fpfd);
+
+		for (n = n_min; n < n_max; ++n) {
+			unsigned long fvco;
+			unsigned int e_min;
+			unsigned int e;
+
+			/*
+			 * The output frequency is limited to 1039.5 MHz,
+			 * limiting again the allowed values for the
+			 * post-divider E (normal value 1, 2 or 4).
+			 *
+			 * Fout = Fvco / E
+			 */
+			fvco = fpfd * n;
+			e_min = fvco > 1039500000 ? 1 : 0;
+
+			for (e = e_min; e < 3; ++e) {
+				unsigned long fout;
+				unsigned long diff;
+				unsigned int div;
+
+				/*
+				 * Finally we have a programable divider after
+				 * the PLL, followed by a an optional fixed /7
+				 * divider.
+				 */
+				fout = fvco / (1 << e) / 7;
+				div = DIV_ROUND_CLOSEST(fout, target);
+				diff = abs(fout / div - target);
+
+				if (diff < pll->diff) {
+					pll->clk = clk;
+					pll->diff = diff;
+					pll->pll_m = m;
+					pll->pll_n = n;
+					pll->pll_e = e;
+					pll->div = div;
+
+					if (diff == 0)
+						goto done;
+				}
+			}
+		}
+	}
+
+done:
+#if defined(CONFIG_DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
+	{
+		unsigned long output = fin * pll->pll_n / pll->pll_m
+				     / (1 << pll->pll_e) / 7 / pll->div;
+		int error = (long)(output - target) * 10000 / (long)target;
+
+		dev_dbg(lvds->dev,
+			"%pC %lu Hz -> Fout %lu Hz (target %lu Hz, error %d.%02u%%), PLL M/N/E/DIV %u/%u/%u/%u\n",
+			clk, fin, output, target, error / 100,
+			error < 0 ? -error % 100 : error % 100,
+			pll->pll_m, pll->pll_n, pll->pll_e, pll->div);
+	}
+#endif
 }
 
-static u32 rcar_lvds_lvdpllcr_gen3(unsigned int freq)
+static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned int freq)
 {
-	if (freq < 42000)
-		return LVDPLLCR_PLLDIVCNT_42M;
-	else if (freq < 85000)
-		return LVDPLLCR_PLLDIVCNT_85M;
-	else if (freq < 128000)
-		return LVDPLLCR_PLLDIVCNT_128M;
+	struct drm_crtc *crtc = lvds->bridge.encoder->crtc;
+	struct pll_info pll = { .diff = (unsigned long)-1 };
+	u32 lvdpllcr;
+
+	if (lvds->clocks.dotclkin[0] || lvds->clocks.dotclkin[1]) {
+		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[0],
+					 freq, &pll);
+		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[1],
+					 freq, &pll);
+	} else if (lvds->clocks.extal) {
+		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.extal,
+					 freq, &pll);
+	}
+
+	lvdpllcr = LVDPLLCR_PLLON | LVDPLLCR_CLKOUT
+		 | LVDPLLCR_PLLN(pll.pll_n - 1) | LVDPLLCR_PLLM(pll.pll_m - 1);
+
+	if (pll.clk == lvds->clocks.extal)
+		lvdpllcr |= LVDPLLCR_CKSEL_EXTAL;
+	else
+		lvdpllcr |= LVDPLLCR_CKSEL_DU_DOTCLKIN(drm_crtc_index(crtc));
+
+	if (pll.pll_e > 0)
+		lvdpllcr |= LVDPLLCR_STP_CLKOUTE | LVDPLLCR_OUTCLKSEL
+			 |  LVDPLLCR_PLLE(pll.pll_e - 1);
+
+	rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
+
+	if (pll.div > 1)
+		rcar_lvds_write(lvds, LVDDIV, LVDDIV_DIVSEL |
+				LVDDIV_DIVRESET | LVDDIV_DIV(pll.div - 1));
 	else
-		return LVDPLLCR_PLLDIVCNT_148M;
+		rcar_lvds_write(lvds, LVDDIV, 0);
 }
 
+/* -----------------------------------------------------------------------------
+ * Bridge
+ */
+
 static void rcar_lvds_enable(struct drm_bridge *bridge)
 {
 	struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
@@ -164,14 +361,13 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
 	 * do we get a state pointer?
 	 */
 	struct drm_crtc *crtc = lvds->bridge.encoder->crtc;
-	u32 lvdpllcr;
 	u32 lvdhcr;
 	u32 lvdcr0;
 	int ret;
 
 	WARN_ON(lvds->enabled);
 
-	ret = clk_prepare_enable(lvds->clock);
+	ret = clk_prepare_enable(lvds->clocks.mod);
 	if (ret < 0)
 		return;
 
@@ -196,12 +392,13 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
 
 	rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
 
+	if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) {
+		/* Disable dual-link mode. */
+		rcar_lvds_write(lvds, LVDSTRIPE, 0);
+	}
+
 	/* PLL clock configuration. */
-	if (lvds->info->quirks & RCAR_LVDS_QUIRK_GEN2_PLLCR)
-		lvdpllcr = rcar_lvds_lvdpllcr_gen2(mode->clock);
-	else
-		lvdpllcr = rcar_lvds_lvdpllcr_gen3(mode->clock);
-	rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
+	lvds->info->pll_setup(lvds, mode->clock * 1000);
 
 	/* Set the LVDS mode and select the input. */
 	lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT;
@@ -220,11 +417,16 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
 		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
 	}
 
-	/* Turn the PLL on. */
-	lvdcr0 |= LVDCR0_PLLON;
-	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
+	if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) {
+		/*
+		 * Turn the PLL on (simple PLL only, extended PLL is fully
+		 * controlled through LVDPLLCR).
+		 */
+		lvdcr0 |= LVDCR0_PLLON;
+		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
+	}
 
-	if (lvds->info->gen > 2) {
+	if (lvds->info->quirks & RCAR_LVDS_QUIRK_PWD) {
 		/* Set LVDS normal mode. */
 		lvdcr0 |= LVDCR0_PWD;
 		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
@@ -236,8 +438,10 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
 		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
 	}
 
-	/* Wait for the startup delay. */
-	usleep_range(100, 150);
+	if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) {
+		/* Wait for the PLL startup delay (simple PLL only). */
+		usleep_range(100, 150);
+	}
 
 	/* Turn the output on. */
 	lvdcr0 |= LVDCR0_LVRES;
@@ -264,8 +468,9 @@ static void rcar_lvds_disable(struct drm_bridge *bridge)
 
 	rcar_lvds_write(lvds, LVDCR0, 0);
 	rcar_lvds_write(lvds, LVDCR1, 0);
+	rcar_lvds_write(lvds, LVDPLLCR, 0);
 
-	clk_disable_unprepare(lvds->clock);
+	clk_disable_unprepare(lvds->clocks.mod);
 
 	lvds->enabled = false;
 }
@@ -446,6 +651,60 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
 	return ret;
 }
 
+static struct clk *rcar_lvds_get_clock(struct rcar_lvds *lvds, const char *name,
+				       bool optional)
+{
+	struct clk *clk;
+
+	clk = devm_clk_get(lvds->dev, name);
+	if (!IS_ERR(clk))
+		return clk;
+
+	if (PTR_ERR(clk) == -ENOENT && optional)
+		return NULL;
+
+	if (PTR_ERR(clk) != -EPROBE_DEFER)
+		dev_err(lvds->dev, "failed to get %s clock\n",
+			name ? name : "module");
+
+	return clk;
+}
+
+static int rcar_lvds_get_clocks(struct rcar_lvds *lvds)
+{
+	lvds->clocks.mod = rcar_lvds_get_clock(lvds, NULL, false);
+	if (IS_ERR(lvds->clocks.mod))
+		return PTR_ERR(lvds->clocks.mod);
+
+	/*
+	 * LVDS encoders without an extended PLL have no external clock inputs.
+	 */
+	if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL))
+		return 0;
+
+	lvds->clocks.extal = rcar_lvds_get_clock(lvds, "extal", true);
+	if (IS_ERR(lvds->clocks.extal))
+		return PTR_ERR(lvds->clocks.extal);
+
+	lvds->clocks.dotclkin[0] = rcar_lvds_get_clock(lvds, "dclkin.0", true);
+	if (IS_ERR(lvds->clocks.dotclkin[0]))
+		return PTR_ERR(lvds->clocks.dotclkin[0]);
+
+	lvds->clocks.dotclkin[1] = rcar_lvds_get_clock(lvds, "dclkin.1", true);
+	if (IS_ERR(lvds->clocks.dotclkin[1]))
+		return PTR_ERR(lvds->clocks.dotclkin[1]);
+
+	/* At least one input to the PLL must be available. */
+	if (!lvds->clocks.extal && !lvds->clocks.dotclkin[0] &&
+	    !lvds->clocks.dotclkin[1]) {
+		dev_err(lvds->dev,
+			"no input clock (extal, dclkin.0 or dclkin.1)\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int rcar_lvds_probe(struct platform_device *pdev)
 {
 	struct rcar_lvds *lvds;
@@ -475,11 +734,9 @@ static int rcar_lvds_probe(struct platform_device *pdev)
 	if (IS_ERR(lvds->mmio))
 		return PTR_ERR(lvds->mmio);
 
-	lvds->clock = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(lvds->clock)) {
-		dev_err(&pdev->dev, "failed to get clock\n");
-		return PTR_ERR(lvds->clock);
-	}
+	ret = rcar_lvds_get_clocks(lvds);
+	if (ret < 0)
+		return ret;
 
 	drm_bridge_add(&lvds->bridge);
 
@@ -497,21 +754,39 @@ static int rcar_lvds_remove(struct platform_device *pdev)
 
 static const struct rcar_lvds_device_info rcar_lvds_gen2_info = {
 	.gen = 2,
-	.quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR,
+	.pll_setup = rcar_lvds_pll_setup_gen2,
 };
 
 static const struct rcar_lvds_device_info rcar_lvds_r8a7790_info = {
 	.gen = 2,
-	.quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR | RCAR_LVDS_QUIRK_LANES,
+	.quirks = RCAR_LVDS_QUIRK_LANES,
+	.pll_setup = rcar_lvds_pll_setup_gen2,
 };
 
 static const struct rcar_lvds_device_info rcar_lvds_gen3_info = {
 	.gen = 3,
+	.quirks = RCAR_LVDS_QUIRK_PWD,
+	.pll_setup = rcar_lvds_pll_setup_gen3,
 };
 
 static const struct rcar_lvds_device_info rcar_lvds_r8a77970_info = {
 	.gen = 3,
-	.quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR | RCAR_LVDS_QUIRK_GEN3_LVEN,
+	.quirks = RCAR_LVDS_QUIRK_PWD | RCAR_LVDS_QUIRK_GEN3_LVEN,
+	.pll_setup = rcar_lvds_pll_setup_gen2,
+};
+
+static const struct rcar_lvds_device_info rcar_lvds_r8a77990_info = {
+	.gen = 3,
+	.quirks = RCAR_LVDS_QUIRK_GEN3_LVEN | RCAR_LVDS_QUIRK_EXT_PLL
+		| RCAR_LVDS_QUIRK_DUAL_LINK,
+	.pll_setup = rcar_lvds_pll_setup_d3_e3,
+};
+
+static const struct rcar_lvds_device_info rcar_lvds_r8a77995_info = {
+	.gen = 3,
+	.quirks = RCAR_LVDS_QUIRK_GEN3_LVEN | RCAR_LVDS_QUIRK_PWD
+		| RCAR_LVDS_QUIRK_EXT_PLL | RCAR_LVDS_QUIRK_DUAL_LINK,
+	.pll_setup = rcar_lvds_pll_setup_d3_e3,
 };
 
 static const struct of_device_id rcar_lvds_of_table[] = {
@@ -523,6 +798,8 @@ static const struct of_device_id rcar_lvds_of_table[] = {
 	{ .compatible = "renesas,r8a7796-lvds", .data = &rcar_lvds_gen3_info },
 	{ .compatible = "renesas,r8a77970-lvds", .data = &rcar_lvds_r8a77970_info },
 	{ .compatible = "renesas,r8a77980-lvds", .data = &rcar_lvds_gen3_info },
+	{ .compatible = "renesas,r8a77990-lvds", .data = &rcar_lvds_r8a77990_info },
+	{ .compatible = "renesas,r8a77995-lvds", .data = &rcar_lvds_r8a77995_info },
 	{ }
 };
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
index 4870f50d9bec..87149f2f8056 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_PLLON			(1 << 4)
 #define LVDCR0_PWD			(1 << 2)		/* Gen3 only */
 #define LVDCR0_BEN			(1 << 2)		/* Gen2 only */
-#define LVDCR0_LVEN			(1 << 1)		/* Gen2 only */
+#define LVDCR0_LVEN			(1 << 1)
 #define LVDCR0_LVRES			(1 << 0)
 
 #define LVDCR1				0x0004
@@ -27,21 +27,36 @@
 #define LVDCR1_CLKSTBY			(3 << 0)
 
 #define LVDPLLCR			0x0008
+/* Gen2 & V3M */
 #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 */
+/* Gen3 but V3M,D3 and E3 */
 #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)
+/* D3 and E3 */
+#define LVDPLLCR_PLLON			(1 << 22)
+#define LVDPLLCR_PLLSEL_PLL0		(0 << 20)
+#define LVDPLLCR_PLLSEL_LVX		(1 << 20)
+#define LVDPLLCR_PLLSEL_PLL1		(2 << 20)
+#define LVDPLLCR_CKSEL_LVX		(1 << 17)
+#define LVDPLLCR_CKSEL_EXTAL		(3 << 17)
+#define LVDPLLCR_CKSEL_DU_DOTCLKIN(n)	((5 + (n) * 2) << 17)
+#define LVDPLLCR_OCKSEL			(1 << 16)
+#define LVDPLLCR_STP_CLKOUTE		(1 << 14)
+#define LVDPLLCR_OUTCLKSEL		(1 << 12)
+#define LVDPLLCR_CLKOUT			(1 << 11)
+#define LVDPLLCR_PLLE(n)		((n) << 10)
+#define LVDPLLCR_PLLN(n)		((n) << 3)
+#define LVDPLLCR_PLLM(n)		((n) << 0)
 
 #define LVDCTRCR			0x000c
 #define LVDCTRCR_CTR3SEL_ZERO		(0 << 12)
@@ -71,4 +86,26 @@
 #define LVDCHCR_CHSEL_CH(n, c)		((((c) - (n)) & 3) << ((n) * 4))
 #define LVDCHCR_CHSEL_MASK(n)		(3 << ((n) * 4))
 
+/* All registers below are specific to D3 and E3 */
+#define LVDSTRIPE			0x0014
+#define LVDSTRIPE_ST_TRGSEL_DISP	(0 << 2)
+#define LVDSTRIPE_ST_TRGSEL_HSYNC_R	(1 << 2)
+#define LVDSTRIPE_ST_TRGSEL_HSYNC_F	(2 << 2)
+#define LVDSTRIPE_ST_SWAP		(1 << 1)
+#define LVDSTRIPE_ST_ON			(1 << 0)
+
+#define LVDSCR				0x0018
+#define LVDSCR_DEPTH(n)			(((n) - 1) << 29)
+#define LVDSCR_BANDSET			(1 << 28)
+#define LVDSCR_TWGCNT(n)		((((n) - 256) / 16) << 24)
+#define LVDSCR_SDIV(n)			((n) << 22)
+#define LVDSCR_MODE			(1 << 21)
+#define LVDSCR_RSTN			(1 << 20)
+
+#define LVDDIV				0x001c
+#define LVDDIV_DIVSEL			(1 << 8)
+#define LVDDIV_DIVRESET			(1 << 7)
+#define LVDDIV_DIVSTP			(1 << 6)
+#define LVDDIV_DIV(n)			((n) << 0)
+
 #endif /* __RCAR_LVDS_REGS_H__ */
-- 
Regards,

Laurent Pinchart

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

* [PATCH 05/16] drm: rcar-du: lvds: D3/E3 support
@ 2018-09-04 12:10   ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

The LVDS encoders in the D3 and E3 SoCs differ significantly from those
in the other R-Car Gen3 family members:

- The LVDS PLL architecture is more complex and requires computing PLL
  parameters manually.
- The PLL uses external clocks as inputs, which need to be retrieved
  from DT.
- In addition to the different PLL setup, the startup sequence has
  changed *again* (seems someone had trouble making his/her mind).

Supporting all this requires DT bindings extensions for external clocks,
brand new PLL setup code, and a few quirks to handle the differences in
the startup sequence.

The implementation doesn't support all hardware features yet, namely

- Using the LV[01] clocks generated by the CPG as PLL input.
- Providing the LVDS PLL clock to the DU for use with the RGB output.

Those features can be added later when the need will arise.

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

diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
index ce0eb68c3416..aac4acbcfbfc 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
@@ -24,6 +24,8 @@
 
 #include "rcar_lvds_regs.h"
 
+struct rcar_lvds;
+
 /* Keep in sync with the LVDCR0.LVMD hardware register values. */
 enum rcar_lvds_mode {
 	RCAR_LVDS_MODE_JEIDA = 0,
@@ -31,14 +33,16 @@ enum rcar_lvds_mode {
 	RCAR_LVDS_MODE_VESA = 4,
 };
 
-#define RCAR_LVDS_QUIRK_LANES	(1 << 0)	/* LVDS lanes 1 and 3 inverted */
-#define RCAR_LVDS_QUIRK_GEN2_PLLCR (1 << 1)	/* LVDPLLCR has gen2 layout */
-#define RCAR_LVDS_QUIRK_GEN3_LVEN (1 << 2)	/* LVEN bit needs to be set */
-						/* on R8A77970/R8A7799x */
+#define RCAR_LVDS_QUIRK_LANES		BIT(0)	/* LVDS lanes 1 and 3 inverted */
+#define RCAR_LVDS_QUIRK_GEN3_LVEN	BIT(1)	/* LVEN bit needs to be set on R8A77970/R8A7799x */
+#define RCAR_LVDS_QUIRK_PWD		BIT(2)	/* PWD bit available (all of Gen3 but E3) */
+#define RCAR_LVDS_QUIRK_EXT_PLL		BIT(3)	/* Has extended PLL */
+#define RCAR_LVDS_QUIRK_DUAL_LINK	BIT(4)	/* Supports dual-link operation */
 
 struct rcar_lvds_device_info {
 	unsigned int gen;
 	unsigned int quirks;
+	void (*pll_setup)(struct rcar_lvds *lvds, unsigned int freq);
 };
 
 struct rcar_lvds {
@@ -52,7 +56,11 @@ struct rcar_lvds {
 	struct drm_panel *panel;
 
 	void __iomem *mmio;
-	struct clk *clock;
+	struct {
+		struct clk *mod;		/* CPG module clock */
+		struct clk *extal;		/* External clock */
+		struct clk *dotclkin[2];	/* External DU clocks */
+	} clocks;
 	bool enabled;
 
 	struct drm_display_mode display_mode;
@@ -128,33 +136,222 @@ static const struct drm_connector_funcs rcar_lvds_conn_funcs = {
 };
 
 /* -----------------------------------------------------------------------------
- * Bridge
+ * PLL Setup
  */
 
-static u32 rcar_lvds_lvdpllcr_gen2(unsigned int freq)
+static void rcar_lvds_pll_setup_gen2(struct rcar_lvds *lvds, unsigned int freq)
+{
+	u32 val;
+
+	if (freq < 39000000)
+		val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
+	else if (freq < 61000000)
+		val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
+	else if (freq < 121000000)
+		val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
+	else
+		val = LVDPLLCR_PLLDLYCNT_150M;
+
+	rcar_lvds_write(lvds, LVDPLLCR, val);
+}
+
+static void rcar_lvds_pll_setup_gen3(struct rcar_lvds *lvds, unsigned int freq)
 {
-	if (freq < 39000)
-		return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
-	else if (freq < 61000)
-		return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
-	else if (freq < 121000)
-		return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
+	u32 val;
+
+	if (freq < 42000000)
+		val = LVDPLLCR_PLLDIVCNT_42M;
+	else if (freq < 85000000)
+		val = LVDPLLCR_PLLDIVCNT_85M;
+	else if (freq < 128000000)
+		val = LVDPLLCR_PLLDIVCNT_128M;
 	else
-		return LVDPLLCR_PLLDLYCNT_150M;
+		val = LVDPLLCR_PLLDIVCNT_148M;
+
+	rcar_lvds_write(lvds, LVDPLLCR, val);
+}
+
+struct pll_info {
+	struct clk *clk;
+	unsigned long diff;
+	unsigned int pll_m;
+	unsigned int pll_n;
+	unsigned int pll_e;
+	unsigned int div;
+};
+
+static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk,
+				     unsigned long target, struct pll_info *pll)
+{
+	unsigned long fin;
+	unsigned int m_min;
+	unsigned int m_max;
+	unsigned int m;
+
+	if (!clk)
+		return;
+
+	/*
+	 * The LVDS PLL is made of a pre-divider and a multiplier (strangerly
+	 * enough called M and N respectively), followed by a post-divider E.
+	 *
+	 *         ,-----.         ,-----.     ,-----.         ,-----.
+	 * Fin --> | 1/M | -Fpdf-> | PFD | --> | VCO | -Fvco-> | 1/E | --> Fout
+	 *         `-----'     ,-> |     |     `-----'   |     `-----'
+	 *                     |   `-----'               |
+	 *                     |         ,-----.         |
+	 *                     `-------- | 1/N | <-------'
+	 *                               `-----'
+	 *
+	 * The clock output by the PLL is then further divided by a programmable
+	 * divider DIV to achieve the desired target frequency. Finally, an
+	 * optional fixed /7 divider is used to convert the bit clock to a pixel
+	 * clock (as LVDS transmits 7 bits per lane per clock sample).
+	 *
+	 *          ,-------.     ,-----.     |\
+	 * Fout --> | 1/DIV | --> | 1/7 | --> | |
+	 *          `-------'  |  `-----'     | | --> dot clock
+	 *                     `------------> | |
+	 *                                    |/
+	 *
+	 * The /7 divider is optional when the LVDS PLL is used to generate a
+	 * dot clock for the DU RGB output, without using the LVDS encoder. We
+	 * don't support this configuration yet.
+	 *
+	 * The PLL allowed input frequency range is 12 MHz to 192 MHz.
+	 */
+
+	fin = clk_get_rate(clk);
+	if (fin < 12000000 || fin > 192000000)
+		return;
+
+	/*
+	 * The comparison frequency range is 12 MHz to 24 MHz, which limits the
+	 * allowed values for the pre-divider M (normal range 1-8).
+	 *
+	 * Fpfd = Fin / M
+	 */
+	m_min = max_t(unsigned int, 1, DIV_ROUND_UP(fin, 24000000));
+	m_max = min_t(unsigned int, 8, fin / 12000000);
+
+	for (m = m_min; m <= m_max; ++m) {
+		unsigned long fpfd;
+		unsigned int n_min;
+		unsigned int n_max;
+		unsigned int n;
+
+		/*
+		 * The VCO operating range is 900 Mhz to 1800 MHz, which limits
+		 * the allowed values for the multiplier N (normal range
+		 * 60-120).
+		 *
+		 * Fvco = Fin * N / M
+		 */
+		fpfd = fin / m;
+		n_min = max_t(unsigned int, 60, DIV_ROUND_UP(900000000, fpfd));
+		n_max = min_t(unsigned int, 120, 1800000000 / fpfd);
+
+		for (n = n_min; n < n_max; ++n) {
+			unsigned long fvco;
+			unsigned int e_min;
+			unsigned int e;
+
+			/*
+			 * The output frequency is limited to 1039.5 MHz,
+			 * limiting again the allowed values for the
+			 * post-divider E (normal value 1, 2 or 4).
+			 *
+			 * Fout = Fvco / E
+			 */
+			fvco = fpfd * n;
+			e_min = fvco > 1039500000 ? 1 : 0;
+
+			for (e = e_min; e < 3; ++e) {
+				unsigned long fout;
+				unsigned long diff;
+				unsigned int div;
+
+				/*
+				 * Finally we have a programable divider after
+				 * the PLL, followed by a an optional fixed /7
+				 * divider.
+				 */
+				fout = fvco / (1 << e) / 7;
+				div = DIV_ROUND_CLOSEST(fout, target);
+				diff = abs(fout / div - target);
+
+				if (diff < pll->diff) {
+					pll->clk = clk;
+					pll->diff = diff;
+					pll->pll_m = m;
+					pll->pll_n = n;
+					pll->pll_e = e;
+					pll->div = div;
+
+					if (diff == 0)
+						goto done;
+				}
+			}
+		}
+	}
+
+done:
+#if defined(CONFIG_DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
+	{
+		unsigned long output = fin * pll->pll_n / pll->pll_m
+				     / (1 << pll->pll_e) / 7 / pll->div;
+		int error = (long)(output - target) * 10000 / (long)target;
+
+		dev_dbg(lvds->dev,
+			"%pC %lu Hz -> Fout %lu Hz (target %lu Hz, error %d.%02u%%), PLL M/N/E/DIV %u/%u/%u/%u\n",
+			clk, fin, output, target, error / 100,
+			error < 0 ? -error % 100 : error % 100,
+			pll->pll_m, pll->pll_n, pll->pll_e, pll->div);
+	}
+#endif
 }
 
-static u32 rcar_lvds_lvdpllcr_gen3(unsigned int freq)
+static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned int freq)
 {
-	if (freq < 42000)
-		return LVDPLLCR_PLLDIVCNT_42M;
-	else if (freq < 85000)
-		return LVDPLLCR_PLLDIVCNT_85M;
-	else if (freq < 128000)
-		return LVDPLLCR_PLLDIVCNT_128M;
+	struct drm_crtc *crtc = lvds->bridge.encoder->crtc;
+	struct pll_info pll = { .diff = (unsigned long)-1 };
+	u32 lvdpllcr;
+
+	if (lvds->clocks.dotclkin[0] || lvds->clocks.dotclkin[1]) {
+		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[0],
+					 freq, &pll);
+		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[1],
+					 freq, &pll);
+	} else if (lvds->clocks.extal) {
+		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.extal,
+					 freq, &pll);
+	}
+
+	lvdpllcr = LVDPLLCR_PLLON | LVDPLLCR_CLKOUT
+		 | LVDPLLCR_PLLN(pll.pll_n - 1) | LVDPLLCR_PLLM(pll.pll_m - 1);
+
+	if (pll.clk == lvds->clocks.extal)
+		lvdpllcr |= LVDPLLCR_CKSEL_EXTAL;
+	else
+		lvdpllcr |= LVDPLLCR_CKSEL_DU_DOTCLKIN(drm_crtc_index(crtc));
+
+	if (pll.pll_e > 0)
+		lvdpllcr |= LVDPLLCR_STP_CLKOUTE | LVDPLLCR_OUTCLKSEL
+			 |  LVDPLLCR_PLLE(pll.pll_e - 1);
+
+	rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
+
+	if (pll.div > 1)
+		rcar_lvds_write(lvds, LVDDIV, LVDDIV_DIVSEL |
+				LVDDIV_DIVRESET | LVDDIV_DIV(pll.div - 1));
 	else
-		return LVDPLLCR_PLLDIVCNT_148M;
+		rcar_lvds_write(lvds, LVDDIV, 0);
 }
 
+/* -----------------------------------------------------------------------------
+ * Bridge
+ */
+
 static void rcar_lvds_enable(struct drm_bridge *bridge)
 {
 	struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
@@ -164,14 +361,13 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
 	 * do we get a state pointer?
 	 */
 	struct drm_crtc *crtc = lvds->bridge.encoder->crtc;
-	u32 lvdpllcr;
 	u32 lvdhcr;
 	u32 lvdcr0;
 	int ret;
 
 	WARN_ON(lvds->enabled);
 
-	ret = clk_prepare_enable(lvds->clock);
+	ret = clk_prepare_enable(lvds->clocks.mod);
 	if (ret < 0)
 		return;
 
@@ -196,12 +392,13 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
 
 	rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
 
+	if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) {
+		/* Disable dual-link mode. */
+		rcar_lvds_write(lvds, LVDSTRIPE, 0);
+	}
+
 	/* PLL clock configuration. */
-	if (lvds->info->quirks & RCAR_LVDS_QUIRK_GEN2_PLLCR)
-		lvdpllcr = rcar_lvds_lvdpllcr_gen2(mode->clock);
-	else
-		lvdpllcr = rcar_lvds_lvdpllcr_gen3(mode->clock);
-	rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
+	lvds->info->pll_setup(lvds, mode->clock * 1000);
 
 	/* Set the LVDS mode and select the input. */
 	lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT;
@@ -220,11 +417,16 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
 		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
 	}
 
-	/* Turn the PLL on. */
-	lvdcr0 |= LVDCR0_PLLON;
-	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
+	if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) {
+		/*
+		 * Turn the PLL on (simple PLL only, extended PLL is fully
+		 * controlled through LVDPLLCR).
+		 */
+		lvdcr0 |= LVDCR0_PLLON;
+		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
+	}
 
-	if (lvds->info->gen > 2) {
+	if (lvds->info->quirks & RCAR_LVDS_QUIRK_PWD) {
 		/* Set LVDS normal mode. */
 		lvdcr0 |= LVDCR0_PWD;
 		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
@@ -236,8 +438,10 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
 		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
 	}
 
-	/* Wait for the startup delay. */
-	usleep_range(100, 150);
+	if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) {
+		/* Wait for the PLL startup delay (simple PLL only). */
+		usleep_range(100, 150);
+	}
 
 	/* Turn the output on. */
 	lvdcr0 |= LVDCR0_LVRES;
@@ -264,8 +468,9 @@ static void rcar_lvds_disable(struct drm_bridge *bridge)
 
 	rcar_lvds_write(lvds, LVDCR0, 0);
 	rcar_lvds_write(lvds, LVDCR1, 0);
+	rcar_lvds_write(lvds, LVDPLLCR, 0);
 
-	clk_disable_unprepare(lvds->clock);
+	clk_disable_unprepare(lvds->clocks.mod);
 
 	lvds->enabled = false;
 }
@@ -446,6 +651,60 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
 	return ret;
 }
 
+static struct clk *rcar_lvds_get_clock(struct rcar_lvds *lvds, const char *name,
+				       bool optional)
+{
+	struct clk *clk;
+
+	clk = devm_clk_get(lvds->dev, name);
+	if (!IS_ERR(clk))
+		return clk;
+
+	if (PTR_ERR(clk) == -ENOENT && optional)
+		return NULL;
+
+	if (PTR_ERR(clk) != -EPROBE_DEFER)
+		dev_err(lvds->dev, "failed to get %s clock\n",
+			name ? name : "module");
+
+	return clk;
+}
+
+static int rcar_lvds_get_clocks(struct rcar_lvds *lvds)
+{
+	lvds->clocks.mod = rcar_lvds_get_clock(lvds, NULL, false);
+	if (IS_ERR(lvds->clocks.mod))
+		return PTR_ERR(lvds->clocks.mod);
+
+	/*
+	 * LVDS encoders without an extended PLL have no external clock inputs.
+	 */
+	if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL))
+		return 0;
+
+	lvds->clocks.extal = rcar_lvds_get_clock(lvds, "extal", true);
+	if (IS_ERR(lvds->clocks.extal))
+		return PTR_ERR(lvds->clocks.extal);
+
+	lvds->clocks.dotclkin[0] = rcar_lvds_get_clock(lvds, "dclkin.0", true);
+	if (IS_ERR(lvds->clocks.dotclkin[0]))
+		return PTR_ERR(lvds->clocks.dotclkin[0]);
+
+	lvds->clocks.dotclkin[1] = rcar_lvds_get_clock(lvds, "dclkin.1", true);
+	if (IS_ERR(lvds->clocks.dotclkin[1]))
+		return PTR_ERR(lvds->clocks.dotclkin[1]);
+
+	/* At least one input to the PLL must be available. */
+	if (!lvds->clocks.extal && !lvds->clocks.dotclkin[0] &&
+	    !lvds->clocks.dotclkin[1]) {
+		dev_err(lvds->dev,
+			"no input clock (extal, dclkin.0 or dclkin.1)\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int rcar_lvds_probe(struct platform_device *pdev)
 {
 	struct rcar_lvds *lvds;
@@ -475,11 +734,9 @@ static int rcar_lvds_probe(struct platform_device *pdev)
 	if (IS_ERR(lvds->mmio))
 		return PTR_ERR(lvds->mmio);
 
-	lvds->clock = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(lvds->clock)) {
-		dev_err(&pdev->dev, "failed to get clock\n");
-		return PTR_ERR(lvds->clock);
-	}
+	ret = rcar_lvds_get_clocks(lvds);
+	if (ret < 0)
+		return ret;
 
 	drm_bridge_add(&lvds->bridge);
 
@@ -497,21 +754,39 @@ static int rcar_lvds_remove(struct platform_device *pdev)
 
 static const struct rcar_lvds_device_info rcar_lvds_gen2_info = {
 	.gen = 2,
-	.quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR,
+	.pll_setup = rcar_lvds_pll_setup_gen2,
 };
 
 static const struct rcar_lvds_device_info rcar_lvds_r8a7790_info = {
 	.gen = 2,
-	.quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR | RCAR_LVDS_QUIRK_LANES,
+	.quirks = RCAR_LVDS_QUIRK_LANES,
+	.pll_setup = rcar_lvds_pll_setup_gen2,
 };
 
 static const struct rcar_lvds_device_info rcar_lvds_gen3_info = {
 	.gen = 3,
+	.quirks = RCAR_LVDS_QUIRK_PWD,
+	.pll_setup = rcar_lvds_pll_setup_gen3,
 };
 
 static const struct rcar_lvds_device_info rcar_lvds_r8a77970_info = {
 	.gen = 3,
-	.quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR | RCAR_LVDS_QUIRK_GEN3_LVEN,
+	.quirks = RCAR_LVDS_QUIRK_PWD | RCAR_LVDS_QUIRK_GEN3_LVEN,
+	.pll_setup = rcar_lvds_pll_setup_gen2,
+};
+
+static const struct rcar_lvds_device_info rcar_lvds_r8a77990_info = {
+	.gen = 3,
+	.quirks = RCAR_LVDS_QUIRK_GEN3_LVEN | RCAR_LVDS_QUIRK_EXT_PLL
+		| RCAR_LVDS_QUIRK_DUAL_LINK,
+	.pll_setup = rcar_lvds_pll_setup_d3_e3,
+};
+
+static const struct rcar_lvds_device_info rcar_lvds_r8a77995_info = {
+	.gen = 3,
+	.quirks = RCAR_LVDS_QUIRK_GEN3_LVEN | RCAR_LVDS_QUIRK_PWD
+		| RCAR_LVDS_QUIRK_EXT_PLL | RCAR_LVDS_QUIRK_DUAL_LINK,
+	.pll_setup = rcar_lvds_pll_setup_d3_e3,
 };
 
 static const struct of_device_id rcar_lvds_of_table[] = {
@@ -523,6 +798,8 @@ static const struct of_device_id rcar_lvds_of_table[] = {
 	{ .compatible = "renesas,r8a7796-lvds", .data = &rcar_lvds_gen3_info },
 	{ .compatible = "renesas,r8a77970-lvds", .data = &rcar_lvds_r8a77970_info },
 	{ .compatible = "renesas,r8a77980-lvds", .data = &rcar_lvds_gen3_info },
+	{ .compatible = "renesas,r8a77990-lvds", .data = &rcar_lvds_r8a77990_info },
+	{ .compatible = "renesas,r8a77995-lvds", .data = &rcar_lvds_r8a77995_info },
 	{ }
 };
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
index 4870f50d9bec..87149f2f8056 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_PLLON			(1 << 4)
 #define LVDCR0_PWD			(1 << 2)		/* Gen3 only */
 #define LVDCR0_BEN			(1 << 2)		/* Gen2 only */
-#define LVDCR0_LVEN			(1 << 1)		/* Gen2 only */
+#define LVDCR0_LVEN			(1 << 1)
 #define LVDCR0_LVRES			(1 << 0)
 
 #define LVDCR1				0x0004
@@ -27,21 +27,36 @@
 #define LVDCR1_CLKSTBY			(3 << 0)
 
 #define LVDPLLCR			0x0008
+/* Gen2 & V3M */
 #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 */
+/* Gen3 but V3M,D3 and E3 */
 #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)
+/* D3 and E3 */
+#define LVDPLLCR_PLLON			(1 << 22)
+#define LVDPLLCR_PLLSEL_PLL0		(0 << 20)
+#define LVDPLLCR_PLLSEL_LVX		(1 << 20)
+#define LVDPLLCR_PLLSEL_PLL1		(2 << 20)
+#define LVDPLLCR_CKSEL_LVX		(1 << 17)
+#define LVDPLLCR_CKSEL_EXTAL		(3 << 17)
+#define LVDPLLCR_CKSEL_DU_DOTCLKIN(n)	((5 + (n) * 2) << 17)
+#define LVDPLLCR_OCKSEL			(1 << 16)
+#define LVDPLLCR_STP_CLKOUTE		(1 << 14)
+#define LVDPLLCR_OUTCLKSEL		(1 << 12)
+#define LVDPLLCR_CLKOUT			(1 << 11)
+#define LVDPLLCR_PLLE(n)		((n) << 10)
+#define LVDPLLCR_PLLN(n)		((n) << 3)
+#define LVDPLLCR_PLLM(n)		((n) << 0)
 
 #define LVDCTRCR			0x000c
 #define LVDCTRCR_CTR3SEL_ZERO		(0 << 12)
@@ -71,4 +86,26 @@
 #define LVDCHCR_CHSEL_CH(n, c)		((((c) - (n)) & 3) << ((n) * 4))
 #define LVDCHCR_CHSEL_MASK(n)		(3 << ((n) * 4))
 
+/* All registers below are specific to D3 and E3 */
+#define LVDSTRIPE			0x0014
+#define LVDSTRIPE_ST_TRGSEL_DISP	(0 << 2)
+#define LVDSTRIPE_ST_TRGSEL_HSYNC_R	(1 << 2)
+#define LVDSTRIPE_ST_TRGSEL_HSYNC_F	(2 << 2)
+#define LVDSTRIPE_ST_SWAP		(1 << 1)
+#define LVDSTRIPE_ST_ON			(1 << 0)
+
+#define LVDSCR				0x0018
+#define LVDSCR_DEPTH(n)			(((n) - 1) << 29)
+#define LVDSCR_BANDSET			(1 << 28)
+#define LVDSCR_TWGCNT(n)		((((n) - 256) / 16) << 24)
+#define LVDSCR_SDIV(n)			((n) << 22)
+#define LVDSCR_MODE			(1 << 21)
+#define LVDSCR_RSTN			(1 << 20)
+
+#define LVDDIV				0x001c
+#define LVDDIV_DIVSEL			(1 << 8)
+#define LVDDIV_DIVRESET			(1 << 7)
+#define LVDDIV_DIVSTP			(1 << 6)
+#define LVDDIV_DIV(n)			((n) << 0)
+
 #endif /* __RCAR_LVDS_REGS_H__ */
-- 
Regards,

Laurent Pinchart

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

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

* [PATCH 06/16] drm: rcar-du: Perform the initial CRTC setup from rcar_du_crtc_get()
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-04 12:10   ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

The rcar_du_crtc_get() function is always immediately followed by a call
to rcar_du_crtc_setup(). Call the later from the former to simplify the
code, and add a comment to explain how the get and put calls are
balanced.

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

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 4c9572d7ea89..1d81eb244441 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -66,39 +66,6 @@ static void rcar_du_crtc_clr_set(struct rcar_du_crtc *rcrtc, u32 reg,
 	rcar_du_write(rcdu, rcrtc->mmio_offset + reg, (value & ~clr) | set);
 }
 
-static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
-{
-	int ret;
-
-	ret = clk_prepare_enable(rcrtc->clock);
-	if (ret < 0)
-		return ret;
-
-	ret = clk_prepare_enable(rcrtc->extclock);
-	if (ret < 0)
-		goto error_clock;
-
-	ret = rcar_du_group_get(rcrtc->group);
-	if (ret < 0)
-		goto error_group;
-
-	return 0;
-
-error_group:
-	clk_disable_unprepare(rcrtc->extclock);
-error_clock:
-	clk_disable_unprepare(rcrtc->clock);
-	return ret;
-}
-
-static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
-{
-	rcar_du_group_put(rcrtc->group);
-
-	clk_disable_unprepare(rcrtc->extclock);
-	clk_disable_unprepare(rcrtc->clock);
-}
-
 /* -----------------------------------------------------------------------------
  * Hardware Setup
  */
@@ -546,6 +513,51 @@ static void rcar_du_crtc_setup(struct rcar_du_crtc *rcrtc)
 	drm_crtc_vblank_on(&rcrtc->crtc);
 }
 
+static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
+{
+	int ret;
+
+	/*
+	 * Guard against double-get, as the function is called from both the
+	 * .atomic_enable() and .atomic_begin() handlers.
+	 */
+	if (rcrtc->initialized)
+		return 0;
+
+	ret = clk_prepare_enable(rcrtc->clock);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_prepare_enable(rcrtc->extclock);
+	if (ret < 0)
+		goto error_clock;
+
+	ret = rcar_du_group_get(rcrtc->group);
+	if (ret < 0)
+		goto error_group;
+
+	rcar_du_crtc_setup(rcrtc);
+	rcrtc->initialized = true;
+
+	return 0;
+
+error_group:
+	clk_disable_unprepare(rcrtc->extclock);
+error_clock:
+	clk_disable_unprepare(rcrtc->clock);
+	return ret;
+}
+
+static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
+{
+	rcar_du_group_put(rcrtc->group);
+
+	clk_disable_unprepare(rcrtc->extclock);
+	clk_disable_unprepare(rcrtc->clock);
+
+	rcrtc->initialized = false;
+}
+
 static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
 {
 	bool interlaced;
@@ -639,16 +651,7 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
 {
 	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
 
-	/*
-	 * If the CRTC has already been setup by the .atomic_begin() handler we
-	 * can skip the setup stage.
-	 */
-	if (!rcrtc->initialized) {
-		rcar_du_crtc_get(rcrtc);
-		rcar_du_crtc_setup(rcrtc);
-		rcrtc->initialized = true;
-	}
-
+	rcar_du_crtc_get(rcrtc);
 	rcar_du_crtc_start(rcrtc);
 }
 
@@ -667,7 +670,6 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
 	}
 	spin_unlock_irq(&crtc->dev->event_lock);
 
-	rcrtc->initialized = false;
 	rcrtc->outputs = 0;
 }
 
@@ -680,14 +682,17 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
 
 	/*
 	 * If a mode set is in progress we can be called with the CRTC disabled.
-	 * We then need to first setup the CRTC in order to configure planes.
-	 * The .atomic_enable() handler will notice and skip the CRTC setup.
+	 * We thus need to first get and setup the CRTC in order to configure
+	 * planes. We must *not* put the CRTC in .atomic_flush(), as it must be
+	 * kept awake until the .atomic_enable() call that will follow. The get
+	 * operation in .atomic_enable() will in that case be a no-op, and the
+	 * CRTC will be put later in .atomic_disable().
+	 *
+	 * If a mode set is not in progress the CRTC is enabled, and the
+	 * following get call will be a no-op. There is thus no need to belance
+	 * it in .atomic_flush() either.
 	 */
-	if (!rcrtc->initialized) {
-		rcar_du_crtc_get(rcrtc);
-		rcar_du_crtc_setup(rcrtc);
-		rcrtc->initialized = true;
-	}
+	rcar_du_crtc_get(rcrtc);
 
 	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
 		rcar_du_vsp_atomic_begin(rcrtc);
-- 
Regards,

Laurent Pinchart

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

* [PATCH 06/16] drm: rcar-du: Perform the initial CRTC setup from rcar_du_crtc_get()
@ 2018-09-04 12:10   ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

The rcar_du_crtc_get() function is always immediately followed by a call
to rcar_du_crtc_setup(). Call the later from the former to simplify the
code, and add a comment to explain how the get and put calls are
balanced.

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

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 4c9572d7ea89..1d81eb244441 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -66,39 +66,6 @@ static void rcar_du_crtc_clr_set(struct rcar_du_crtc *rcrtc, u32 reg,
 	rcar_du_write(rcdu, rcrtc->mmio_offset + reg, (value & ~clr) | set);
 }
 
-static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
-{
-	int ret;
-
-	ret = clk_prepare_enable(rcrtc->clock);
-	if (ret < 0)
-		return ret;
-
-	ret = clk_prepare_enable(rcrtc->extclock);
-	if (ret < 0)
-		goto error_clock;
-
-	ret = rcar_du_group_get(rcrtc->group);
-	if (ret < 0)
-		goto error_group;
-
-	return 0;
-
-error_group:
-	clk_disable_unprepare(rcrtc->extclock);
-error_clock:
-	clk_disable_unprepare(rcrtc->clock);
-	return ret;
-}
-
-static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
-{
-	rcar_du_group_put(rcrtc->group);
-
-	clk_disable_unprepare(rcrtc->extclock);
-	clk_disable_unprepare(rcrtc->clock);
-}
-
 /* -----------------------------------------------------------------------------
  * Hardware Setup
  */
@@ -546,6 +513,51 @@ static void rcar_du_crtc_setup(struct rcar_du_crtc *rcrtc)
 	drm_crtc_vblank_on(&rcrtc->crtc);
 }
 
+static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
+{
+	int ret;
+
+	/*
+	 * Guard against double-get, as the function is called from both the
+	 * .atomic_enable() and .atomic_begin() handlers.
+	 */
+	if (rcrtc->initialized)
+		return 0;
+
+	ret = clk_prepare_enable(rcrtc->clock);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_prepare_enable(rcrtc->extclock);
+	if (ret < 0)
+		goto error_clock;
+
+	ret = rcar_du_group_get(rcrtc->group);
+	if (ret < 0)
+		goto error_group;
+
+	rcar_du_crtc_setup(rcrtc);
+	rcrtc->initialized = true;
+
+	return 0;
+
+error_group:
+	clk_disable_unprepare(rcrtc->extclock);
+error_clock:
+	clk_disable_unprepare(rcrtc->clock);
+	return ret;
+}
+
+static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
+{
+	rcar_du_group_put(rcrtc->group);
+
+	clk_disable_unprepare(rcrtc->extclock);
+	clk_disable_unprepare(rcrtc->clock);
+
+	rcrtc->initialized = false;
+}
+
 static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
 {
 	bool interlaced;
@@ -639,16 +651,7 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
 {
 	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
 
-	/*
-	 * If the CRTC has already been setup by the .atomic_begin() handler we
-	 * can skip the setup stage.
-	 */
-	if (!rcrtc->initialized) {
-		rcar_du_crtc_get(rcrtc);
-		rcar_du_crtc_setup(rcrtc);
-		rcrtc->initialized = true;
-	}
-
+	rcar_du_crtc_get(rcrtc);
 	rcar_du_crtc_start(rcrtc);
 }
 
@@ -667,7 +670,6 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
 	}
 	spin_unlock_irq(&crtc->dev->event_lock);
 
-	rcrtc->initialized = false;
 	rcrtc->outputs = 0;
 }
 
@@ -680,14 +682,17 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
 
 	/*
 	 * If a mode set is in progress we can be called with the CRTC disabled.
-	 * We then need to first setup the CRTC in order to configure planes.
-	 * The .atomic_enable() handler will notice and skip the CRTC setup.
+	 * We thus need to first get and setup the CRTC in order to configure
+	 * planes. We must *not* put the CRTC in .atomic_flush(), as it must be
+	 * kept awake until the .atomic_enable() call that will follow. The get
+	 * operation in .atomic_enable() will in that case be a no-op, and the
+	 * CRTC will be put later in .atomic_disable().
+	 *
+	 * If a mode set is not in progress the CRTC is enabled, and the
+	 * following get call will be a no-op. There is thus no need to belance
+	 * it in .atomic_flush() either.
 	 */
-	if (!rcrtc->initialized) {
-		rcar_du_crtc_get(rcrtc);
-		rcar_du_crtc_setup(rcrtc);
-		rcrtc->initialized = true;
-	}
+	rcar_du_crtc_get(rcrtc);
 
 	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
 		rcar_du_vsp_atomic_begin(rcrtc);
-- 
Regards,

Laurent Pinchart

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

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

* [PATCH 07/16] drm: rcar-du: Use LVDS PLL clock as dot clock when possible
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-04 12:10   ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

On selected SoCs, the DU can use the clock output by the LVDS encoder
PLL as its input dot clock. This feature is optional, but on the D3 and
E3 SoC it is often the only way to obtain a precise dot clock frequency,
as the other available clocks (CPG-generated clock and external clock)
usually have fixed rates.

Add a DU model information field to describe which DU channels can use
the LVDS PLL output clock as their input clock, and configure clock
routing accordingly.

This feature is available on H2, M2-W, M2-N, D3 and E3 SoCs, with D3 and
E3 being the primary targets. It is left disabled in this commit, and
will be enabled per-SoC after careful testing.

At the hardware level, clock routing is configured at runtime in two
steps, first selecting an internal dot clock between the LVDS PLL clock
and the external DOTCLKIN clock, and then selecting between the internal
dot clock and the CPG-generated clock. The first part requires stopping
the whole DU group in order for the change to take effect, thus causing
flickering on the screen. For this reason we currently hardcode the
clock source the the LVDS PLL clock if available, and allow flicker-free
selection of the external DOTCLKIN clock or CPG-generated clock
otherwise. A more dynamic clock selection process can be implemented
later if the need arises.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  8 +++++
 drivers/gpu/drm/rcar-du/rcar_du_drv.h   |  2 ++
 drivers/gpu/drm/rcar-du/rcar_du_group.c | 64 +++++++++++++++++++++++++--------
 3 files changed, 59 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 1d81eb244441..39d2fee6d7b8 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -261,6 +261,14 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
 		rcar_du_group_write(rcrtc->group, DPLLCR, dpllcr);
 
 		escr = ESCR_DCLKSEL_DCLKIN | div;
+	} else if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) {
+		/*
+		 * Use the LVDS PLL output as the dot clock when outputting to
+		 * the LVDS encoder on an SoC that supports this clock routing
+		 * option. We use the clock directly in that case, without any
+		 * additional divider.
+		 */
+		escr = ESCR_DCLKSEL_DCLKIN;
 	} else {
 		struct du_clk_params params = { .diff = (unsigned long)-1 };
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index fef9ea5c22f3..ebba9aefba6a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -53,6 +53,7 @@ struct rcar_du_output_routing {
  * @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*)
  * @num_lvds: number of internal LVDS encoders
  * @dpll_mask: bit mask of DU channels equipped with a DPLL
+ * @lvds_clk_mask: bitmask of channels that can use the LVDS clock as dot clock
  */
 struct rcar_du_device_info {
 	unsigned int gen;
@@ -62,6 +63,7 @@ struct rcar_du_device_info {
 	struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX];
 	unsigned int num_lvds;
 	unsigned int dpll_mask;
+	unsigned int lvds_clk_mask;
 };
 
 #define RCAR_DU_MAX_CRTCS		4
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index ef2c177afb6d..4c62841eff2f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -89,6 +89,54 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 	rcar_du_group_write(rgrp, DEFR8, defr8);
 }
 
+static void rcar_du_group_setup_didsr(struct rcar_du_group *rgrp)
+{
+	struct rcar_du_device *rcdu = rgrp->dev;
+	struct rcar_du_crtc *rcrtc;
+	unsigned int num_crtcs = 0;
+	unsigned int i;
+	u32 didsr;
+
+	/*
+	 * Configure input dot clock routing with a hardcoded configuration. If
+	 * the DU channel can use the LVDS encoder output clock as the dot
+	 * clock, do so. Otherwise route DU_DOTCLKINn signal to DUn.
+	 *
+	 * Each channel can then select between the dot clock configured here
+	 * and the clock provided by the CPG through the ESCR register.
+	 */
+	if (rcdu->info->gen < 3 && rgrp->index == 0) {
+		/*
+		 * On Gen2 a single register in the first group controls dot
+		 * clock selection for all channels.
+		 */
+		rcrtc = rcdu->crtcs;
+		num_crtcs = rcdu->num_crtcs;
+	} else if (rcdu->info->gen == 3 && rgrp->num_crtcs > 1) {
+		/*
+		 * On Gen3 dot clocks are setup through per-group registers,
+		 * only available when the group has two channels.
+		 */
+		rcrtc = &rcdu->crtcs[rgrp->index * 2];
+		num_crtcs = rgrp->num_crtcs;
+	}
+
+	if (!num_crtcs)
+		return;
+
+	didsr = DIDSR_CODE;
+	for (i = 0; i < num_crtcs; ++i, ++rcrtc) {
+		if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index))
+			didsr |= DIDSR_LCDS_LVDS0(i)
+			      |  DIDSR_PDCS_CLK(i, 0);
+		else
+			didsr |= DIDSR_LCDS_DCLKIN(i)
+			      |  DIDSR_PDCS_CLK(i, 0);
+	}
+
+	rcar_du_group_write(rgrp, DIDSR, didsr);
+}
+
 static void rcar_du_group_setup(struct rcar_du_group *rgrp)
 {
 	struct rcar_du_device *rcdu = rgrp->dev;
@@ -106,21 +154,7 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
 
 	if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) {
 		rcar_du_group_setup_defr8(rgrp);
-
-		/*
-		 * Configure input dot clock routing. We currently hardcode the
-		 * configuration to routing DOTCLKINn to DUn. Register fields
-		 * depend on the DU generation, but the resulting value is 0 in
-		 * all cases.
-		 *
-		 * On Gen2 a single register in the first group controls dot
-		 * clock selection for all channels, while on Gen3 dot clocks
-		 * are setup through per-group registers, only available when
-		 * the group has two channels.
-		 */
-		if ((rcdu->info->gen < 3 && rgrp->index == 0) ||
-		    (rcdu->info->gen == 3 &&  rgrp->num_crtcs > 1))
-			rcar_du_group_write(rgrp, DIDSR, DIDSR_CODE);
+		rcar_du_group_setup_didsr(rgrp);
 	}
 
 	if (rcdu->info->gen >= 3)
-- 
Regards,

Laurent Pinchart

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

* [PATCH 07/16] drm: rcar-du: Use LVDS PLL clock as dot clock when possible
@ 2018-09-04 12:10   ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

On selected SoCs, the DU can use the clock output by the LVDS encoder
PLL as its input dot clock. This feature is optional, but on the D3 and
E3 SoC it is often the only way to obtain a precise dot clock frequency,
as the other available clocks (CPG-generated clock and external clock)
usually have fixed rates.

Add a DU model information field to describe which DU channels can use
the LVDS PLL output clock as their input clock, and configure clock
routing accordingly.

This feature is available on H2, M2-W, M2-N, D3 and E3 SoCs, with D3 and
E3 being the primary targets. It is left disabled in this commit, and
will be enabled per-SoC after careful testing.

At the hardware level, clock routing is configured at runtime in two
steps, first selecting an internal dot clock between the LVDS PLL clock
and the external DOTCLKIN clock, and then selecting between the internal
dot clock and the CPG-generated clock. The first part requires stopping
the whole DU group in order for the change to take effect, thus causing
flickering on the screen. For this reason we currently hardcode the
clock source the the LVDS PLL clock if available, and allow flicker-free
selection of the external DOTCLKIN clock or CPG-generated clock
otherwise. A more dynamic clock selection process can be implemented
later if the need arises.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  8 +++++
 drivers/gpu/drm/rcar-du/rcar_du_drv.h   |  2 ++
 drivers/gpu/drm/rcar-du/rcar_du_group.c | 64 +++++++++++++++++++++++++--------
 3 files changed, 59 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 1d81eb244441..39d2fee6d7b8 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -261,6 +261,14 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
 		rcar_du_group_write(rcrtc->group, DPLLCR, dpllcr);
 
 		escr = ESCR_DCLKSEL_DCLKIN | div;
+	} else if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) {
+		/*
+		 * Use the LVDS PLL output as the dot clock when outputting to
+		 * the LVDS encoder on an SoC that supports this clock routing
+		 * option. We use the clock directly in that case, without any
+		 * additional divider.
+		 */
+		escr = ESCR_DCLKSEL_DCLKIN;
 	} else {
 		struct du_clk_params params = { .diff = (unsigned long)-1 };
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index fef9ea5c22f3..ebba9aefba6a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -53,6 +53,7 @@ struct rcar_du_output_routing {
  * @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*)
  * @num_lvds: number of internal LVDS encoders
  * @dpll_mask: bit mask of DU channels equipped with a DPLL
+ * @lvds_clk_mask: bitmask of channels that can use the LVDS clock as dot clock
  */
 struct rcar_du_device_info {
 	unsigned int gen;
@@ -62,6 +63,7 @@ struct rcar_du_device_info {
 	struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX];
 	unsigned int num_lvds;
 	unsigned int dpll_mask;
+	unsigned int lvds_clk_mask;
 };
 
 #define RCAR_DU_MAX_CRTCS		4
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index ef2c177afb6d..4c62841eff2f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -89,6 +89,54 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 	rcar_du_group_write(rgrp, DEFR8, defr8);
 }
 
+static void rcar_du_group_setup_didsr(struct rcar_du_group *rgrp)
+{
+	struct rcar_du_device *rcdu = rgrp->dev;
+	struct rcar_du_crtc *rcrtc;
+	unsigned int num_crtcs = 0;
+	unsigned int i;
+	u32 didsr;
+
+	/*
+	 * Configure input dot clock routing with a hardcoded configuration. If
+	 * the DU channel can use the LVDS encoder output clock as the dot
+	 * clock, do so. Otherwise route DU_DOTCLKINn signal to DUn.
+	 *
+	 * Each channel can then select between the dot clock configured here
+	 * and the clock provided by the CPG through the ESCR register.
+	 */
+	if (rcdu->info->gen < 3 && rgrp->index == 0) {
+		/*
+		 * On Gen2 a single register in the first group controls dot
+		 * clock selection for all channels.
+		 */
+		rcrtc = rcdu->crtcs;
+		num_crtcs = rcdu->num_crtcs;
+	} else if (rcdu->info->gen == 3 && rgrp->num_crtcs > 1) {
+		/*
+		 * On Gen3 dot clocks are setup through per-group registers,
+		 * only available when the group has two channels.
+		 */
+		rcrtc = &rcdu->crtcs[rgrp->index * 2];
+		num_crtcs = rgrp->num_crtcs;
+	}
+
+	if (!num_crtcs)
+		return;
+
+	didsr = DIDSR_CODE;
+	for (i = 0; i < num_crtcs; ++i, ++rcrtc) {
+		if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index))
+			didsr |= DIDSR_LCDS_LVDS0(i)
+			      |  DIDSR_PDCS_CLK(i, 0);
+		else
+			didsr |= DIDSR_LCDS_DCLKIN(i)
+			      |  DIDSR_PDCS_CLK(i, 0);
+	}
+
+	rcar_du_group_write(rgrp, DIDSR, didsr);
+}
+
 static void rcar_du_group_setup(struct rcar_du_group *rgrp)
 {
 	struct rcar_du_device *rcdu = rgrp->dev;
@@ -106,21 +154,7 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
 
 	if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) {
 		rcar_du_group_setup_defr8(rgrp);
-
-		/*
-		 * Configure input dot clock routing. We currently hardcode the
-		 * configuration to routing DOTCLKINn to DUn. Register fields
-		 * depend on the DU generation, but the resulting value is 0 in
-		 * all cases.
-		 *
-		 * On Gen2 a single register in the first group controls dot
-		 * clock selection for all channels, while on Gen3 dot clocks
-		 * are setup through per-group registers, only available when
-		 * the group has two channels.
-		 */
-		if ((rcdu->info->gen < 3 && rgrp->index == 0) ||
-		    (rcdu->info->gen == 3 &&  rgrp->num_crtcs > 1))
-			rcar_du_group_write(rgrp, DIDSR, DIDSR_CODE);
+		rcar_du_group_setup_didsr(rgrp);
 	}
 
 	if (rcdu->info->gen >= 3)
-- 
Regards,

Laurent Pinchart

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

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

* [PATCH 08/16] drm: rcar-du: Enable configurable DPAD0 routing on Gen3
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-04 12:10   ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

All Gen3 SoCs supported so far have a fixed association between DPAD0
and DU channels, which led to hardcoding that association when writing
the corresponding hardware register. The D3 and E3 will break that
mechanism as DPAD0 can be dynamically connected to either DU0 or DU1.

Make DPAD0 routing dynamic on Gen3. To ensure a valid hardware
configuration when the DU starts without the RGB output enabled, DPAD0
is associated at initialization time to the first DU channel that it can
be connected to. This makes no change on Gen2 as all Gen2 SoCs can
connected DPAD0 to DU0, which is the current implicit default value.

As the DPAD0 source is always 0 when a single source is possible on
Gen2, we can also simplify the Gen2 code in the same function to remove
a conditional check.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_group.c | 17 ++++++-----------
 drivers/gpu/drm/rcar-du/rcar_du_kms.c   | 12 ++++++++++++
 2 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 4c62841eff2f..f38703e7a10d 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -56,8 +56,6 @@ static void rcar_du_group_setup_pins(struct rcar_du_group *rgrp)
 static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 {
 	struct rcar_du_device *rcdu = rgrp->dev;
-	unsigned int possible_crtcs =
-		rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;
 	u32 defr8 = DEFR8_CODE;
 
 	if (rcdu->info->gen < 3) {
@@ -69,21 +67,18 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 		 * DU instances that support it.
 		 */
 		if (rgrp->index == 0) {
-			if (possible_crtcs > 1)
-				defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source);
+			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.
+		 * On Gen3 VSPD routing can't be configured, and DPAD routing
+		 * is set in the group corresponding to the DPAD output (no Gen3
+		 * SoC has multiple DPAD sources belonging to separate groups).
 		 */
-		unsigned int rgb_crtc = ffs(possible_crtcs) - 1;
-		struct rcar_du_crtc *crtc = &rcdu->crtcs[rgb_crtc];
-
-		if (crtc->index / 2 == rgrp->index)
-			defr8 |= DEFR8_DRGBS_DU(crtc->index);
+		if (rgrp->index == rcdu->dpad0_source / 2)
+			defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source);
 	}
 
 	rcar_du_group_write(rgrp, DEFR8, defr8);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index ed7fa3204892..bd01197700c5 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -501,6 +501,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 	struct drm_device *dev = rcdu->ddev;
 	struct drm_encoder *encoder;
 	struct drm_fbdev_cma *fbdev;
+	unsigned int dpad0_sources;
 	unsigned int num_encoders;
 	unsigned int num_groups;
 	unsigned int swindex;
@@ -613,6 +614,17 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 		encoder->possible_clones = (1 << num_encoders) - 1;
 	}
 
+	/*
+	 * Initialize the default DPAD0 source to the index of the first DU
+	 * channel that can be connected to DPAD0. The exact value doesn't
+	 * matter as it should be overwritten by mode setting for the RGB
+	 * output, but it is nonetheless required to ensure a valid initial
+	 * hardware configuration on Gen3 where DU0 can't always be connected to
+	 * DPAD0.
+	 */
+	dpad0_sources = rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;
+	rcdu->dpad0_source = ffs(dpad0_sources) - 1;
+
 	drm_mode_config_reset(dev);
 
 	drm_kms_helper_poll_init(dev);
-- 
Regards,

Laurent Pinchart

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

* [PATCH 08/16] drm: rcar-du: Enable configurable DPAD0 routing on Gen3
@ 2018-09-04 12:10   ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

All Gen3 SoCs supported so far have a fixed association between DPAD0
and DU channels, which led to hardcoding that association when writing
the corresponding hardware register. The D3 and E3 will break that
mechanism as DPAD0 can be dynamically connected to either DU0 or DU1.

Make DPAD0 routing dynamic on Gen3. To ensure a valid hardware
configuration when the DU starts without the RGB output enabled, DPAD0
is associated at initialization time to the first DU channel that it can
be connected to. This makes no change on Gen2 as all Gen2 SoCs can
connected DPAD0 to DU0, which is the current implicit default value.

As the DPAD0 source is always 0 when a single source is possible on
Gen2, we can also simplify the Gen2 code in the same function to remove
a conditional check.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_group.c | 17 ++++++-----------
 drivers/gpu/drm/rcar-du/rcar_du_kms.c   | 12 ++++++++++++
 2 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 4c62841eff2f..f38703e7a10d 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -56,8 +56,6 @@ static void rcar_du_group_setup_pins(struct rcar_du_group *rgrp)
 static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 {
 	struct rcar_du_device *rcdu = rgrp->dev;
-	unsigned int possible_crtcs =
-		rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;
 	u32 defr8 = DEFR8_CODE;
 
 	if (rcdu->info->gen < 3) {
@@ -69,21 +67,18 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
 		 * DU instances that support it.
 		 */
 		if (rgrp->index == 0) {
-			if (possible_crtcs > 1)
-				defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source);
+			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.
+		 * On Gen3 VSPD routing can't be configured, and DPAD routing
+		 * is set in the group corresponding to the DPAD output (no Gen3
+		 * SoC has multiple DPAD sources belonging to separate groups).
 		 */
-		unsigned int rgb_crtc = ffs(possible_crtcs) - 1;
-		struct rcar_du_crtc *crtc = &rcdu->crtcs[rgb_crtc];
-
-		if (crtc->index / 2 == rgrp->index)
-			defr8 |= DEFR8_DRGBS_DU(crtc->index);
+		if (rgrp->index == rcdu->dpad0_source / 2)
+			defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source);
 	}
 
 	rcar_du_group_write(rgrp, DEFR8, defr8);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index ed7fa3204892..bd01197700c5 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -501,6 +501,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 	struct drm_device *dev = rcdu->ddev;
 	struct drm_encoder *encoder;
 	struct drm_fbdev_cma *fbdev;
+	unsigned int dpad0_sources;
 	unsigned int num_encoders;
 	unsigned int num_groups;
 	unsigned int swindex;
@@ -613,6 +614,17 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 		encoder->possible_clones = (1 << num_encoders) - 1;
 	}
 
+	/*
+	 * Initialize the default DPAD0 source to the index of the first DU
+	 * channel that can be connected to DPAD0. The exact value doesn't
+	 * matter as it should be overwritten by mode setting for the RGB
+	 * output, but it is nonetheless required to ensure a valid initial
+	 * hardware configuration on Gen3 where DU0 can't always be connected to
+	 * DPAD0.
+	 */
+	dpad0_sources = rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;
+	rcdu->dpad0_source = ffs(dpad0_sources) - 1;
+
 	drm_mode_config_reset(dev);
 
 	drm_kms_helper_poll_init(dev);
-- 
Regards,

Laurent Pinchart

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

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

* [PATCH 09/16] drm: rcar-du: Cache DSYSR value to ensure known initial value
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-04 12:10   ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

DSYSR is a DU channel register that also contains group fields. It is
thus written to by both the group and CRTC code, using read-update-write
sequences. As the register isn't initialized explicitly at startup time,
this can lead to invalid or otherwise unexpected values being written to
some of the fields if they have been modified by the firmware or just
not reset properly.

To fix this we can write a fully known value to the DSYSR register when
turning a channel's functional clock on. However, the mix of group and
channel fields complicate this. A simpler solution is to cache the
register and initialize the cached value to the desired hardware
defaults.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c  | 16 ++++++++--------
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h  |  5 +++++
 drivers/gpu/drm/rcar-du/rcar_du_group.c |  7 ++++---
 3 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 39d2fee6d7b8..1903e8e5e617 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -57,13 +57,12 @@ static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set)
 		      rcar_du_read(rcdu, rcrtc->mmio_offset + reg) | set);
 }
 
-static void rcar_du_crtc_clr_set(struct rcar_du_crtc *rcrtc, u32 reg,
-				 u32 clr, u32 set)
+void rcar_du_crtc_dsysr_clr_set(struct rcar_du_crtc *rcrtc, u32 clr, u32 set)
 {
 	struct rcar_du_device *rcdu = rcrtc->group->dev;
-	u32 value = rcar_du_read(rcdu, rcrtc->mmio_offset + reg);
 
-	rcar_du_write(rcdu, rcrtc->mmio_offset + reg, (value & ~clr) | set);
+	rcrtc->dsysr = (rcrtc->dsysr & ~clr) | set;
+	rcar_du_write(rcdu, rcrtc->mmio_offset + DSYSR, rcrtc->dsysr);
 }
 
 /* -----------------------------------------------------------------------------
@@ -576,9 +575,9 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
 	 * actively driven).
 	 */
 	interlaced = rcrtc->crtc.mode.flags & DRM_MODE_FLAG_INTERLACE;
-	rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK | DSYSR_SCM_MASK,
-			     (interlaced ? DSYSR_SCM_INT_VIDEO : 0) |
-			     DSYSR_TVM_MASTER);
+	rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_TVM_MASK | DSYSR_SCM_MASK,
+				   (interlaced ? DSYSR_SCM_INT_VIDEO : 0) |
+				   DSYSR_TVM_MASTER);
 
 	rcar_du_group_start_stop(rcrtc->group, true);
 }
@@ -645,7 +644,7 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
 	 * Select switch sync mode. This stops display operation and configures
 	 * the HSYNC and VSYNC signals as inputs.
 	 */
-	rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH);
+	rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH);
 
 	rcar_du_group_start_stop(rcrtc->group, false);
 }
@@ -1016,6 +1015,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
 	rcrtc->group = rgrp;
 	rcrtc->mmio_offset = mmio_offsets[hwindex];
 	rcrtc->index = hwindex;
+	rcrtc->dsysr = (rcrtc->index % 2 ? 0 : DSYSR_DRES) | DSYSR_TVM_TVSYNC;
 
 	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
 		primary = &rcrtc->vsp->planes[rcrtc->vsp_pipe].plane;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index f353a63d3ddf..5f0af21ce9e1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -30,6 +30,7 @@ struct rcar_du_vsp;
  * @mmio_offset: offset of the CRTC registers in the DU MMIO block
  * @index: CRTC software and hardware index
  * @initialized: whether the CRTC has been initialized and clocks enabled
+ * @dsysr: cached value of the DSYSR register
  * @vblank_enable: whether vblank events are enabled on this CRTC
  * @event: event to post when the pending page flip completes
  * @flip_wait: wait queue used to signal page flip completion
@@ -50,6 +51,8 @@ struct rcar_du_crtc {
 	unsigned int index;
 	bool initialized;
 
+	u32 dsysr;
+
 	bool vblank_enable;
 	struct drm_pending_vblank_event *event;
 	wait_queue_head_t flip_wait;
@@ -100,4 +103,6 @@ void rcar_du_crtc_route_output(struct drm_crtc *crtc,
 			       enum rcar_du_output output);
 void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc);
 
+void rcar_du_crtc_dsysr_clr_set(struct rcar_du_crtc *rcrtc, u32 clr, u32 set);
+
 #endif /* __RCAR_DU_CRTC_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index f38703e7a10d..d85f0a1c1581 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -202,9 +202,10 @@ void rcar_du_group_put(struct rcar_du_group *rgrp)
 
 static void __rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
 {
-	rcar_du_group_write(rgrp, DSYSR,
-		(rcar_du_group_read(rgrp, DSYSR) & ~(DSYSR_DRES | DSYSR_DEN)) |
-		(start ? DSYSR_DEN : DSYSR_DRES));
+	struct rcar_du_crtc *rcrtc = &rgrp->dev->crtcs[rgrp->index * 2];
+
+	rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_DRES | DSYSR_DEN,
+				   start ? DSYSR_DEN : DSYSR_DRES);
 }
 
 void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
-- 
Regards,

Laurent Pinchart

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

* [PATCH 09/16] drm: rcar-du: Cache DSYSR value to ensure known initial value
@ 2018-09-04 12:10   ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

DSYSR is a DU channel register that also contains group fields. It is
thus written to by both the group and CRTC code, using read-update-write
sequences. As the register isn't initialized explicitly at startup time,
this can lead to invalid or otherwise unexpected values being written to
some of the fields if they have been modified by the firmware or just
not reset properly.

To fix this we can write a fully known value to the DSYSR register when
turning a channel's functional clock on. However, the mix of group and
channel fields complicate this. A simpler solution is to cache the
register and initialize the cached value to the desired hardware
defaults.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c  | 16 ++++++++--------
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h  |  5 +++++
 drivers/gpu/drm/rcar-du/rcar_du_group.c |  7 ++++---
 3 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 39d2fee6d7b8..1903e8e5e617 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -57,13 +57,12 @@ static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set)
 		      rcar_du_read(rcdu, rcrtc->mmio_offset + reg) | set);
 }
 
-static void rcar_du_crtc_clr_set(struct rcar_du_crtc *rcrtc, u32 reg,
-				 u32 clr, u32 set)
+void rcar_du_crtc_dsysr_clr_set(struct rcar_du_crtc *rcrtc, u32 clr, u32 set)
 {
 	struct rcar_du_device *rcdu = rcrtc->group->dev;
-	u32 value = rcar_du_read(rcdu, rcrtc->mmio_offset + reg);
 
-	rcar_du_write(rcdu, rcrtc->mmio_offset + reg, (value & ~clr) | set);
+	rcrtc->dsysr = (rcrtc->dsysr & ~clr) | set;
+	rcar_du_write(rcdu, rcrtc->mmio_offset + DSYSR, rcrtc->dsysr);
 }
 
 /* -----------------------------------------------------------------------------
@@ -576,9 +575,9 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
 	 * actively driven).
 	 */
 	interlaced = rcrtc->crtc.mode.flags & DRM_MODE_FLAG_INTERLACE;
-	rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK | DSYSR_SCM_MASK,
-			     (interlaced ? DSYSR_SCM_INT_VIDEO : 0) |
-			     DSYSR_TVM_MASTER);
+	rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_TVM_MASK | DSYSR_SCM_MASK,
+				   (interlaced ? DSYSR_SCM_INT_VIDEO : 0) |
+				   DSYSR_TVM_MASTER);
 
 	rcar_du_group_start_stop(rcrtc->group, true);
 }
@@ -645,7 +644,7 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
 	 * Select switch sync mode. This stops display operation and configures
 	 * the HSYNC and VSYNC signals as inputs.
 	 */
-	rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH);
+	rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH);
 
 	rcar_du_group_start_stop(rcrtc->group, false);
 }
@@ -1016,6 +1015,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
 	rcrtc->group = rgrp;
 	rcrtc->mmio_offset = mmio_offsets[hwindex];
 	rcrtc->index = hwindex;
+	rcrtc->dsysr = (rcrtc->index % 2 ? 0 : DSYSR_DRES) | DSYSR_TVM_TVSYNC;
 
 	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
 		primary = &rcrtc->vsp->planes[rcrtc->vsp_pipe].plane;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index f353a63d3ddf..5f0af21ce9e1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -30,6 +30,7 @@ struct rcar_du_vsp;
  * @mmio_offset: offset of the CRTC registers in the DU MMIO block
  * @index: CRTC software and hardware index
  * @initialized: whether the CRTC has been initialized and clocks enabled
+ * @dsysr: cached value of the DSYSR register
  * @vblank_enable: whether vblank events are enabled on this CRTC
  * @event: event to post when the pending page flip completes
  * @flip_wait: wait queue used to signal page flip completion
@@ -50,6 +51,8 @@ struct rcar_du_crtc {
 	unsigned int index;
 	bool initialized;
 
+	u32 dsysr;
+
 	bool vblank_enable;
 	struct drm_pending_vblank_event *event;
 	wait_queue_head_t flip_wait;
@@ -100,4 +103,6 @@ void rcar_du_crtc_route_output(struct drm_crtc *crtc,
 			       enum rcar_du_output output);
 void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc);
 
+void rcar_du_crtc_dsysr_clr_set(struct rcar_du_crtc *rcrtc, u32 clr, u32 set);
+
 #endif /* __RCAR_DU_CRTC_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index f38703e7a10d..d85f0a1c1581 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -202,9 +202,10 @@ void rcar_du_group_put(struct rcar_du_group *rgrp)
 
 static void __rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
 {
-	rcar_du_group_write(rgrp, DSYSR,
-		(rcar_du_group_read(rgrp, DSYSR) & ~(DSYSR_DRES | DSYSR_DEN)) |
-		(start ? DSYSR_DEN : DSYSR_DRES));
+	struct rcar_du_crtc *rcrtc = &rgrp->dev->crtcs[rgrp->index * 2];
+
+	rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_DRES | DSYSR_DEN,
+				   start ? DSYSR_DEN : DSYSR_DRES);
 }
 
 void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
-- 
Regards,

Laurent Pinchart

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

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

* [PATCH 10/16] drm: rcar-du: Don't use TV sync mode when not supported by the hardware
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-04 12:10   ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

The official way to stop the display is to clear the display enable
(DEN) bit in the DSYSR register, but that operates at a group level and
affects the two channels in the group. To disable channels selectively,
the driver uses TV sync mode that stops display operation on the channel
and turns output signals into inputs.

While TV sync mode is available in all DU models currently supported,
the D3 and E3 DUs don't support it. We will thus need to find an
alternative way to turn channels off.

In the meantime, condition the switch to TV sync mode to the
availability of the feature, to avoid writing an invalid value to the
DSYSR register. The display output will turn blank as all planes are
disabled when stopping the CRTC.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c |  7 ++++++-
 drivers/gpu/drm/rcar-du/rcar_du_drv.c  | 33 ++++++++++++++++++++++-----------
 drivers/gpu/drm/rcar-du/rcar_du_drv.h  |  1 +
 3 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 1903e8e5e617..112c65ae7c99 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -643,8 +643,13 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
 	/*
 	 * Select switch sync mode. This stops display operation and configures
 	 * the HSYNC and VSYNC signals as inputs.
+	 *
+	 * TODO: Find another way to stop the display for DUs that don't support
+	 * TVM sync.
 	 */
-	rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH);
+	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_TVM_SYNC))
+		rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_TVM_MASK,
+					   DSYSR_TVM_SWITCH);
 
 	rcar_du_group_start_stop(rcrtc->group, false);
 }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 0954ecd2f943..fa0d381c2d0f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -36,7 +36,8 @@ static const struct rcar_du_device_info rzg1_du_r8a7743_info = {
 	.gen = 2,
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -58,7 +59,8 @@ static const struct rcar_du_device_info rzg1_du_r8a7745_info = {
 	.gen = 2,
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -77,7 +79,8 @@ static const struct rcar_du_device_info rzg1_du_r8a7745_info = {
 
 static const struct rcar_du_device_info rcar_du_r8a7779_info = {
 	.gen = 2,
-	.features = RCAR_DU_FEATURE_INTERLACED,
+	.features = RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -99,7 +102,8 @@ 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
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.quirks = RCAR_DU_QUIRK_ALIGN_128B,
 	.channels_mask = BIT(2) | BIT(1) | BIT(0),
 	.routes = {
@@ -128,7 +132,8 @@ 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
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -151,7 +156,8 @@ static const struct rcar_du_device_info rcar_du_r8a7792_info = {
 	.gen = 2,
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(1) | BIT(0),
 	.routes = {
 		/* R8A7792 has two RGB outputs. */
@@ -170,7 +176,8 @@ 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
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -193,7 +200,8 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = {
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
 		  | RCAR_DU_FEATURE_VSP1_SOURCE
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -226,7 +234,8 @@ static const struct rcar_du_device_info rcar_du_r8a7796_info = {
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
 		  | RCAR_DU_FEATURE_VSP1_SOURCE
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(2) | BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -255,7 +264,8 @@ static const struct rcar_du_device_info rcar_du_r8a77965_info = {
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
 		  | RCAR_DU_FEATURE_VSP1_SOURCE
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(3) | BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -284,7 +294,8 @@ static const struct rcar_du_device_info rcar_du_r8a77970_info = {
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
 		  | RCAR_DU_FEATURE_VSP1_SOURCE
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(0),
 	.routes = {
 		/* R8A77970 has one RGB output and one LVDS output. */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index ebba9aefba6a..143c037e2c0f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -27,6 +27,7 @@ struct rcar_du_device;
 #define RCAR_DU_FEATURE_EXT_CTRL_REGS	BIT(1)	/* Has extended control registers */
 #define RCAR_DU_FEATURE_VSP1_SOURCE	BIT(2)	/* Has inputs from VSP1 */
 #define RCAR_DU_FEATURE_INTERLACED	BIT(3)	/* HW supports interlaced */
+#define RCAR_DU_FEATURE_TVM_SYNC	BIT(4)	/* Has TV switch/sync modes */
 
 #define RCAR_DU_QUIRK_ALIGN_128B	BIT(0)	/* Align pitches to 128 bytes */
 
-- 
Regards,

Laurent Pinchart

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

* [PATCH 10/16] drm: rcar-du: Don't use TV sync mode when not supported by the hardware
@ 2018-09-04 12:10   ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

The official way to stop the display is to clear the display enable
(DEN) bit in the DSYSR register, but that operates at a group level and
affects the two channels in the group. To disable channels selectively,
the driver uses TV sync mode that stops display operation on the channel
and turns output signals into inputs.

While TV sync mode is available in all DU models currently supported,
the D3 and E3 DUs don't support it. We will thus need to find an
alternative way to turn channels off.

In the meantime, condition the switch to TV sync mode to the
availability of the feature, to avoid writing an invalid value to the
DSYSR register. The display output will turn blank as all planes are
disabled when stopping the CRTC.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c |  7 ++++++-
 drivers/gpu/drm/rcar-du/rcar_du_drv.c  | 33 ++++++++++++++++++++++-----------
 drivers/gpu/drm/rcar-du/rcar_du_drv.h  |  1 +
 3 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 1903e8e5e617..112c65ae7c99 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -643,8 +643,13 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
 	/*
 	 * Select switch sync mode. This stops display operation and configures
 	 * the HSYNC and VSYNC signals as inputs.
+	 *
+	 * TODO: Find another way to stop the display for DUs that don't support
+	 * TVM sync.
 	 */
-	rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH);
+	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_TVM_SYNC))
+		rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_TVM_MASK,
+					   DSYSR_TVM_SWITCH);
 
 	rcar_du_group_start_stop(rcrtc->group, false);
 }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 0954ecd2f943..fa0d381c2d0f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -36,7 +36,8 @@ static const struct rcar_du_device_info rzg1_du_r8a7743_info = {
 	.gen = 2,
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -58,7 +59,8 @@ static const struct rcar_du_device_info rzg1_du_r8a7745_info = {
 	.gen = 2,
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -77,7 +79,8 @@ static const struct rcar_du_device_info rzg1_du_r8a7745_info = {
 
 static const struct rcar_du_device_info rcar_du_r8a7779_info = {
 	.gen = 2,
-	.features = RCAR_DU_FEATURE_INTERLACED,
+	.features = RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -99,7 +102,8 @@ 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
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.quirks = RCAR_DU_QUIRK_ALIGN_128B,
 	.channels_mask = BIT(2) | BIT(1) | BIT(0),
 	.routes = {
@@ -128,7 +132,8 @@ 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
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -151,7 +156,8 @@ static const struct rcar_du_device_info rcar_du_r8a7792_info = {
 	.gen = 2,
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(1) | BIT(0),
 	.routes = {
 		/* R8A7792 has two RGB outputs. */
@@ -170,7 +176,8 @@ 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
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -193,7 +200,8 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = {
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
 		  | RCAR_DU_FEATURE_VSP1_SOURCE
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -226,7 +234,8 @@ static const struct rcar_du_device_info rcar_du_r8a7796_info = {
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
 		  | RCAR_DU_FEATURE_VSP1_SOURCE
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(2) | BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -255,7 +264,8 @@ static const struct rcar_du_device_info rcar_du_r8a77965_info = {
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
 		  | RCAR_DU_FEATURE_VSP1_SOURCE
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(3) | BIT(1) | BIT(0),
 	.routes = {
 		/*
@@ -284,7 +294,8 @@ static const struct rcar_du_device_info rcar_du_r8a77970_info = {
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
 		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
 		  | RCAR_DU_FEATURE_VSP1_SOURCE
-		  | RCAR_DU_FEATURE_INTERLACED,
+		  | RCAR_DU_FEATURE_INTERLACED
+		  | RCAR_DU_FEATURE_TVM_SYNC,
 	.channels_mask = BIT(0),
 	.routes = {
 		/* R8A77970 has one RGB output and one LVDS output. */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index ebba9aefba6a..143c037e2c0f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -27,6 +27,7 @@ struct rcar_du_device;
 #define RCAR_DU_FEATURE_EXT_CTRL_REGS	BIT(1)	/* Has extended control registers */
 #define RCAR_DU_FEATURE_VSP1_SOURCE	BIT(2)	/* Has inputs from VSP1 */
 #define RCAR_DU_FEATURE_INTERLACED	BIT(3)	/* HW supports interlaced */
+#define RCAR_DU_FEATURE_TVM_SYNC	BIT(4)	/* Has TV switch/sync modes */
 
 #define RCAR_DU_QUIRK_ALIGN_128B	BIT(0)	/* Align pitches to 128 bytes */
 
-- 
Regards,

Laurent Pinchart

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

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

* [PATCH 11/16] drm: rcar-du: Add r8a77990 and r8a77995 device support
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-04 12:10   ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Ulrich Hecht

From: Ulrich Hecht <uli+renesas@fpond.eu>

Add support for the R-Car D3 (R8A77995) and E3 (R8A77990) SoCs to the
R-Car DU driver. The two SoCs instantiate compatible DUs, so a single
information structure is enough.

Signed-off-by: Ulrich Hecht <uli+renesas@fpond.eu>
[Add support for R8A77990]
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_drv.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index fa0d381c2d0f..084f58df4a8c 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -311,6 +311,34 @@ static const struct rcar_du_device_info rcar_du_r8a77970_info = {
 	.num_lvds = 1,
 };
 
+static const struct rcar_du_device_info rcar_du_r8a7799x_info = {
+	.gen = 3,
+	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
+		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
+		  | RCAR_DU_FEATURE_VSP1_SOURCE,
+	.channels_mask = BIT(1) | BIT(0),
+	.routes = {
+		/*
+		 * R8A77990 and R8A77995 have one RGB output and two LVDS
+		 * outputs.
+		 */
+		[RCAR_DU_OUTPUT_DPAD0] = {
+			.possible_crtcs = BIT(0) | BIT(1),
+			.port = 0,
+		},
+		[RCAR_DU_OUTPUT_LVDS0] = {
+			.possible_crtcs = BIT(0),
+			.port = 1,
+		},
+		[RCAR_DU_OUTPUT_LVDS1] = {
+			.possible_crtcs = BIT(1),
+			.port = 2,
+		},
+	},
+	.num_lvds = 2,
+	.lvds_clk_mask =  BIT(1) | BIT(0),
+};
+
 static const struct of_device_id rcar_du_of_table[] = {
 	{ .compatible = "renesas,du-r8a7743", .data = &rzg1_du_r8a7743_info },
 	{ .compatible = "renesas,du-r8a7745", .data = &rzg1_du_r8a7745_info },
@@ -324,6 +352,8 @@ static const struct of_device_id rcar_du_of_table[] = {
 	{ .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info },
 	{ .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info },
 	{ .compatible = "renesas,du-r8a77970", .data = &rcar_du_r8a77970_info },
+	{ .compatible = "renesas,du-r8a77990", .data = &rcar_du_r8a7799x_info },
+	{ .compatible = "renesas,du-r8a77995", .data = &rcar_du_r8a7799x_info },
 	{ }
 };
 
-- 
Regards,

Laurent Pinchart

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

* [PATCH 11/16] drm: rcar-du: Add r8a77990 and r8a77995 device support
@ 2018-09-04 12:10   ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Ulrich Hecht

From: Ulrich Hecht <uli+renesas@fpond.eu>

Add support for the R-Car D3 (R8A77995) and E3 (R8A77990) SoCs to the
R-Car DU driver. The two SoCs instantiate compatible DUs, so a single
information structure is enough.

Signed-off-by: Ulrich Hecht <uli+renesas@fpond.eu>
[Add support for R8A77990]
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_drv.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index fa0d381c2d0f..084f58df4a8c 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -311,6 +311,34 @@ static const struct rcar_du_device_info rcar_du_r8a77970_info = {
 	.num_lvds = 1,
 };
 
+static const struct rcar_du_device_info rcar_du_r8a7799x_info = {
+	.gen = 3,
+	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
+		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
+		  | RCAR_DU_FEATURE_VSP1_SOURCE,
+	.channels_mask = BIT(1) | BIT(0),
+	.routes = {
+		/*
+		 * R8A77990 and R8A77995 have one RGB output and two LVDS
+		 * outputs.
+		 */
+		[RCAR_DU_OUTPUT_DPAD0] = {
+			.possible_crtcs = BIT(0) | BIT(1),
+			.port = 0,
+		},
+		[RCAR_DU_OUTPUT_LVDS0] = {
+			.possible_crtcs = BIT(0),
+			.port = 1,
+		},
+		[RCAR_DU_OUTPUT_LVDS1] = {
+			.possible_crtcs = BIT(1),
+			.port = 2,
+		},
+	},
+	.num_lvds = 2,
+	.lvds_clk_mask =  BIT(1) | BIT(0),
+};
+
 static const struct of_device_id rcar_du_of_table[] = {
 	{ .compatible = "renesas,du-r8a7743", .data = &rzg1_du_r8a7743_info },
 	{ .compatible = "renesas,du-r8a7745", .data = &rzg1_du_r8a7745_info },
@@ -324,6 +352,8 @@ static const struct of_device_id rcar_du_of_table[] = {
 	{ .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info },
 	{ .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info },
 	{ .compatible = "renesas,du-r8a77970", .data = &rcar_du_r8a77970_info },
+	{ .compatible = "renesas,du-r8a77990", .data = &rcar_du_r8a7799x_info },
+	{ .compatible = "renesas,du-r8a77995", .data = &rcar_du_r8a7799x_info },
 	{ }
 };
 
-- 
Regards,

Laurent Pinchart

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

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

* [PATCH 12/16] arm64: dts: renesas: r8a77990: Add I2C device nodes
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-04 12:10   ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Takeshi Kihara

From: Takeshi Kihara <takeshi.kihara.df@renesas.com>

Add device nodes for I2C ch{0,1,2,3,4,5,6,7} to R-Car E3 R8A77990 device
tree.

Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
---
 arch/arm64/boot/dts/renesas/r8a77990.dtsi | 123 ++++++++++++++++++++++++++++++
 1 file changed, 123 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
index ae89260baad9..abb14af76c0e 100644
--- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
@@ -14,6 +14,17 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		i2c4 = &i2c4;
+		i2c5 = &i2c5;
+		i2c6 = &i2c6;
+		i2c7 = &i2c7;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -185,6 +196,118 @@
 			resets = <&cpg 906>;
 		};
 
+		i2c0: i2c@e6500000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a77990",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe6500000 0 0x40>;
+			interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 931>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 931>;
+			i2c-scl-internal-delay-ns = <110>;
+			status = "disabled";
+		};
+
+		i2c1: i2c@e6508000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a77990",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe6508000 0 0x40>;
+			interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 930>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 930>;
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
+		i2c2: i2c@e6510000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a77990",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe6510000 0 0x40>;
+			interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 929>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 929>;
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
+		i2c3: i2c@e66d0000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a77990",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe66d0000 0 0x40>;
+			interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 928>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 928>;
+			i2c-scl-internal-delay-ns = <110>;
+			status = "disabled";
+		};
+
+		i2c4: i2c@e66d8000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a77990",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe66d8000 0 0x40>;
+			interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 927>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 927>;
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
+		i2c5: i2c@e66e0000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a77990",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe66e0000 0 0x40>;
+			interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 919>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 919>;
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
+		i2c6: i2c@e66e8000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a77990",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe66e8000 0 0x40>;
+			interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 918>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 918>;
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
+		i2c7: i2c@e6690000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a77990",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe6690000 0 0x40>;
+			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 1003>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 1003>;
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
 		pfc: pin-controller@e6060000 {
 			compatible = "renesas,pfc-r8a77990";
 			reg = <0 0xe6060000 0 0x508>;
-- 
Regards,

Laurent Pinchart

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

* [PATCH 12/16] arm64: dts: renesas: r8a77990: Add I2C device nodes
@ 2018-09-04 12:10   ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Takeshi Kihara

From: Takeshi Kihara <takeshi.kihara.df@renesas.com>

Add device nodes for I2C ch{0,1,2,3,4,5,6,7} to R-Car E3 R8A77990 device
tree.

Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
---
 arch/arm64/boot/dts/renesas/r8a77990.dtsi | 123 ++++++++++++++++++++++++++++++
 1 file changed, 123 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
index ae89260baad9..abb14af76c0e 100644
--- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
@@ -14,6 +14,17 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		i2c4 = &i2c4;
+		i2c5 = &i2c5;
+		i2c6 = &i2c6;
+		i2c7 = &i2c7;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -185,6 +196,118 @@
 			resets = <&cpg 906>;
 		};
 
+		i2c0: i2c@e6500000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a77990",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe6500000 0 0x40>;
+			interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 931>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 931>;
+			i2c-scl-internal-delay-ns = <110>;
+			status = "disabled";
+		};
+
+		i2c1: i2c@e6508000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a77990",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe6508000 0 0x40>;
+			interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 930>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 930>;
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
+		i2c2: i2c@e6510000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a77990",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe6510000 0 0x40>;
+			interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 929>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 929>;
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
+		i2c3: i2c@e66d0000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a77990",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe66d0000 0 0x40>;
+			interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 928>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 928>;
+			i2c-scl-internal-delay-ns = <110>;
+			status = "disabled";
+		};
+
+		i2c4: i2c@e66d8000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a77990",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe66d8000 0 0x40>;
+			interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 927>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 927>;
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
+		i2c5: i2c@e66e0000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a77990",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe66e0000 0 0x40>;
+			interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 919>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 919>;
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
+		i2c6: i2c@e66e8000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a77990",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe66e8000 0 0x40>;
+			interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 918>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 918>;
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
+		i2c7: i2c@e6690000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a77990",
+				     "renesas,rcar-gen3-i2c";
+			reg = <0 0xe6690000 0 0x40>;
+			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 1003>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 1003>;
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
 		pfc: pin-controller@e6060000 {
 			compatible = "renesas,pfc-r8a77990";
 			reg = <0 0xe6060000 0 0x508>;
-- 
Regards,

Laurent Pinchart

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

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

* [PATCH 13/16] arm64: dts: renesas: r8a77990: Add display output support
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-04 12:10   ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

The R8A77990 (E3) platform has one RGB output and two LVDS outputs
connected to the DU. Add the DT nodes for the DU, LVDS encoders and
supporting VSP and FCP.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm64/boot/dts/renesas/r8a77990.dtsi | 167 ++++++++++++++++++++++++++++++
 1 file changed, 167 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
index abb14af76c0e..600074ca3ee5 100644
--- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
@@ -537,6 +537,173 @@
 			resets = <&cpg 408>;
 		};
 
+		vspb0: vsp@fe960000 {
+			compatible = "renesas,vsp2";
+			reg = <0 0xfe960000 0 0x8000>;
+			interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 626>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 626>;
+			renesas,fcp = <&fcpvb0>;
+		};
+
+		fcpvb0: fcp@fe96f000 {
+			compatible = "renesas,fcpv";
+			reg = <0 0xfe96f000 0 0x200>;
+			clocks = <&cpg CPG_MOD 607>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 607>;
+			iommus = <&ipmmu_vp0 5>;
+		};
+
+		vspi0: vsp@fe9a0000 {
+			compatible = "renesas,vsp2";
+			reg = <0 0xfe9a0000 0 0x8000>;
+			interrupts = <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 622>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 631>;
+			renesas,fcp = <&fcpvi0>;
+		};
+
+		fcpvi0: fcp@fe9af000 {
+			compatible = "renesas,fcpv";
+			reg = <0 0xfe9af000 0 0x200>;
+			clocks = <&cpg CPG_MOD 611>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 611>;
+			iommus = <&ipmmu_vp0 8>;
+		};
+
+		vspd0: vsp@fea20000 {
+			compatible = "renesas,vsp2";
+			reg = <0 0xfea20000 0 0x7000>;
+			interrupts = <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 623>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 623>;
+			renesas,fcp = <&fcpvd0>;
+		};
+
+		fcpvd0: fcp@fea27000 {
+			compatible = "renesas,fcpv";
+			reg = <0 0xfea27000 0 0x200>;
+			clocks = <&cpg CPG_MOD 603>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 603>;
+			iommus = <&ipmmu_vi0 8>;
+		};
+
+		vspd1: vsp@fea28000 {
+			compatible = "renesas,vsp2";
+			reg = <0 0xfea28000 0 0x7000>;
+			interrupts = <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 622>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 622>;
+			renesas,fcp = <&fcpvd1>;
+		};
+
+		fcpvd1: fcp@fea2f000 {
+			compatible = "renesas,fcpv";
+			reg = <0 0xfea2f000 0 0x200>;
+			clocks = <&cpg CPG_MOD 602>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 602>;
+			iommus = <&ipmmu_vi0 9>;
+		};
+
+		du: display@feb00000 {
+			compatible = "renesas,du-r8a77990";
+			reg = <0 0xfeb00000 0 0x80000>;
+			interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 724>,
+				 <&cpg CPG_MOD 723>;
+			clock-names = "du.0", "du.1";
+			vsps = <&vspd0 0 &vspd1 0>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					du_out_rgb: endpoint {
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					du_out_lvds0: endpoint {
+						remote-endpoint = <&lvds0_in>;
+					};
+				};
+
+				port@2 {
+					reg = <2>;
+					du_out_lvds1: endpoint {
+						remote-endpoint = <&lvds1_in>;
+					};
+				};
+			};
+		};
+
+		lvds0: lvds-encoder@feb90000 {
+			compatible = "renesas,r8a77990-lvds";
+			reg = <0 0xfeb90000 0 0x20>;
+			clocks = <&cpg CPG_MOD 727>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 727>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					lvds0_in: endpoint {
+						remote-endpoint = <&du_out_lvds0>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					lvds0_out: endpoint {
+					};
+				};
+			};
+		};
+
+		lvds1: lvds-encoder@feb90100 {
+			compatible = "renesas,r8a77990-lvds";
+			reg = <0 0xfeb90100 0 0x20>;
+			clocks = <&cpg CPG_MOD 727>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 726>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					lvds1_in: endpoint {
+						remote-endpoint = <&du_out_lvds1>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					lvds1_out: endpoint {
+					};
+				};
+			};
+		};
+
 		prr: chipid@fff00044 {
 			compatible = "renesas,prr";
 			reg = <0 0xfff00044 0 4>;
-- 
Regards,

Laurent Pinchart

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

* [PATCH 13/16] arm64: dts: renesas: r8a77990: Add display output support
@ 2018-09-04 12:10   ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

The R8A77990 (E3) platform has one RGB output and two LVDS outputs
connected to the DU. Add the DT nodes for the DU, LVDS encoders and
supporting VSP and FCP.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm64/boot/dts/renesas/r8a77990.dtsi | 167 ++++++++++++++++++++++++++++++
 1 file changed, 167 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
index abb14af76c0e..600074ca3ee5 100644
--- a/arch/arm64/boot/dts/renesas/r8a77990.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
@@ -537,6 +537,173 @@
 			resets = <&cpg 408>;
 		};
 
+		vspb0: vsp@fe960000 {
+			compatible = "renesas,vsp2";
+			reg = <0 0xfe960000 0 0x8000>;
+			interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 626>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 626>;
+			renesas,fcp = <&fcpvb0>;
+		};
+
+		fcpvb0: fcp@fe96f000 {
+			compatible = "renesas,fcpv";
+			reg = <0 0xfe96f000 0 0x200>;
+			clocks = <&cpg CPG_MOD 607>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 607>;
+			iommus = <&ipmmu_vp0 5>;
+		};
+
+		vspi0: vsp@fe9a0000 {
+			compatible = "renesas,vsp2";
+			reg = <0 0xfe9a0000 0 0x8000>;
+			interrupts = <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 622>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 631>;
+			renesas,fcp = <&fcpvi0>;
+		};
+
+		fcpvi0: fcp@fe9af000 {
+			compatible = "renesas,fcpv";
+			reg = <0 0xfe9af000 0 0x200>;
+			clocks = <&cpg CPG_MOD 611>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 611>;
+			iommus = <&ipmmu_vp0 8>;
+		};
+
+		vspd0: vsp@fea20000 {
+			compatible = "renesas,vsp2";
+			reg = <0 0xfea20000 0 0x7000>;
+			interrupts = <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 623>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 623>;
+			renesas,fcp = <&fcpvd0>;
+		};
+
+		fcpvd0: fcp@fea27000 {
+			compatible = "renesas,fcpv";
+			reg = <0 0xfea27000 0 0x200>;
+			clocks = <&cpg CPG_MOD 603>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 603>;
+			iommus = <&ipmmu_vi0 8>;
+		};
+
+		vspd1: vsp@fea28000 {
+			compatible = "renesas,vsp2";
+			reg = <0 0xfea28000 0 0x7000>;
+			interrupts = <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 622>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 622>;
+			renesas,fcp = <&fcpvd1>;
+		};
+
+		fcpvd1: fcp@fea2f000 {
+			compatible = "renesas,fcpv";
+			reg = <0 0xfea2f000 0 0x200>;
+			clocks = <&cpg CPG_MOD 602>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 602>;
+			iommus = <&ipmmu_vi0 9>;
+		};
+
+		du: display@feb00000 {
+			compatible = "renesas,du-r8a77990";
+			reg = <0 0xfeb00000 0 0x80000>;
+			interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 724>,
+				 <&cpg CPG_MOD 723>;
+			clock-names = "du.0", "du.1";
+			vsps = <&vspd0 0 &vspd1 0>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					du_out_rgb: endpoint {
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					du_out_lvds0: endpoint {
+						remote-endpoint = <&lvds0_in>;
+					};
+				};
+
+				port@2 {
+					reg = <2>;
+					du_out_lvds1: endpoint {
+						remote-endpoint = <&lvds1_in>;
+					};
+				};
+			};
+		};
+
+		lvds0: lvds-encoder@feb90000 {
+			compatible = "renesas,r8a77990-lvds";
+			reg = <0 0xfeb90000 0 0x20>;
+			clocks = <&cpg CPG_MOD 727>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 727>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					lvds0_in: endpoint {
+						remote-endpoint = <&du_out_lvds0>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					lvds0_out: endpoint {
+					};
+				};
+			};
+		};
+
+		lvds1: lvds-encoder@feb90100 {
+			compatible = "renesas,r8a77990-lvds";
+			reg = <0 0xfeb90100 0 0x20>;
+			clocks = <&cpg CPG_MOD 727>;
+			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+			resets = <&cpg 726>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					lvds1_in: endpoint {
+						remote-endpoint = <&du_out_lvds1>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					lvds1_out: endpoint {
+					};
+				};
+			};
+		};
+
 		prr: chipid@fff00044 {
 			compatible = "renesas,prr";
 			reg = <0 0xfff00044 0 4>;
-- 
Regards,

Laurent Pinchart

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

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

* [PATCH 14/16] arm64: dts: renesas: r8a77995: Add LVDS support
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-04 12:10   ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Kieran Bingham

From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

The r8a77995 D3 platform has 2 LVDS channels connected to the DU.

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
[uli: moved lvds* into the soc node, added PM domains, resets]
Signed-off-by: Ulrich Hecht <uli+renesas@fpond.eu>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 arch/arm64/boot/dts/renesas/r8a77995.dtsi | 56 +++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
index fe77bc43c447..32c473143b19 100644
--- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
@@ -960,12 +960,68 @@
 				port@1 {
 					reg = <1>;
 					du_out_lvds0: endpoint {
+						remote-endpoint = <&lvds0_in>;
 					};
 				};
 
 				port@2 {
 					reg = <2>;
 					du_out_lvds1: endpoint {
+						remote-endpoint = <&lvds1_in>;
+					};
+				};
+			};
+		};
+
+		lvds0: lvds-encoder@feb90000 {
+			compatible = "renesas,r8a77995-lvds";
+			reg = <0 0xfeb90000 0 0x20>;
+			clocks = <&cpg CPG_MOD 727>;
+			power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+			resets = <&cpg 727>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					lvds0_in: endpoint {
+						remote-endpoint = <&du_out_lvds0>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					lvds0_out: endpoint {
+					};
+				};
+			};
+		};
+
+		lvds1: lvds-encoder@feb90100 {
+			compatible = "renesas,r8a77995-lvds";
+			reg = <0 0xfeb90100 0 0x20>;
+			clocks = <&cpg CPG_MOD 727>;
+			power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+			resets = <&cpg 726>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					lvds1_in: endpoint {
+						remote-endpoint = <&du_out_lvds1>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					lvds1_out: endpoint {
 					};
 				};
 			};
-- 
Regards,

Laurent Pinchart

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

* [PATCH 14/16] arm64: dts: renesas: r8a77995: Add LVDS support
@ 2018-09-04 12:10   ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Kieran Bingham

From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

The r8a77995 D3 platform has 2 LVDS channels connected to the DU.

Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
[uli: moved lvds* into the soc node, added PM domains, resets]
Signed-off-by: Ulrich Hecht <uli+renesas@fpond.eu>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 arch/arm64/boot/dts/renesas/r8a77995.dtsi | 56 +++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
index fe77bc43c447..32c473143b19 100644
--- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
@@ -960,12 +960,68 @@
 				port@1 {
 					reg = <1>;
 					du_out_lvds0: endpoint {
+						remote-endpoint = <&lvds0_in>;
 					};
 				};
 
 				port@2 {
 					reg = <2>;
 					du_out_lvds1: endpoint {
+						remote-endpoint = <&lvds1_in>;
+					};
+				};
+			};
+		};
+
+		lvds0: lvds-encoder@feb90000 {
+			compatible = "renesas,r8a77995-lvds";
+			reg = <0 0xfeb90000 0 0x20>;
+			clocks = <&cpg CPG_MOD 727>;
+			power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+			resets = <&cpg 727>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					lvds0_in: endpoint {
+						remote-endpoint = <&du_out_lvds0>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					lvds0_out: endpoint {
+					};
+				};
+			};
+		};
+
+		lvds1: lvds-encoder@feb90100 {
+			compatible = "renesas,r8a77995-lvds";
+			reg = <0 0xfeb90100 0 0x20>;
+			clocks = <&cpg CPG_MOD 727>;
+			power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+			resets = <&cpg 726>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					lvds1_in: endpoint {
+						remote-endpoint = <&du_out_lvds1>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					lvds1_out: endpoint {
 					};
 				};
 			};
-- 
Regards,

Laurent Pinchart

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

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

* [PATCH 15/16] arm64: dts: renesas: r8a77990: ebisu: Enable VGA and HDMI outputs
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-04 12:10   ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

Add the LVDS decoder, HDMI encoder, VGA encoder and HDMI and VGA
connectors, and wire up the display-related nodes with clocks, pinmux
and regulators.

The LVDS0 and LVDS1 encoders can use the DU_DOTCLKIN0, DU_DOTCLKIN1 and
EXTAL externals clocks. Two of them are provided to the SoC on the Ebisu
board, hook them up in DT.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts | 166 +++++++++++++++++++++++++
 1 file changed, 166 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
index 2bc3a4884b00..772ea8843d84 100644
--- a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
@@ -28,6 +28,88 @@
 		/* first 128MB is reserved for secure area. */
 		reg = <0x0 0x48000000 0x0 0x38000000>;
 	};
+
+	hdmi-out {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_con_out: endpoint {
+				remote-endpoint = <&adv7511_out>;
+			};
+		};
+	};
+
+	lvds-decoder {
+		compatible = "thine,thc63lvd1024";
+		vcc-supply = <&reg_3p3v>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				thc63lvd1024_in: endpoint {
+					remote-endpoint = <&lvds0_out>;
+				};
+			};
+
+			port@2 {
+				reg = <2>;
+				thc63lvd1024_out: endpoint {
+					remote-endpoint = <&adv7511_in>;
+				};
+			};
+		};
+	};
+
+	vga {
+		compatible = "vga-connector";
+
+		port {
+			vga_in: endpoint {
+				remote-endpoint = <&adv7123_out>;
+			};
+		};
+	};
+
+	vga-encoder {
+		compatible = "adi,adv7123";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				adv7123_in: endpoint {
+					remote-endpoint = <&du_out_rgb>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+				adv7123_out: endpoint {
+					remote-endpoint = <&vga_in>;
+				};
+			};
+		};
+	};
+
+	reg_3p3v: regulator1 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	x13_clk: x13 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <74250000>;
+	};
 };
 
 &avb {
@@ -47,6 +129,25 @@
 	};
 };
 
+&du {
+	pinctrl-0 = <&du_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	clocks = <&cpg CPG_MOD 724>,
+		 <&cpg CPG_MOD 723>,
+		 <&x13_clk>;
+	clock-names = "du.0", "du.1", "dclkin.0";
+
+	ports {
+		port@0 {
+			endpoint {
+				remote-endpoint = <&adv7123_in>;
+			};
+		};
+	};
+};
+
 &ehci0 {
 	status = "okay";
 };
@@ -55,6 +156,66 @@
 	clock-frequency = <48000000>;
 };
 
+&i2c0 {
+	status = "okay";
+
+	hdmi-encoder@39 {
+		compatible = "adi,adv7511w";
+		reg = <0x39>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+
+		adi,input-depth = <8>;
+		adi,input-colorspace = "rgb";
+		adi,input-clock = "1x";
+		adi,input-style = <1>;
+		adi,input-justification = "evenly";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				adv7511_in: endpoint {
+					remote-endpoint = <&thc63lvd1024_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				adv7511_out: endpoint {
+					remote-endpoint = <&hdmi_con_out>;
+				};
+			};
+		};
+	};
+};
+
+&lvds0 {
+	status = "okay";
+
+	clocks = <&cpg CPG_MOD 727>,
+		 <&x13_clk>,
+		 <&extal_clk>;
+	clock-names = "fck", "dclkin.0", "extal";
+
+	ports {
+		port@1 {
+			lvds0_out: endpoint {
+				remote-endpoint = <&thc63lvd1024_in>;
+			};
+		};
+	};
+};
+
+&lvds1 {
+	clocks = <&cpg CPG_MOD 727>,
+		 <&x13_clk>,
+		 <&extal_clk>;
+	clock-names = "fck", "dclkin.0", "extal";
+};
+
 &ohci0 {
 	status = "okay";
 };
@@ -67,6 +228,11 @@
 		};
 	};
 
+	du_pins: du {
+		groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0";
+		function = "du";
+	};
+
 	usb0_pins: usb {
 		groups = "usb0_b";
 		function = "usb0";
-- 
Regards,

Laurent Pinchart

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

* [PATCH 15/16] arm64: dts: renesas: r8a77990: ebisu: Enable VGA and HDMI outputs
@ 2018-09-04 12:10   ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

Add the LVDS decoder, HDMI encoder, VGA encoder and HDMI and VGA
connectors, and wire up the display-related nodes with clocks, pinmux
and regulators.

The LVDS0 and LVDS1 encoders can use the DU_DOTCLKIN0, DU_DOTCLKIN1 and
EXTAL externals clocks. Two of them are provided to the SoC on the Ebisu
board, hook them up in DT.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts | 166 +++++++++++++++++++++++++
 1 file changed, 166 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
index 2bc3a4884b00..772ea8843d84 100644
--- a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
@@ -28,6 +28,88 @@
 		/* first 128MB is reserved for secure area. */
 		reg = <0x0 0x48000000 0x0 0x38000000>;
 	};
+
+	hdmi-out {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_con_out: endpoint {
+				remote-endpoint = <&adv7511_out>;
+			};
+		};
+	};
+
+	lvds-decoder {
+		compatible = "thine,thc63lvd1024";
+		vcc-supply = <&reg_3p3v>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				thc63lvd1024_in: endpoint {
+					remote-endpoint = <&lvds0_out>;
+				};
+			};
+
+			port@2 {
+				reg = <2>;
+				thc63lvd1024_out: endpoint {
+					remote-endpoint = <&adv7511_in>;
+				};
+			};
+		};
+	};
+
+	vga {
+		compatible = "vga-connector";
+
+		port {
+			vga_in: endpoint {
+				remote-endpoint = <&adv7123_out>;
+			};
+		};
+	};
+
+	vga-encoder {
+		compatible = "adi,adv7123";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				adv7123_in: endpoint {
+					remote-endpoint = <&du_out_rgb>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+				adv7123_out: endpoint {
+					remote-endpoint = <&vga_in>;
+				};
+			};
+		};
+	};
+
+	reg_3p3v: regulator1 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	x13_clk: x13 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <74250000>;
+	};
 };
 
 &avb {
@@ -47,6 +129,25 @@
 	};
 };
 
+&du {
+	pinctrl-0 = <&du_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	clocks = <&cpg CPG_MOD 724>,
+		 <&cpg CPG_MOD 723>,
+		 <&x13_clk>;
+	clock-names = "du.0", "du.1", "dclkin.0";
+
+	ports {
+		port@0 {
+			endpoint {
+				remote-endpoint = <&adv7123_in>;
+			};
+		};
+	};
+};
+
 &ehci0 {
 	status = "okay";
 };
@@ -55,6 +156,66 @@
 	clock-frequency = <48000000>;
 };
 
+&i2c0 {
+	status = "okay";
+
+	hdmi-encoder@39 {
+		compatible = "adi,adv7511w";
+		reg = <0x39>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+
+		adi,input-depth = <8>;
+		adi,input-colorspace = "rgb";
+		adi,input-clock = "1x";
+		adi,input-style = <1>;
+		adi,input-justification = "evenly";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				adv7511_in: endpoint {
+					remote-endpoint = <&thc63lvd1024_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				adv7511_out: endpoint {
+					remote-endpoint = <&hdmi_con_out>;
+				};
+			};
+		};
+	};
+};
+
+&lvds0 {
+	status = "okay";
+
+	clocks = <&cpg CPG_MOD 727>,
+		 <&x13_clk>,
+		 <&extal_clk>;
+	clock-names = "fck", "dclkin.0", "extal";
+
+	ports {
+		port@1 {
+			lvds0_out: endpoint {
+				remote-endpoint = <&thc63lvd1024_in>;
+			};
+		};
+	};
+};
+
+&lvds1 {
+	clocks = <&cpg CPG_MOD 727>,
+		 <&x13_clk>,
+		 <&extal_clk>;
+	clock-names = "fck", "dclkin.0", "extal";
+};
+
 &ohci0 {
 	status = "okay";
 };
@@ -67,6 +228,11 @@
 		};
 	};
 
+	du_pins: du {
+		groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0";
+		function = "du";
+	};
+
 	usb0_pins: usb {
 		groups = "usb0_b";
 		function = "usb0";
-- 
Regards,

Laurent Pinchart

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

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

* [PATCH 16/16] arm64: dts: renesas: r8a77995: draak: Enable HDMI display output
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-04 12:10   ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Ulrich Hecht

From: Ulrich Hecht <uli+renesas@fpond.eu>

Adds LVDS decoder, HDMI encoder and connector for the Draak board.

The LVDS0 and LVDS1 encoders can use the DU_DOTCLKIN0, DU_DOTCLKIN1 and
EXTAL externals clocks. Two of them are provided to the SoC on the Draak
board, hook them up in DT.

Signed-off-by: Ulrich Hecht <uli+renesas@fpond.eu>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm64/boot/dts/renesas/r8a77995-draak.dts | 98 +++++++++++++++++++++++++-
 1 file changed, 97 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
index a8e8f2669d4c..3055c39bbe07 100644
--- a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
@@ -2,7 +2,7 @@
 /*
  * Device Tree Source for the Draak board
  *
- * Copyright (C) 2016 Renesas Electronics Corp.
+ * Copyright (C) 2016-2018 Renesas Electronics Corp.
  * Copyright (C) 2017 Glider bvba
  */
 
@@ -24,6 +24,41 @@
 		stdout-path = "serial0:115200n8";
 	};
 
+	lvds-decoder {
+		compatible = "thine,thc63lvd1024";
+		vcc-supply = <&reg_3p3v>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				thc63lvd1024_in: endpoint {
+					remote-endpoint = <&lvds0_out>;
+				};
+			};
+
+			port@2 {
+				reg = <2>;
+				thc63lvd1024_out: endpoint {
+					remote-endpoint = <&adv7511_in>;
+				};
+			};
+		};
+	};
+
+	hdmi-out {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_con_out: endpoint {
+				remote-endpoint = <&adv7511_out>;
+			};
+		};
+	};
+
 	vga {
 		compatible = "vga-connector";
 
@@ -218,6 +253,43 @@
 
 	};
 
+	hdmi-encoder@39 {
+		compatible = "adi,adv7511w";
+		reg = <0x39>, <0x3f>, <0x38>, <0x3c>;
+		reg-names = "main", "edid", "packet", "cec";
+		interrupt-parent = <&gpio1>;
+		interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
+
+		/* Depends on LVDS */
+		max-clock = <135000000>;
+		min-vrefresh = <50>;
+
+		adi,input-depth = <8>;
+		adi,input-colorspace = "rgb";
+		adi,input-clock = "1x";
+		adi,input-style = <1>;
+		adi,input-justification = "evenly";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				adv7511_in: endpoint {
+					remote-endpoint = <&thc63lvd1024_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				adv7511_out: endpoint {
+					remote-endpoint = <&hdmi_con_out>;
+				};
+			};
+		};
+	};
+
 	hdmi-decoder@4c {
 		compatible = "adi,adv7612";
 		reg = <0x4c>;
@@ -281,6 +353,30 @@
 	};
 };
 
+&lvds0 {
+	status = "okay";
+
+	clocks = <&cpg CPG_MOD 727>,
+		 <&x12_clk>,
+		 <&extal_clk>;
+	clock-names = "fck", "dclkin.0", "extal";
+
+	ports {
+		port@1 {
+			lvds0_out: endpoint {
+				remote-endpoint = <&thc63lvd1024_in>;
+			};
+		};
+	};
+};
+
+&lvds1 {
+	clocks = <&cpg CPG_MOD 727>,
+		 <&x12_clk>,
+		 <&extal_clk>;
+	clock-names = "fck", "dclkin.0", "extal";
+};
+
 &ehci0 {
 	status = "okay";
 };
-- 
Regards,

Laurent Pinchart

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

* [PATCH 16/16] arm64: dts: renesas: r8a77995: draak: Enable HDMI display output
@ 2018-09-04 12:10   ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-04 12:10 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Ulrich Hecht

From: Ulrich Hecht <uli+renesas@fpond.eu>

Adds LVDS decoder, HDMI encoder and connector for the Draak board.

The LVDS0 and LVDS1 encoders can use the DU_DOTCLKIN0, DU_DOTCLKIN1 and
EXTAL externals clocks. Two of them are provided to the SoC on the Draak
board, hook them up in DT.

Signed-off-by: Ulrich Hecht <uli+renesas@fpond.eu>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm64/boot/dts/renesas/r8a77995-draak.dts | 98 +++++++++++++++++++++++++-
 1 file changed, 97 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
index a8e8f2669d4c..3055c39bbe07 100644
--- a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
@@ -2,7 +2,7 @@
 /*
  * Device Tree Source for the Draak board
  *
- * Copyright (C) 2016 Renesas Electronics Corp.
+ * Copyright (C) 2016-2018 Renesas Electronics Corp.
  * Copyright (C) 2017 Glider bvba
  */
 
@@ -24,6 +24,41 @@
 		stdout-path = "serial0:115200n8";
 	};
 
+	lvds-decoder {
+		compatible = "thine,thc63lvd1024";
+		vcc-supply = <&reg_3p3v>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				thc63lvd1024_in: endpoint {
+					remote-endpoint = <&lvds0_out>;
+				};
+			};
+
+			port@2 {
+				reg = <2>;
+				thc63lvd1024_out: endpoint {
+					remote-endpoint = <&adv7511_in>;
+				};
+			};
+		};
+	};
+
+	hdmi-out {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_con_out: endpoint {
+				remote-endpoint = <&adv7511_out>;
+			};
+		};
+	};
+
 	vga {
 		compatible = "vga-connector";
 
@@ -218,6 +253,43 @@
 
 	};
 
+	hdmi-encoder@39 {
+		compatible = "adi,adv7511w";
+		reg = <0x39>, <0x3f>, <0x38>, <0x3c>;
+		reg-names = "main", "edid", "packet", "cec";
+		interrupt-parent = <&gpio1>;
+		interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
+
+		/* Depends on LVDS */
+		max-clock = <135000000>;
+		min-vrefresh = <50>;
+
+		adi,input-depth = <8>;
+		adi,input-colorspace = "rgb";
+		adi,input-clock = "1x";
+		adi,input-style = <1>;
+		adi,input-justification = "evenly";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				adv7511_in: endpoint {
+					remote-endpoint = <&thc63lvd1024_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				adv7511_out: endpoint {
+					remote-endpoint = <&hdmi_con_out>;
+				};
+			};
+		};
+	};
+
 	hdmi-decoder@4c {
 		compatible = "adi,adv7612";
 		reg = <0x4c>;
@@ -281,6 +353,30 @@
 	};
 };
 
+&lvds0 {
+	status = "okay";
+
+	clocks = <&cpg CPG_MOD 727>,
+		 <&x12_clk>,
+		 <&extal_clk>;
+	clock-names = "fck", "dclkin.0", "extal";
+
+	ports {
+		port@1 {
+			lvds0_out: endpoint {
+				remote-endpoint = <&thc63lvd1024_in>;
+			};
+		};
+	};
+};
+
+&lvds1 {
+	clocks = <&cpg CPG_MOD 727>,
+		 <&x12_clk>,
+		 <&extal_clk>;
+	clock-names = "fck", "dclkin.0", "extal";
+};
+
 &ehci0 {
 	status = "okay";
 };
-- 
Regards,

Laurent Pinchart

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

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

* Re: [PATCH 05/16] drm: rcar-du: lvds: D3/E3 support
  2018-09-04 12:10   ` Laurent Pinchart
@ 2018-09-04 14:29     ` Geert Uytterhoeven
  -1 siblings, 0 replies; 86+ messages in thread
From: Geert Uytterhoeven @ 2018-09-04 14:29 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: DRI Development, Linux-Renesas

Hi Laurent,

On Tue, Sep 4, 2018 at 2:10 PM Laurent Pinchart
<laurent.pinchart+renesas@ideasonboard.com> wrote:
> The LVDS encoders in the D3 and E3 SoCs differ significantly from those
> in the other R-Car Gen3 family members:
>
> - The LVDS PLL architecture is more complex and requires computing PLL
>   parameters manually.
> - The PLL uses external clocks as inputs, which need to be retrieved
>   from DT.
> - In addition to the different PLL setup, the startup sequence has
>   changed *again* (seems someone had trouble making his/her mind).
>
> Supporting all this requires DT bindings extensions for external clocks,
> brand new PLL setup code, and a few quirks to handle the differences in
> the startup sequence.
>
> The implementation doesn't support all hardware features yet, namely
>
> - Using the LV[01] clocks generated by the CPG as PLL input.
> - Providing the LVDS PLL clock to the DU for use with the RGB output.
>
> Those features can be added later when the need will arise.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Thanks for your patch!

> --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c

> +static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk,
> +                                    unsigned long target, struct pll_info *pll)
> +{

> +#if defined(CONFIG_DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
> +       {

As this code has no dependencies, you can improve compile coverage:

    if (IS_ENABLED(...) || ...) {

BTW, was CONFIG_DEBUG intended? Or just DEBUG?

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] 86+ messages in thread

* Re: [PATCH 05/16] drm: rcar-du: lvds: D3/E3 support
@ 2018-09-04 14:29     ` Geert Uytterhoeven
  0 siblings, 0 replies; 86+ messages in thread
From: Geert Uytterhoeven @ 2018-09-04 14:29 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Linux-Renesas, DRI Development

Hi Laurent,

On Tue, Sep 4, 2018 at 2:10 PM Laurent Pinchart
<laurent.pinchart+renesas@ideasonboard.com> wrote:
> The LVDS encoders in the D3 and E3 SoCs differ significantly from those
> in the other R-Car Gen3 family members:
>
> - The LVDS PLL architecture is more complex and requires computing PLL
>   parameters manually.
> - The PLL uses external clocks as inputs, which need to be retrieved
>   from DT.
> - In addition to the different PLL setup, the startup sequence has
>   changed *again* (seems someone had trouble making his/her mind).
>
> Supporting all this requires DT bindings extensions for external clocks,
> brand new PLL setup code, and a few quirks to handle the differences in
> the startup sequence.
>
> The implementation doesn't support all hardware features yet, namely
>
> - Using the LV[01] clocks generated by the CPG as PLL input.
> - Providing the LVDS PLL clock to the DU for use with the RGB output.
>
> Those features can be added later when the need will arise.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Thanks for your patch!

> --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c

> +static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk,
> +                                    unsigned long target, struct pll_info *pll)
> +{

> +#if defined(CONFIG_DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
> +       {

As this code has no dependencies, you can improve compile coverage:

    if (IS_ENABLED(...) || ...) {

BTW, was CONFIG_DEBUG intended? Or just DEBUG?

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
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 12/16] arm64: dts: renesas: r8a77990: Add I2C device nodes
  2018-09-04 12:10   ` Laurent Pinchart
@ 2018-09-04 14:32     ` Geert Uytterhoeven
  -1 siblings, 0 replies; 86+ messages in thread
From: Geert Uytterhoeven @ 2018-09-04 14:32 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: DRI Development, Linux-Renesas, Takeshi Kihara

On Tue, Sep 4, 2018 at 2:10 PM Laurent Pinchart
<laurent.pinchart+renesas@ideasonboard.com> wrote:
> From: Takeshi Kihara <takeshi.kihara.df@renesas.com>
>
> Add device nodes for I2C ch{0,1,2,3,4,5,6,7} to R-Car E3 R8A77990 device
> tree.
>
> Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

My

    Reviewed-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
    Tested-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>

are still valid.

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] 86+ messages in thread

* Re: [PATCH 12/16] arm64: dts: renesas: r8a77990: Add I2C device nodes
@ 2018-09-04 14:32     ` Geert Uytterhoeven
  0 siblings, 0 replies; 86+ messages in thread
From: Geert Uytterhoeven @ 2018-09-04 14:32 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Linux-Renesas, Takeshi Kihara, DRI Development

On Tue, Sep 4, 2018 at 2:10 PM Laurent Pinchart
<laurent.pinchart+renesas@ideasonboard.com> wrote:
> From: Takeshi Kihara <takeshi.kihara.df@renesas.com>
>
> Add device nodes for I2C ch{0,1,2,3,4,5,6,7} to R-Car E3 R8A77990 device
> tree.
>
> Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

My

    Reviewed-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
    Tested-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>

are still valid.

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
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 12/16] arm64: dts: renesas: r8a77990: Add I2C device nodes
  2018-09-04 14:32     ` Geert Uytterhoeven
@ 2018-09-04 14:49       ` jacopo mondi
  -1 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-04 14:49 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Laurent Pinchart, DRI Development, Linux-Renesas, Takeshi Kihara

[-- Attachment #1: Type: text/plain, Size: 1211 bytes --]

Hi Laurent, Geert,

On Tue, Sep 04, 2018 at 04:32:32PM +0200, Geert Uytterhoeven wrote:
> On Tue, Sep 4, 2018 at 2:10 PM Laurent Pinchart
> <laurent.pinchart+renesas@ideasonboard.com> wrote:
> > From: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> >
> > Add device nodes for I2C ch{0,1,2,3,4,5,6,7} to R-Car E3 R8A77990 device
> > tree.
> >
> > Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> > Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
>
> My
>
>     Reviewed-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
>     Tested-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
>
> are still valid.

I was about to send a v2 with these and the slight change Geert
suggested on the ch[0-7] list.

Would you prefer me to drop it from my v2 series and re-base HDMI and
CVBS enablement for E3 on top of this series?

Thanks
  j
>
> 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

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH 12/16] arm64: dts: renesas: r8a77990: Add I2C device nodes
@ 2018-09-04 14:49       ` jacopo mondi
  0 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-04 14:49 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Linux-Renesas, Takeshi Kihara, Laurent Pinchart, DRI Development


[-- Attachment #1.1: Type: text/plain, Size: 1211 bytes --]

Hi Laurent, Geert,

On Tue, Sep 04, 2018 at 04:32:32PM +0200, Geert Uytterhoeven wrote:
> On Tue, Sep 4, 2018 at 2:10 PM Laurent Pinchart
> <laurent.pinchart+renesas@ideasonboard.com> wrote:
> > From: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> >
> > Add device nodes for I2C ch{0,1,2,3,4,5,6,7} to R-Car E3 R8A77990 device
> > tree.
> >
> > Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> > Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
>
> My
>
>     Reviewed-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
>     Tested-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
>
> are still valid.

I was about to send a v2 with these and the slight change Geert
suggested on the ch[0-7] list.

Would you prefer me to drop it from my v2 series and re-base HDMI and
CVBS enablement for E3 on top of this series?

Thanks
  j
>
> 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

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* Re: [PATCH 12/16] arm64: dts: renesas: r8a77990: Add I2C device nodes
  2018-09-04 14:32     ` Geert Uytterhoeven
@ 2018-09-05 13:52       ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-05 13:52 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Laurent Pinchart, DRI Development, Linux-Renesas, Takeshi Kihara

Hi Geert,

On Tuesday, 4 September 2018 17:32:32 EEST Geert Uytterhoeven wrote:
> On Tue, Sep 4, 2018 at 2:10 PM Laurent Pinchart wrote:
> > From: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> > 
> > Add device nodes for I2C ch{0,1,2,3,4,5,6,7} to R-Car E3 R8A77990 device
> > tree.
> > 
> > Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> > Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> 
> My
> 
>     Reviewed-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
>     Tested-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
> 
> are still valid.

Sorry for not picking them up. I've included the patch in my series as it's a 
necessary prerequisite, but was expecting it to be merged separately.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 12/16] arm64: dts: renesas: r8a77990: Add I2C device nodes
@ 2018-09-05 13:52       ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-05 13:52 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Linux-Renesas, Takeshi Kihara, Laurent Pinchart, DRI Development

Hi Geert,

On Tuesday, 4 September 2018 17:32:32 EEST Geert Uytterhoeven wrote:
> On Tue, Sep 4, 2018 at 2:10 PM Laurent Pinchart wrote:
> > From: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> > 
> > Add device nodes for I2C ch{0,1,2,3,4,5,6,7} to R-Car E3 R8A77990 device
> > tree.
> > 
> > Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> > Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> 
> My
> 
>     Reviewed-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
>     Tested-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
> 
> are still valid.

Sorry for not picking them up. I've included the patch in my series as it's a 
necessary prerequisite, but was expecting it to be merged separately.

-- 
Regards,

Laurent Pinchart



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

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

* Re: [PATCH 12/16] arm64: dts: renesas: r8a77990: Add I2C device nodes
  2018-09-04 14:49       ` jacopo mondi
@ 2018-09-05 13:53         ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-05 13:53 UTC (permalink / raw)
  To: jacopo mondi
  Cc: Geert Uytterhoeven, Laurent Pinchart, DRI Development,
	Linux-Renesas, Takeshi Kihara

Hi Jacopo,

On Tuesday, 4 September 2018 17:49:53 EEST jacopo mondi wrote:
> On Tue, Sep 04, 2018 at 04:32:32PM +0200, Geert Uytterhoeven wrote:
> > On Tue, Sep 4, 2018 at 2:10 PM Laurent Pinchart wrote:
> >> From: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> >> 
> >> Add device nodes for I2C ch{0,1,2,3,4,5,6,7} to R-Car E3 R8A77990 device
> >> tree.
> >> 
> >> Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> >> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> > 
> > My
> > 
> >     Reviewed-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
> >     Tested-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
> > 
> > are still valid.
> 
> I was about to send a v2 with these and the slight change Geert
> suggested on the ch[0-7] list.
> 
> Would you prefer me to drop it from my v2 series and re-base HDMI and
> CVBS enablement for E3 on top of this series?

Please don't. We don't know which series will go in first. In any case I'd 
like to fast-track this patch, so if you could post an updated version on its 
own it would be helpful.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 12/16] arm64: dts: renesas: r8a77990: Add I2C device nodes
@ 2018-09-05 13:53         ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-05 13:53 UTC (permalink / raw)
  To: jacopo mondi
  Cc: Linux-Renesas, Takeshi Kihara, Laurent Pinchart,
	Geert Uytterhoeven, DRI Development

Hi Jacopo,

On Tuesday, 4 September 2018 17:49:53 EEST jacopo mondi wrote:
> On Tue, Sep 04, 2018 at 04:32:32PM +0200, Geert Uytterhoeven wrote:
> > On Tue, Sep 4, 2018 at 2:10 PM Laurent Pinchart wrote:
> >> From: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> >> 
> >> Add device nodes for I2C ch{0,1,2,3,4,5,6,7} to R-Car E3 R8A77990 device
> >> tree.
> >> 
> >> Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> >> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> > 
> > My
> > 
> >     Reviewed-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
> >     Tested-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
> > 
> > are still valid.
> 
> I was about to send a v2 with these and the slight change Geert
> suggested on the ch[0-7] list.
> 
> Would you prefer me to drop it from my v2 series and re-base HDMI and
> CVBS enablement for E3 on top of this series?

Please don't. We don't know which series will go in first. In any case I'd 
like to fast-track this patch, so if you could post an updated version on its 
own it would be helpful.

-- 
Regards,

Laurent Pinchart



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

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

* Re: [PATCH 05/16] drm: rcar-du: lvds: D3/E3 support
  2018-09-04 14:29     ` Geert Uytterhoeven
@ 2018-09-05 14:01       ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-05 14:01 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: Laurent Pinchart, DRI Development, Linux-Renesas

Hi Geert,

On Tuesday, 4 September 2018 17:29:29 EEST Geert Uytterhoeven wrote:
> On Tue, Sep 4, 2018 at 2:10 PM Laurent Pinchart wrote:
> > The LVDS encoders in the D3 and E3 SoCs differ significantly from those
> > in the other R-Car Gen3 family members:
> > 
> > - The LVDS PLL architecture is more complex and requires computing PLL
> >   parameters manually.
> > 
> > - The PLL uses external clocks as inputs, which need to be retrieved
> >   from DT.
> > 
> > - In addition to the different PLL setup, the startup sequence has
> >   changed *again* (seems someone had trouble making his/her mind).
> > 
> > Supporting all this requires DT bindings extensions for external clocks,
> > brand new PLL setup code, and a few quirks to handle the differences in
> > the startup sequence.
> > 
> > The implementation doesn't support all hardware features yet, namely
> > 
> > - Using the LV[01] clocks generated by the CPG as PLL input.
> > - Providing the LVDS PLL clock to the DU for use with the RGB output.
> > 
> > Those features can be added later when the need will arise.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> Thanks for your patch!
> 
> > --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > 
> > +static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk
> > *clk, +                                    unsigned long target, struct
> > pll_info *pll) +{
> > 
> > +#if defined(CONFIG_DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
> > +       {
> 
> As this code has no dependencies, you can improve compile coverage:
> 
>     if (IS_ENABLED(...) || ...) {
> 
> BTW, was CONFIG_DEBUG intended? Or just DEBUG?

It should have been just DEBUG, yes.

I was trying to guard against dev_dbg() being defined as a no-op and gcc 
throwing unused variables warnings, but it looks like that has never been an 
issue in the first place, so I'll drop the guard.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 05/16] drm: rcar-du: lvds: D3/E3 support
@ 2018-09-05 14:01       ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-05 14:01 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: Linux-Renesas, Laurent Pinchart, DRI Development

Hi Geert,

On Tuesday, 4 September 2018 17:29:29 EEST Geert Uytterhoeven wrote:
> On Tue, Sep 4, 2018 at 2:10 PM Laurent Pinchart wrote:
> > The LVDS encoders in the D3 and E3 SoCs differ significantly from those
> > in the other R-Car Gen3 family members:
> > 
> > - The LVDS PLL architecture is more complex and requires computing PLL
> >   parameters manually.
> > 
> > - The PLL uses external clocks as inputs, which need to be retrieved
> >   from DT.
> > 
> > - In addition to the different PLL setup, the startup sequence has
> >   changed *again* (seems someone had trouble making his/her mind).
> > 
> > Supporting all this requires DT bindings extensions for external clocks,
> > brand new PLL setup code, and a few quirks to handle the differences in
> > the startup sequence.
> > 
> > The implementation doesn't support all hardware features yet, namely
> > 
> > - Using the LV[01] clocks generated by the CPG as PLL input.
> > - Providing the LVDS PLL clock to the DU for use with the RGB output.
> > 
> > Those features can be added later when the need will arise.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> Thanks for your patch!
> 
> > --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > 
> > +static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk
> > *clk, +                                    unsigned long target, struct
> > pll_info *pll) +{
> > 
> > +#if defined(CONFIG_DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
> > +       {
> 
> As this code has no dependencies, you can improve compile coverage:
> 
>     if (IS_ENABLED(...) || ...) {
> 
> BTW, was CONFIG_DEBUG intended? Or just DEBUG?

It should have been just DEBUG, yes.

I was trying to guard against dev_dbg() being defined as a no-op and gcc 
throwing unused variables warnings, but it looks like that has never been an 
issue in the first place, so I'll drop the guard.

-- 
Regards,

Laurent Pinchart



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

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

* Re: [PATCH 00/16] R-Car D3/E3 display support (with LVDS PLL)
  2018-09-04 12:10 ` Laurent Pinchart
@ 2018-09-05 16:22   ` jacopo mondi
  -1 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-05 16:22 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: devicetree, Ulrich Hecht, dri-devel, linux-renesas-soc


[-- Attachment #1.1: Type: text/plain, Size: 5492 bytes --]

Hi Laurent,

On Tue, Sep 04, 2018 at 03:10:11PM +0300, Laurent Pinchart wrote:
> Hello everybody,
>
> This patch series adds display support for the D3 and E3 SoCs, and in
> particular the Draak and Ebisu boards.
>
> The code is based on Ulrich's "[PROTO][PATCH 00/10] R-Car D3 LVDS/HDMI support
> (with PLL)" series previously posted to the dri-devel and linux-renesas-soc
> mailing lists. It has been extensively reworked and partly rewritten, and
> support for E3 and Ebisu has been added.
>
> The DU in the D3 and E3 SoCs has no internal PLL. In order to achieve precise
> pixel clock rates (required, among other use cases, for HDMI operation), the
> PLL from the internal LVDS encoder must be programmed and its output clock
> routed back to the DU.
>
> The series starts with update to the DU and LVDS encoder DT bindings to add E3
> (R8A77990) support (patches 01/16 and 02/16) and new clock sources for the
> LVDS encoder (patch 03/16).
>
> The next patch (04/16) adds a .mode_valid() operation to the thc63lvd1024
> driver, to reject modes outside of the LVDS decoder's pixel clock operating
> range (8 MHz to 135 MHz). The patch can be merged on its own separately from
> this series.
>
> Patch (05/16) adds support for D3 and E3 to the LVDS encoder driver. Compared
> to the already supported SoCs, D3 and E3 use a different initialization
> sequence and have a different PLL architecture, with more options for the
> input clock.
>
> The next five patches (06/16 to 10/16) perform small reworks or add support
> for miscellaneous missing features and limitations of the DU, to be followed
> by patch 11/16 that adds support for the D3 and E3 to the DU driver.
>
> Finally patches 12/16 to 16/16 enable display for the D3 and E3 boards in DT.
> Patch 12/16 adds support for the I2C controllers in the E3 DT, and will likely
> be merged separately from this series. Patch 13/16 adds all the display IP
> cores (FCP, VSP, DU and LVDS encoders) to the E3 DT, while patch 14/16 adds
> (and wires up) the missing LVDS encoders to the D3 DT. Patches 15/16 and 16/16
> then enable display output for the Ebisu and Draak boards respectively.
>
> I believe the patch series to be ready for upstreaming (after fixing the
> issues found during review of course). There is no big hack in the code, and I
> haven't noticed any regression. A few issues are still unsolved, such as how
> to disable display outputs independently on D3 and E3, and usage of the LVDS
> PLL for the RGB output, but those are not regressions and shouldn't in my
> opinion be considered as show stoppers.
>
> The patches are available from
>
> 	git://linuxtv.org/pinchartl/media.git drm/du/lvds-pll
>
> with an additional patch for E3 pinctrl that is required for testing and has
> been queued by Geert for v4.20 already.
>
> I have successfully tested the series with the HDMI output of the Ebisu board.
> Ulrich, Jacopo, could you test it on D3 if you have time ? You only need to
> run kmstest or modetest to display an image on the HDMI output.

HDMI output works fine with several modes I have tested:
1920x1080, 1280x720, 1024x768 and 1366x768

You can add my:
Tested-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

If you need more testing please let me know.

Thanks
  j

>
> Kieran Bingham (1):
>   arm64: dts: renesas: r8a77995: Add LVDS support
>
> Laurent Pinchart (12):
>   dt-bindings: display: renesas: du: Document r8a77990 bindings
>   dt-bindings: display: renesas: lvds: Document r8a77990 bindings
>   dt-bindings: display: renesas: lvds: Add EXTAL and DU_DOTCLKIN clocks
>   drm: bridge: thc63: Restrict modes based on hardware operating
>     frequency
>   drm: rcar-du: lvds: D3/E3 support
>   drm: rcar-du: Perform the initial CRTC setup from rcar_du_crtc_get()
>   drm: rcar-du: Use LVDS PLL clock as dot clock when possible
>   drm: rcar-du: Enable configurable DPAD0 routing on Gen3
>   drm: rcar-du: Cache DSYSR value to ensure known initial value
>   drm: rcar-du: Don't use TV sync mode when not supported by the
>     hardware
>   arm64: dts: renesas: r8a77990: Add display output support
>   arm64: dts: renesas: r8a77990: ebisu: Enable VGA and HDMI outputs
>
> Takeshi Kihara (1):
>   arm64: dts: renesas: r8a77990: Add I2C device nodes
>
> Ulrich Hecht (2):
>   drm: rcar-du: Add r8a77990 and r8a77995 device support
>   arm64: dts: renesas: r8a77995: draak: Enable HDMI display output
>
>  .../bindings/display/bridge/renesas,lvds.txt       |  13 +-
>  .../devicetree/bindings/display/renesas,du.txt     |   2 +
>  arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts     | 166 ++++++++++
>  arch/arm64/boot/dts/renesas/r8a77990.dtsi          | 290 ++++++++++++++++
>  arch/arm64/boot/dts/renesas/r8a77995-draak.dts     |  98 +++++-
>  arch/arm64/boot/dts/renesas/r8a77995.dtsi          |  56 ++++
>  drivers/gpu/drm/bridge/thc63lvd1024.c              |  18 +
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c             | 136 ++++----
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.h             |   5 +
>  drivers/gpu/drm/rcar-du/rcar_du_drv.c              |  63 +++-
>  drivers/gpu/drm/rcar-du/rcar_du_drv.h              |   3 +
>  drivers/gpu/drm/rcar-du/rcar_du_group.c            |  88 +++--
>  drivers/gpu/drm/rcar-du/rcar_du_kms.c              |  12 +
>  drivers/gpu/drm/rcar-du/rcar_lvds.c                | 365 ++++++++++++++++++---
>  drivers/gpu/drm/rcar-du/rcar_lvds_regs.h           |  43 ++-
>  15 files changed, 1210 insertions(+), 148 deletions(-)
>
> --
> Regards,
>
> Laurent Pinchart
>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* Re: [PATCH 00/16] R-Car D3/E3 display support (with LVDS PLL)
@ 2018-09-05 16:22   ` jacopo mondi
  0 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-05 16:22 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: dri-devel, linux-renesas-soc, devicetree, Archit Taneja,
	Andrzej Hajda, Ulrich Hecht

[-- Attachment #1: Type: text/plain, Size: 5492 bytes --]

Hi Laurent,

On Tue, Sep 04, 2018 at 03:10:11PM +0300, Laurent Pinchart wrote:
> Hello everybody,
>
> This patch series adds display support for the D3 and E3 SoCs, and in
> particular the Draak and Ebisu boards.
>
> The code is based on Ulrich's "[PROTO][PATCH 00/10] R-Car D3 LVDS/HDMI support
> (with PLL)" series previously posted to the dri-devel and linux-renesas-soc
> mailing lists. It has been extensively reworked and partly rewritten, and
> support for E3 and Ebisu has been added.
>
> The DU in the D3 and E3 SoCs has no internal PLL. In order to achieve precise
> pixel clock rates (required, among other use cases, for HDMI operation), the
> PLL from the internal LVDS encoder must be programmed and its output clock
> routed back to the DU.
>
> The series starts with update to the DU and LVDS encoder DT bindings to add E3
> (R8A77990) support (patches 01/16 and 02/16) and new clock sources for the
> LVDS encoder (patch 03/16).
>
> The next patch (04/16) adds a .mode_valid() operation to the thc63lvd1024
> driver, to reject modes outside of the LVDS decoder's pixel clock operating
> range (8 MHz to 135 MHz). The patch can be merged on its own separately from
> this series.
>
> Patch (05/16) adds support for D3 and E3 to the LVDS encoder driver. Compared
> to the already supported SoCs, D3 and E3 use a different initialization
> sequence and have a different PLL architecture, with more options for the
> input clock.
>
> The next five patches (06/16 to 10/16) perform small reworks or add support
> for miscellaneous missing features and limitations of the DU, to be followed
> by patch 11/16 that adds support for the D3 and E3 to the DU driver.
>
> Finally patches 12/16 to 16/16 enable display for the D3 and E3 boards in DT.
> Patch 12/16 adds support for the I2C controllers in the E3 DT, and will likely
> be merged separately from this series. Patch 13/16 adds all the display IP
> cores (FCP, VSP, DU and LVDS encoders) to the E3 DT, while patch 14/16 adds
> (and wires up) the missing LVDS encoders to the D3 DT. Patches 15/16 and 16/16
> then enable display output for the Ebisu and Draak boards respectively.
>
> I believe the patch series to be ready for upstreaming (after fixing the
> issues found during review of course). There is no big hack in the code, and I
> haven't noticed any regression. A few issues are still unsolved, such as how
> to disable display outputs independently on D3 and E3, and usage of the LVDS
> PLL for the RGB output, but those are not regressions and shouldn't in my
> opinion be considered as show stoppers.
>
> The patches are available from
>
> 	git://linuxtv.org/pinchartl/media.git drm/du/lvds-pll
>
> with an additional patch for E3 pinctrl that is required for testing and has
> been queued by Geert for v4.20 already.
>
> I have successfully tested the series with the HDMI output of the Ebisu board.
> Ulrich, Jacopo, could you test it on D3 if you have time ? You only need to
> run kmstest or modetest to display an image on the HDMI output.

HDMI output works fine with several modes I have tested:
1920x1080, 1280x720, 1024x768 and 1366x768

You can add my:
Tested-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

If you need more testing please let me know.

Thanks
  j

>
> Kieran Bingham (1):
>   arm64: dts: renesas: r8a77995: Add LVDS support
>
> Laurent Pinchart (12):
>   dt-bindings: display: renesas: du: Document r8a77990 bindings
>   dt-bindings: display: renesas: lvds: Document r8a77990 bindings
>   dt-bindings: display: renesas: lvds: Add EXTAL and DU_DOTCLKIN clocks
>   drm: bridge: thc63: Restrict modes based on hardware operating
>     frequency
>   drm: rcar-du: lvds: D3/E3 support
>   drm: rcar-du: Perform the initial CRTC setup from rcar_du_crtc_get()
>   drm: rcar-du: Use LVDS PLL clock as dot clock when possible
>   drm: rcar-du: Enable configurable DPAD0 routing on Gen3
>   drm: rcar-du: Cache DSYSR value to ensure known initial value
>   drm: rcar-du: Don't use TV sync mode when not supported by the
>     hardware
>   arm64: dts: renesas: r8a77990: Add display output support
>   arm64: dts: renesas: r8a77990: ebisu: Enable VGA and HDMI outputs
>
> Takeshi Kihara (1):
>   arm64: dts: renesas: r8a77990: Add I2C device nodes
>
> Ulrich Hecht (2):
>   drm: rcar-du: Add r8a77990 and r8a77995 device support
>   arm64: dts: renesas: r8a77995: draak: Enable HDMI display output
>
>  .../bindings/display/bridge/renesas,lvds.txt       |  13 +-
>  .../devicetree/bindings/display/renesas,du.txt     |   2 +
>  arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts     | 166 ++++++++++
>  arch/arm64/boot/dts/renesas/r8a77990.dtsi          | 290 ++++++++++++++++
>  arch/arm64/boot/dts/renesas/r8a77995-draak.dts     |  98 +++++-
>  arch/arm64/boot/dts/renesas/r8a77995.dtsi          |  56 ++++
>  drivers/gpu/drm/bridge/thc63lvd1024.c              |  18 +
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c             | 136 ++++----
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.h             |   5 +
>  drivers/gpu/drm/rcar-du/rcar_du_drv.c              |  63 +++-
>  drivers/gpu/drm/rcar-du/rcar_du_drv.h              |   3 +
>  drivers/gpu/drm/rcar-du/rcar_du_group.c            |  88 +++--
>  drivers/gpu/drm/rcar-du/rcar_du_kms.c              |  12 +
>  drivers/gpu/drm/rcar-du/rcar_lvds.c                | 365 ++++++++++++++++++---
>  drivers/gpu/drm/rcar-du/rcar_lvds_regs.h           |  43 ++-
>  15 files changed, 1210 insertions(+), 148 deletions(-)
>
> --
> Regards,
>
> Laurent Pinchart
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH 12/16] arm64: dts: renesas: r8a77990: Add I2C device nodes
  2018-09-05 13:53         ` Laurent Pinchart
@ 2018-09-06  9:26           ` Simon Horman
  -1 siblings, 0 replies; 86+ messages in thread
From: Simon Horman @ 2018-09-06  9:26 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: jacopo mondi, Geert Uytterhoeven, Laurent Pinchart,
	DRI Development, Linux-Renesas, Takeshi Kihara

On Wed, Sep 05, 2018 at 04:53:26PM +0300, Laurent Pinchart wrote:
> Hi Jacopo,
> 
> On Tuesday, 4 September 2018 17:49:53 EEST jacopo mondi wrote:
> > On Tue, Sep 04, 2018 at 04:32:32PM +0200, Geert Uytterhoeven wrote:
> > > On Tue, Sep 4, 2018 at 2:10 PM Laurent Pinchart wrote:
> > >> From: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> > >> 
> > >> Add device nodes for I2C ch{0,1,2,3,4,5,6,7} to R-Car E3 R8A77990 device
> > >> tree.
> > >> 
> > >> Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> > >> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> > > 
> > > My
> > > 
> > >     Reviewed-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
> > >     Tested-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
> > > 
> > > are still valid.
> > 
> > I was about to send a v2 with these and the slight change Geert
> > suggested on the ch[0-7] list.
> > 
> > Would you prefer me to drop it from my v2 series and re-base HDMI and
> > CVBS enablement for E3 on top of this series?
> 
> Please don't. We don't know which series will go in first. In any case I'd 
> like to fast-track this patch, so if you could post an updated version on its 
> own it would be helpful.

The patch should appear in the next branch later today.
Hopefully that will make everyones lives just that little
bit easier.

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

* Re: [PATCH 12/16] arm64: dts: renesas: r8a77990: Add I2C device nodes
@ 2018-09-06  9:26           ` Simon Horman
  0 siblings, 0 replies; 86+ messages in thread
From: Simon Horman @ 2018-09-06  9:26 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: jacopo mondi, Laurent Pinchart, Takeshi Kihara, DRI Development,
	Linux-Renesas, Geert Uytterhoeven

On Wed, Sep 05, 2018 at 04:53:26PM +0300, Laurent Pinchart wrote:
> Hi Jacopo,
> 
> On Tuesday, 4 September 2018 17:49:53 EEST jacopo mondi wrote:
> > On Tue, Sep 04, 2018 at 04:32:32PM +0200, Geert Uytterhoeven wrote:
> > > On Tue, Sep 4, 2018 at 2:10 PM Laurent Pinchart wrote:
> > >> From: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> > >> 
> > >> Add device nodes for I2C ch{0,1,2,3,4,5,6,7} to R-Car E3 R8A77990 device
> > >> tree.
> > >> 
> > >> Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> > >> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> > > 
> > > My
> > > 
> > >     Reviewed-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
> > >     Tested-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
> > > 
> > > are still valid.
> > 
> > I was about to send a v2 with these and the slight change Geert
> > suggested on the ch[0-7] list.
> > 
> > Would you prefer me to drop it from my v2 series and re-base HDMI and
> > CVBS enablement for E3 on top of this series?
> 
> Please don't. We don't know which series will go in first. In any case I'd 
> like to fast-track this patch, so if you could post an updated version on its 
> own it would be helpful.

The patch should appear in the next branch later today.
Hopefully that will make everyones lives just that little
bit easier.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 12/16] arm64: dts: renesas: r8a77990: Add I2C device nodes
  2018-09-06  9:26           ` Simon Horman
@ 2018-09-06  9:48             ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-06  9:48 UTC (permalink / raw)
  To: Simon Horman
  Cc: jacopo mondi, Geert Uytterhoeven, Laurent Pinchart,
	DRI Development, Linux-Renesas, Takeshi Kihara

Hi Simon,

On Thursday, 6 September 2018 12:26:46 EEST Simon Horman wrote:
> On Wed, Sep 05, 2018 at 04:53:26PM +0300, Laurent Pinchart wrote:
> > On Tuesday, 4 September 2018 17:49:53 EEST jacopo mondi wrote:
> > > On Tue, Sep 04, 2018 at 04:32:32PM +0200, Geert Uytterhoeven wrote:
> > > > On Tue, Sep 4, 2018 at 2:10 PM Laurent Pinchart wrote:
> > > >> From: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> > > >> 
> > > >> Add device nodes for I2C ch{0,1,2,3,4,5,6,7} to R-Car E3 R8A77990
> > > >> device
> > > >> tree.
> > > >> 
> > > >> Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> > > >> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> > > > 
> > > > My
> > > > 
> > > >     Reviewed-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
> > > >     Tested-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
> > > > 
> > > > are still valid.
> > > 
> > > I was about to send a v2 with these and the slight change Geert
> > > suggested on the ch[0-7] list.
> > > 
> > > Would you prefer me to drop it from my v2 series and re-base HDMI and
> > > CVBS enablement for E3 on top of this series?
> > 
> > Please don't. We don't know which series will go in first. In any case I'd
> > like to fast-track this patch, so if you could post an updated version on
> > its own it would be helpful.
> 
> The patch should appear in the next branch later today.
> Hopefully that will make everyones lives just that little
> bit easier.

Thank you very much.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 12/16] arm64: dts: renesas: r8a77990: Add I2C device nodes
@ 2018-09-06  9:48             ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-06  9:48 UTC (permalink / raw)
  To: Simon Horman
  Cc: jacopo mondi, Laurent Pinchart, Takeshi Kihara, DRI Development,
	Linux-Renesas, Geert Uytterhoeven

Hi Simon,

On Thursday, 6 September 2018 12:26:46 EEST Simon Horman wrote:
> On Wed, Sep 05, 2018 at 04:53:26PM +0300, Laurent Pinchart wrote:
> > On Tuesday, 4 September 2018 17:49:53 EEST jacopo mondi wrote:
> > > On Tue, Sep 04, 2018 at 04:32:32PM +0200, Geert Uytterhoeven wrote:
> > > > On Tue, Sep 4, 2018 at 2:10 PM Laurent Pinchart wrote:
> > > >> From: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> > > >> 
> > > >> Add device nodes for I2C ch{0,1,2,3,4,5,6,7} to R-Car E3 R8A77990
> > > >> device
> > > >> tree.
> > > >> 
> > > >> Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> > > >> Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> > > > 
> > > > My
> > > > 
> > > >     Reviewed-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
> > > >     Tested-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
> > > > 
> > > > are still valid.
> > > 
> > > I was about to send a v2 with these and the slight change Geert
> > > suggested on the ch[0-7] list.
> > > 
> > > Would you prefer me to drop it from my v2 series and re-base HDMI and
> > > CVBS enablement for E3 on top of this series?
> > 
> > Please don't. We don't know which series will go in first. In any case I'd
> > like to fast-track this patch, so if you could post an updated version on
> > its own it would be helpful.
> 
> The patch should appear in the next branch later today.
> Hopefully that will make everyones lives just that little
> bit easier.

Thank you very much.

-- 
Regards,

Laurent Pinchart



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

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

* Re: [PATCH 06/16] drm: rcar-du: Perform the initial CRTC setup from rcar_du_crtc_get()
  2018-09-04 12:10   ` Laurent Pinchart
@ 2018-09-07 18:19     ` jacopo mondi
  -1 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-07 18:19 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel, linux-renesas-soc

[-- Attachment #1: Type: text/plain, Size: 4971 bytes --]

Hi Laurent,

On Tue, Sep 04, 2018 at 03:10:17PM +0300, Laurent Pinchart wrote:
> The rcar_du_crtc_get() function is always immediately followed by a call
> to rcar_du_crtc_setup(). Call the later from the former to simplify the
> code, and add a comment to explain how the get and put calls are
> balanced.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 107 +++++++++++++++++----------------
>  1 file changed, 56 insertions(+), 51 deletions(-)
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> index 4c9572d7ea89..1d81eb244441 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> @@ -66,39 +66,6 @@ static void rcar_du_crtc_clr_set(struct rcar_du_crtc *rcrtc, u32 reg,
>  	rcar_du_write(rcdu, rcrtc->mmio_offset + reg, (value & ~clr) | set);
>  }
>
> -static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
> -{
> -	int ret;
> -
> -	ret = clk_prepare_enable(rcrtc->clock);
> -	if (ret < 0)
> -		return ret;
> -
> -	ret = clk_prepare_enable(rcrtc->extclock);
> -	if (ret < 0)
> -		goto error_clock;
> -
> -	ret = rcar_du_group_get(rcrtc->group);
> -	if (ret < 0)
> -		goto error_group;
> -
> -	return 0;
> -
> -error_group:
> -	clk_disable_unprepare(rcrtc->extclock);
> -error_clock:
> -	clk_disable_unprepare(rcrtc->clock);
> -	return ret;
> -}
> -
> -static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)

For what I see, rcar_du_crtc_stop() is also called once just before
_put(). Have you considered doing with them what you've done with
_get() and _setup() ?

Thanks
   j

> -{
> -	rcar_du_group_put(rcrtc->group);
> -
> -	clk_disable_unprepare(rcrtc->extclock);
> -	clk_disable_unprepare(rcrtc->clock);
> -}
> -
>  /* -----------------------------------------------------------------------------
>   * Hardware Setup
>   */
> @@ -546,6 +513,51 @@ static void rcar_du_crtc_setup(struct rcar_du_crtc *rcrtc)
>  	drm_crtc_vblank_on(&rcrtc->crtc);
>  }
>
> +static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
> +{
> +	int ret;
> +
> +	/*
> +	 * Guard against double-get, as the function is called from both the
> +	 * .atomic_enable() and .atomic_begin() handlers.
> +	 */
> +	if (rcrtc->initialized)
> +		return 0;
> +
> +	ret = clk_prepare_enable(rcrtc->clock);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = clk_prepare_enable(rcrtc->extclock);
> +	if (ret < 0)
> +		goto error_clock;
> +
> +	ret = rcar_du_group_get(rcrtc->group);
> +	if (ret < 0)
> +		goto error_group;
> +
> +	rcar_du_crtc_setup(rcrtc);
> +	rcrtc->initialized = true;
> +
> +	return 0;
> +
> +error_group:
> +	clk_disable_unprepare(rcrtc->extclock);
> +error_clock:
> +	clk_disable_unprepare(rcrtc->clock);
> +	return ret;
> +}
> +
> +static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
> +{
> +	rcar_du_group_put(rcrtc->group);
> +
> +	clk_disable_unprepare(rcrtc->extclock);
> +	clk_disable_unprepare(rcrtc->clock);
> +
> +	rcrtc->initialized = false;
> +}
> +
>  static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
>  {
>  	bool interlaced;
> @@ -639,16 +651,7 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
>  {
>  	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
>
> -	/*
> -	 * If the CRTC has already been setup by the .atomic_begin() handler we
> -	 * can skip the setup stage.
> -	 */
> -	if (!rcrtc->initialized) {
> -		rcar_du_crtc_get(rcrtc);
> -		rcar_du_crtc_setup(rcrtc);
> -		rcrtc->initialized = true;
> -	}
> -
> +	rcar_du_crtc_get(rcrtc);
>  	rcar_du_crtc_start(rcrtc);
>  }
>
> @@ -667,7 +670,6 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
>  	}
>  	spin_unlock_irq(&crtc->dev->event_lock);
>
> -	rcrtc->initialized = false;
>  	rcrtc->outputs = 0;
>  }
>
> @@ -680,14 +682,17 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
>
>  	/*
>  	 * If a mode set is in progress we can be called with the CRTC disabled.
> -	 * We then need to first setup the CRTC in order to configure planes.
> -	 * The .atomic_enable() handler will notice and skip the CRTC setup.
> +	 * We thus need to first get and setup the CRTC in order to configure
> +	 * planes. We must *not* put the CRTC in .atomic_flush(), as it must be
> +	 * kept awake until the .atomic_enable() call that will follow. The get
> +	 * operation in .atomic_enable() will in that case be a no-op, and the
> +	 * CRTC will be put later in .atomic_disable().
> +	 *
> +	 * If a mode set is not in progress the CRTC is enabled, and the
> +	 * following get call will be a no-op. There is thus no need to belance
> +	 * it in .atomic_flush() either.
>  	 */
> -	if (!rcrtc->initialized) {
> -		rcar_du_crtc_get(rcrtc);
> -		rcar_du_crtc_setup(rcrtc);
> -		rcrtc->initialized = true;
> -	}
> +	rcar_du_crtc_get(rcrtc);
>
>  	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
>  		rcar_du_vsp_atomic_begin(rcrtc);
> --
> Regards,
>
> Laurent Pinchart
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH 06/16] drm: rcar-du: Perform the initial CRTC setup from rcar_du_crtc_get()
@ 2018-09-07 18:19     ` jacopo mondi
  0 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-07 18:19 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 4971 bytes --]

Hi Laurent,

On Tue, Sep 04, 2018 at 03:10:17PM +0300, Laurent Pinchart wrote:
> The rcar_du_crtc_get() function is always immediately followed by a call
> to rcar_du_crtc_setup(). Call the later from the former to simplify the
> code, and add a comment to explain how the get and put calls are
> balanced.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 107 +++++++++++++++++----------------
>  1 file changed, 56 insertions(+), 51 deletions(-)
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> index 4c9572d7ea89..1d81eb244441 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> @@ -66,39 +66,6 @@ static void rcar_du_crtc_clr_set(struct rcar_du_crtc *rcrtc, u32 reg,
>  	rcar_du_write(rcdu, rcrtc->mmio_offset + reg, (value & ~clr) | set);
>  }
>
> -static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
> -{
> -	int ret;
> -
> -	ret = clk_prepare_enable(rcrtc->clock);
> -	if (ret < 0)
> -		return ret;
> -
> -	ret = clk_prepare_enable(rcrtc->extclock);
> -	if (ret < 0)
> -		goto error_clock;
> -
> -	ret = rcar_du_group_get(rcrtc->group);
> -	if (ret < 0)
> -		goto error_group;
> -
> -	return 0;
> -
> -error_group:
> -	clk_disable_unprepare(rcrtc->extclock);
> -error_clock:
> -	clk_disable_unprepare(rcrtc->clock);
> -	return ret;
> -}
> -
> -static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)

For what I see, rcar_du_crtc_stop() is also called once just before
_put(). Have you considered doing with them what you've done with
_get() and _setup() ?

Thanks
   j

> -{
> -	rcar_du_group_put(rcrtc->group);
> -
> -	clk_disable_unprepare(rcrtc->extclock);
> -	clk_disable_unprepare(rcrtc->clock);
> -}
> -
>  /* -----------------------------------------------------------------------------
>   * Hardware Setup
>   */
> @@ -546,6 +513,51 @@ static void rcar_du_crtc_setup(struct rcar_du_crtc *rcrtc)
>  	drm_crtc_vblank_on(&rcrtc->crtc);
>  }
>
> +static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
> +{
> +	int ret;
> +
> +	/*
> +	 * Guard against double-get, as the function is called from both the
> +	 * .atomic_enable() and .atomic_begin() handlers.
> +	 */
> +	if (rcrtc->initialized)
> +		return 0;
> +
> +	ret = clk_prepare_enable(rcrtc->clock);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = clk_prepare_enable(rcrtc->extclock);
> +	if (ret < 0)
> +		goto error_clock;
> +
> +	ret = rcar_du_group_get(rcrtc->group);
> +	if (ret < 0)
> +		goto error_group;
> +
> +	rcar_du_crtc_setup(rcrtc);
> +	rcrtc->initialized = true;
> +
> +	return 0;
> +
> +error_group:
> +	clk_disable_unprepare(rcrtc->extclock);
> +error_clock:
> +	clk_disable_unprepare(rcrtc->clock);
> +	return ret;
> +}
> +
> +static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
> +{
> +	rcar_du_group_put(rcrtc->group);
> +
> +	clk_disable_unprepare(rcrtc->extclock);
> +	clk_disable_unprepare(rcrtc->clock);
> +
> +	rcrtc->initialized = false;
> +}
> +
>  static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
>  {
>  	bool interlaced;
> @@ -639,16 +651,7 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
>  {
>  	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
>
> -	/*
> -	 * If the CRTC has already been setup by the .atomic_begin() handler we
> -	 * can skip the setup stage.
> -	 */
> -	if (!rcrtc->initialized) {
> -		rcar_du_crtc_get(rcrtc);
> -		rcar_du_crtc_setup(rcrtc);
> -		rcrtc->initialized = true;
> -	}
> -
> +	rcar_du_crtc_get(rcrtc);
>  	rcar_du_crtc_start(rcrtc);
>  }
>
> @@ -667,7 +670,6 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
>  	}
>  	spin_unlock_irq(&crtc->dev->event_lock);
>
> -	rcrtc->initialized = false;
>  	rcrtc->outputs = 0;
>  }
>
> @@ -680,14 +682,17 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
>
>  	/*
>  	 * If a mode set is in progress we can be called with the CRTC disabled.
> -	 * We then need to first setup the CRTC in order to configure planes.
> -	 * The .atomic_enable() handler will notice and skip the CRTC setup.
> +	 * We thus need to first get and setup the CRTC in order to configure
> +	 * planes. We must *not* put the CRTC in .atomic_flush(), as it must be
> +	 * kept awake until the .atomic_enable() call that will follow. The get
> +	 * operation in .atomic_enable() will in that case be a no-op, and the
> +	 * CRTC will be put later in .atomic_disable().
> +	 *
> +	 * If a mode set is not in progress the CRTC is enabled, and the
> +	 * following get call will be a no-op. There is thus no need to belance
> +	 * it in .atomic_flush() either.
>  	 */
> -	if (!rcrtc->initialized) {
> -		rcar_du_crtc_get(rcrtc);
> -		rcar_du_crtc_setup(rcrtc);
> -		rcrtc->initialized = true;
> -	}
> +	rcar_du_crtc_get(rcrtc);
>
>  	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
>  		rcar_du_vsp_atomic_begin(rcrtc);
> --
> Regards,
>
> Laurent Pinchart
>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* Re: [PATCH 06/16] drm: rcar-du: Perform the initial CRTC setup from rcar_du_crtc_get()
  2018-09-07 18:19     ` jacopo mondi
@ 2018-09-09 16:44       ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-09 16:44 UTC (permalink / raw)
  To: jacopo mondi; +Cc: Laurent Pinchart, dri-devel, linux-renesas-soc

Hi Jacopo,

On Friday, 7 September 2018 21:19:38 EEST jacopo mondi wrote:
> On Tue, Sep 04, 2018 at 03:10:17PM +0300, Laurent Pinchart wrote:
> > The rcar_du_crtc_get() function is always immediately followed by a call
> > to rcar_du_crtc_setup(). Call the later from the former to simplify the
> > code, and add a comment to explain how the get and put calls are
> > balanced.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 107 +++++++++++++++-------------
> >  1 file changed, 56 insertions(+), 51 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 4c9572d7ea89..1d81eb244441
> > 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > @@ -66,39 +66,6 @@ static void rcar_du_crtc_clr_set(struct rcar_du_crtc
> > *rcrtc, u32 reg,
> >  	rcar_du_write(rcdu, rcrtc->mmio_offset + reg, (value & ~clr) | set);
> >  }
> > 
> > -static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
> > -{
> > -	int ret;
> > -
> > -	ret = clk_prepare_enable(rcrtc->clock);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	ret = clk_prepare_enable(rcrtc->extclock);
> > -	if (ret < 0)
> > -		goto error_clock;
> > -
> > -	ret = rcar_du_group_get(rcrtc->group);
> > -	if (ret < 0)
> > -		goto error_group;
> > -
> > -	return 0;
> > -
> > -error_group:
> > -	clk_disable_unprepare(rcrtc->extclock);
> > -error_clock:
> > -	clk_disable_unprepare(rcrtc->clock);
> > -	return ret;
> > -}
> > -
> > -static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
> 
> For what I see, rcar_du_crtc_stop() is also called once just before
> _put(). Have you considered doing with them what you've done with
> _get() and _setup() ?

I have, but given that we have an explicit get(); start(); sequence in 
rcar_du_crtc_atomic_enable(), I'd rather keep the stop(); put(); sequence in 
rcar_du_crtc_atomic_disable().

> > -{
> > -	rcar_du_group_put(rcrtc->group);
> > -
> > -	clk_disable_unprepare(rcrtc->extclock);
> > -	clk_disable_unprepare(rcrtc->clock);
> > -}
> > -
> > 
> >  /*
> >  ------------------------------------------------------------------------
> >  ----->  
> >   * Hardware Setup
> >   */
> > 
> > @@ -546,6 +513,51 @@ static void rcar_du_crtc_setup(struct rcar_du_crtc
> > *rcrtc)> 
> >  	drm_crtc_vblank_on(&rcrtc->crtc);
> >  
> >  }
> > 
> > +static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
> > +{
> > +	int ret;
> > +
> > +	/*
> > +	 * Guard against double-get, as the function is called from both the
> > +	 * .atomic_enable() and .atomic_begin() handlers.
> > +	 */
> > +	if (rcrtc->initialized)
> > +		return 0;
> > +
> > +	ret = clk_prepare_enable(rcrtc->clock);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = clk_prepare_enable(rcrtc->extclock);
> > +	if (ret < 0)
> > +		goto error_clock;
> > +
> > +	ret = rcar_du_group_get(rcrtc->group);
> > +	if (ret < 0)
> > +		goto error_group;
> > +
> > +	rcar_du_crtc_setup(rcrtc);
> > +	rcrtc->initialized = true;
> > +
> > +	return 0;
> > +
> > +error_group:
> > +	clk_disable_unprepare(rcrtc->extclock);
> > +error_clock:
> > +	clk_disable_unprepare(rcrtc->clock);
> > +	return ret;
> > +}
> > +
> > +static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
> > +{
> > +	rcar_du_group_put(rcrtc->group);
> > +
> > +	clk_disable_unprepare(rcrtc->extclock);
> > +	clk_disable_unprepare(rcrtc->clock);
> > +
> > +	rcrtc->initialized = false;
> > +}
> > +
> > 
> >  static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
> >  {
> >  
> >  	bool interlaced;
> > 
> > @@ -639,16 +651,7 @@ static void rcar_du_crtc_atomic_enable(struct
> > drm_crtc *crtc,> 
> >  {
> >  
> >  	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
> > 
> > -	/*
> > -	 * If the CRTC has already been setup by the .atomic_begin() handler we
> > -	 * can skip the setup stage.
> > -	 */
> > -	if (!rcrtc->initialized) {
> > -		rcar_du_crtc_get(rcrtc);
> > -		rcar_du_crtc_setup(rcrtc);
> > -		rcrtc->initialized = true;
> > -	}
> > -
> > +	rcar_du_crtc_get(rcrtc);
> > 
> >  	rcar_du_crtc_start(rcrtc);
> >  
> >  }
> > 
> > @@ -667,7 +670,6 @@ static void rcar_du_crtc_atomic_disable(struct
> > drm_crtc *crtc,> 
> >  	}
> >  	spin_unlock_irq(&crtc->dev->event_lock);
> > 
> > -	rcrtc->initialized = false;
> > 
> >  	rcrtc->outputs = 0;
> >  
> >  }
> > 
> > @@ -680,14 +682,17 @@ static void rcar_du_crtc_atomic_begin(struct
> > drm_crtc *crtc,> 
> >  	/*
> >  	
> >  	 * If a mode set is in progress we can be called with the CRTC 
disabled.
> > 
> > -	 * We then need to first setup the CRTC in order to configure planes.
> > -	 * The .atomic_enable() handler will notice and skip the CRTC setup.
> > +	 * We thus need to first get and setup the CRTC in order to configure
> > +	 * planes. We must *not* put the CRTC in .atomic_flush(), as it must be
> > +	 * kept awake until the .atomic_enable() call that will follow. The get
> > +	 * operation in .atomic_enable() will in that case be a no-op, and the
> > +	 * CRTC will be put later in .atomic_disable().
> > +	 *
> > +	 * If a mode set is not in progress the CRTC is enabled, and the
> > +	 * following get call will be a no-op. There is thus no need to belance
> > +	 * it in .atomic_flush() either.
> > 
> >  	 */
> > 
> > -	if (!rcrtc->initialized) {
> > -		rcar_du_crtc_get(rcrtc);
> > -		rcar_du_crtc_setup(rcrtc);
> > -		rcrtc->initialized = true;
> > -	}
> > +	rcar_du_crtc_get(rcrtc);
> > 
> >  	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
> >  	
> >  		rcar_du_vsp_atomic_begin(rcrtc);


-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 06/16] drm: rcar-du: Perform the initial CRTC setup from rcar_du_crtc_get()
@ 2018-09-09 16:44       ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-09 16:44 UTC (permalink / raw)
  To: jacopo mondi; +Cc: linux-renesas-soc, Laurent Pinchart, dri-devel

Hi Jacopo,

On Friday, 7 September 2018 21:19:38 EEST jacopo mondi wrote:
> On Tue, Sep 04, 2018 at 03:10:17PM +0300, Laurent Pinchart wrote:
> > The rcar_du_crtc_get() function is always immediately followed by a call
> > to rcar_du_crtc_setup(). Call the later from the former to simplify the
> > code, and add a comment to explain how the get and put calls are
> > balanced.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 107 +++++++++++++++-------------
> >  1 file changed, 56 insertions(+), 51 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 4c9572d7ea89..1d81eb244441
> > 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > @@ -66,39 +66,6 @@ static void rcar_du_crtc_clr_set(struct rcar_du_crtc
> > *rcrtc, u32 reg,
> >  	rcar_du_write(rcdu, rcrtc->mmio_offset + reg, (value & ~clr) | set);
> >  }
> > 
> > -static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
> > -{
> > -	int ret;
> > -
> > -	ret = clk_prepare_enable(rcrtc->clock);
> > -	if (ret < 0)
> > -		return ret;
> > -
> > -	ret = clk_prepare_enable(rcrtc->extclock);
> > -	if (ret < 0)
> > -		goto error_clock;
> > -
> > -	ret = rcar_du_group_get(rcrtc->group);
> > -	if (ret < 0)
> > -		goto error_group;
> > -
> > -	return 0;
> > -
> > -error_group:
> > -	clk_disable_unprepare(rcrtc->extclock);
> > -error_clock:
> > -	clk_disable_unprepare(rcrtc->clock);
> > -	return ret;
> > -}
> > -
> > -static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
> 
> For what I see, rcar_du_crtc_stop() is also called once just before
> _put(). Have you considered doing with them what you've done with
> _get() and _setup() ?

I have, but given that we have an explicit get(); start(); sequence in 
rcar_du_crtc_atomic_enable(), I'd rather keep the stop(); put(); sequence in 
rcar_du_crtc_atomic_disable().

> > -{
> > -	rcar_du_group_put(rcrtc->group);
> > -
> > -	clk_disable_unprepare(rcrtc->extclock);
> > -	clk_disable_unprepare(rcrtc->clock);
> > -}
> > -
> > 
> >  /*
> >  ------------------------------------------------------------------------
> >  ----->  
> >   * Hardware Setup
> >   */
> > 
> > @@ -546,6 +513,51 @@ static void rcar_du_crtc_setup(struct rcar_du_crtc
> > *rcrtc)> 
> >  	drm_crtc_vblank_on(&rcrtc->crtc);
> >  
> >  }
> > 
> > +static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
> > +{
> > +	int ret;
> > +
> > +	/*
> > +	 * Guard against double-get, as the function is called from both the
> > +	 * .atomic_enable() and .atomic_begin() handlers.
> > +	 */
> > +	if (rcrtc->initialized)
> > +		return 0;
> > +
> > +	ret = clk_prepare_enable(rcrtc->clock);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	ret = clk_prepare_enable(rcrtc->extclock);
> > +	if (ret < 0)
> > +		goto error_clock;
> > +
> > +	ret = rcar_du_group_get(rcrtc->group);
> > +	if (ret < 0)
> > +		goto error_group;
> > +
> > +	rcar_du_crtc_setup(rcrtc);
> > +	rcrtc->initialized = true;
> > +
> > +	return 0;
> > +
> > +error_group:
> > +	clk_disable_unprepare(rcrtc->extclock);
> > +error_clock:
> > +	clk_disable_unprepare(rcrtc->clock);
> > +	return ret;
> > +}
> > +
> > +static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
> > +{
> > +	rcar_du_group_put(rcrtc->group);
> > +
> > +	clk_disable_unprepare(rcrtc->extclock);
> > +	clk_disable_unprepare(rcrtc->clock);
> > +
> > +	rcrtc->initialized = false;
> > +}
> > +
> > 
> >  static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
> >  {
> >  
> >  	bool interlaced;
> > 
> > @@ -639,16 +651,7 @@ static void rcar_du_crtc_atomic_enable(struct
> > drm_crtc *crtc,> 
> >  {
> >  
> >  	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
> > 
> > -	/*
> > -	 * If the CRTC has already been setup by the .atomic_begin() handler we
> > -	 * can skip the setup stage.
> > -	 */
> > -	if (!rcrtc->initialized) {
> > -		rcar_du_crtc_get(rcrtc);
> > -		rcar_du_crtc_setup(rcrtc);
> > -		rcrtc->initialized = true;
> > -	}
> > -
> > +	rcar_du_crtc_get(rcrtc);
> > 
> >  	rcar_du_crtc_start(rcrtc);
> >  
> >  }
> > 
> > @@ -667,7 +670,6 @@ static void rcar_du_crtc_atomic_disable(struct
> > drm_crtc *crtc,> 
> >  	}
> >  	spin_unlock_irq(&crtc->dev->event_lock);
> > 
> > -	rcrtc->initialized = false;
> > 
> >  	rcrtc->outputs = 0;
> >  
> >  }
> > 
> > @@ -680,14 +682,17 @@ static void rcar_du_crtc_atomic_begin(struct
> > drm_crtc *crtc,> 
> >  	/*
> >  	
> >  	 * If a mode set is in progress we can be called with the CRTC 
disabled.
> > 
> > -	 * We then need to first setup the CRTC in order to configure planes.
> > -	 * The .atomic_enable() handler will notice and skip the CRTC setup.
> > +	 * We thus need to first get and setup the CRTC in order to configure
> > +	 * planes. We must *not* put the CRTC in .atomic_flush(), as it must be
> > +	 * kept awake until the .atomic_enable() call that will follow. The get
> > +	 * operation in .atomic_enable() will in that case be a no-op, and the
> > +	 * CRTC will be put later in .atomic_disable().
> > +	 *
> > +	 * If a mode set is not in progress the CRTC is enabled, and the
> > +	 * following get call will be a no-op. There is thus no need to belance
> > +	 * it in .atomic_flush() either.
> > 
> >  	 */
> > 
> > -	if (!rcrtc->initialized) {
> > -		rcar_du_crtc_get(rcrtc);
> > -		rcar_du_crtc_setup(rcrtc);
> > -		rcrtc->initialized = true;
> > -	}
> > +	rcar_du_crtc_get(rcrtc);
> > 
> >  	if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
> >  	
> >  		rcar_du_vsp_atomic_begin(rcrtc);


-- 
Regards,

Laurent Pinchart



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

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

* Re: [PATCH 05/16] drm: rcar-du: lvds: D3/E3 support
  2018-09-04 12:10   ` Laurent Pinchart
@ 2018-09-11 13:23     ` jacopo mondi
  -1 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-11 13:23 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel, linux-renesas-soc

[-- Attachment #1: Type: text/plain, Size: 21344 bytes --]

Hi Laurent,

On Tue, Sep 04, 2018 at 03:10:16PM +0300, Laurent Pinchart wrote:
> The LVDS encoders in the D3 and E3 SoCs differ significantly from those
> in the other R-Car Gen3 family members:
>
> - The LVDS PLL architecture is more complex and requires computing PLL
>   parameters manually.
> - The PLL uses external clocks as inputs, which need to be retrieved
>   from DT.
> - In addition to the different PLL setup, the startup sequence has
>   changed *again* (seems someone had trouble making his/her mind).
>
> Supporting all this requires DT bindings extensions for external clocks,
> brand new PLL setup code, and a few quirks to handle the differences in
> the startup sequence.
>
> The implementation doesn't support all hardware features yet, namely
>
> - Using the LV[01] clocks generated by the CPG as PLL input.
> - Providing the LVDS PLL clock to the DU for use with the RGB output.
>
> Those features can be added later when the need will arise.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/rcar-du/rcar_lvds.c      | 365 +++++++++++++++++++++++++++----
>  drivers/gpu/drm/rcar-du/rcar_lvds_regs.h |  43 +++-
>  2 files changed, 361 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> index ce0eb68c3416..aac4acbcfbfc 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> @@ -24,6 +24,8 @@
>
>  #include "rcar_lvds_regs.h"
>
> +struct rcar_lvds;
> +
>  /* Keep in sync with the LVDCR0.LVMD hardware register values. */
>  enum rcar_lvds_mode {
>  	RCAR_LVDS_MODE_JEIDA = 0,
> @@ -31,14 +33,16 @@ enum rcar_lvds_mode {
>  	RCAR_LVDS_MODE_VESA = 4,
>  };
>
> -#define RCAR_LVDS_QUIRK_LANES	(1 << 0)	/* LVDS lanes 1 and 3 inverted */
> -#define RCAR_LVDS_QUIRK_GEN2_PLLCR (1 << 1)	/* LVDPLLCR has gen2 layout */
> -#define RCAR_LVDS_QUIRK_GEN3_LVEN (1 << 2)	/* LVEN bit needs to be set */
> -						/* on R8A77970/R8A7799x */
> +#define RCAR_LVDS_QUIRK_LANES		BIT(0)	/* LVDS lanes 1 and 3 inverted */
> +#define RCAR_LVDS_QUIRK_GEN3_LVEN	BIT(1)	/* LVEN bit needs to be set on R8A77970/R8A7799x */
> +#define RCAR_LVDS_QUIRK_PWD		BIT(2)	/* PWD bit available (all of Gen3 but E3) */
> +#define RCAR_LVDS_QUIRK_EXT_PLL		BIT(3)	/* Has extended PLL */
> +#define RCAR_LVDS_QUIRK_DUAL_LINK	BIT(4)	/* Supports dual-link operation */
>
>  struct rcar_lvds_device_info {
>  	unsigned int gen;
>  	unsigned int quirks;
> +	void (*pll_setup)(struct rcar_lvds *lvds, unsigned int freq);
>  };
>
>  struct rcar_lvds {
> @@ -52,7 +56,11 @@ struct rcar_lvds {
>  	struct drm_panel *panel;
>
>  	void __iomem *mmio;
> -	struct clk *clock;
> +	struct {
> +		struct clk *mod;		/* CPG module clock */
> +		struct clk *extal;		/* External clock */
> +		struct clk *dotclkin[2];	/* External DU clocks */
> +	} clocks;
>  	bool enabled;
>
>  	struct drm_display_mode display_mode;
> @@ -128,33 +136,222 @@ static const struct drm_connector_funcs rcar_lvds_conn_funcs = {
>  };
>
>  /* -----------------------------------------------------------------------------
> - * Bridge
> + * PLL Setup
>   */
>
> -static u32 rcar_lvds_lvdpllcr_gen2(unsigned int freq)
> +static void rcar_lvds_pll_setup_gen2(struct rcar_lvds *lvds, unsigned int freq)
> +{
> +	u32 val;
> +
> +	if (freq < 39000000)
> +		val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
> +	else if (freq < 61000000)
> +		val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
> +	else if (freq < 121000000)
> +		val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
> +	else
> +		val = LVDPLLCR_PLLDLYCNT_150M;
> +
> +	rcar_lvds_write(lvds, LVDPLLCR, val);
> +}
> +
> +static void rcar_lvds_pll_setup_gen3(struct rcar_lvds *lvds, unsigned int freq)
>  {
> -	if (freq < 39000)
> -		return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
> -	else if (freq < 61000)
> -		return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
> -	else if (freq < 121000)
> -		return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
> +	u32 val;
> +
> +	if (freq < 42000000)
> +		val = LVDPLLCR_PLLDIVCNT_42M;
> +	else if (freq < 85000000)
> +		val = LVDPLLCR_PLLDIVCNT_85M;
> +	else if (freq < 128000000)
> +		val = LVDPLLCR_PLLDIVCNT_128M;
>  	else
> -		return LVDPLLCR_PLLDLYCNT_150M;
> +		val = LVDPLLCR_PLLDIVCNT_148M;
> +
> +	rcar_lvds_write(lvds, LVDPLLCR, val);
> +}
> +
> +struct pll_info {
> +	struct clk *clk;
> +	unsigned long diff;
> +	unsigned int pll_m;
> +	unsigned int pll_n;
> +	unsigned int pll_e;
> +	unsigned int div;
> +};
> +
> +static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk,
> +				     unsigned long target, struct pll_info *pll)

Do you think it is worth mentioning d3_e3 in the function name? I know
it's not a big deal, but in future generation this PLL circuit may be
re-used.

> +{
> +	unsigned long fin;
> +	unsigned int m_min;
> +	unsigned int m_max;
> +	unsigned int m;
> +
> +	if (!clk)
> +		return;
> +
> +	/*
> +	 * The LVDS PLL is made of a pre-divider and a multiplier (strangerly
> +	 * enough called M and N respectively), followed by a post-divider E.
> +	 *
> +	 *         ,-----.         ,-----.     ,-----.         ,-----.
> +	 * Fin --> | 1/M | -Fpdf-> | PFD | --> | VCO | -Fvco-> | 1/E | --> Fout
> +	 *         `-----'     ,-> |     |     `-----'   |     `-----'
> +	 *                     |   `-----'               |
> +	 *                     |         ,-----.         |
> +	 *                     `-------- | 1/N | <-------'
> +	 *                               `-----'
> +	 *
> +	 * The clock output by the PLL is then further divided by a programmable
> +	 * divider DIV to achieve the desired target frequency. Finally, an
> +	 * optional fixed /7 divider is used to convert the bit clock to a pixel
> +	 * clock (as LVDS transmits 7 bits per lane per clock sample).
> +	 *
> +	 *          ,-------.     ,-----.     |\
> +	 * Fout --> | 1/DIV | --> | 1/7 | --> | |
> +	 *          `-------'  |  `-----'     | | --> dot clock
> +	 *                     `------------> | |
> +	 *                                    |/
> +	 *
> +	 * The /7 divider is optional when the LVDS PLL is used to generate a
> +	 * dot clock for the DU RGB output, without using the LVDS encoder. We
> +	 * don't support this configuration yet.
> +	 *
> +	 * The PLL allowed input frequency range is 12 MHz to 192 MHz.
> +	 */
> +
> +	fin = clk_get_rate(clk);
> +	if (fin < 12000000 || fin > 192000000)
> +		return;
> +
> +	/*
> +	 * The comparison frequency range is 12 MHz to 24 MHz, which limits the
> +	 * allowed values for the pre-divider M (normal range 1-8).
> +	 *
> +	 * Fpfd = Fin / M
> +	 */
> +	m_min = max_t(unsigned int, 1, DIV_ROUND_UP(fin, 24000000));
> +	m_max = min_t(unsigned int, 8, fin / 12000000);
> +
> +	for (m = m_min; m <= m_max; ++m) {
> +		unsigned long fpfd;
> +		unsigned int n_min;
> +		unsigned int n_max;
> +		unsigned int n;
> +
> +		/*
> +		 * The VCO operating range is 900 Mhz to 1800 MHz, which limits
> +		 * the allowed values for the multiplier N (normal range
> +		 * 60-120).
> +		 *
> +		 * Fvco = Fin * N / M
> +		 */
> +		fpfd = fin / m;
> +		n_min = max_t(unsigned int, 60, DIV_ROUND_UP(900000000, fpfd));
> +		n_max = min_t(unsigned int, 120, 1800000000 / fpfd);
> +
> +		for (n = n_min; n < n_max; ++n) {
> +			unsigned long fvco;
> +			unsigned int e_min;
> +			unsigned int e;
> +
> +			/*
> +			 * The output frequency is limited to 1039.5 MHz,
> +			 * limiting again the allowed values for the
> +			 * post-divider E (normal value 1, 2 or 4).
> +			 *
> +			 * Fout = Fvco / E
> +			 */
> +			fvco = fpfd * n;
> +			e_min = fvco > 1039500000 ? 1 : 0;
> +
> +			for (e = e_min; e < 3; ++e) {
> +				unsigned long fout;
> +				unsigned long diff;
> +				unsigned int div;
> +
> +				/*
> +				 * Finally we have a programable divider after
> +				 * the PLL, followed by a an optional fixed /7
> +				 * divider.
> +				 */
> +				fout = fvco / (1 << e) / 7;
> +				div = DIV_ROUND_CLOSEST(fout, target);
> +				diff = abs(fout / div - target);
> +
> +				if (diff < pll->diff) {
> +					pll->clk = clk;
> +					pll->diff = diff;
> +					pll->pll_m = m;
> +					pll->pll_n = n;
> +					pll->pll_e = e;
> +					pll->div = div;
> +
> +					if (diff == 0)
> +						goto done;
> +				}
> +			}
> +		}
> +	}

Very nice :)

> +
> +done:
> +#if defined(CONFIG_DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
> +	{
> +		unsigned long output = fin * pll->pll_n / pll->pll_m
> +				     / (1 << pll->pll_e) / 7 / pll->div;
> +		int error = (long)(output - target) * 10000 / (long)target;
> +
> +		dev_dbg(lvds->dev,
> +			"%pC %lu Hz -> Fout %lu Hz (target %lu Hz, error %d.%02u%%), PLL M/N/E/DIV %u/%u/%u/%u\n",
> +			clk, fin, output, target, error / 100,
> +			error < 0 ? -error % 100 : error % 100,
> +			pll->pll_m, pll->pll_n, pll->pll_e, pll->div);
> +	}
> +#endif

I know you know about this already, but

../drivers/gpu/drm/rcar-du/rcar_lvds.c:298:1: error: label at end of
compound statement

I'm still not sure what actually disturbs gcc here

>  }
>
> -static u32 rcar_lvds_lvdpllcr_gen3(unsigned int freq)
> +static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned int freq)
>  {
> -	if (freq < 42000)
> -		return LVDPLLCR_PLLDIVCNT_42M;
> -	else if (freq < 85000)
> -		return LVDPLLCR_PLLDIVCNT_85M;
> -	else if (freq < 128000)
> -		return LVDPLLCR_PLLDIVCNT_128M;
> +	struct drm_crtc *crtc = lvds->bridge.encoder->crtc;
> +	struct pll_info pll = { .diff = (unsigned long)-1 };
> +	u32 lvdpllcr;
> +
> +	if (lvds->clocks.dotclkin[0] || lvds->clocks.dotclkin[1]) {
> +		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[0],
> +					 freq, &pll);
> +		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[1],
> +					 freq, &pll);
> +	} else if (lvds->clocks.extal) {
> +		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.extal,
> +					 freq, &pll);
> +	}

here it's either ((dotclkin[0] or dotclock[1]) or extal). Are they
mutually exclusive? Can't we try all of them? The probe routine
guarantees we have at least of of them...

> +
> +	lvdpllcr = LVDPLLCR_PLLON | LVDPLLCR_CLKOUT
> +		 | LVDPLLCR_PLLN(pll.pll_n - 1) | LVDPLLCR_PLLM(pll.pll_m - 1);
> +
> +	if (pll.clk == lvds->clocks.extal)
> +		lvdpllcr |= LVDPLLCR_CKSEL_EXTAL;
> +	else
> +		lvdpllcr |= LVDPLLCR_CKSEL_DU_DOTCLKIN(drm_crtc_index(crtc));

Here you select du_clkin[0] or du_clkin[1] based on the DU index (btw,
the drm_crtc_index() function is funny, it simply "crtc->index" no
checks, no validation, what's the benefit of using it?).

Looking at the LVDS PLL block diagram for D3/E3 (Figure 37.3) I see
that both clkin[0] and clkin[1] could be used independently from the du
index. Shouldn't we use the one performing better? (now how to make
sure it gets not selected twice in case of both DU0 and DU1 using the
LVDS PLL it's another problem)

> +
> +	if (pll.pll_e > 0)
> +		lvdpllcr |= LVDPLLCR_STP_CLKOUTE | LVDPLLCR_OUTCLKSEL
> +			 |  LVDPLLCR_PLLE(pll.pll_e - 1);
> +
> +	rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
> +
> +	if (pll.div > 1)
> +		rcar_lvds_write(lvds, LVDDIV, LVDDIV_DIVSEL |
> +				LVDDIV_DIVRESET | LVDDIV_DIV(pll.div - 1));
>  	else
> -		return LVDPLLCR_PLLDIVCNT_148M;
> +		rcar_lvds_write(lvds, LVDDIV, 0);
>  }
>
> +/* -----------------------------------------------------------------------------
> + * Bridge
> + */
> +
>  static void rcar_lvds_enable(struct drm_bridge *bridge)
>  {
>  	struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
> @@ -164,14 +361,13 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
>  	 * do we get a state pointer?
>  	 */
>  	struct drm_crtc *crtc = lvds->bridge.encoder->crtc;
> -	u32 lvdpllcr;
>  	u32 lvdhcr;
>  	u32 lvdcr0;
>  	int ret;
>
>  	WARN_ON(lvds->enabled);
>
> -	ret = clk_prepare_enable(lvds->clock);
> +	ret = clk_prepare_enable(lvds->clocks.mod);
>  	if (ret < 0)
>  		return;
>
> @@ -196,12 +392,13 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
>
>  	rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
>
> +	if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) {
> +		/* Disable dual-link mode. */
> +		rcar_lvds_write(lvds, LVDSTRIPE, 0);
> +	}
> +
>  	/* PLL clock configuration. */
> -	if (lvds->info->quirks & RCAR_LVDS_QUIRK_GEN2_PLLCR)
> -		lvdpllcr = rcar_lvds_lvdpllcr_gen2(mode->clock);
> -	else
> -		lvdpllcr = rcar_lvds_lvdpllcr_gen3(mode->clock);
> -	rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
> +	lvds->info->pll_setup(lvds, mode->clock * 1000);
>
>  	/* Set the LVDS mode and select the input. */
>  	lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT;
> @@ -220,11 +417,16 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
>  		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
>  	}
>
> -	/* Turn the PLL on. */
> -	lvdcr0 |= LVDCR0_PLLON;
> -	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
> +	if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) {
> +		/*
> +		 * Turn the PLL on (simple PLL only, extended PLL is fully
> +		 * controlled through LVDPLLCR).
> +		 */
> +		lvdcr0 |= LVDCR0_PLLON;
> +		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
> +	}
>
> -	if (lvds->info->gen > 2) {
> +	if (lvds->info->quirks & RCAR_LVDS_QUIRK_PWD) {
>  		/* Set LVDS normal mode. */
>  		lvdcr0 |= LVDCR0_PWD;
>  		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
> @@ -236,8 +438,10 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
>  		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
>  	}
>
> -	/* Wait for the startup delay. */
> -	usleep_range(100, 150);
> +	if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) {
> +		/* Wait for the PLL startup delay (simple PLL only). */
> +		usleep_range(100, 150);
> +	}
>
>  	/* Turn the output on. */
>  	lvdcr0 |= LVDCR0_LVRES;
> @@ -264,8 +468,9 @@ static void rcar_lvds_disable(struct drm_bridge *bridge)
>
>  	rcar_lvds_write(lvds, LVDCR0, 0);
>  	rcar_lvds_write(lvds, LVDCR1, 0);
> +	rcar_lvds_write(lvds, LVDPLLCR, 0);
>
> -	clk_disable_unprepare(lvds->clock);
> +	clk_disable_unprepare(lvds->clocks.mod);
>
>  	lvds->enabled = false;
>  }
> @@ -446,6 +651,60 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
>  	return ret;
>  }
>
> +static struct clk *rcar_lvds_get_clock(struct rcar_lvds *lvds, const char *name,
> +				       bool optional)
> +{
> +	struct clk *clk;
> +
> +	clk = devm_clk_get(lvds->dev, name);

I wish we had clk_get_optional() as we have gpiod_get_optional().
There are probably good reasons if it's not there though...

> +	if (!IS_ERR(clk))
> +		return clk;
> +
> +	if (PTR_ERR(clk) == -ENOENT && optional)
> +		return NULL;
> +
> +	if (PTR_ERR(clk) != -EPROBE_DEFER)
> +		dev_err(lvds->dev, "failed to get %s clock\n",
> +			name ? name : "module");
> +
> +	return clk;
> +}
> +
> +static int rcar_lvds_get_clocks(struct rcar_lvds *lvds)
> +{
> +	lvds->clocks.mod = rcar_lvds_get_clock(lvds, NULL, false);
> +	if (IS_ERR(lvds->clocks.mod))
> +		return PTR_ERR(lvds->clocks.mod);
> +
> +	/*
> +	 * LVDS encoders without an extended PLL have no external clock inputs.
> +	 */
> +	if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL))
> +		return 0;
> +
> +	lvds->clocks.extal = rcar_lvds_get_clock(lvds, "extal", true);
> +	if (IS_ERR(lvds->clocks.extal))
> +		return PTR_ERR(lvds->clocks.extal);
> +
> +	lvds->clocks.dotclkin[0] = rcar_lvds_get_clock(lvds, "dclkin.0", true);
> +	if (IS_ERR(lvds->clocks.dotclkin[0]))
> +		return PTR_ERR(lvds->clocks.dotclkin[0]);
> +
> +	lvds->clocks.dotclkin[1] = rcar_lvds_get_clock(lvds, "dclkin.1", true);
> +	if (IS_ERR(lvds->clocks.dotclkin[1]))
> +		return PTR_ERR(lvds->clocks.dotclkin[1]);
> +
> +	/* At least one input to the PLL must be available. */
> +	if (!lvds->clocks.extal && !lvds->clocks.dotclkin[0] &&
> +	    !lvds->clocks.dotclkin[1]) {
> +		dev_err(lvds->dev,
> +			"no input clock (extal, dclkin.0 or dclkin.1)\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
>  static int rcar_lvds_probe(struct platform_device *pdev)
>  {
>  	struct rcar_lvds *lvds;
> @@ -475,11 +734,9 @@ static int rcar_lvds_probe(struct platform_device *pdev)
>  	if (IS_ERR(lvds->mmio))
>  		return PTR_ERR(lvds->mmio);
>
> -	lvds->clock = devm_clk_get(&pdev->dev, NULL);
> -	if (IS_ERR(lvds->clock)) {
> -		dev_err(&pdev->dev, "failed to get clock\n");
> -		return PTR_ERR(lvds->clock);
> -	}
> +	ret = rcar_lvds_get_clocks(lvds);
> +	if (ret < 0)
> +		return ret;
>
>  	drm_bridge_add(&lvds->bridge);
>
> @@ -497,21 +754,39 @@ static int rcar_lvds_remove(struct platform_device *pdev)
>
>  static const struct rcar_lvds_device_info rcar_lvds_gen2_info = {
>  	.gen = 2,
> -	.quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR,
> +	.pll_setup = rcar_lvds_pll_setup_gen2,
>  };
>
>  static const struct rcar_lvds_device_info rcar_lvds_r8a7790_info = {
>  	.gen = 2,
> -	.quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR | RCAR_LVDS_QUIRK_LANES,
> +	.quirks = RCAR_LVDS_QUIRK_LANES,
> +	.pll_setup = rcar_lvds_pll_setup_gen2,
>  };
>
>  static const struct rcar_lvds_device_info rcar_lvds_gen3_info = {
>  	.gen = 3,
> +	.quirks = RCAR_LVDS_QUIRK_PWD,
> +	.pll_setup = rcar_lvds_pll_setup_gen3,
>  };
>
>  static const struct rcar_lvds_device_info rcar_lvds_r8a77970_info = {
>  	.gen = 3,
> -	.quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR | RCAR_LVDS_QUIRK_GEN3_LVEN,
> +	.quirks = RCAR_LVDS_QUIRK_PWD | RCAR_LVDS_QUIRK_GEN3_LVEN,
> +	.pll_setup = rcar_lvds_pll_setup_gen2,
> +};
> +
> +static const struct rcar_lvds_device_info rcar_lvds_r8a77990_info = {
> +	.gen = 3,
> +	.quirks = RCAR_LVDS_QUIRK_GEN3_LVEN | RCAR_LVDS_QUIRK_EXT_PLL
> +		| RCAR_LVDS_QUIRK_DUAL_LINK,
> +	.pll_setup = rcar_lvds_pll_setup_d3_e3,
> +};
> +
> +static const struct rcar_lvds_device_info rcar_lvds_r8a77995_info = {
> +	.gen = 3,
> +	.quirks = RCAR_LVDS_QUIRK_GEN3_LVEN | RCAR_LVDS_QUIRK_PWD
> +		| RCAR_LVDS_QUIRK_EXT_PLL | RCAR_LVDS_QUIRK_DUAL_LINK,
> +	.pll_setup = rcar_lvds_pll_setup_d3_e3,
>  };
>
>  static const struct of_device_id rcar_lvds_of_table[] = {
> @@ -523,6 +798,8 @@ static const struct of_device_id rcar_lvds_of_table[] = {
>  	{ .compatible = "renesas,r8a7796-lvds", .data = &rcar_lvds_gen3_info },
>  	{ .compatible = "renesas,r8a77970-lvds", .data = &rcar_lvds_r8a77970_info },
>  	{ .compatible = "renesas,r8a77980-lvds", .data = &rcar_lvds_gen3_info },
> +	{ .compatible = "renesas,r8a77990-lvds", .data = &rcar_lvds_r8a77990_info },
> +	{ .compatible = "renesas,r8a77995-lvds", .data = &rcar_lvds_r8a77995_info },
>  	{ }
>  };
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
> index 4870f50d9bec..87149f2f8056 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_PLLON			(1 << 4)
>  #define LVDCR0_PWD			(1 << 2)		/* Gen3 only */
>  #define LVDCR0_BEN			(1 << 2)		/* Gen2 only */
> -#define LVDCR0_LVEN			(1 << 1)		/* Gen2 only */
> +#define LVDCR0_LVEN			(1 << 1)
>  #define LVDCR0_LVRES			(1 << 0)
>
>  #define LVDCR1				0x0004
> @@ -27,21 +27,36 @@
>  #define LVDCR1_CLKSTBY			(3 << 0)
>
>  #define LVDPLLCR			0x0008
> +/* Gen2 & V3M */
>  #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 */
> +/* Gen3 but V3M,D3 and E3 */
>  #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)
> +/* D3 and E3 */
> +#define LVDPLLCR_PLLON			(1 << 22)
> +#define LVDPLLCR_PLLSEL_PLL0		(0 << 20)
> +#define LVDPLLCR_PLLSEL_LVX		(1 << 20)
> +#define LVDPLLCR_PLLSEL_PLL1		(2 << 20)
> +#define LVDPLLCR_CKSEL_LVX		(1 << 17)
> +#define LVDPLLCR_CKSEL_EXTAL		(3 << 17)
> +#define LVDPLLCR_CKSEL_DU_DOTCLKIN(n)	((5 + (n) * 2) << 17)
> +#define LVDPLLCR_OCKSEL			(1 << 16)
> +#define LVDPLLCR_STP_CLKOUTE		(1 << 14)
> +#define LVDPLLCR_OUTCLKSEL		(1 << 12)
> +#define LVDPLLCR_CLKOUT			(1 << 11)
> +#define LVDPLLCR_PLLE(n)		((n) << 10)
> +#define LVDPLLCR_PLLN(n)		((n) << 3)
> +#define LVDPLLCR_PLLM(n)		((n) << 0)
>
>  #define LVDCTRCR			0x000c
>  #define LVDCTRCR_CTR3SEL_ZERO		(0 << 12)
> @@ -71,4 +86,26 @@
>  #define LVDCHCR_CHSEL_CH(n, c)		((((c) - (n)) & 3) << ((n) * 4))
>  #define LVDCHCR_CHSEL_MASK(n)		(3 << ((n) * 4))
>
> +/* All registers below are specific to D3 and E3 */
> +#define LVDSTRIPE			0x0014
> +#define LVDSTRIPE_ST_TRGSEL_DISP	(0 << 2)
> +#define LVDSTRIPE_ST_TRGSEL_HSYNC_R	(1 << 2)
> +#define LVDSTRIPE_ST_TRGSEL_HSYNC_F	(2 << 2)
> +#define LVDSTRIPE_ST_SWAP		(1 << 1)
> +#define LVDSTRIPE_ST_ON			(1 << 0)
> +
> +#define LVDSCR				0x0018
> +#define LVDSCR_DEPTH(n)			(((n) - 1) << 29)
> +#define LVDSCR_BANDSET			(1 << 28)
> +#define LVDSCR_TWGCNT(n)		((((n) - 256) / 16) << 24)
> +#define LVDSCR_SDIV(n)			((n) << 22)
> +#define LVDSCR_MODE			(1 << 21)
> +#define LVDSCR_RSTN			(1 << 20)
> +
> +#define LVDDIV				0x001c
> +#define LVDDIV_DIVSEL			(1 << 8)
> +#define LVDDIV_DIVRESET			(1 << 7)
> +#define LVDDIV_DIVSTP			(1 << 6)
> +#define LVDDIV_DIV(n)			((n) << 0)
> +
>  #endif /* __RCAR_LVDS_REGS_H__ */
> --
> Regards,
>
> Laurent Pinchart
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH 05/16] drm: rcar-du: lvds: D3/E3 support
@ 2018-09-11 13:23     ` jacopo mondi
  0 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-11 13:23 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 21344 bytes --]

Hi Laurent,

On Tue, Sep 04, 2018 at 03:10:16PM +0300, Laurent Pinchart wrote:
> The LVDS encoders in the D3 and E3 SoCs differ significantly from those
> in the other R-Car Gen3 family members:
>
> - The LVDS PLL architecture is more complex and requires computing PLL
>   parameters manually.
> - The PLL uses external clocks as inputs, which need to be retrieved
>   from DT.
> - In addition to the different PLL setup, the startup sequence has
>   changed *again* (seems someone had trouble making his/her mind).
>
> Supporting all this requires DT bindings extensions for external clocks,
> brand new PLL setup code, and a few quirks to handle the differences in
> the startup sequence.
>
> The implementation doesn't support all hardware features yet, namely
>
> - Using the LV[01] clocks generated by the CPG as PLL input.
> - Providing the LVDS PLL clock to the DU for use with the RGB output.
>
> Those features can be added later when the need will arise.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/rcar-du/rcar_lvds.c      | 365 +++++++++++++++++++++++++++----
>  drivers/gpu/drm/rcar-du/rcar_lvds_regs.h |  43 +++-
>  2 files changed, 361 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> index ce0eb68c3416..aac4acbcfbfc 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
> @@ -24,6 +24,8 @@
>
>  #include "rcar_lvds_regs.h"
>
> +struct rcar_lvds;
> +
>  /* Keep in sync with the LVDCR0.LVMD hardware register values. */
>  enum rcar_lvds_mode {
>  	RCAR_LVDS_MODE_JEIDA = 0,
> @@ -31,14 +33,16 @@ enum rcar_lvds_mode {
>  	RCAR_LVDS_MODE_VESA = 4,
>  };
>
> -#define RCAR_LVDS_QUIRK_LANES	(1 << 0)	/* LVDS lanes 1 and 3 inverted */
> -#define RCAR_LVDS_QUIRK_GEN2_PLLCR (1 << 1)	/* LVDPLLCR has gen2 layout */
> -#define RCAR_LVDS_QUIRK_GEN3_LVEN (1 << 2)	/* LVEN bit needs to be set */
> -						/* on R8A77970/R8A7799x */
> +#define RCAR_LVDS_QUIRK_LANES		BIT(0)	/* LVDS lanes 1 and 3 inverted */
> +#define RCAR_LVDS_QUIRK_GEN3_LVEN	BIT(1)	/* LVEN bit needs to be set on R8A77970/R8A7799x */
> +#define RCAR_LVDS_QUIRK_PWD		BIT(2)	/* PWD bit available (all of Gen3 but E3) */
> +#define RCAR_LVDS_QUIRK_EXT_PLL		BIT(3)	/* Has extended PLL */
> +#define RCAR_LVDS_QUIRK_DUAL_LINK	BIT(4)	/* Supports dual-link operation */
>
>  struct rcar_lvds_device_info {
>  	unsigned int gen;
>  	unsigned int quirks;
> +	void (*pll_setup)(struct rcar_lvds *lvds, unsigned int freq);
>  };
>
>  struct rcar_lvds {
> @@ -52,7 +56,11 @@ struct rcar_lvds {
>  	struct drm_panel *panel;
>
>  	void __iomem *mmio;
> -	struct clk *clock;
> +	struct {
> +		struct clk *mod;		/* CPG module clock */
> +		struct clk *extal;		/* External clock */
> +		struct clk *dotclkin[2];	/* External DU clocks */
> +	} clocks;
>  	bool enabled;
>
>  	struct drm_display_mode display_mode;
> @@ -128,33 +136,222 @@ static const struct drm_connector_funcs rcar_lvds_conn_funcs = {
>  };
>
>  /* -----------------------------------------------------------------------------
> - * Bridge
> + * PLL Setup
>   */
>
> -static u32 rcar_lvds_lvdpllcr_gen2(unsigned int freq)
> +static void rcar_lvds_pll_setup_gen2(struct rcar_lvds *lvds, unsigned int freq)
> +{
> +	u32 val;
> +
> +	if (freq < 39000000)
> +		val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
> +	else if (freq < 61000000)
> +		val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
> +	else if (freq < 121000000)
> +		val = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
> +	else
> +		val = LVDPLLCR_PLLDLYCNT_150M;
> +
> +	rcar_lvds_write(lvds, LVDPLLCR, val);
> +}
> +
> +static void rcar_lvds_pll_setup_gen3(struct rcar_lvds *lvds, unsigned int freq)
>  {
> -	if (freq < 39000)
> -		return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
> -	else if (freq < 61000)
> -		return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
> -	else if (freq < 121000)
> -		return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
> +	u32 val;
> +
> +	if (freq < 42000000)
> +		val = LVDPLLCR_PLLDIVCNT_42M;
> +	else if (freq < 85000000)
> +		val = LVDPLLCR_PLLDIVCNT_85M;
> +	else if (freq < 128000000)
> +		val = LVDPLLCR_PLLDIVCNT_128M;
>  	else
> -		return LVDPLLCR_PLLDLYCNT_150M;
> +		val = LVDPLLCR_PLLDIVCNT_148M;
> +
> +	rcar_lvds_write(lvds, LVDPLLCR, val);
> +}
> +
> +struct pll_info {
> +	struct clk *clk;
> +	unsigned long diff;
> +	unsigned int pll_m;
> +	unsigned int pll_n;
> +	unsigned int pll_e;
> +	unsigned int div;
> +};
> +
> +static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk,
> +				     unsigned long target, struct pll_info *pll)

Do you think it is worth mentioning d3_e3 in the function name? I know
it's not a big deal, but in future generation this PLL circuit may be
re-used.

> +{
> +	unsigned long fin;
> +	unsigned int m_min;
> +	unsigned int m_max;
> +	unsigned int m;
> +
> +	if (!clk)
> +		return;
> +
> +	/*
> +	 * The LVDS PLL is made of a pre-divider and a multiplier (strangerly
> +	 * enough called M and N respectively), followed by a post-divider E.
> +	 *
> +	 *         ,-----.         ,-----.     ,-----.         ,-----.
> +	 * Fin --> | 1/M | -Fpdf-> | PFD | --> | VCO | -Fvco-> | 1/E | --> Fout
> +	 *         `-----'     ,-> |     |     `-----'   |     `-----'
> +	 *                     |   `-----'               |
> +	 *                     |         ,-----.         |
> +	 *                     `-------- | 1/N | <-------'
> +	 *                               `-----'
> +	 *
> +	 * The clock output by the PLL is then further divided by a programmable
> +	 * divider DIV to achieve the desired target frequency. Finally, an
> +	 * optional fixed /7 divider is used to convert the bit clock to a pixel
> +	 * clock (as LVDS transmits 7 bits per lane per clock sample).
> +	 *
> +	 *          ,-------.     ,-----.     |\
> +	 * Fout --> | 1/DIV | --> | 1/7 | --> | |
> +	 *          `-------'  |  `-----'     | | --> dot clock
> +	 *                     `------------> | |
> +	 *                                    |/
> +	 *
> +	 * The /7 divider is optional when the LVDS PLL is used to generate a
> +	 * dot clock for the DU RGB output, without using the LVDS encoder. We
> +	 * don't support this configuration yet.
> +	 *
> +	 * The PLL allowed input frequency range is 12 MHz to 192 MHz.
> +	 */
> +
> +	fin = clk_get_rate(clk);
> +	if (fin < 12000000 || fin > 192000000)
> +		return;
> +
> +	/*
> +	 * The comparison frequency range is 12 MHz to 24 MHz, which limits the
> +	 * allowed values for the pre-divider M (normal range 1-8).
> +	 *
> +	 * Fpfd = Fin / M
> +	 */
> +	m_min = max_t(unsigned int, 1, DIV_ROUND_UP(fin, 24000000));
> +	m_max = min_t(unsigned int, 8, fin / 12000000);
> +
> +	for (m = m_min; m <= m_max; ++m) {
> +		unsigned long fpfd;
> +		unsigned int n_min;
> +		unsigned int n_max;
> +		unsigned int n;
> +
> +		/*
> +		 * The VCO operating range is 900 Mhz to 1800 MHz, which limits
> +		 * the allowed values for the multiplier N (normal range
> +		 * 60-120).
> +		 *
> +		 * Fvco = Fin * N / M
> +		 */
> +		fpfd = fin / m;
> +		n_min = max_t(unsigned int, 60, DIV_ROUND_UP(900000000, fpfd));
> +		n_max = min_t(unsigned int, 120, 1800000000 / fpfd);
> +
> +		for (n = n_min; n < n_max; ++n) {
> +			unsigned long fvco;
> +			unsigned int e_min;
> +			unsigned int e;
> +
> +			/*
> +			 * The output frequency is limited to 1039.5 MHz,
> +			 * limiting again the allowed values for the
> +			 * post-divider E (normal value 1, 2 or 4).
> +			 *
> +			 * Fout = Fvco / E
> +			 */
> +			fvco = fpfd * n;
> +			e_min = fvco > 1039500000 ? 1 : 0;
> +
> +			for (e = e_min; e < 3; ++e) {
> +				unsigned long fout;
> +				unsigned long diff;
> +				unsigned int div;
> +
> +				/*
> +				 * Finally we have a programable divider after
> +				 * the PLL, followed by a an optional fixed /7
> +				 * divider.
> +				 */
> +				fout = fvco / (1 << e) / 7;
> +				div = DIV_ROUND_CLOSEST(fout, target);
> +				diff = abs(fout / div - target);
> +
> +				if (diff < pll->diff) {
> +					pll->clk = clk;
> +					pll->diff = diff;
> +					pll->pll_m = m;
> +					pll->pll_n = n;
> +					pll->pll_e = e;
> +					pll->div = div;
> +
> +					if (diff == 0)
> +						goto done;
> +				}
> +			}
> +		}
> +	}

Very nice :)

> +
> +done:
> +#if defined(CONFIG_DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
> +	{
> +		unsigned long output = fin * pll->pll_n / pll->pll_m
> +				     / (1 << pll->pll_e) / 7 / pll->div;
> +		int error = (long)(output - target) * 10000 / (long)target;
> +
> +		dev_dbg(lvds->dev,
> +			"%pC %lu Hz -> Fout %lu Hz (target %lu Hz, error %d.%02u%%), PLL M/N/E/DIV %u/%u/%u/%u\n",
> +			clk, fin, output, target, error / 100,
> +			error < 0 ? -error % 100 : error % 100,
> +			pll->pll_m, pll->pll_n, pll->pll_e, pll->div);
> +	}
> +#endif

I know you know about this already, but

../drivers/gpu/drm/rcar-du/rcar_lvds.c:298:1: error: label at end of
compound statement

I'm still not sure what actually disturbs gcc here

>  }
>
> -static u32 rcar_lvds_lvdpllcr_gen3(unsigned int freq)
> +static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned int freq)
>  {
> -	if (freq < 42000)
> -		return LVDPLLCR_PLLDIVCNT_42M;
> -	else if (freq < 85000)
> -		return LVDPLLCR_PLLDIVCNT_85M;
> -	else if (freq < 128000)
> -		return LVDPLLCR_PLLDIVCNT_128M;
> +	struct drm_crtc *crtc = lvds->bridge.encoder->crtc;
> +	struct pll_info pll = { .diff = (unsigned long)-1 };
> +	u32 lvdpllcr;
> +
> +	if (lvds->clocks.dotclkin[0] || lvds->clocks.dotclkin[1]) {
> +		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[0],
> +					 freq, &pll);
> +		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[1],
> +					 freq, &pll);
> +	} else if (lvds->clocks.extal) {
> +		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.extal,
> +					 freq, &pll);
> +	}

here it's either ((dotclkin[0] or dotclock[1]) or extal). Are they
mutually exclusive? Can't we try all of them? The probe routine
guarantees we have at least of of them...

> +
> +	lvdpllcr = LVDPLLCR_PLLON | LVDPLLCR_CLKOUT
> +		 | LVDPLLCR_PLLN(pll.pll_n - 1) | LVDPLLCR_PLLM(pll.pll_m - 1);
> +
> +	if (pll.clk == lvds->clocks.extal)
> +		lvdpllcr |= LVDPLLCR_CKSEL_EXTAL;
> +	else
> +		lvdpllcr |= LVDPLLCR_CKSEL_DU_DOTCLKIN(drm_crtc_index(crtc));

Here you select du_clkin[0] or du_clkin[1] based on the DU index (btw,
the drm_crtc_index() function is funny, it simply "crtc->index" no
checks, no validation, what's the benefit of using it?).

Looking at the LVDS PLL block diagram for D3/E3 (Figure 37.3) I see
that both clkin[0] and clkin[1] could be used independently from the du
index. Shouldn't we use the one performing better? (now how to make
sure it gets not selected twice in case of both DU0 and DU1 using the
LVDS PLL it's another problem)

> +
> +	if (pll.pll_e > 0)
> +		lvdpllcr |= LVDPLLCR_STP_CLKOUTE | LVDPLLCR_OUTCLKSEL
> +			 |  LVDPLLCR_PLLE(pll.pll_e - 1);
> +
> +	rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
> +
> +	if (pll.div > 1)
> +		rcar_lvds_write(lvds, LVDDIV, LVDDIV_DIVSEL |
> +				LVDDIV_DIVRESET | LVDDIV_DIV(pll.div - 1));
>  	else
> -		return LVDPLLCR_PLLDIVCNT_148M;
> +		rcar_lvds_write(lvds, LVDDIV, 0);
>  }
>
> +/* -----------------------------------------------------------------------------
> + * Bridge
> + */
> +
>  static void rcar_lvds_enable(struct drm_bridge *bridge)
>  {
>  	struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
> @@ -164,14 +361,13 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
>  	 * do we get a state pointer?
>  	 */
>  	struct drm_crtc *crtc = lvds->bridge.encoder->crtc;
> -	u32 lvdpllcr;
>  	u32 lvdhcr;
>  	u32 lvdcr0;
>  	int ret;
>
>  	WARN_ON(lvds->enabled);
>
> -	ret = clk_prepare_enable(lvds->clock);
> +	ret = clk_prepare_enable(lvds->clocks.mod);
>  	if (ret < 0)
>  		return;
>
> @@ -196,12 +392,13 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
>
>  	rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
>
> +	if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) {
> +		/* Disable dual-link mode. */
> +		rcar_lvds_write(lvds, LVDSTRIPE, 0);
> +	}
> +
>  	/* PLL clock configuration. */
> -	if (lvds->info->quirks & RCAR_LVDS_QUIRK_GEN2_PLLCR)
> -		lvdpllcr = rcar_lvds_lvdpllcr_gen2(mode->clock);
> -	else
> -		lvdpllcr = rcar_lvds_lvdpllcr_gen3(mode->clock);
> -	rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
> +	lvds->info->pll_setup(lvds, mode->clock * 1000);
>
>  	/* Set the LVDS mode and select the input. */
>  	lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT;
> @@ -220,11 +417,16 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
>  		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
>  	}
>
> -	/* Turn the PLL on. */
> -	lvdcr0 |= LVDCR0_PLLON;
> -	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
> +	if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) {
> +		/*
> +		 * Turn the PLL on (simple PLL only, extended PLL is fully
> +		 * controlled through LVDPLLCR).
> +		 */
> +		lvdcr0 |= LVDCR0_PLLON;
> +		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
> +	}
>
> -	if (lvds->info->gen > 2) {
> +	if (lvds->info->quirks & RCAR_LVDS_QUIRK_PWD) {
>  		/* Set LVDS normal mode. */
>  		lvdcr0 |= LVDCR0_PWD;
>  		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
> @@ -236,8 +438,10 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
>  		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
>  	}
>
> -	/* Wait for the startup delay. */
> -	usleep_range(100, 150);
> +	if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) {
> +		/* Wait for the PLL startup delay (simple PLL only). */
> +		usleep_range(100, 150);
> +	}
>
>  	/* Turn the output on. */
>  	lvdcr0 |= LVDCR0_LVRES;
> @@ -264,8 +468,9 @@ static void rcar_lvds_disable(struct drm_bridge *bridge)
>
>  	rcar_lvds_write(lvds, LVDCR0, 0);
>  	rcar_lvds_write(lvds, LVDCR1, 0);
> +	rcar_lvds_write(lvds, LVDPLLCR, 0);
>
> -	clk_disable_unprepare(lvds->clock);
> +	clk_disable_unprepare(lvds->clocks.mod);
>
>  	lvds->enabled = false;
>  }
> @@ -446,6 +651,60 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
>  	return ret;
>  }
>
> +static struct clk *rcar_lvds_get_clock(struct rcar_lvds *lvds, const char *name,
> +				       bool optional)
> +{
> +	struct clk *clk;
> +
> +	clk = devm_clk_get(lvds->dev, name);

I wish we had clk_get_optional() as we have gpiod_get_optional().
There are probably good reasons if it's not there though...

> +	if (!IS_ERR(clk))
> +		return clk;
> +
> +	if (PTR_ERR(clk) == -ENOENT && optional)
> +		return NULL;
> +
> +	if (PTR_ERR(clk) != -EPROBE_DEFER)
> +		dev_err(lvds->dev, "failed to get %s clock\n",
> +			name ? name : "module");
> +
> +	return clk;
> +}
> +
> +static int rcar_lvds_get_clocks(struct rcar_lvds *lvds)
> +{
> +	lvds->clocks.mod = rcar_lvds_get_clock(lvds, NULL, false);
> +	if (IS_ERR(lvds->clocks.mod))
> +		return PTR_ERR(lvds->clocks.mod);
> +
> +	/*
> +	 * LVDS encoders without an extended PLL have no external clock inputs.
> +	 */
> +	if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL))
> +		return 0;
> +
> +	lvds->clocks.extal = rcar_lvds_get_clock(lvds, "extal", true);
> +	if (IS_ERR(lvds->clocks.extal))
> +		return PTR_ERR(lvds->clocks.extal);
> +
> +	lvds->clocks.dotclkin[0] = rcar_lvds_get_clock(lvds, "dclkin.0", true);
> +	if (IS_ERR(lvds->clocks.dotclkin[0]))
> +		return PTR_ERR(lvds->clocks.dotclkin[0]);
> +
> +	lvds->clocks.dotclkin[1] = rcar_lvds_get_clock(lvds, "dclkin.1", true);
> +	if (IS_ERR(lvds->clocks.dotclkin[1]))
> +		return PTR_ERR(lvds->clocks.dotclkin[1]);
> +
> +	/* At least one input to the PLL must be available. */
> +	if (!lvds->clocks.extal && !lvds->clocks.dotclkin[0] &&
> +	    !lvds->clocks.dotclkin[1]) {
> +		dev_err(lvds->dev,
> +			"no input clock (extal, dclkin.0 or dclkin.1)\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
>  static int rcar_lvds_probe(struct platform_device *pdev)
>  {
>  	struct rcar_lvds *lvds;
> @@ -475,11 +734,9 @@ static int rcar_lvds_probe(struct platform_device *pdev)
>  	if (IS_ERR(lvds->mmio))
>  		return PTR_ERR(lvds->mmio);
>
> -	lvds->clock = devm_clk_get(&pdev->dev, NULL);
> -	if (IS_ERR(lvds->clock)) {
> -		dev_err(&pdev->dev, "failed to get clock\n");
> -		return PTR_ERR(lvds->clock);
> -	}
> +	ret = rcar_lvds_get_clocks(lvds);
> +	if (ret < 0)
> +		return ret;
>
>  	drm_bridge_add(&lvds->bridge);
>
> @@ -497,21 +754,39 @@ static int rcar_lvds_remove(struct platform_device *pdev)
>
>  static const struct rcar_lvds_device_info rcar_lvds_gen2_info = {
>  	.gen = 2,
> -	.quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR,
> +	.pll_setup = rcar_lvds_pll_setup_gen2,
>  };
>
>  static const struct rcar_lvds_device_info rcar_lvds_r8a7790_info = {
>  	.gen = 2,
> -	.quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR | RCAR_LVDS_QUIRK_LANES,
> +	.quirks = RCAR_LVDS_QUIRK_LANES,
> +	.pll_setup = rcar_lvds_pll_setup_gen2,
>  };
>
>  static const struct rcar_lvds_device_info rcar_lvds_gen3_info = {
>  	.gen = 3,
> +	.quirks = RCAR_LVDS_QUIRK_PWD,
> +	.pll_setup = rcar_lvds_pll_setup_gen3,
>  };
>
>  static const struct rcar_lvds_device_info rcar_lvds_r8a77970_info = {
>  	.gen = 3,
> -	.quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR | RCAR_LVDS_QUIRK_GEN3_LVEN,
> +	.quirks = RCAR_LVDS_QUIRK_PWD | RCAR_LVDS_QUIRK_GEN3_LVEN,
> +	.pll_setup = rcar_lvds_pll_setup_gen2,
> +};
> +
> +static const struct rcar_lvds_device_info rcar_lvds_r8a77990_info = {
> +	.gen = 3,
> +	.quirks = RCAR_LVDS_QUIRK_GEN3_LVEN | RCAR_LVDS_QUIRK_EXT_PLL
> +		| RCAR_LVDS_QUIRK_DUAL_LINK,
> +	.pll_setup = rcar_lvds_pll_setup_d3_e3,
> +};
> +
> +static const struct rcar_lvds_device_info rcar_lvds_r8a77995_info = {
> +	.gen = 3,
> +	.quirks = RCAR_LVDS_QUIRK_GEN3_LVEN | RCAR_LVDS_QUIRK_PWD
> +		| RCAR_LVDS_QUIRK_EXT_PLL | RCAR_LVDS_QUIRK_DUAL_LINK,
> +	.pll_setup = rcar_lvds_pll_setup_d3_e3,
>  };
>
>  static const struct of_device_id rcar_lvds_of_table[] = {
> @@ -523,6 +798,8 @@ static const struct of_device_id rcar_lvds_of_table[] = {
>  	{ .compatible = "renesas,r8a7796-lvds", .data = &rcar_lvds_gen3_info },
>  	{ .compatible = "renesas,r8a77970-lvds", .data = &rcar_lvds_r8a77970_info },
>  	{ .compatible = "renesas,r8a77980-lvds", .data = &rcar_lvds_gen3_info },
> +	{ .compatible = "renesas,r8a77990-lvds", .data = &rcar_lvds_r8a77990_info },
> +	{ .compatible = "renesas,r8a77995-lvds", .data = &rcar_lvds_r8a77995_info },
>  	{ }
>  };
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h
> index 4870f50d9bec..87149f2f8056 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_PLLON			(1 << 4)
>  #define LVDCR0_PWD			(1 << 2)		/* Gen3 only */
>  #define LVDCR0_BEN			(1 << 2)		/* Gen2 only */
> -#define LVDCR0_LVEN			(1 << 1)		/* Gen2 only */
> +#define LVDCR0_LVEN			(1 << 1)
>  #define LVDCR0_LVRES			(1 << 0)
>
>  #define LVDCR1				0x0004
> @@ -27,21 +27,36 @@
>  #define LVDCR1_CLKSTBY			(3 << 0)
>
>  #define LVDPLLCR			0x0008
> +/* Gen2 & V3M */
>  #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 */
> +/* Gen3 but V3M,D3 and E3 */
>  #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)
> +/* D3 and E3 */
> +#define LVDPLLCR_PLLON			(1 << 22)
> +#define LVDPLLCR_PLLSEL_PLL0		(0 << 20)
> +#define LVDPLLCR_PLLSEL_LVX		(1 << 20)
> +#define LVDPLLCR_PLLSEL_PLL1		(2 << 20)
> +#define LVDPLLCR_CKSEL_LVX		(1 << 17)
> +#define LVDPLLCR_CKSEL_EXTAL		(3 << 17)
> +#define LVDPLLCR_CKSEL_DU_DOTCLKIN(n)	((5 + (n) * 2) << 17)
> +#define LVDPLLCR_OCKSEL			(1 << 16)
> +#define LVDPLLCR_STP_CLKOUTE		(1 << 14)
> +#define LVDPLLCR_OUTCLKSEL		(1 << 12)
> +#define LVDPLLCR_CLKOUT			(1 << 11)
> +#define LVDPLLCR_PLLE(n)		((n) << 10)
> +#define LVDPLLCR_PLLN(n)		((n) << 3)
> +#define LVDPLLCR_PLLM(n)		((n) << 0)
>
>  #define LVDCTRCR			0x000c
>  #define LVDCTRCR_CTR3SEL_ZERO		(0 << 12)
> @@ -71,4 +86,26 @@
>  #define LVDCHCR_CHSEL_CH(n, c)		((((c) - (n)) & 3) << ((n) * 4))
>  #define LVDCHCR_CHSEL_MASK(n)		(3 << ((n) * 4))
>
> +/* All registers below are specific to D3 and E3 */
> +#define LVDSTRIPE			0x0014
> +#define LVDSTRIPE_ST_TRGSEL_DISP	(0 << 2)
> +#define LVDSTRIPE_ST_TRGSEL_HSYNC_R	(1 << 2)
> +#define LVDSTRIPE_ST_TRGSEL_HSYNC_F	(2 << 2)
> +#define LVDSTRIPE_ST_SWAP		(1 << 1)
> +#define LVDSTRIPE_ST_ON			(1 << 0)
> +
> +#define LVDSCR				0x0018
> +#define LVDSCR_DEPTH(n)			(((n) - 1) << 29)
> +#define LVDSCR_BANDSET			(1 << 28)
> +#define LVDSCR_TWGCNT(n)		((((n) - 256) / 16) << 24)
> +#define LVDSCR_SDIV(n)			((n) << 22)
> +#define LVDSCR_MODE			(1 << 21)
> +#define LVDSCR_RSTN			(1 << 20)
> +
> +#define LVDDIV				0x001c
> +#define LVDDIV_DIVSEL			(1 << 8)
> +#define LVDDIV_DIVRESET			(1 << 7)
> +#define LVDDIV_DIVSTP			(1 << 6)
> +#define LVDDIV_DIV(n)			((n) << 0)
> +
>  #endif /* __RCAR_LVDS_REGS_H__ */
> --
> Regards,
>
> Laurent Pinchart
>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* Re: [PATCH 04/16] drm: bridge: thc63: Restrict modes based on hardware operating frequency
  2018-09-04 12:10   ` Laurent Pinchart
@ 2018-09-11 13:31     ` jacopo mondi
  -1 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-11 13:31 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: dri-devel, linux-renesas-soc, Archit Taneja, Andrzej Hajda

[-- Attachment #1: Type: text/plain, Size: 2334 bytes --]

Hi Laurent,
   sorry, I might be confused but,

On Tue, Sep 04, 2018 at 03:10:15PM +0300, Laurent Pinchart wrote:
> The THC63LVD1024 is restricted to a pixel clock frequency in the range
> of 8 to 135 MHz. Implement the bridge .mode_valid() operation
> accordingly.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/bridge/thc63lvd1024.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
>
> diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c b/drivers/gpu/drm/bridge/thc63lvd1024.c
> index c8b9edd5a7f4..63609ba16b6d 100644
> --- a/drivers/gpu/drm/bridge/thc63lvd1024.c
> +++ b/drivers/gpu/drm/bridge/thc63lvd1024.c
> @@ -45,6 +45,23 @@ static int thc63_attach(struct drm_bridge *bridge)
>  	return drm_bridge_attach(bridge->encoder, thc63->next, bridge);
>  }
>
> +static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge,
> +					const struct drm_display_mode *mode)
> +{
> +	/*
> +	 * The THC63LVD0124 clock frequency range is 8 to 135 MHz in single-in,
> +	 * single-out mode. Note that the limits depends on the mode and will
> +	 * need to be adjusted accordingly.
> +	 */
> +	if (mode->clock < 8000)
> +		return MODE_CLOCK_LOW;
> +
> +	if (mode->clock > 135000)
> +		return MODE_CLOCK_HIGH;
> +
> +	return MODE_OK;
> +}
> +

Are we talking about the CLKOUT frequency? Because that's the one I
see depending on the dual/single output mode, and I assume we're
checking for the mode->clock of the DRM mode to be applied to the
connector (which receives an RGB stream from this bridge).

In case we're talking about CLKOUT, I read

"Dual LVDS port IN/Dual TTL port Out Mode:
 8 - 135MHz(CLKOUT)
 Dual LVDS port IN/Single TTL port Out Mode:
 40 - 150MHz(CLKOUT)"

If we're talking about the PLL input clock (RCLK) then used to
generate CLKOUT it's indeed defined in the 8-135Mhz range, but
I don't see mention on it depending on the mode.

>  static void thc63_enable(struct drm_bridge *bridge)
>  {
>  	struct thc63_dev *thc63 = to_thc63(bridge);
> @@ -77,6 +94,7 @@ static void thc63_disable(struct drm_bridge *bridge)
>
>  static const struct drm_bridge_funcs thc63_bridge_func = {
>  	.attach	= thc63_attach,
> +	.mode_valid = thc63_mode_valid,
>  	.enable = thc63_enable,
>  	.disable = thc63_disable,
>  };
> --
> Regards,
>
> Laurent Pinchart
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH 04/16] drm: bridge: thc63: Restrict modes based on hardware operating frequency
@ 2018-09-11 13:31     ` jacopo mondi
  0 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-11 13:31 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 2334 bytes --]

Hi Laurent,
   sorry, I might be confused but,

On Tue, Sep 04, 2018 at 03:10:15PM +0300, Laurent Pinchart wrote:
> The THC63LVD1024 is restricted to a pixel clock frequency in the range
> of 8 to 135 MHz. Implement the bridge .mode_valid() operation
> accordingly.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/bridge/thc63lvd1024.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
>
> diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c b/drivers/gpu/drm/bridge/thc63lvd1024.c
> index c8b9edd5a7f4..63609ba16b6d 100644
> --- a/drivers/gpu/drm/bridge/thc63lvd1024.c
> +++ b/drivers/gpu/drm/bridge/thc63lvd1024.c
> @@ -45,6 +45,23 @@ static int thc63_attach(struct drm_bridge *bridge)
>  	return drm_bridge_attach(bridge->encoder, thc63->next, bridge);
>  }
>
> +static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge,
> +					const struct drm_display_mode *mode)
> +{
> +	/*
> +	 * The THC63LVD0124 clock frequency range is 8 to 135 MHz in single-in,
> +	 * single-out mode. Note that the limits depends on the mode and will
> +	 * need to be adjusted accordingly.
> +	 */
> +	if (mode->clock < 8000)
> +		return MODE_CLOCK_LOW;
> +
> +	if (mode->clock > 135000)
> +		return MODE_CLOCK_HIGH;
> +
> +	return MODE_OK;
> +}
> +

Are we talking about the CLKOUT frequency? Because that's the one I
see depending on the dual/single output mode, and I assume we're
checking for the mode->clock of the DRM mode to be applied to the
connector (which receives an RGB stream from this bridge).

In case we're talking about CLKOUT, I read

"Dual LVDS port IN/Dual TTL port Out Mode:
 8 - 135MHz(CLKOUT)
 Dual LVDS port IN/Single TTL port Out Mode:
 40 - 150MHz(CLKOUT)"

If we're talking about the PLL input clock (RCLK) then used to
generate CLKOUT it's indeed defined in the 8-135Mhz range, but
I don't see mention on it depending on the mode.

>  static void thc63_enable(struct drm_bridge *bridge)
>  {
>  	struct thc63_dev *thc63 = to_thc63(bridge);
> @@ -77,6 +94,7 @@ static void thc63_disable(struct drm_bridge *bridge)
>
>  static const struct drm_bridge_funcs thc63_bridge_func = {
>  	.attach	= thc63_attach,
> +	.mode_valid = thc63_mode_valid,
>  	.enable = thc63_enable,
>  	.disable = thc63_disable,
>  };
> --
> Regards,
>
> Laurent Pinchart
>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* Re: [PATCH 07/16] drm: rcar-du: Use LVDS PLL clock as dot clock when possible
  2018-09-04 12:10   ` Laurent Pinchart
@ 2018-09-11 14:59     ` jacopo mondi
  -1 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-11 14:59 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel, linux-renesas-soc

[-- Attachment #1: Type: text/plain, Size: 7024 bytes --]

Hi Laurent,

On Tue, Sep 04, 2018 at 03:10:18PM +0300, Laurent Pinchart wrote:
> On selected SoCs, the DU can use the clock output by the LVDS encoder
> PLL as its input dot clock. This feature is optional, but on the D3 and
> E3 SoC it is often the only way to obtain a precise dot clock frequency,
> as the other available clocks (CPG-generated clock and external clock)
> usually have fixed rates.
>
> Add a DU model information field to describe which DU channels can use
> the LVDS PLL output clock as their input clock, and configure clock
> routing accordingly.
>
> This feature is available on H2, M2-W, M2-N, D3 and E3 SoCs, with D3 and
> E3 being the primary targets. It is left disabled in this commit, and
> will be enabled per-SoC after careful testing.
>
> At the hardware level, clock routing is configured at runtime in two
> steps, first selecting an internal dot clock between the LVDS PLL clock
> and the external DOTCLKIN clock, and then selecting between the internal
> dot clock and the CPG-generated clock. The first part requires stopping
> the whole DU group in order for the change to take effect, thus causing
> flickering on the screen. For this reason we currently hardcode the
> clock source the the LVDS PLL clock if available, and allow flicker-free

s/the the/to the/ ?

> selection of the external DOTCLKIN clock or CPG-generated clock
> otherwise. A more dynamic clock selection process can be implemented
> later if the need arises.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  8 +++++
>  drivers/gpu/drm/rcar-du/rcar_du_drv.h   |  2 ++
>  drivers/gpu/drm/rcar-du/rcar_du_group.c | 64 +++++++++++++++++++++++++--------
>  3 files changed, 59 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> index 1d81eb244441..39d2fee6d7b8 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> @@ -261,6 +261,14 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
>  		rcar_du_group_write(rcrtc->group, DPLLCR, dpllcr);
>
>  		escr = ESCR_DCLKSEL_DCLKIN | div;
> +	} else if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) {
> +		/*
> +		 * Use the LVDS PLL output as the dot clock when outputting to
> +		 * the LVDS encoder on an SoC that supports this clock routing
> +		 * option. We use the clock directly in that case, without any
> +		 * additional divider.
> +		 */
> +		escr = ESCR_DCLKSEL_DCLKIN;

This confused me, but we have later clarified offline.
Setting the DCLKIN bit alone does not guarantee that we use the LVDS
PLL clock output, but the DIDSR mux must be configured to select LVDS
over dotclkin[0] or dotclkin[1] first. Would you consider mentioning DIDSR
in the comment here?

>  	} else {
>  		struct du_clk_params params = { .diff = (unsigned long)-1 };
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> index fef9ea5c22f3..ebba9aefba6a 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> @@ -53,6 +53,7 @@ struct rcar_du_output_routing {
>   * @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*)
>   * @num_lvds: number of internal LVDS encoders
>   * @dpll_mask: bit mask of DU channels equipped with a DPLL
> + * @lvds_clk_mask: bitmask of channels that can use the LVDS clock as dot clock
>   */
>  struct rcar_du_device_info {
>  	unsigned int gen;
> @@ -62,6 +63,7 @@ struct rcar_du_device_info {
>  	struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX];
>  	unsigned int num_lvds;
>  	unsigned int dpll_mask;
> +	unsigned int lvds_clk_mask;
>  };
>
>  #define RCAR_DU_MAX_CRTCS		4
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> index ef2c177afb6d..4c62841eff2f 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> @@ -89,6 +89,54 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
>  	rcar_du_group_write(rgrp, DEFR8, defr8);
>  }
>
> +static void rcar_du_group_setup_didsr(struct rcar_du_group *rgrp)
> +{
> +	struct rcar_du_device *rcdu = rgrp->dev;
> +	struct rcar_du_crtc *rcrtc;
> +	unsigned int num_crtcs = 0;
> +	unsigned int i;
> +	u32 didsr;
> +
> +	/*
> +	 * Configure input dot clock routing with a hardcoded configuration. If
> +	 * the DU channel can use the LVDS encoder output clock as the dot
> +	 * clock, do so. Otherwise route DU_DOTCLKINn signal to DUn.
> +	 *
> +	 * Each channel can then select between the dot clock configured here
> +	 * and the clock provided by the CPG through the ESCR register.
> +	 */

well, you mention ESCR here, so maybe no need to do the same above...
up to you...

> +	if (rcdu->info->gen < 3 && rgrp->index == 0) {
> +		/*
> +		 * On Gen2 a single register in the first group controls dot
> +		 * clock selection for all channels.
> +		 */
> +		rcrtc = rcdu->crtcs;
> +		num_crtcs = rcdu->num_crtcs;
> +	} else if (rcdu->info->gen == 3 && rgrp->num_crtcs > 1) {
> +		/*
> +		 * On Gen3 dot clocks are setup through per-group registers,
> +		 * only available when the group has two channels.
> +		 */
> +		rcrtc = &rcdu->crtcs[rgrp->index * 2];
> +		num_crtcs = rgrp->num_crtcs;
> +	}
> +
> +	if (!num_crtcs)
> +		return;
> +
> +	didsr = DIDSR_CODE;
> +	for (i = 0; i < num_crtcs; ++i, ++rcrtc) {
> +		if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index))
> +			didsr |= DIDSR_LCDS_LVDS0(i)
> +			      |  DIDSR_PDCS_CLK(i, 0);
> +		else
> +			didsr |= DIDSR_LCDS_DCLKIN(i)
> +			      |  DIDSR_PDCS_CLK(i, 0);
> +	}
> +
> +	rcar_du_group_write(rgrp, DIDSR, didsr);
> +}
> +
>  static void rcar_du_group_setup(struct rcar_du_group *rgrp)
>  {
>  	struct rcar_du_device *rcdu = rgrp->dev;
> @@ -106,21 +154,7 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
>
>  	if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) {
>  		rcar_du_group_setup_defr8(rgrp);
> -
> -		/*
> -		 * Configure input dot clock routing. We currently hardcode the
> -		 * configuration to routing DOTCLKINn to DUn. Register fields
> -		 * depend on the DU generation, but the resulting value is 0 in
> -		 * all cases.
> -		 *
> -		 * On Gen2 a single register in the first group controls dot
> -		 * clock selection for all channels, while on Gen3 dot clocks
> -		 * are setup through per-group registers, only available when
> -		 * the group has two channels.
> -		 */
> -		if ((rcdu->info->gen < 3 && rgrp->index == 0) ||
> -		    (rcdu->info->gen == 3 &&  rgrp->num_crtcs > 1))
> -			rcar_du_group_write(rgrp, DIDSR, DIDSR_CODE);
> +		rcar_du_group_setup_didsr(rgrp);

This setting is performed for all Gen3 SoCs, while relevant only for
D3/E3. It doens't harm though.

Only minor comments, so
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

Thanks
  j

>  	}
>
>  	if (rcdu->info->gen >= 3)
> --
> Regards,
>
> Laurent Pinchart
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH 07/16] drm: rcar-du: Use LVDS PLL clock as dot clock when possible
@ 2018-09-11 14:59     ` jacopo mondi
  0 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-11 14:59 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 7024 bytes --]

Hi Laurent,

On Tue, Sep 04, 2018 at 03:10:18PM +0300, Laurent Pinchart wrote:
> On selected SoCs, the DU can use the clock output by the LVDS encoder
> PLL as its input dot clock. This feature is optional, but on the D3 and
> E3 SoC it is often the only way to obtain a precise dot clock frequency,
> as the other available clocks (CPG-generated clock and external clock)
> usually have fixed rates.
>
> Add a DU model information field to describe which DU channels can use
> the LVDS PLL output clock as their input clock, and configure clock
> routing accordingly.
>
> This feature is available on H2, M2-W, M2-N, D3 and E3 SoCs, with D3 and
> E3 being the primary targets. It is left disabled in this commit, and
> will be enabled per-SoC after careful testing.
>
> At the hardware level, clock routing is configured at runtime in two
> steps, first selecting an internal dot clock between the LVDS PLL clock
> and the external DOTCLKIN clock, and then selecting between the internal
> dot clock and the CPG-generated clock. The first part requires stopping
> the whole DU group in order for the change to take effect, thus causing
> flickering on the screen. For this reason we currently hardcode the
> clock source the the LVDS PLL clock if available, and allow flicker-free

s/the the/to the/ ?

> selection of the external DOTCLKIN clock or CPG-generated clock
> otherwise. A more dynamic clock selection process can be implemented
> later if the need arises.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  8 +++++
>  drivers/gpu/drm/rcar-du/rcar_du_drv.h   |  2 ++
>  drivers/gpu/drm/rcar-du/rcar_du_group.c | 64 +++++++++++++++++++++++++--------
>  3 files changed, 59 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> index 1d81eb244441..39d2fee6d7b8 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> @@ -261,6 +261,14 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
>  		rcar_du_group_write(rcrtc->group, DPLLCR, dpllcr);
>
>  		escr = ESCR_DCLKSEL_DCLKIN | div;
> +	} else if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) {
> +		/*
> +		 * Use the LVDS PLL output as the dot clock when outputting to
> +		 * the LVDS encoder on an SoC that supports this clock routing
> +		 * option. We use the clock directly in that case, without any
> +		 * additional divider.
> +		 */
> +		escr = ESCR_DCLKSEL_DCLKIN;

This confused me, but we have later clarified offline.
Setting the DCLKIN bit alone does not guarantee that we use the LVDS
PLL clock output, but the DIDSR mux must be configured to select LVDS
over dotclkin[0] or dotclkin[1] first. Would you consider mentioning DIDSR
in the comment here?

>  	} else {
>  		struct du_clk_params params = { .diff = (unsigned long)-1 };
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> index fef9ea5c22f3..ebba9aefba6a 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
> @@ -53,6 +53,7 @@ struct rcar_du_output_routing {
>   * @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*)
>   * @num_lvds: number of internal LVDS encoders
>   * @dpll_mask: bit mask of DU channels equipped with a DPLL
> + * @lvds_clk_mask: bitmask of channels that can use the LVDS clock as dot clock
>   */
>  struct rcar_du_device_info {
>  	unsigned int gen;
> @@ -62,6 +63,7 @@ struct rcar_du_device_info {
>  	struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX];
>  	unsigned int num_lvds;
>  	unsigned int dpll_mask;
> +	unsigned int lvds_clk_mask;
>  };
>
>  #define RCAR_DU_MAX_CRTCS		4
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> index ef2c177afb6d..4c62841eff2f 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> @@ -89,6 +89,54 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
>  	rcar_du_group_write(rgrp, DEFR8, defr8);
>  }
>
> +static void rcar_du_group_setup_didsr(struct rcar_du_group *rgrp)
> +{
> +	struct rcar_du_device *rcdu = rgrp->dev;
> +	struct rcar_du_crtc *rcrtc;
> +	unsigned int num_crtcs = 0;
> +	unsigned int i;
> +	u32 didsr;
> +
> +	/*
> +	 * Configure input dot clock routing with a hardcoded configuration. If
> +	 * the DU channel can use the LVDS encoder output clock as the dot
> +	 * clock, do so. Otherwise route DU_DOTCLKINn signal to DUn.
> +	 *
> +	 * Each channel can then select between the dot clock configured here
> +	 * and the clock provided by the CPG through the ESCR register.
> +	 */

well, you mention ESCR here, so maybe no need to do the same above...
up to you...

> +	if (rcdu->info->gen < 3 && rgrp->index == 0) {
> +		/*
> +		 * On Gen2 a single register in the first group controls dot
> +		 * clock selection for all channels.
> +		 */
> +		rcrtc = rcdu->crtcs;
> +		num_crtcs = rcdu->num_crtcs;
> +	} else if (rcdu->info->gen == 3 && rgrp->num_crtcs > 1) {
> +		/*
> +		 * On Gen3 dot clocks are setup through per-group registers,
> +		 * only available when the group has two channels.
> +		 */
> +		rcrtc = &rcdu->crtcs[rgrp->index * 2];
> +		num_crtcs = rgrp->num_crtcs;
> +	}
> +
> +	if (!num_crtcs)
> +		return;
> +
> +	didsr = DIDSR_CODE;
> +	for (i = 0; i < num_crtcs; ++i, ++rcrtc) {
> +		if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index))
> +			didsr |= DIDSR_LCDS_LVDS0(i)
> +			      |  DIDSR_PDCS_CLK(i, 0);
> +		else
> +			didsr |= DIDSR_LCDS_DCLKIN(i)
> +			      |  DIDSR_PDCS_CLK(i, 0);
> +	}
> +
> +	rcar_du_group_write(rgrp, DIDSR, didsr);
> +}
> +
>  static void rcar_du_group_setup(struct rcar_du_group *rgrp)
>  {
>  	struct rcar_du_device *rcdu = rgrp->dev;
> @@ -106,21 +154,7 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
>
>  	if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) {
>  		rcar_du_group_setup_defr8(rgrp);
> -
> -		/*
> -		 * Configure input dot clock routing. We currently hardcode the
> -		 * configuration to routing DOTCLKINn to DUn. Register fields
> -		 * depend on the DU generation, but the resulting value is 0 in
> -		 * all cases.
> -		 *
> -		 * On Gen2 a single register in the first group controls dot
> -		 * clock selection for all channels, while on Gen3 dot clocks
> -		 * are setup through per-group registers, only available when
> -		 * the group has two channels.
> -		 */
> -		if ((rcdu->info->gen < 3 && rgrp->index == 0) ||
> -		    (rcdu->info->gen == 3 &&  rgrp->num_crtcs > 1))
> -			rcar_du_group_write(rgrp, DIDSR, DIDSR_CODE);
> +		rcar_du_group_setup_didsr(rgrp);

This setting is performed for all Gen3 SoCs, while relevant only for
D3/E3. It doens't harm though.

Only minor comments, so
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

Thanks
  j

>  	}
>
>  	if (rcdu->info->gen >= 3)
> --
> Regards,
>
> Laurent Pinchart
>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* Re: [PATCH 08/16] drm: rcar-du: Enable configurable DPAD0 routing on Gen3
  2018-09-04 12:10   ` Laurent Pinchart
@ 2018-09-11 15:46     ` jacopo mondi
  -1 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-11 15:46 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel, linux-renesas-soc

[-- Attachment #1: Type: text/plain, Size: 4841 bytes --]

Hi Laurent,

On Tue, Sep 04, 2018 at 03:10:19PM +0300, Laurent Pinchart wrote:
> All Gen3 SoCs supported so far have a fixed association between DPAD0
> and DU channels, which led to hardcoding that association when writing
> the corresponding hardware register. The D3 and E3 will break that
> mechanism as DPAD0 can be dynamically connected to either DU0 or DU1.
>
> Make DPAD0 routing dynamic on Gen3. To ensure a valid hardware
> configuration when the DU starts without the RGB output enabled, DPAD0
> is associated at initialization time to the first DU channel that it can
> be connected to. This makes no change on Gen2 as all Gen2 SoCs can
> connected DPAD0 to DU0, which is the current implicit default value.
>
> As the DPAD0 source is always 0 when a single source is possible on
> Gen2, we can also simplify the Gen2 code in the same function to remove
> a conditional check.
>

Does this patch only prepares for routing to be mad dynamic or it is
already supported?

I am missing where those dynamic association happens, as I see the
possible dpad0 source being changed in 'rcar_du_crtc_route_output()'
which is in turn called by the mode set operation
'rcar_du_crtc_route_output()'.

But at the same time, I only see the routing register DEFR8 being
written by rcar_du_group_setup_defr8() called by the group route setup
operation rcar_du_group_set_routing() called at crtc setup time only.

Would the mode set operation on the encoder being supporsed to go to
the group's set_routing operation? Or does DEFR8 configuration happens
with a different call path?

Thanks
  j

> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/rcar-du/rcar_du_group.c | 17 ++++++-----------
>  drivers/gpu/drm/rcar-du/rcar_du_kms.c   | 12 ++++++++++++
>  2 files changed, 18 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> index 4c62841eff2f..f38703e7a10d 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> @@ -56,8 +56,6 @@ static void rcar_du_group_setup_pins(struct rcar_du_group *rgrp)
>  static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
>  {
>  	struct rcar_du_device *rcdu = rgrp->dev;
> -	unsigned int possible_crtcs =
> -		rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;
>  	u32 defr8 = DEFR8_CODE;
>
>  	if (rcdu->info->gen < 3) {
> @@ -69,21 +67,18 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
>  		 * DU instances that support it.
>  		 */
>  		if (rgrp->index == 0) {
> -			if (possible_crtcs > 1)
> -				defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source);
> +			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.
> +		 * On Gen3 VSPD routing can't be configured, and DPAD routing
> +		 * is set in the group corresponding to the DPAD output (no Gen3
> +		 * SoC has multiple DPAD sources belonging to separate groups).
>  		 */
> -		unsigned int rgb_crtc = ffs(possible_crtcs) - 1;
> -		struct rcar_du_crtc *crtc = &rcdu->crtcs[rgb_crtc];
> -
> -		if (crtc->index / 2 == rgrp->index)
> -			defr8 |= DEFR8_DRGBS_DU(crtc->index);
> +		if (rgrp->index == rcdu->dpad0_source / 2)
> +			defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source);
>  	}
>
>  	rcar_du_group_write(rgrp, DEFR8, defr8);
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> index ed7fa3204892..bd01197700c5 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> @@ -501,6 +501,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
>  	struct drm_device *dev = rcdu->ddev;
>  	struct drm_encoder *encoder;
>  	struct drm_fbdev_cma *fbdev;
> +	unsigned int dpad0_sources;
>  	unsigned int num_encoders;
>  	unsigned int num_groups;
>  	unsigned int swindex;
> @@ -613,6 +614,17 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
>  		encoder->possible_clones = (1 << num_encoders) - 1;
>  	}
>
> +	/*
> +	 * Initialize the default DPAD0 source to the index of the first DU
> +	 * channel that can be connected to DPAD0. The exact value doesn't
> +	 * matter as it should be overwritten by mode setting for the RGB
> +	 * output, but it is nonetheless required to ensure a valid initial
> +	 * hardware configuration on Gen3 where DU0 can't always be connected to
> +	 * DPAD0.
> +	 */
> +	dpad0_sources = rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;
> +	rcdu->dpad0_source = ffs(dpad0_sources) - 1;
> +
>  	drm_mode_config_reset(dev);
>
>  	drm_kms_helper_poll_init(dev);
> --
> Regards,
>
> Laurent Pinchart
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH 08/16] drm: rcar-du: Enable configurable DPAD0 routing on Gen3
@ 2018-09-11 15:46     ` jacopo mondi
  0 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-11 15:46 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 4841 bytes --]

Hi Laurent,

On Tue, Sep 04, 2018 at 03:10:19PM +0300, Laurent Pinchart wrote:
> All Gen3 SoCs supported so far have a fixed association between DPAD0
> and DU channels, which led to hardcoding that association when writing
> the corresponding hardware register. The D3 and E3 will break that
> mechanism as DPAD0 can be dynamically connected to either DU0 or DU1.
>
> Make DPAD0 routing dynamic on Gen3. To ensure a valid hardware
> configuration when the DU starts without the RGB output enabled, DPAD0
> is associated at initialization time to the first DU channel that it can
> be connected to. This makes no change on Gen2 as all Gen2 SoCs can
> connected DPAD0 to DU0, which is the current implicit default value.
>
> As the DPAD0 source is always 0 when a single source is possible on
> Gen2, we can also simplify the Gen2 code in the same function to remove
> a conditional check.
>

Does this patch only prepares for routing to be mad dynamic or it is
already supported?

I am missing where those dynamic association happens, as I see the
possible dpad0 source being changed in 'rcar_du_crtc_route_output()'
which is in turn called by the mode set operation
'rcar_du_crtc_route_output()'.

But at the same time, I only see the routing register DEFR8 being
written by rcar_du_group_setup_defr8() called by the group route setup
operation rcar_du_group_set_routing() called at crtc setup time only.

Would the mode set operation on the encoder being supporsed to go to
the group's set_routing operation? Or does DEFR8 configuration happens
with a different call path?

Thanks
  j

> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/rcar-du/rcar_du_group.c | 17 ++++++-----------
>  drivers/gpu/drm/rcar-du/rcar_du_kms.c   | 12 ++++++++++++
>  2 files changed, 18 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> index 4c62841eff2f..f38703e7a10d 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> @@ -56,8 +56,6 @@ static void rcar_du_group_setup_pins(struct rcar_du_group *rgrp)
>  static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
>  {
>  	struct rcar_du_device *rcdu = rgrp->dev;
> -	unsigned int possible_crtcs =
> -		rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;
>  	u32 defr8 = DEFR8_CODE;
>
>  	if (rcdu->info->gen < 3) {
> @@ -69,21 +67,18 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
>  		 * DU instances that support it.
>  		 */
>  		if (rgrp->index == 0) {
> -			if (possible_crtcs > 1)
> -				defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source);
> +			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.
> +		 * On Gen3 VSPD routing can't be configured, and DPAD routing
> +		 * is set in the group corresponding to the DPAD output (no Gen3
> +		 * SoC has multiple DPAD sources belonging to separate groups).
>  		 */
> -		unsigned int rgb_crtc = ffs(possible_crtcs) - 1;
> -		struct rcar_du_crtc *crtc = &rcdu->crtcs[rgb_crtc];
> -
> -		if (crtc->index / 2 == rgrp->index)
> -			defr8 |= DEFR8_DRGBS_DU(crtc->index);
> +		if (rgrp->index == rcdu->dpad0_source / 2)
> +			defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source);
>  	}
>
>  	rcar_du_group_write(rgrp, DEFR8, defr8);
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> index ed7fa3204892..bd01197700c5 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> @@ -501,6 +501,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
>  	struct drm_device *dev = rcdu->ddev;
>  	struct drm_encoder *encoder;
>  	struct drm_fbdev_cma *fbdev;
> +	unsigned int dpad0_sources;
>  	unsigned int num_encoders;
>  	unsigned int num_groups;
>  	unsigned int swindex;
> @@ -613,6 +614,17 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
>  		encoder->possible_clones = (1 << num_encoders) - 1;
>  	}
>
> +	/*
> +	 * Initialize the default DPAD0 source to the index of the first DU
> +	 * channel that can be connected to DPAD0. The exact value doesn't
> +	 * matter as it should be overwritten by mode setting for the RGB
> +	 * output, but it is nonetheless required to ensure a valid initial
> +	 * hardware configuration on Gen3 where DU0 can't always be connected to
> +	 * DPAD0.
> +	 */
> +	dpad0_sources = rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;
> +	rcdu->dpad0_source = ffs(dpad0_sources) - 1;
> +
>  	drm_mode_config_reset(dev);
>
>  	drm_kms_helper_poll_init(dev);
> --
> Regards,
>
> Laurent Pinchart
>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* Re: [PATCH 04/16] drm: bridge: thc63: Restrict modes based on hardware operating frequency
  2018-09-04 12:10   ` Laurent Pinchart
@ 2018-09-13 12:36     ` Andrzej Hajda
  -1 siblings, 0 replies; 86+ messages in thread
From: Andrzej Hajda @ 2018-09-13 12:36 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel
  Cc: linux-renesas-soc, Archit Taneja, Jacopo Mondi

On 04.09.2018 14:10, Laurent Pinchart wrote:
> The THC63LVD1024 is restricted to a pixel clock frequency in the range
> of 8 to 135 MHz. Implement the bridge .mode_valid() operation
> accordingly.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

 --
Regards
Andrzej

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

* Re: [PATCH 04/16] drm: bridge: thc63: Restrict modes based on hardware operating frequency
@ 2018-09-13 12:36     ` Andrzej Hajda
  0 siblings, 0 replies; 86+ messages in thread
From: Andrzej Hajda @ 2018-09-13 12:36 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel; +Cc: linux-renesas-soc, Jacopo Mondi

On 04.09.2018 14:10, Laurent Pinchart wrote:
> The THC63LVD1024 is restricted to a pixel clock frequency in the range
> of 8 to 135 MHz. Implement the bridge .mode_valid() operation
> accordingly.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>

 --
Regards
Andrzej


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

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

* Re: [PATCH 04/16] drm: bridge: thc63: Restrict modes based on hardware operating frequency
  2018-09-11 13:31     ` jacopo mondi
@ 2018-09-13 21:08       ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-13 21:08 UTC (permalink / raw)
  To: jacopo mondi
  Cc: Laurent Pinchart, dri-devel, linux-renesas-soc, Archit Taneja,
	Andrzej Hajda

Hi Jacopo,

On Tuesday, 11 September 2018 16:31:55 EEST jacopo mondi wrote:
> Hi Laurent,
>    sorry, I might be confused but,
> 
> On Tue, Sep 04, 2018 at 03:10:15PM +0300, Laurent Pinchart wrote:
> > The THC63LVD1024 is restricted to a pixel clock frequency in the range
> > of 8 to 135 MHz. Implement the bridge .mode_valid() operation
> > accordingly.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/bridge/thc63lvd1024.c | 18 ++++++++++++++++++
> >  1 file changed, 18 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c
> > b/drivers/gpu/drm/bridge/thc63lvd1024.c index c8b9edd5a7f4..63609ba16b6d
> > 100644
> > --- a/drivers/gpu/drm/bridge/thc63lvd1024.c
> > +++ b/drivers/gpu/drm/bridge/thc63lvd1024.c
> > @@ -45,6 +45,23 @@ static int thc63_attach(struct drm_bridge *bridge)
> >  	return drm_bridge_attach(bridge->encoder, thc63->next, bridge);
> >  }
> > 
> > +static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge,
> > +					const struct drm_display_mode *mode)
> > +{
> > +	/*
> > +	 * The THC63LVD0124 clock frequency range is 8 to 135 MHz in single-in,
> > +	 * single-out mode. Note that the limits depends on the mode and will
> > +	 * need to be adjusted accordingly.
> > +	 */
> > +	if (mode->clock < 8000)
> > +		return MODE_CLOCK_LOW;
> > +
> > +	if (mode->clock > 135000)
> > +		return MODE_CLOCK_HIGH;
> > +
> > +	return MODE_OK;
> > +}
> > +
> 
> Are we talking about the CLKOUT frequency? Because that's the one I
> see depending on the dual/single output mode, and I assume we're
> checking for the mode->clock of the DRM mode to be applied to the
> connector (which receives an RGB stream from this bridge).
> 
> In case we're talking about CLKOUT, I read
> 
> "Dual LVDS port IN/Dual TTL port Out Mode:
>  8 - 135MHz(CLKOUT)
>  Dual LVDS port IN/Single TTL port Out Mode:
>  40 - 150MHz(CLKOUT)"
> 
> If we're talking about the PLL input clock (RCLK) then used to
> generate CLKOUT it's indeed defined in the 8-135Mhz range, but
> I don't see mention on it depending on the mode.

This is about the input clock on the LVDS side of the LVDS decoder, named 
RCLK. It is received from the LVDS interface on the other side and its 
frequency is equal to the pixel clock.

> >  static void thc63_enable(struct drm_bridge *bridge)
> >  {
> >  	struct thc63_dev *thc63 = to_thc63(bridge);
> > @@ -77,6 +94,7 @@ static void thc63_disable(struct drm_bridge *bridge)
> > 
> >  static const struct drm_bridge_funcs thc63_bridge_func = {
> >  	.attach	= thc63_attach,
> > +	.mode_valid = thc63_mode_valid,
> >  	.enable = thc63_enable,
> >  	.disable = thc63_disable,
> >  };

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 04/16] drm: bridge: thc63: Restrict modes based on hardware operating frequency
@ 2018-09-13 21:08       ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-13 21:08 UTC (permalink / raw)
  To: jacopo mondi; +Cc: linux-renesas-soc, Laurent Pinchart, dri-devel

Hi Jacopo,

On Tuesday, 11 September 2018 16:31:55 EEST jacopo mondi wrote:
> Hi Laurent,
>    sorry, I might be confused but,
> 
> On Tue, Sep 04, 2018 at 03:10:15PM +0300, Laurent Pinchart wrote:
> > The THC63LVD1024 is restricted to a pixel clock frequency in the range
> > of 8 to 135 MHz. Implement the bridge .mode_valid() operation
> > accordingly.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/bridge/thc63lvd1024.c | 18 ++++++++++++++++++
> >  1 file changed, 18 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c
> > b/drivers/gpu/drm/bridge/thc63lvd1024.c index c8b9edd5a7f4..63609ba16b6d
> > 100644
> > --- a/drivers/gpu/drm/bridge/thc63lvd1024.c
> > +++ b/drivers/gpu/drm/bridge/thc63lvd1024.c
> > @@ -45,6 +45,23 @@ static int thc63_attach(struct drm_bridge *bridge)
> >  	return drm_bridge_attach(bridge->encoder, thc63->next, bridge);
> >  }
> > 
> > +static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge,
> > +					const struct drm_display_mode *mode)
> > +{
> > +	/*
> > +	 * The THC63LVD0124 clock frequency range is 8 to 135 MHz in single-in,
> > +	 * single-out mode. Note that the limits depends on the mode and will
> > +	 * need to be adjusted accordingly.
> > +	 */
> > +	if (mode->clock < 8000)
> > +		return MODE_CLOCK_LOW;
> > +
> > +	if (mode->clock > 135000)
> > +		return MODE_CLOCK_HIGH;
> > +
> > +	return MODE_OK;
> > +}
> > +
> 
> Are we talking about the CLKOUT frequency? Because that's the one I
> see depending on the dual/single output mode, and I assume we're
> checking for the mode->clock of the DRM mode to be applied to the
> connector (which receives an RGB stream from this bridge).
> 
> In case we're talking about CLKOUT, I read
> 
> "Dual LVDS port IN/Dual TTL port Out Mode:
>  8 - 135MHz(CLKOUT)
>  Dual LVDS port IN/Single TTL port Out Mode:
>  40 - 150MHz(CLKOUT)"
> 
> If we're talking about the PLL input clock (RCLK) then used to
> generate CLKOUT it's indeed defined in the 8-135Mhz range, but
> I don't see mention on it depending on the mode.

This is about the input clock on the LVDS side of the LVDS decoder, named 
RCLK. It is received from the LVDS interface on the other side and its 
frequency is equal to the pixel clock.

> >  static void thc63_enable(struct drm_bridge *bridge)
> >  {
> >  	struct thc63_dev *thc63 = to_thc63(bridge);
> > @@ -77,6 +94,7 @@ static void thc63_disable(struct drm_bridge *bridge)
> > 
> >  static const struct drm_bridge_funcs thc63_bridge_func = {
> >  	.attach	= thc63_attach,
> > +	.mode_valid = thc63_mode_valid,
> >  	.enable = thc63_enable,
> >  	.disable = thc63_disable,
> >  };

-- 
Regards,

Laurent Pinchart



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

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

* Re: [PATCH 05/16] drm: rcar-du: lvds: D3/E3 support
  2018-09-11 13:23     ` jacopo mondi
@ 2018-09-13 21:14       ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-13 21:14 UTC (permalink / raw)
  To: jacopo mondi; +Cc: Laurent Pinchart, dri-devel, linux-renesas-soc

Hi Jacopo,

On Tuesday, 11 September 2018 16:23:23 EEST jacopo mondi wrote:
> On Tue, Sep 04, 2018 at 03:10:16PM +0300, Laurent Pinchart wrote:
> > The LVDS encoders in the D3 and E3 SoCs differ significantly from those
> > in the other R-Car Gen3 family members:
> > 
> > - The LVDS PLL architecture is more complex and requires computing PLL
> >   parameters manually.
> > 
> > - The PLL uses external clocks as inputs, which need to be retrieved
> >   from DT.
> > 
> > - In addition to the different PLL setup, the startup sequence has
> >   changed *again* (seems someone had trouble making his/her mind).
> > 
> > Supporting all this requires DT bindings extensions for external clocks,
> > brand new PLL setup code, and a few quirks to handle the differences in
> > the startup sequence.
> > 
> > The implementation doesn't support all hardware features yet, namely
> > 
> > - Using the LV[01] clocks generated by the CPG as PLL input.
> > - Providing the LVDS PLL clock to the DU for use with the RGB output.
> > 
> > Those features can be added later when the need will arise.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/rcar-du/rcar_lvds.c      | 365 ++++++++++++++++++++++----
> >  drivers/gpu/drm/rcar-du/rcar_lvds_regs.h |  43 +++-
> >  2 files changed, 361 insertions(+), 47 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > b/drivers/gpu/drm/rcar-du/rcar_lvds.c index ce0eb68c3416..aac4acbcfbfc
> > 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c

[snip]

> > +struct pll_info {
> > +	struct clk *clk;
> > +	unsigned long diff;
> > +	unsigned int pll_m;
> > +	unsigned int pll_n;
> > +	unsigned int pll_e;
> > +	unsigned int div;
> > +};
> > +
> > +static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk
> > *clk,
> > +				     unsigned long target, struct pll_info *pll)
> 
> Do you think it is worth mentioning d3_e3 in the function name? I know
> it's not a big deal, but in future generation this PLL circuit may be
> re-used.

How would you name it ? Other LVDS encoder instances have a different PLL, and 
they are not named in the datasheet. I propose renaming it later if needed.

> > +{
> > +	unsigned long fin;
> > +	unsigned int m_min;
> > +	unsigned int m_max;
> > +	unsigned int m;
> > +
> > +	if (!clk)
> > +		return;
> > +
> > +	/*
> > +	 * The LVDS PLL is made of a pre-divider and a multiplier (strangerly
> > +	 * enough called M and N respectively), followed by a post-divider E.
> > +	 *
> > +	 *         ,-----.         ,-----.     ,-----.         ,-----.
> > +	 * Fin --> | 1/M | -Fpdf-> | PFD | --> | VCO | -Fvco-> | 1/E | --> Fout
> > +	 *         `-----'     ,-> |     |     `-----'   |     `-----'
> > +	 *                     |   `-----'               |
> > +	 *                     |         ,-----.         |
> > +	 *                     `-------- | 1/N | <-------'
> > +	 *                               `-----'
> > +	 *
> > +	 * The clock output by the PLL is then further divided by a 
programmable
> > +	 * divider DIV to achieve the desired target frequency. Finally, an
> > +	 * optional fixed /7 divider is used to convert the bit clock to a 
pixel
> > +	 * clock (as LVDS transmits 7 bits per lane per clock sample).
> > +	 *
> > +	 *          ,-------.     ,-----.     |\
> > +	 * Fout --> | 1/DIV | --> | 1/7 | --> | |
> > +	 *          `-------'  |  `-----'     | | --> dot clock
> > +	 *                     `------------> | |
> > +	 *                                    |/
> > +	 *
> > +	 * The /7 divider is optional when the LVDS PLL is used to generate a
> > +	 * dot clock for the DU RGB output, without using the LVDS encoder. We
> > +	 * don't support this configuration yet.
> > +	 *
> > +	 * The PLL allowed input frequency range is 12 MHz to 192 MHz.
> > +	 */
> > +
> > +	fin = clk_get_rate(clk);
> > +	if (fin < 12000000 || fin > 192000000)
> > +		return;
> > +
> > +	/*
> > +	 * The comparison frequency range is 12 MHz to 24 MHz, which limits the
> > +	 * allowed values for the pre-divider M (normal range 1-8).
> > +	 *
> > +	 * Fpfd = Fin / M
> > +	 */
> > +	m_min = max_t(unsigned int, 1, DIV_ROUND_UP(fin, 24000000));
> > +	m_max = min_t(unsigned int, 8, fin / 12000000);
> > +
> > +	for (m = m_min; m <= m_max; ++m) {
> > +		unsigned long fpfd;
> > +		unsigned int n_min;
> > +		unsigned int n_max;
> > +		unsigned int n;
> > +
> > +		/*
> > +		 * The VCO operating range is 900 Mhz to 1800 MHz, which limits
> > +		 * the allowed values for the multiplier N (normal range
> > +		 * 60-120).
> > +		 *
> > +		 * Fvco = Fin * N / M
> > +		 */
> > +		fpfd = fin / m;
> > +		n_min = max_t(unsigned int, 60, DIV_ROUND_UP(900000000, fpfd));
> > +		n_max = min_t(unsigned int, 120, 1800000000 / fpfd);
> > +
> > +		for (n = n_min; n < n_max; ++n) {
> > +			unsigned long fvco;
> > +			unsigned int e_min;
> > +			unsigned int e;
> > +
> > +			/*
> > +			 * The output frequency is limited to 1039.5 MHz,
> > +			 * limiting again the allowed values for the
> > +			 * post-divider E (normal value 1, 2 or 4).
> > +			 *
> > +			 * Fout = Fvco / E
> > +			 */
> > +			fvco = fpfd * n;
> > +			e_min = fvco > 1039500000 ? 1 : 0;
> > +
> > +			for (e = e_min; e < 3; ++e) {
> > +				unsigned long fout;
> > +				unsigned long diff;
> > +				unsigned int div;
> > +
> > +				/*
> > +				 * Finally we have a programable divider after
> > +				 * the PLL, followed by a an optional fixed /7
> > +				 * divider.
> > +				 */
> > +				fout = fvco / (1 << e) / 7;
> > +				div = DIV_ROUND_CLOSEST(fout, target);
> > +				diff = abs(fout / div - target);
> > +
> > +				if (diff < pll->diff) {
> > +					pll->clk = clk;
> > +					pll->diff = diff;
> > +					pll->pll_m = m;
> > +					pll->pll_n = n;
> > +					pll->pll_e = e;
> > +					pll->div = div;
> > +
> > +					if (diff == 0)
> > +						goto done;
> > +				}
> > +			}
> > +		}
> > +	}
> 
> Very nice :)

Thanks :-)

> > +
> > +done:
> > +#if defined(CONFIG_DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
> > +	{
> > +		unsigned long output = fin * pll->pll_n / pll->pll_m
> > +				     / (1 << pll->pll_e) / 7 / pll->div;
> > +		int error = (long)(output - target) * 10000 / (long)target;
> > +
> > +		dev_dbg(lvds->dev,
> > +			"%pC %lu Hz -> Fout %lu Hz (target %lu Hz, error %d.%02u%%), PLL
> > M/N/E/DIV %u/%u/%u/%u\n", +			clk, fin, output, target, error / 100,
> > +			error < 0 ? -error % 100 : error % 100,
> > +			pll->pll_m, pll->pll_n, pll->pll_e, pll->div);
> > +	}
> > +#endif
> 
> I know you know about this already, but
> 
> ../drivers/gpu/drm/rcar-du/rcar_lvds.c:298:1: error: label at end of
> compound statement
> 
> I'm still not sure what actually disturbs gcc here

Neither do I, but I've fixed it anyway.

> >  }
> > 
> > -static u32 rcar_lvds_lvdpllcr_gen3(unsigned int freq)
> > +static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned
> > int freq)> 
> >  {
> > 
> > -	if (freq < 42000)
> > -		return LVDPLLCR_PLLDIVCNT_42M;
> > -	else if (freq < 85000)
> > -		return LVDPLLCR_PLLDIVCNT_85M;
> > -	else if (freq < 128000)
> > -		return LVDPLLCR_PLLDIVCNT_128M;
> > +	struct drm_crtc *crtc = lvds->bridge.encoder->crtc;
> > +	struct pll_info pll = { .diff = (unsigned long)-1 };
> > +	u32 lvdpllcr;
> > +
> > +	if (lvds->clocks.dotclkin[0] || lvds->clocks.dotclkin[1]) {
> > +		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[0],
> > +					 freq, &pll);
> > +		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[1],
> > +					 freq, &pll);
> > +	} else if (lvds->clocks.extal) {
> > +		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.extal,
> > +					 freq, &pll);
> > +	}
> 
> here it's either ((dotclkin[0] or dotclock[1]) or extal). Are they
> mutually exclusive? Can't we try all of them? The probe routine
> guarantees we have at least of of them...

I think you're right, I can't remember why I did it this way. I'll update the 
code to try the three clocks.

> > +
> > +	lvdpllcr = LVDPLLCR_PLLON | LVDPLLCR_CLKOUT
> > +		 | LVDPLLCR_PLLN(pll.pll_n - 1) | LVDPLLCR_PLLM(pll.pll_m - 1);
> > +
> > +	if (pll.clk == lvds->clocks.extal)
> > +		lvdpllcr |= LVDPLLCR_CKSEL_EXTAL;
> > +	else
> > +		lvdpllcr |= LVDPLLCR_CKSEL_DU_DOTCLKIN(drm_crtc_index(crtc));
> 
> Here you select du_clkin[0] or du_clkin[1] based on the DU index (btw,
> the drm_crtc_index() function is funny, it simply "crtc->index" no
> checks, no validation, what's the benefit of using it?).

See

commit 490d3d1b91201fd3d3d01d64e11df4eac1d92bd4
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri May 27 20:05:00 2016 +0100

    drm: Store the plane's index

> Looking at the LVDS PLL block diagram for D3/E3 (Figure 37.3) I see
> that both clkin[0] and clkin[1] could be used independently from the du
> index. Shouldn't we use the one performing better? (now how to make
> sure it gets not selected twice in case of both DU0 and DU1 using the
> LVDS PLL it's another problem)

You're right again, I'll fix that.

> > +
> > +	if (pll.pll_e > 0)
> > +		lvdpllcr |= LVDPLLCR_STP_CLKOUTE | LVDPLLCR_OUTCLKSEL
> > +			 |  LVDPLLCR_PLLE(pll.pll_e - 1);
> > +
> > +	rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
> > +
> > +	if (pll.div > 1)
> > +		rcar_lvds_write(lvds, LVDDIV, LVDDIV_DIVSEL |
> > +				LVDDIV_DIVRESET | LVDDIV_DIV(pll.div - 1));
> >  	else
> > -		return LVDPLLCR_PLLDIVCNT_148M;
> > +		rcar_lvds_write(lvds, LVDDIV, 0);
> >  }

[snip]

> > +static struct clk *rcar_lvds_get_clock(struct rcar_lvds *lvds, const char
> > *name,
> > +				       bool optional)
> > +{
> > +	struct clk *clk;
> > +
> > +	clk = devm_clk_get(lvds->dev, name);
> 
> I wish we had clk_get_optional() as we have gpiod_get_optional().
> There are probably good reasons if it's not there though...

I don't know, given that this function is pretty much a clk_get_optional(), it 
would seem useful to me. Feel free to propose it :-)

> > +	if (!IS_ERR(clk))
> > +		return clk;
> > +
> > +	if (PTR_ERR(clk) == -ENOENT && optional)
> > +		return NULL;
> > +
> > +	if (PTR_ERR(clk) != -EPROBE_DEFER)
> > +		dev_err(lvds->dev, "failed to get %s clock\n",
> > +			name ? name : "module");
> > +
> > +	return clk;
> > +}

[snip]

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 05/16] drm: rcar-du: lvds: D3/E3 support
@ 2018-09-13 21:14       ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-13 21:14 UTC (permalink / raw)
  To: jacopo mondi; +Cc: linux-renesas-soc, Laurent Pinchart, dri-devel

Hi Jacopo,

On Tuesday, 11 September 2018 16:23:23 EEST jacopo mondi wrote:
> On Tue, Sep 04, 2018 at 03:10:16PM +0300, Laurent Pinchart wrote:
> > The LVDS encoders in the D3 and E3 SoCs differ significantly from those
> > in the other R-Car Gen3 family members:
> > 
> > - The LVDS PLL architecture is more complex and requires computing PLL
> >   parameters manually.
> > 
> > - The PLL uses external clocks as inputs, which need to be retrieved
> >   from DT.
> > 
> > - In addition to the different PLL setup, the startup sequence has
> >   changed *again* (seems someone had trouble making his/her mind).
> > 
> > Supporting all this requires DT bindings extensions for external clocks,
> > brand new PLL setup code, and a few quirks to handle the differences in
> > the startup sequence.
> > 
> > The implementation doesn't support all hardware features yet, namely
> > 
> > - Using the LV[01] clocks generated by the CPG as PLL input.
> > - Providing the LVDS PLL clock to the DU for use with the RGB output.
> > 
> > Those features can be added later when the need will arise.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/rcar-du/rcar_lvds.c      | 365 ++++++++++++++++++++++----
> >  drivers/gpu/drm/rcar-du/rcar_lvds_regs.h |  43 +++-
> >  2 files changed, 361 insertions(+), 47 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > b/drivers/gpu/drm/rcar-du/rcar_lvds.c index ce0eb68c3416..aac4acbcfbfc
> > 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c

[snip]

> > +struct pll_info {
> > +	struct clk *clk;
> > +	unsigned long diff;
> > +	unsigned int pll_m;
> > +	unsigned int pll_n;
> > +	unsigned int pll_e;
> > +	unsigned int div;
> > +};
> > +
> > +static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk
> > *clk,
> > +				     unsigned long target, struct pll_info *pll)
> 
> Do you think it is worth mentioning d3_e3 in the function name? I know
> it's not a big deal, but in future generation this PLL circuit may be
> re-used.

How would you name it ? Other LVDS encoder instances have a different PLL, and 
they are not named in the datasheet. I propose renaming it later if needed.

> > +{
> > +	unsigned long fin;
> > +	unsigned int m_min;
> > +	unsigned int m_max;
> > +	unsigned int m;
> > +
> > +	if (!clk)
> > +		return;
> > +
> > +	/*
> > +	 * The LVDS PLL is made of a pre-divider and a multiplier (strangerly
> > +	 * enough called M and N respectively), followed by a post-divider E.
> > +	 *
> > +	 *         ,-----.         ,-----.     ,-----.         ,-----.
> > +	 * Fin --> | 1/M | -Fpdf-> | PFD | --> | VCO | -Fvco-> | 1/E | --> Fout
> > +	 *         `-----'     ,-> |     |     `-----'   |     `-----'
> > +	 *                     |   `-----'               |
> > +	 *                     |         ,-----.         |
> > +	 *                     `-------- | 1/N | <-------'
> > +	 *                               `-----'
> > +	 *
> > +	 * The clock output by the PLL is then further divided by a 
programmable
> > +	 * divider DIV to achieve the desired target frequency. Finally, an
> > +	 * optional fixed /7 divider is used to convert the bit clock to a 
pixel
> > +	 * clock (as LVDS transmits 7 bits per lane per clock sample).
> > +	 *
> > +	 *          ,-------.     ,-----.     |\
> > +	 * Fout --> | 1/DIV | --> | 1/7 | --> | |
> > +	 *          `-------'  |  `-----'     | | --> dot clock
> > +	 *                     `------------> | |
> > +	 *                                    |/
> > +	 *
> > +	 * The /7 divider is optional when the LVDS PLL is used to generate a
> > +	 * dot clock for the DU RGB output, without using the LVDS encoder. We
> > +	 * don't support this configuration yet.
> > +	 *
> > +	 * The PLL allowed input frequency range is 12 MHz to 192 MHz.
> > +	 */
> > +
> > +	fin = clk_get_rate(clk);
> > +	if (fin < 12000000 || fin > 192000000)
> > +		return;
> > +
> > +	/*
> > +	 * The comparison frequency range is 12 MHz to 24 MHz, which limits the
> > +	 * allowed values for the pre-divider M (normal range 1-8).
> > +	 *
> > +	 * Fpfd = Fin / M
> > +	 */
> > +	m_min = max_t(unsigned int, 1, DIV_ROUND_UP(fin, 24000000));
> > +	m_max = min_t(unsigned int, 8, fin / 12000000);
> > +
> > +	for (m = m_min; m <= m_max; ++m) {
> > +		unsigned long fpfd;
> > +		unsigned int n_min;
> > +		unsigned int n_max;
> > +		unsigned int n;
> > +
> > +		/*
> > +		 * The VCO operating range is 900 Mhz to 1800 MHz, which limits
> > +		 * the allowed values for the multiplier N (normal range
> > +		 * 60-120).
> > +		 *
> > +		 * Fvco = Fin * N / M
> > +		 */
> > +		fpfd = fin / m;
> > +		n_min = max_t(unsigned int, 60, DIV_ROUND_UP(900000000, fpfd));
> > +		n_max = min_t(unsigned int, 120, 1800000000 / fpfd);
> > +
> > +		for (n = n_min; n < n_max; ++n) {
> > +			unsigned long fvco;
> > +			unsigned int e_min;
> > +			unsigned int e;
> > +
> > +			/*
> > +			 * The output frequency is limited to 1039.5 MHz,
> > +			 * limiting again the allowed values for the
> > +			 * post-divider E (normal value 1, 2 or 4).
> > +			 *
> > +			 * Fout = Fvco / E
> > +			 */
> > +			fvco = fpfd * n;
> > +			e_min = fvco > 1039500000 ? 1 : 0;
> > +
> > +			for (e = e_min; e < 3; ++e) {
> > +				unsigned long fout;
> > +				unsigned long diff;
> > +				unsigned int div;
> > +
> > +				/*
> > +				 * Finally we have a programable divider after
> > +				 * the PLL, followed by a an optional fixed /7
> > +				 * divider.
> > +				 */
> > +				fout = fvco / (1 << e) / 7;
> > +				div = DIV_ROUND_CLOSEST(fout, target);
> > +				diff = abs(fout / div - target);
> > +
> > +				if (diff < pll->diff) {
> > +					pll->clk = clk;
> > +					pll->diff = diff;
> > +					pll->pll_m = m;
> > +					pll->pll_n = n;
> > +					pll->pll_e = e;
> > +					pll->div = div;
> > +
> > +					if (diff == 0)
> > +						goto done;
> > +				}
> > +			}
> > +		}
> > +	}
> 
> Very nice :)

Thanks :-)

> > +
> > +done:
> > +#if defined(CONFIG_DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
> > +	{
> > +		unsigned long output = fin * pll->pll_n / pll->pll_m
> > +				     / (1 << pll->pll_e) / 7 / pll->div;
> > +		int error = (long)(output - target) * 10000 / (long)target;
> > +
> > +		dev_dbg(lvds->dev,
> > +			"%pC %lu Hz -> Fout %lu Hz (target %lu Hz, error %d.%02u%%), PLL
> > M/N/E/DIV %u/%u/%u/%u\n", +			clk, fin, output, target, error / 100,
> > +			error < 0 ? -error % 100 : error % 100,
> > +			pll->pll_m, pll->pll_n, pll->pll_e, pll->div);
> > +	}
> > +#endif
> 
> I know you know about this already, but
> 
> ../drivers/gpu/drm/rcar-du/rcar_lvds.c:298:1: error: label at end of
> compound statement
> 
> I'm still not sure what actually disturbs gcc here

Neither do I, but I've fixed it anyway.

> >  }
> > 
> > -static u32 rcar_lvds_lvdpllcr_gen3(unsigned int freq)
> > +static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned
> > int freq)> 
> >  {
> > 
> > -	if (freq < 42000)
> > -		return LVDPLLCR_PLLDIVCNT_42M;
> > -	else if (freq < 85000)
> > -		return LVDPLLCR_PLLDIVCNT_85M;
> > -	else if (freq < 128000)
> > -		return LVDPLLCR_PLLDIVCNT_128M;
> > +	struct drm_crtc *crtc = lvds->bridge.encoder->crtc;
> > +	struct pll_info pll = { .diff = (unsigned long)-1 };
> > +	u32 lvdpllcr;
> > +
> > +	if (lvds->clocks.dotclkin[0] || lvds->clocks.dotclkin[1]) {
> > +		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[0],
> > +					 freq, &pll);
> > +		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[1],
> > +					 freq, &pll);
> > +	} else if (lvds->clocks.extal) {
> > +		rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.extal,
> > +					 freq, &pll);
> > +	}
> 
> here it's either ((dotclkin[0] or dotclock[1]) or extal). Are they
> mutually exclusive? Can't we try all of them? The probe routine
> guarantees we have at least of of them...

I think you're right, I can't remember why I did it this way. I'll update the 
code to try the three clocks.

> > +
> > +	lvdpllcr = LVDPLLCR_PLLON | LVDPLLCR_CLKOUT
> > +		 | LVDPLLCR_PLLN(pll.pll_n - 1) | LVDPLLCR_PLLM(pll.pll_m - 1);
> > +
> > +	if (pll.clk == lvds->clocks.extal)
> > +		lvdpllcr |= LVDPLLCR_CKSEL_EXTAL;
> > +	else
> > +		lvdpllcr |= LVDPLLCR_CKSEL_DU_DOTCLKIN(drm_crtc_index(crtc));
> 
> Here you select du_clkin[0] or du_clkin[1] based on the DU index (btw,
> the drm_crtc_index() function is funny, it simply "crtc->index" no
> checks, no validation, what's the benefit of using it?).

See

commit 490d3d1b91201fd3d3d01d64e11df4eac1d92bd4
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri May 27 20:05:00 2016 +0100

    drm: Store the plane's index

> Looking at the LVDS PLL block diagram for D3/E3 (Figure 37.3) I see
> that both clkin[0] and clkin[1] could be used independently from the du
> index. Shouldn't we use the one performing better? (now how to make
> sure it gets not selected twice in case of both DU0 and DU1 using the
> LVDS PLL it's another problem)

You're right again, I'll fix that.

> > +
> > +	if (pll.pll_e > 0)
> > +		lvdpllcr |= LVDPLLCR_STP_CLKOUTE | LVDPLLCR_OUTCLKSEL
> > +			 |  LVDPLLCR_PLLE(pll.pll_e - 1);
> > +
> > +	rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
> > +
> > +	if (pll.div > 1)
> > +		rcar_lvds_write(lvds, LVDDIV, LVDDIV_DIVSEL |
> > +				LVDDIV_DIVRESET | LVDDIV_DIV(pll.div - 1));
> >  	else
> > -		return LVDPLLCR_PLLDIVCNT_148M;
> > +		rcar_lvds_write(lvds, LVDDIV, 0);
> >  }

[snip]

> > +static struct clk *rcar_lvds_get_clock(struct rcar_lvds *lvds, const char
> > *name,
> > +				       bool optional)
> > +{
> > +	struct clk *clk;
> > +
> > +	clk = devm_clk_get(lvds->dev, name);
> 
> I wish we had clk_get_optional() as we have gpiod_get_optional().
> There are probably good reasons if it's not there though...

I don't know, given that this function is pretty much a clk_get_optional(), it 
would seem useful to me. Feel free to propose it :-)

> > +	if (!IS_ERR(clk))
> > +		return clk;
> > +
> > +	if (PTR_ERR(clk) == -ENOENT && optional)
> > +		return NULL;
> > +
> > +	if (PTR_ERR(clk) != -EPROBE_DEFER)
> > +		dev_err(lvds->dev, "failed to get %s clock\n",
> > +			name ? name : "module");
> > +
> > +	return clk;
> > +}

[snip]

-- 
Regards,

Laurent Pinchart



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

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

* Re: [PATCH 07/16] drm: rcar-du: Use LVDS PLL clock as dot clock when possible
  2018-09-11 14:59     ` jacopo mondi
@ 2018-09-13 21:17       ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-13 21:17 UTC (permalink / raw)
  To: jacopo mondi; +Cc: Laurent Pinchart, dri-devel, linux-renesas-soc

Hi Jacopo,

On Tuesday, 11 September 2018 17:59:02 EEST jacopo mondi wrote:
> On Tue, Sep 04, 2018 at 03:10:18PM +0300, Laurent Pinchart wrote:
> > On selected SoCs, the DU can use the clock output by the LVDS encoder
> > PLL as its input dot clock. This feature is optional, but on the D3 and
> > E3 SoC it is often the only way to obtain a precise dot clock frequency,
> > as the other available clocks (CPG-generated clock and external clock)
> > usually have fixed rates.
> > 
> > Add a DU model information field to describe which DU channels can use
> > the LVDS PLL output clock as their input clock, and configure clock
> > routing accordingly.
> > 
> > This feature is available on H2, M2-W, M2-N, D3 and E3 SoCs, with D3 and
> > E3 being the primary targets. It is left disabled in this commit, and
> > will be enabled per-SoC after careful testing.
> > 
> > At the hardware level, clock routing is configured at runtime in two
> > steps, first selecting an internal dot clock between the LVDS PLL clock
> > and the external DOTCLKIN clock, and then selecting between the internal
> > dot clock and the CPG-generated clock. The first part requires stopping
> > the whole DU group in order for the change to take effect, thus causing
> > flickering on the screen. For this reason we currently hardcode the
> > clock source the the LVDS PLL clock if available, and allow flicker-free
> 
> s/the the/to the/ ?

Fixed.

> > selection of the external DOTCLKIN clock or CPG-generated clock
> > otherwise. A more dynamic clock selection process can be implemented
> > later if the need arises.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  8 +++++
> >  drivers/gpu/drm/rcar-du/rcar_du_drv.h   |  2 ++
> >  drivers/gpu/drm/rcar-du/rcar_du_group.c | 64 +++++++++++++++++++++-------
> >  3 files changed, 59 insertions(+), 15 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 1d81eb244441..39d2fee6d7b8
> > 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > @@ -261,6 +261,14 @@ static void rcar_du_crtc_set_display_timing(struct
> > rcar_du_crtc *rcrtc)
> >  		rcar_du_group_write(rcrtc->group, DPLLCR, dpllcr);
> >  		
> >  		escr = ESCR_DCLKSEL_DCLKIN | div;
> > +	} else if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) {
> > +		/*
> > +		 * Use the LVDS PLL output as the dot clock when outputting to
> > +		 * the LVDS encoder on an SoC that supports this clock routing
> > +		 * option. We use the clock directly in that case, without any
> > +		 * additional divider.
> > +		 */
> > +		escr = ESCR_DCLKSEL_DCLKIN;
> 
> This confused me, but we have later clarified offline.
> Setting the DCLKIN bit alone does not guarantee that we use the LVDS
> PLL clock output, but the DIDSR mux must be configured to select LVDS
> over dotclkin[0] or dotclkin[1] first. Would you consider mentioning DIDSR
> in the comment here?

Please see below.

> >  	} else {
> >  		struct du_clk_params params = { .diff = (unsigned long)-1 };

[snip]

> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_group.c index
> > ef2c177afb6d..4c62841eff2f 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > @@ -89,6 +89,54 @@ static void rcar_du_group_setup_defr8(struct
> > rcar_du_group *rgrp)
> >  	rcar_du_group_write(rgrp, DEFR8, defr8);
> >  }
> > 
> > +static void rcar_du_group_setup_didsr(struct rcar_du_group *rgrp)
> > +{
> > +	struct rcar_du_device *rcdu = rgrp->dev;
> > +	struct rcar_du_crtc *rcrtc;
> > +	unsigned int num_crtcs = 0;
> > +	unsigned int i;
> > +	u32 didsr;
> > +
> > +	/*
> > +	 * Configure input dot clock routing with a hardcoded configuration. If
> > +	 * the DU channel can use the LVDS encoder output clock as the dot
> > +	 * clock, do so. Otherwise route DU_DOTCLKINn signal to DUn.
> > +	 *
> > +	 * Each channel can then select between the dot clock configured here
> > +	 * and the clock provided by the CPG through the ESCR register.
> > +	 */
> 
> well, you mention ESCR here, so maybe no need to do the same above...
> up to you...

Being lazy at this time of the night I won't change it unless you think I 
should :-)

> > +	if (rcdu->info->gen < 3 && rgrp->index == 0) {
> > +		/*
> > +		 * On Gen2 a single register in the first group controls dot
> > +		 * clock selection for all channels.
> > +		 */
> > +		rcrtc = rcdu->crtcs;
> > +		num_crtcs = rcdu->num_crtcs;
> > +	} else if (rcdu->info->gen == 3 && rgrp->num_crtcs > 1) {
> > +		/*
> > +		 * On Gen3 dot clocks are setup through per-group registers,
> > +		 * only available when the group has two channels.
> > +		 */
> > +		rcrtc = &rcdu->crtcs[rgrp->index * 2];
> > +		num_crtcs = rgrp->num_crtcs;
> > +	}
> > +
> > +	if (!num_crtcs)
> > +		return;
> > +
> > +	didsr = DIDSR_CODE;
> > +	for (i = 0; i < num_crtcs; ++i, ++rcrtc) {
> > +		if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index))
> > +			didsr |= DIDSR_LCDS_LVDS0(i)
> > +			      |  DIDSR_PDCS_CLK(i, 0);
> > +		else
> > +			didsr |= DIDSR_LCDS_DCLKIN(i)
> > +			      |  DIDSR_PDCS_CLK(i, 0);
> > +	}
> > +
> > +	rcar_du_group_write(rgrp, DIDSR, didsr);
> > +}
> > +
> >  static void rcar_du_group_setup(struct rcar_du_group *rgrp)
> >  {
> >  	struct rcar_du_device *rcdu = rgrp->dev;
> > @@ -106,21 +154,7 @@ static void rcar_du_group_setup(struct rcar_du_group
> > *rgrp)
> > 
> >  	if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) {
> >  		rcar_du_group_setup_defr8(rgrp);
> > -
> > -		/*
> > -		 * Configure input dot clock routing. We currently hardcode the
> > -		 * configuration to routing DOTCLKINn to DUn. Register fields
> > -		 * depend on the DU generation, but the resulting value is 0 in
> > -		 * all cases.
> > -		 *
> > -		 * On Gen2 a single register in the first group controls dot
> > -		 * clock selection for all channels, while on Gen3 dot clocks
> > -		 * are setup through per-group registers, only available when
> > -		 * the group has two channels.
> > -		 */
> > -		if ((rcdu->info->gen < 3 && rgrp->index == 0) ||
> > -		    (rcdu->info->gen == 3 &&  rgrp->num_crtcs > 1))
> > -			rcar_du_group_write(rgrp, DIDSR, DIDSR_CODE);
> > +		rcar_du_group_setup_didsr(rgrp);
> 
> This setting is performed for all Gen3 SoCs, while relevant only for
> D3/E3. It doens't harm though.

The DIDSR register exists in other SoCs than D3 and E3. It doesn't allow 
selecting the LVDS clock, but it should still be programmed.

> Only minor comments, so
> Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> 
> >  	}
> >  	
> >  	if (rcdu->info->gen >= 3)

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 07/16] drm: rcar-du: Use LVDS PLL clock as dot clock when possible
@ 2018-09-13 21:17       ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-13 21:17 UTC (permalink / raw)
  To: jacopo mondi; +Cc: linux-renesas-soc, Laurent Pinchart, dri-devel

Hi Jacopo,

On Tuesday, 11 September 2018 17:59:02 EEST jacopo mondi wrote:
> On Tue, Sep 04, 2018 at 03:10:18PM +0300, Laurent Pinchart wrote:
> > On selected SoCs, the DU can use the clock output by the LVDS encoder
> > PLL as its input dot clock. This feature is optional, but on the D3 and
> > E3 SoC it is often the only way to obtain a precise dot clock frequency,
> > as the other available clocks (CPG-generated clock and external clock)
> > usually have fixed rates.
> > 
> > Add a DU model information field to describe which DU channels can use
> > the LVDS PLL output clock as their input clock, and configure clock
> > routing accordingly.
> > 
> > This feature is available on H2, M2-W, M2-N, D3 and E3 SoCs, with D3 and
> > E3 being the primary targets. It is left disabled in this commit, and
> > will be enabled per-SoC after careful testing.
> > 
> > At the hardware level, clock routing is configured at runtime in two
> > steps, first selecting an internal dot clock between the LVDS PLL clock
> > and the external DOTCLKIN clock, and then selecting between the internal
> > dot clock and the CPG-generated clock. The first part requires stopping
> > the whole DU group in order for the change to take effect, thus causing
> > flickering on the screen. For this reason we currently hardcode the
> > clock source the the LVDS PLL clock if available, and allow flicker-free
> 
> s/the the/to the/ ?

Fixed.

> > selection of the external DOTCLKIN clock or CPG-generated clock
> > otherwise. A more dynamic clock selection process can be implemented
> > later if the need arises.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |  8 +++++
> >  drivers/gpu/drm/rcar-du/rcar_du_drv.h   |  2 ++
> >  drivers/gpu/drm/rcar-du/rcar_du_group.c | 64 +++++++++++++++++++++-------
> >  3 files changed, 59 insertions(+), 15 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 1d81eb244441..39d2fee6d7b8
> > 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
> > @@ -261,6 +261,14 @@ static void rcar_du_crtc_set_display_timing(struct
> > rcar_du_crtc *rcrtc)
> >  		rcar_du_group_write(rcrtc->group, DPLLCR, dpllcr);
> >  		
> >  		escr = ESCR_DCLKSEL_DCLKIN | div;
> > +	} else if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) {
> > +		/*
> > +		 * Use the LVDS PLL output as the dot clock when outputting to
> > +		 * the LVDS encoder on an SoC that supports this clock routing
> > +		 * option. We use the clock directly in that case, without any
> > +		 * additional divider.
> > +		 */
> > +		escr = ESCR_DCLKSEL_DCLKIN;
> 
> This confused me, but we have later clarified offline.
> Setting the DCLKIN bit alone does not guarantee that we use the LVDS
> PLL clock output, but the DIDSR mux must be configured to select LVDS
> over dotclkin[0] or dotclkin[1] first. Would you consider mentioning DIDSR
> in the comment here?

Please see below.

> >  	} else {
> >  		struct du_clk_params params = { .diff = (unsigned long)-1 };

[snip]

> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_group.c index
> > ef2c177afb6d..4c62841eff2f 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > @@ -89,6 +89,54 @@ static void rcar_du_group_setup_defr8(struct
> > rcar_du_group *rgrp)
> >  	rcar_du_group_write(rgrp, DEFR8, defr8);
> >  }
> > 
> > +static void rcar_du_group_setup_didsr(struct rcar_du_group *rgrp)
> > +{
> > +	struct rcar_du_device *rcdu = rgrp->dev;
> > +	struct rcar_du_crtc *rcrtc;
> > +	unsigned int num_crtcs = 0;
> > +	unsigned int i;
> > +	u32 didsr;
> > +
> > +	/*
> > +	 * Configure input dot clock routing with a hardcoded configuration. If
> > +	 * the DU channel can use the LVDS encoder output clock as the dot
> > +	 * clock, do so. Otherwise route DU_DOTCLKINn signal to DUn.
> > +	 *
> > +	 * Each channel can then select between the dot clock configured here
> > +	 * and the clock provided by the CPG through the ESCR register.
> > +	 */
> 
> well, you mention ESCR here, so maybe no need to do the same above...
> up to you...

Being lazy at this time of the night I won't change it unless you think I 
should :-)

> > +	if (rcdu->info->gen < 3 && rgrp->index == 0) {
> > +		/*
> > +		 * On Gen2 a single register in the first group controls dot
> > +		 * clock selection for all channels.
> > +		 */
> > +		rcrtc = rcdu->crtcs;
> > +		num_crtcs = rcdu->num_crtcs;
> > +	} else if (rcdu->info->gen == 3 && rgrp->num_crtcs > 1) {
> > +		/*
> > +		 * On Gen3 dot clocks are setup through per-group registers,
> > +		 * only available when the group has two channels.
> > +		 */
> > +		rcrtc = &rcdu->crtcs[rgrp->index * 2];
> > +		num_crtcs = rgrp->num_crtcs;
> > +	}
> > +
> > +	if (!num_crtcs)
> > +		return;
> > +
> > +	didsr = DIDSR_CODE;
> > +	for (i = 0; i < num_crtcs; ++i, ++rcrtc) {
> > +		if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index))
> > +			didsr |= DIDSR_LCDS_LVDS0(i)
> > +			      |  DIDSR_PDCS_CLK(i, 0);
> > +		else
> > +			didsr |= DIDSR_LCDS_DCLKIN(i)
> > +			      |  DIDSR_PDCS_CLK(i, 0);
> > +	}
> > +
> > +	rcar_du_group_write(rgrp, DIDSR, didsr);
> > +}
> > +
> >  static void rcar_du_group_setup(struct rcar_du_group *rgrp)
> >  {
> >  	struct rcar_du_device *rcdu = rgrp->dev;
> > @@ -106,21 +154,7 @@ static void rcar_du_group_setup(struct rcar_du_group
> > *rgrp)
> > 
> >  	if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) {
> >  		rcar_du_group_setup_defr8(rgrp);
> > -
> > -		/*
> > -		 * Configure input dot clock routing. We currently hardcode the
> > -		 * configuration to routing DOTCLKINn to DUn. Register fields
> > -		 * depend on the DU generation, but the resulting value is 0 in
> > -		 * all cases.
> > -		 *
> > -		 * On Gen2 a single register in the first group controls dot
> > -		 * clock selection for all channels, while on Gen3 dot clocks
> > -		 * are setup through per-group registers, only available when
> > -		 * the group has two channels.
> > -		 */
> > -		if ((rcdu->info->gen < 3 && rgrp->index == 0) ||
> > -		    (rcdu->info->gen == 3 &&  rgrp->num_crtcs > 1))
> > -			rcar_du_group_write(rgrp, DIDSR, DIDSR_CODE);
> > +		rcar_du_group_setup_didsr(rgrp);
> 
> This setting is performed for all Gen3 SoCs, while relevant only for
> D3/E3. It doens't harm though.

The DIDSR register exists in other SoCs than D3 and E3. It doesn't allow 
selecting the LVDS clock, but it should still be programmed.

> Only minor comments, so
> Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
> 
> >  	}
> >  	
> >  	if (rcdu->info->gen >= 3)

-- 
Regards,

Laurent Pinchart



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

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

* Re: [PATCH 08/16] drm: rcar-du: Enable configurable DPAD0 routing on Gen3
  2018-09-11 15:46     ` jacopo mondi
@ 2018-09-13 21:25       ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-13 21:25 UTC (permalink / raw)
  To: jacopo mondi; +Cc: Laurent Pinchart, dri-devel, linux-renesas-soc

Hi Jacopo,

Thank you for the patch.

On Tuesday, 11 September 2018 18:46:53 EEST jacopo mondi wrote:
> On Tue, Sep 04, 2018 at 03:10:19PM +0300, Laurent Pinchart wrote:
> > All Gen3 SoCs supported so far have a fixed association between DPAD0
> > and DU channels, which led to hardcoding that association when writing
> > the corresponding hardware register. The D3 and E3 will break that
> > mechanism as DPAD0 can be dynamically connected to either DU0 or DU1.
> > 
> > Make DPAD0 routing dynamic on Gen3. To ensure a valid hardware
> > configuration when the DU starts without the RGB output enabled, DPAD0
> > is associated at initialization time to the first DU channel that it can
> > be connected to. This makes no change on Gen2 as all Gen2 SoCs can
> > connected DPAD0 to DU0, which is the current implicit default value.
> > 
> > As the DPAD0 source is always 0 when a single source is possible on
> > Gen2, we can also simplify the Gen2 code in the same function to remove
> > a conditional check.
> 
> Does this patch only prepares for routing to be mad dynamic or it is
> already supported?

It's already dynamic. We support dynamic routing of the DPAD (RGB) output on 
Gen2. On Gen3 all the SoCs supported so far could only route one CRTC to the 
DPAD output, so the routing wasn't very dynamic, but the register still had to 
be programmed accordingly. This patch reuses the existing dynamic routing that 
we use on Gen2 for Gen3.

> I am missing where those dynamic association happens, as I see the
> possible dpad0 source being changed in 'rcar_du_crtc_route_output()'
> which is in turn called by the mode set operation
> 'rcar_du_crtc_route_output()'.
> 
> But at the same time, I only see the routing register DEFR8 being
> written by rcar_du_group_setup_defr8() called by the group route setup
> operation rcar_du_group_set_routing() called at crtc setup time only.
> 
> Would the mode set operation on the encoder being supporsed to go to
> the group's set_routing operation? Or does DEFR8 configuration happens
> with a different call path?

Your analysis of the code flow is right. The reason why we don't write DEFR8 
directly is that changes to the register only take effect when the group is 
disabled (lovely hardware design, isn't it ?). The driver relies on the fact 
that changing the routing involves disabling and enabling CRTCs, but the 
mechanism is fragile, and it might even be buggy.

The RGB output on D3 and E3 isn't officially supported by this patch series, 
so I already plan to revisit the code later and hopefully clean it.

> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/rcar-du/rcar_du_group.c | 17 ++++++-----------
> >  drivers/gpu/drm/rcar-du/rcar_du_kms.c   | 12 ++++++++++++
> >  2 files changed, 18 insertions(+), 11 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_group.c index
> > 4c62841eff2f..f38703e7a10d 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > @@ -56,8 +56,6 @@ static void rcar_du_group_setup_pins(struct
> > rcar_du_group *rgrp)
> >  static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
> >  {
> >  	struct rcar_du_device *rcdu = rgrp->dev;
> > -	unsigned int possible_crtcs =
> > -		rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;
> >  	u32 defr8 = DEFR8_CODE;
> >  	
> >  	if (rcdu->info->gen < 3) {
> > @@ -69,21 +67,18 @@ static void rcar_du_group_setup_defr8(struct
> > rcar_du_group *rgrp)
> >  		 * DU instances that support it.
> >  		 */
> >  		if (rgrp->index == 0) {
> > -			if (possible_crtcs > 1)
> > -				defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source);
> > +			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.
> > +		 * On Gen3 VSPD routing can't be configured, and DPAD routing
> > +		 * is set in the group corresponding to the DPAD output (no Gen3
> > +		 * SoC has multiple DPAD sources belonging to separate groups).
> >  		 */
> > -		unsigned int rgb_crtc = ffs(possible_crtcs) - 1;
> > -		struct rcar_du_crtc *crtc = &rcdu->crtcs[rgb_crtc];
> > -
> > -		if (crtc->index / 2 == rgrp->index)
> > -			defr8 |= DEFR8_DRGBS_DU(crtc->index);
> > +		if (rgrp->index == rcdu->dpad0_source / 2)
> > +			defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source);
> >  	}
> >  	
> >  	rcar_du_group_write(rgrp, DEFR8, defr8);
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index ed7fa3204892..bd01197700c5
> > 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> > @@ -501,6 +501,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
> >  	struct drm_device *dev = rcdu->ddev;
> >  	struct drm_encoder *encoder;
> >  	struct drm_fbdev_cma *fbdev;
> > +	unsigned int dpad0_sources;
> >  	unsigned int num_encoders;
> >  	unsigned int num_groups;
> >  	unsigned int swindex;
> > @@ -613,6 +614,17 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
> >  		encoder->possible_clones = (1 << num_encoders) - 1;
> >  	}
> > 
> > +	/*
> > +	 * Initialize the default DPAD0 source to the index of the first DU
> > +	 * channel that can be connected to DPAD0. The exact value doesn't
> > +	 * matter as it should be overwritten by mode setting for the RGB
> > +	 * output, but it is nonetheless required to ensure a valid initial
> > +	 * hardware configuration on Gen3 where DU0 can't always be connected
> > to
> > +	 * DPAD0.
> > +	 */
> > +	dpad0_sources = rcdu->info->
> > routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;
> > +	rcdu->dpad0_source = ffs(dpad0_sources) - 1;
> > +
> >  	drm_mode_config_reset(dev);
> >  	
> >  	drm_kms_helper_poll_init(dev);

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 08/16] drm: rcar-du: Enable configurable DPAD0 routing on Gen3
@ 2018-09-13 21:25       ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-13 21:25 UTC (permalink / raw)
  To: jacopo mondi; +Cc: linux-renesas-soc, Laurent Pinchart, dri-devel

Hi Jacopo,

Thank you for the patch.

On Tuesday, 11 September 2018 18:46:53 EEST jacopo mondi wrote:
> On Tue, Sep 04, 2018 at 03:10:19PM +0300, Laurent Pinchart wrote:
> > All Gen3 SoCs supported so far have a fixed association between DPAD0
> > and DU channels, which led to hardcoding that association when writing
> > the corresponding hardware register. The D3 and E3 will break that
> > mechanism as DPAD0 can be dynamically connected to either DU0 or DU1.
> > 
> > Make DPAD0 routing dynamic on Gen3. To ensure a valid hardware
> > configuration when the DU starts without the RGB output enabled, DPAD0
> > is associated at initialization time to the first DU channel that it can
> > be connected to. This makes no change on Gen2 as all Gen2 SoCs can
> > connected DPAD0 to DU0, which is the current implicit default value.
> > 
> > As the DPAD0 source is always 0 when a single source is possible on
> > Gen2, we can also simplify the Gen2 code in the same function to remove
> > a conditional check.
> 
> Does this patch only prepares for routing to be mad dynamic or it is
> already supported?

It's already dynamic. We support dynamic routing of the DPAD (RGB) output on 
Gen2. On Gen3 all the SoCs supported so far could only route one CRTC to the 
DPAD output, so the routing wasn't very dynamic, but the register still had to 
be programmed accordingly. This patch reuses the existing dynamic routing that 
we use on Gen2 for Gen3.

> I am missing where those dynamic association happens, as I see the
> possible dpad0 source being changed in 'rcar_du_crtc_route_output()'
> which is in turn called by the mode set operation
> 'rcar_du_crtc_route_output()'.
> 
> But at the same time, I only see the routing register DEFR8 being
> written by rcar_du_group_setup_defr8() called by the group route setup
> operation rcar_du_group_set_routing() called at crtc setup time only.
> 
> Would the mode set operation on the encoder being supporsed to go to
> the group's set_routing operation? Or does DEFR8 configuration happens
> with a different call path?

Your analysis of the code flow is right. The reason why we don't write DEFR8 
directly is that changes to the register only take effect when the group is 
disabled (lovely hardware design, isn't it ?). The driver relies on the fact 
that changing the routing involves disabling and enabling CRTCs, but the 
mechanism is fragile, and it might even be buggy.

The RGB output on D3 and E3 isn't officially supported by this patch series, 
so I already plan to revisit the code later and hopefully clean it.

> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/rcar-du/rcar_du_group.c | 17 ++++++-----------
> >  drivers/gpu/drm/rcar-du/rcar_du_kms.c   | 12 ++++++++++++
> >  2 files changed, 18 insertions(+), 11 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_group.c index
> > 4c62841eff2f..f38703e7a10d 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
> > @@ -56,8 +56,6 @@ static void rcar_du_group_setup_pins(struct
> > rcar_du_group *rgrp)
> >  static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
> >  {
> >  	struct rcar_du_device *rcdu = rgrp->dev;
> > -	unsigned int possible_crtcs =
> > -		rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;
> >  	u32 defr8 = DEFR8_CODE;
> >  	
> >  	if (rcdu->info->gen < 3) {
> > @@ -69,21 +67,18 @@ static void rcar_du_group_setup_defr8(struct
> > rcar_du_group *rgrp)
> >  		 * DU instances that support it.
> >  		 */
> >  		if (rgrp->index == 0) {
> > -			if (possible_crtcs > 1)
> > -				defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source);
> > +			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.
> > +		 * On Gen3 VSPD routing can't be configured, and DPAD routing
> > +		 * is set in the group corresponding to the DPAD output (no Gen3
> > +		 * SoC has multiple DPAD sources belonging to separate groups).
> >  		 */
> > -		unsigned int rgb_crtc = ffs(possible_crtcs) - 1;
> > -		struct rcar_du_crtc *crtc = &rcdu->crtcs[rgb_crtc];
> > -
> > -		if (crtc->index / 2 == rgrp->index)
> > -			defr8 |= DEFR8_DRGBS_DU(crtc->index);
> > +		if (rgrp->index == rcdu->dpad0_source / 2)
> > +			defr8 |= DEFR8_DRGBS_DU(rcdu->dpad0_source);
> >  	}
> >  	
> >  	rcar_du_group_write(rgrp, DEFR8, defr8);
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> > b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index ed7fa3204892..bd01197700c5
> > 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
> > @@ -501,6 +501,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
> >  	struct drm_device *dev = rcdu->ddev;
> >  	struct drm_encoder *encoder;
> >  	struct drm_fbdev_cma *fbdev;
> > +	unsigned int dpad0_sources;
> >  	unsigned int num_encoders;
> >  	unsigned int num_groups;
> >  	unsigned int swindex;
> > @@ -613,6 +614,17 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
> >  		encoder->possible_clones = (1 << num_encoders) - 1;
> >  	}
> > 
> > +	/*
> > +	 * Initialize the default DPAD0 source to the index of the first DU
> > +	 * channel that can be connected to DPAD0. The exact value doesn't
> > +	 * matter as it should be overwritten by mode setting for the RGB
> > +	 * output, but it is nonetheless required to ensure a valid initial
> > +	 * hardware configuration on Gen3 where DU0 can't always be connected
> > to
> > +	 * DPAD0.
> > +	 */
> > +	dpad0_sources = rcdu->info->
> > routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs;
> > +	rcdu->dpad0_source = ffs(dpad0_sources) - 1;
> > +
> >  	drm_mode_config_reset(dev);
> >  	
> >  	drm_kms_helper_poll_init(dev);

-- 
Regards,

Laurent Pinchart



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

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

* Re: [PATCH 01/16] dt-bindings: display: renesas: du: Document r8a77990 bindings
  2018-09-04 12:10   ` Laurent Pinchart
@ 2018-09-14  7:56     ` jacopo mondi
  -1 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-14  7:56 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, devicetree, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 1634 bytes --]

Hi Laurent,

On Tue, Sep 04, 2018 at 03:10:12PM +0300, Laurent Pinchart wrote:
> Document the E3 (r8a77990) SoC in the R-Car DU bindings.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  Documentation/devicetree/bindings/display/renesas,du.txt | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt
> index caae2348a292..9de67be632d1 100644
> --- a/Documentation/devicetree/bindings/display/renesas,du.txt
> +++ b/Documentation/devicetree/bindings/display/renesas,du.txt
> @@ -16,6 +16,7 @@ Required Properties:
>      - "renesas,du-r8a77965" for R8A77965 (R-Car M3-N) compatible DU
>      - "renesas,du-r8a77970" for R8A77970 (R-Car V3M) compatible DU
>      - "renesas,du-r8a77980" for R8A77980 (R-Car V3H) compatible DU
> +    - "renesas,du-r8a77990" for R8A77990 (R-Car E3) compatible DU
>      - "renesas,du-r8a77995" for R8A77995 (R-Car D3) compatible DU
>
>    - reg: the memory-mapped I/O registers base address and length
> @@ -63,6 +64,7 @@ corresponding to each DU output.
>   R8A77965 (R-Car M3-N)  DPAD 0         HDMI 0         LVDS 0         -
>   R8A77970 (R-Car V3M)   DPAD 0         LVDS 0         -              -
>   R8A77980 (R-Car V3H)   DPAD 0         LVDS 0         -              -
> + R8A77990 (R-Car E3)    DPAD 0         LVDS 0         LVDS 1         -
>   R8A77995 (R-Car D3)    DPAD 0         LVDS 0         LVDS 1         -

Thanks,

Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

Thanks
  j

>
>
> --
> Regards,
>
> Laurent Pinchart
>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* Re: [PATCH 01/16] dt-bindings: display: renesas: du: Document r8a77990 bindings
@ 2018-09-14  7:56     ` jacopo mondi
  0 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-14  7:56 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel, linux-renesas-soc, devicetree

[-- Attachment #1: Type: text/plain, Size: 1634 bytes --]

Hi Laurent,

On Tue, Sep 04, 2018 at 03:10:12PM +0300, Laurent Pinchart wrote:
> Document the E3 (r8a77990) SoC in the R-Car DU bindings.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  Documentation/devicetree/bindings/display/renesas,du.txt | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt
> index caae2348a292..9de67be632d1 100644
> --- a/Documentation/devicetree/bindings/display/renesas,du.txt
> +++ b/Documentation/devicetree/bindings/display/renesas,du.txt
> @@ -16,6 +16,7 @@ Required Properties:
>      - "renesas,du-r8a77965" for R8A77965 (R-Car M3-N) compatible DU
>      - "renesas,du-r8a77970" for R8A77970 (R-Car V3M) compatible DU
>      - "renesas,du-r8a77980" for R8A77980 (R-Car V3H) compatible DU
> +    - "renesas,du-r8a77990" for R8A77990 (R-Car E3) compatible DU
>      - "renesas,du-r8a77995" for R8A77995 (R-Car D3) compatible DU
>
>    - reg: the memory-mapped I/O registers base address and length
> @@ -63,6 +64,7 @@ corresponding to each DU output.
>   R8A77965 (R-Car M3-N)  DPAD 0         HDMI 0         LVDS 0         -
>   R8A77970 (R-Car V3M)   DPAD 0         LVDS 0         -              -
>   R8A77980 (R-Car V3H)   DPAD 0         LVDS 0         -              -
> + R8A77990 (R-Car E3)    DPAD 0         LVDS 0         LVDS 1         -
>   R8A77995 (R-Car D3)    DPAD 0         LVDS 0         LVDS 1         -

Thanks,

Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

Thanks
  j

>
>
> --
> Regards,
>
> Laurent Pinchart
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH 02/16] dt-bindings: display: renesas: lvds: Document r8a77990 bindings
  2018-09-04 12:10   ` Laurent Pinchart
@ 2018-09-14  7:57     ` jacopo mondi
  -1 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-14  7:57 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, devicetree, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 1315 bytes --]

Hi Laurent,

On Tue, Sep 04, 2018 at 03:10:13PM +0300, Laurent Pinchart wrote:
> The E3 (r8a77990) supports two LVDS channels. Extend the binding to
> support them.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> index 5a4e379bb414..13af7e2ac7e8 100644
> --- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> +++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> @@ -15,6 +15,7 @@ Required properties:
>    - "renesas,r8a7796-lvds" for R8A7796 (R-Car M3-W) compatible LVDS encoders
>    - "renesas,r8a77970-lvds" for R8A77970 (R-Car V3M) compatible LVDS encoders
>    - "renesas,r8a77980-lvds" for R8A77980 (R-Car V3H) compatible LVDS encoders
> +  - "renesas,r8a77990-lvds" for R8A77990 (R-Car E3) compatible LVDS encoders
>    - "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS encoders
>
>  - reg: Base address and length for the memory-mapped registers
> --
> Regards,
>
Thanks,

Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

> Laurent Pinchart
>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* Re: [PATCH 02/16] dt-bindings: display: renesas: lvds: Document r8a77990 bindings
@ 2018-09-14  7:57     ` jacopo mondi
  0 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-14  7:57 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel, linux-renesas-soc, devicetree

[-- Attachment #1: Type: text/plain, Size: 1315 bytes --]

Hi Laurent,

On Tue, Sep 04, 2018 at 03:10:13PM +0300, Laurent Pinchart wrote:
> The E3 (r8a77990) supports two LVDS channels. Extend the binding to
> support them.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> index 5a4e379bb414..13af7e2ac7e8 100644
> --- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> +++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> @@ -15,6 +15,7 @@ Required properties:
>    - "renesas,r8a7796-lvds" for R8A7796 (R-Car M3-W) compatible LVDS encoders
>    - "renesas,r8a77970-lvds" for R8A77970 (R-Car V3M) compatible LVDS encoders
>    - "renesas,r8a77980-lvds" for R8A77980 (R-Car V3H) compatible LVDS encoders
> +  - "renesas,r8a77990-lvds" for R8A77990 (R-Car E3) compatible LVDS encoders
>    - "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS encoders
>
>  - reg: Base address and length for the memory-mapped registers
> --
> Regards,
>
Thanks,

Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

> Laurent Pinchart
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH 03/16] dt-bindings: display: renesas: lvds: Add EXTAL and DU_DOTCLKIN clocks
  2018-09-04 12:10   ` Laurent Pinchart
@ 2018-09-14  8:00     ` jacopo mondi
  -1 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-14  8:00 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, devicetree, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 2355 bytes --]

Hi Laurent,

On Tue, Sep 04, 2018 at 03:10:14PM +0300, Laurent Pinchart wrote:
> On the D3 and E3 SoCs, the LVDS encoder can derive its internal pixel
> clock from an externally supplied clock, either through the EXTAL pin or
> through one of the DU_DOTCLKINx pins. Add corresponding clocks to the DT
> bindings.
>
> To retain backward compatibility with DT that don't specify the
> clock-names property, the functional clock must always be specified
> first, and the clock-names property is optional when only the functional
> clock is specified.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  .../devicetree/bindings/display/bridge/renesas,lvds.txt      | 12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> index 13af7e2ac7e8..9e3913f6a643 100644
> --- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> +++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> @@ -19,7 +19,17 @@ Required properties:
>    - "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS encoders
>
>  - reg: Base address and length for the memory-mapped registers
> -- clocks: A phandle + clock-specifier pair for the functional clock
> +- clocks: A list of phandles + clock-specifier pairs, one for each entry in
> +  the clock-names property.
> +- clock-names: Name of the clocks. This property is model-dependent.
> +  - The functional clock is mandatory for all models, shall be listed first,

I would write

The functional clock, which is mandatory for all models, shall be listed
first and shall be named "fck".

> +    and shall be named "fck".
> +  - On R8A77990 and R8A77995, the LVDS encoder can use the EXTAL or
> +    DU_DOTCLKINx clocks. Those clocks are optional. When supplied they must be
> +    named "extal" and "dclkin.x" respectively, with "x" being the DU_DOTCLKIN
> +    numerical index.

Is it valid to list other clocks here for the other SoCs?

> +  - When the clocks property only contains the functional clock, the
> +    clock-names property may be omitted.
>  - resets: A phandle + reset specifier for the module reset

Thanks
   j
>
>  Required nodes:
> --
> Regards,
>
> Laurent Pinchart
>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* Re: [PATCH 03/16] dt-bindings: display: renesas: lvds: Add EXTAL and DU_DOTCLKIN clocks
@ 2018-09-14  8:00     ` jacopo mondi
  0 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-14  8:00 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel, linux-renesas-soc, devicetree

[-- Attachment #1: Type: text/plain, Size: 2355 bytes --]

Hi Laurent,

On Tue, Sep 04, 2018 at 03:10:14PM +0300, Laurent Pinchart wrote:
> On the D3 and E3 SoCs, the LVDS encoder can derive its internal pixel
> clock from an externally supplied clock, either through the EXTAL pin or
> through one of the DU_DOTCLKINx pins. Add corresponding clocks to the DT
> bindings.
>
> To retain backward compatibility with DT that don't specify the
> clock-names property, the functional clock must always be specified
> first, and the clock-names property is optional when only the functional
> clock is specified.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  .../devicetree/bindings/display/bridge/renesas,lvds.txt      | 12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> index 13af7e2ac7e8..9e3913f6a643 100644
> --- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> +++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> @@ -19,7 +19,17 @@ Required properties:
>    - "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS encoders
>
>  - reg: Base address and length for the memory-mapped registers
> -- clocks: A phandle + clock-specifier pair for the functional clock
> +- clocks: A list of phandles + clock-specifier pairs, one for each entry in
> +  the clock-names property.
> +- clock-names: Name of the clocks. This property is model-dependent.
> +  - The functional clock is mandatory for all models, shall be listed first,

I would write

The functional clock, which is mandatory for all models, shall be listed
first and shall be named "fck".

> +    and shall be named "fck".
> +  - On R8A77990 and R8A77995, the LVDS encoder can use the EXTAL or
> +    DU_DOTCLKINx clocks. Those clocks are optional. When supplied they must be
> +    named "extal" and "dclkin.x" respectively, with "x" being the DU_DOTCLKIN
> +    numerical index.

Is it valid to list other clocks here for the other SoCs?

> +  - When the clocks property only contains the functional clock, the
> +    clock-names property may be omitted.
>  - resets: A phandle + reset specifier for the module reset

Thanks
   j
>
>  Required nodes:
> --
> Regards,
>
> Laurent Pinchart
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH 03/16] dt-bindings: display: renesas: lvds: Add EXTAL and DU_DOTCLKIN clocks
  2018-09-14  8:00     ` jacopo mondi
@ 2018-09-14  8:24       ` Laurent Pinchart
  -1 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-14  8:24 UTC (permalink / raw)
  To: jacopo mondi; +Cc: linux-renesas-soc, devicetree, Laurent Pinchart, dri-devel

Hi Jacopo,

On Friday, 14 September 2018 11:00:46 EEST jacopo mondi wrote:
> On Tue, Sep 04, 2018 at 03:10:14PM +0300, Laurent Pinchart wrote:
> > On the D3 and E3 SoCs, the LVDS encoder can derive its internal pixel
> > clock from an externally supplied clock, either through the EXTAL pin or
> > through one of the DU_DOTCLKINx pins. Add corresponding clocks to the DT
> > bindings.
> > 
> > To retain backward compatibility with DT that don't specify the
> > clock-names property, the functional clock must always be specified
> > first, and the clock-names property is optional when only the functional
> > clock is specified.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  .../devicetree/bindings/display/bridge/renesas,lvds.txt      | 12 ++++++-
> >  1 file changed, 11 insertions(+), 1 deletion(-)
> > 
> > diff --git
> > a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> > b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt index
> > 13af7e2ac7e8..9e3913f6a643 100644
> > --- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> > +++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> > @@ -19,7 +19,17 @@ Required properties:
> >    - "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS
> >    encoders
> >  
> >  - reg: Base address and length for the memory-mapped registers
> > 
> > -- clocks: A phandle + clock-specifier pair for the functional clock
> > +- clocks: A list of phandles + clock-specifier pairs, one for each entry
> > in
> > +  the clock-names property.
> > +- clock-names: Name of the clocks. This property is model-dependent.
> > +  - The functional clock is mandatory for all models, shall be listed
> > first,
> 
> I would write
> 
> The functional clock, which is mandatory for all models, shall be listed
> first and shall be named "fck".

I'll change that.

> > +    and shall be named "fck".
> > +  - On R8A77990 and R8A77995, the LVDS encoder can use the EXTAL or
> > +    DU_DOTCLKINx clocks. Those clocks are optional. When supplied they
> > must be
> > +    named "extal" and "dclkin.x" respectively, with "x" being the
> > DU_DOTCLKIN
> > +    numerical index.
> 
> Is it valid to list other clocks here for the other SoCs?

No, those clocks only exist for D3 and E3, as stated (R8A77990 and R8A77995). 
Do you think the text isn't clear enough ?

> > +  - When the clocks property only contains the functional clock, the
> > +    clock-names property may be omitted.
> > 
> >  - resets: A phandle + reset specifier for the module reset
> 
> Thanks
>    j
> 
> >  Required nodes:

-- 
Regards,

Laurent Pinchart



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

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

* Re: [PATCH 03/16] dt-bindings: display: renesas: lvds: Add EXTAL and DU_DOTCLKIN clocks
@ 2018-09-14  8:24       ` Laurent Pinchart
  0 siblings, 0 replies; 86+ messages in thread
From: Laurent Pinchart @ 2018-09-14  8:24 UTC (permalink / raw)
  To: jacopo mondi; +Cc: Laurent Pinchart, dri-devel, linux-renesas-soc, devicetree

Hi Jacopo,

On Friday, 14 September 2018 11:00:46 EEST jacopo mondi wrote:
> On Tue, Sep 04, 2018 at 03:10:14PM +0300, Laurent Pinchart wrote:
> > On the D3 and E3 SoCs, the LVDS encoder can derive its internal pixel
> > clock from an externally supplied clock, either through the EXTAL pin or
> > through one of the DU_DOTCLKINx pins. Add corresponding clocks to the DT
> > bindings.
> > 
> > To retain backward compatibility with DT that don't specify the
> > clock-names property, the functional clock must always be specified
> > first, and the clock-names property is optional when only the functional
> > clock is specified.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  .../devicetree/bindings/display/bridge/renesas,lvds.txt      | 12 ++++++-
> >  1 file changed, 11 insertions(+), 1 deletion(-)
> > 
> > diff --git
> > a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> > b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt index
> > 13af7e2ac7e8..9e3913f6a643 100644
> > --- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> > +++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> > @@ -19,7 +19,17 @@ Required properties:
> >    - "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS
> >    encoders
> >  
> >  - reg: Base address and length for the memory-mapped registers
> > 
> > -- clocks: A phandle + clock-specifier pair for the functional clock
> > +- clocks: A list of phandles + clock-specifier pairs, one for each entry
> > in
> > +  the clock-names property.
> > +- clock-names: Name of the clocks. This property is model-dependent.
> > +  - The functional clock is mandatory for all models, shall be listed
> > first,
> 
> I would write
> 
> The functional clock, which is mandatory for all models, shall be listed
> first and shall be named "fck".

I'll change that.

> > +    and shall be named "fck".
> > +  - On R8A77990 and R8A77995, the LVDS encoder can use the EXTAL or
> > +    DU_DOTCLKINx clocks. Those clocks are optional. When supplied they
> > must be
> > +    named "extal" and "dclkin.x" respectively, with "x" being the
> > DU_DOTCLKIN
> > +    numerical index.
> 
> Is it valid to list other clocks here for the other SoCs?

No, those clocks only exist for D3 and E3, as stated (R8A77990 and R8A77995). 
Do you think the text isn't clear enough ?

> > +  - When the clocks property only contains the functional clock, the
> > +    clock-names property may be omitted.
> > 
> >  - resets: A phandle + reset specifier for the module reset
> 
> Thanks
>    j
> 
> >  Required nodes:

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 03/16] dt-bindings: display: renesas: lvds: Add EXTAL and DU_DOTCLKIN clocks
  2018-09-14  8:24       ` Laurent Pinchart
@ 2018-09-14  8:35         ` jacopo mondi
  -1 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-14  8:35 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-renesas-soc, devicetree, Laurent Pinchart, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 3170 bytes --]

Hi Laurent,

On Fri, Sep 14, 2018 at 11:24:32AM +0300, Laurent Pinchart wrote:
> Hi Jacopo,
>
> On Friday, 14 September 2018 11:00:46 EEST jacopo mondi wrote:
> > On Tue, Sep 04, 2018 at 03:10:14PM +0300, Laurent Pinchart wrote:
> > > On the D3 and E3 SoCs, the LVDS encoder can derive its internal pixel
> > > clock from an externally supplied clock, either through the EXTAL pin or
> > > through one of the DU_DOTCLKINx pins. Add corresponding clocks to the DT
> > > bindings.
> > >
> > > To retain backward compatibility with DT that don't specify the
> > > clock-names property, the functional clock must always be specified
> > > first, and the clock-names property is optional when only the functional
> > > clock is specified.
> > >
> > > Signed-off-by: Laurent Pinchart
> > > <laurent.pinchart+renesas@ideasonboard.com>
> > > ---
> > >
> > >  .../devicetree/bindings/display/bridge/renesas,lvds.txt      | 12 ++++++-
> > >  1 file changed, 11 insertions(+), 1 deletion(-)
> > >
> > > diff --git
> > > a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> > > b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt index
> > > 13af7e2ac7e8..9e3913f6a643 100644
> > > --- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> > > +++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> > > @@ -19,7 +19,17 @@ Required properties:
> > >    - "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS
> > >    encoders
> > >
> > >  - reg: Base address and length for the memory-mapped registers
> > >
> > > -- clocks: A phandle + clock-specifier pair for the functional clock
> > > +- clocks: A list of phandles + clock-specifier pairs, one for each entry
> > > in
> > > +  the clock-names property.
> > > +- clock-names: Name of the clocks. This property is model-dependent.
> > > +  - The functional clock is mandatory for all models, shall be listed
> > > first,
> >
> > I would write
> >
> > The functional clock, which is mandatory for all models, shall be listed
> > first and shall be named "fck".
>
> I'll change that.
>
> > > +    and shall be named "fck".
> > > +  - On R8A77990 and R8A77995, the LVDS encoder can use the EXTAL or
> > > +    DU_DOTCLKINx clocks. Those clocks are optional. When supplied they
> > > must be
> > > +    named "extal" and "dclkin.x" respectively, with "x" being the
> > > DU_DOTCLKIN
> > > +    numerical index.
> >
> > Is it valid to list other clocks here for the other SoCs?
>
> No, those clocks only exist for D3 and E3, as stated (R8A77990 and R8A77995).
> Do you think the text isn't clear enough ?

It's fine. I now read it as:
"On R8A77990 and R8A77995 _only_, the LVDS encoder can use the EXTAL or"

It's all good, with the little "which" added to the first statement
please add to v2:
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

Thanks
   j

>
> > > +  - When the clocks property only contains the functional clock, the
> > > +    clock-names property may be omitted.
> > >
> > >  - resets: A phandle + reset specifier for the module reset
> >
> > Thanks
> >    j
> >
> > >  Required nodes:
>
> --
> Regards,
>
> Laurent Pinchart
>
>
>

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* Re: [PATCH 03/16] dt-bindings: display: renesas: lvds: Add EXTAL and DU_DOTCLKIN clocks
@ 2018-09-14  8:35         ` jacopo mondi
  0 siblings, 0 replies; 86+ messages in thread
From: jacopo mondi @ 2018-09-14  8:35 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Laurent Pinchart, dri-devel, linux-renesas-soc, devicetree

[-- Attachment #1: Type: text/plain, Size: 3170 bytes --]

Hi Laurent,

On Fri, Sep 14, 2018 at 11:24:32AM +0300, Laurent Pinchart wrote:
> Hi Jacopo,
>
> On Friday, 14 September 2018 11:00:46 EEST jacopo mondi wrote:
> > On Tue, Sep 04, 2018 at 03:10:14PM +0300, Laurent Pinchart wrote:
> > > On the D3 and E3 SoCs, the LVDS encoder can derive its internal pixel
> > > clock from an externally supplied clock, either through the EXTAL pin or
> > > through one of the DU_DOTCLKINx pins. Add corresponding clocks to the DT
> > > bindings.
> > >
> > > To retain backward compatibility with DT that don't specify the
> > > clock-names property, the functional clock must always be specified
> > > first, and the clock-names property is optional when only the functional
> > > clock is specified.
> > >
> > > Signed-off-by: Laurent Pinchart
> > > <laurent.pinchart+renesas@ideasonboard.com>
> > > ---
> > >
> > >  .../devicetree/bindings/display/bridge/renesas,lvds.txt      | 12 ++++++-
> > >  1 file changed, 11 insertions(+), 1 deletion(-)
> > >
> > > diff --git
> > > a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> > > b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt index
> > > 13af7e2ac7e8..9e3913f6a643 100644
> > > --- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> > > +++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt
> > > @@ -19,7 +19,17 @@ Required properties:
> > >    - "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS
> > >    encoders
> > >
> > >  - reg: Base address and length for the memory-mapped registers
> > >
> > > -- clocks: A phandle + clock-specifier pair for the functional clock
> > > +- clocks: A list of phandles + clock-specifier pairs, one for each entry
> > > in
> > > +  the clock-names property.
> > > +- clock-names: Name of the clocks. This property is model-dependent.
> > > +  - The functional clock is mandatory for all models, shall be listed
> > > first,
> >
> > I would write
> >
> > The functional clock, which is mandatory for all models, shall be listed
> > first and shall be named "fck".
>
> I'll change that.
>
> > > +    and shall be named "fck".
> > > +  - On R8A77990 and R8A77995, the LVDS encoder can use the EXTAL or
> > > +    DU_DOTCLKINx clocks. Those clocks are optional. When supplied they
> > > must be
> > > +    named "extal" and "dclkin.x" respectively, with "x" being the
> > > DU_DOTCLKIN
> > > +    numerical index.
> >
> > Is it valid to list other clocks here for the other SoCs?
>
> No, those clocks only exist for D3 and E3, as stated (R8A77990 and R8A77995).
> Do you think the text isn't clear enough ?

It's fine. I now read it as:
"On R8A77990 and R8A77995 _only_, the LVDS encoder can use the EXTAL or"

It's all good, with the little "which" added to the first statement
please add to v2:
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

Thanks
   j

>
> > > +  - When the clocks property only contains the functional clock, the
> > > +    clock-names property may be omitted.
> > >
> > >  - resets: A phandle + reset specifier for the module reset
> >
> > Thanks
> >    j
> >
> > >  Required nodes:
>
> --
> Regards,
>
> Laurent Pinchart
>
>
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH 01/16] dt-bindings: display: renesas: du: Document r8a77990 bindings
  2018-09-04 12:10   ` Laurent Pinchart
  (?)
  (?)
@ 2018-09-17  5:44   ` Rob Herring
  -1 siblings, 0 replies; 86+ messages in thread
From: Rob Herring @ 2018-09-17  5:44 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, devicetree, dri-devel

On Tue,  4 Sep 2018 15:10:12 +0300, Laurent Pinchart wrote:
> Document the E3 (r8a77990) SoC in the R-Car DU bindings.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  Documentation/devicetree/bindings/display/renesas,du.txt | 2 ++
>  1 file changed, 2 insertions(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

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

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

* Re: [PATCH 02/16] dt-bindings: display: renesas: lvds: Document r8a77990 bindings
  2018-09-04 12:10   ` Laurent Pinchart
  (?)
  (?)
@ 2018-09-17  5:44   ` Rob Herring
  -1 siblings, 0 replies; 86+ messages in thread
From: Rob Herring @ 2018-09-17  5:44 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, devicetree, dri-devel

On Tue,  4 Sep 2018 15:10:13 +0300, Laurent Pinchart wrote:
> The E3 (r8a77990) supports two LVDS channels. Extend the binding to
> support them.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  Documentation/devicetree/bindings/display/bridge/renesas,lvds.txt | 1 +
>  1 file changed, 1 insertion(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

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

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

end of thread, other threads:[~2018-09-17  5:44 UTC | newest]

Thread overview: 86+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-04 12:10 [PATCH 00/16] R-Car D3/E3 display support (with LVDS PLL) Laurent Pinchart
2018-09-04 12:10 ` Laurent Pinchart
2018-09-04 12:10 ` [PATCH 01/16] dt-bindings: display: renesas: du: Document r8a77990 bindings Laurent Pinchart
2018-09-04 12:10   ` Laurent Pinchart
2018-09-14  7:56   ` jacopo mondi
2018-09-14  7:56     ` jacopo mondi
2018-09-17  5:44   ` Rob Herring
2018-09-04 12:10 ` [PATCH 02/16] dt-bindings: display: renesas: lvds: " Laurent Pinchart
2018-09-04 12:10   ` Laurent Pinchart
2018-09-14  7:57   ` jacopo mondi
2018-09-14  7:57     ` jacopo mondi
2018-09-17  5:44   ` Rob Herring
2018-09-04 12:10 ` [PATCH 03/16] dt-bindings: display: renesas: lvds: Add EXTAL and DU_DOTCLKIN clocks Laurent Pinchart
2018-09-04 12:10   ` Laurent Pinchart
2018-09-14  8:00   ` jacopo mondi
2018-09-14  8:00     ` jacopo mondi
2018-09-14  8:24     ` Laurent Pinchart
2018-09-14  8:24       ` Laurent Pinchart
2018-09-14  8:35       ` jacopo mondi
2018-09-14  8:35         ` jacopo mondi
2018-09-04 12:10 ` [PATCH 04/16] drm: bridge: thc63: Restrict modes based on hardware operating frequency Laurent Pinchart
2018-09-04 12:10   ` Laurent Pinchart
2018-09-11 13:31   ` jacopo mondi
2018-09-11 13:31     ` jacopo mondi
2018-09-13 21:08     ` Laurent Pinchart
2018-09-13 21:08       ` Laurent Pinchart
2018-09-13 12:36   ` Andrzej Hajda
2018-09-13 12:36     ` Andrzej Hajda
2018-09-04 12:10 ` [PATCH 05/16] drm: rcar-du: lvds: D3/E3 support Laurent Pinchart
2018-09-04 12:10   ` Laurent Pinchart
2018-09-04 14:29   ` Geert Uytterhoeven
2018-09-04 14:29     ` Geert Uytterhoeven
2018-09-05 14:01     ` Laurent Pinchart
2018-09-05 14:01       ` Laurent Pinchart
2018-09-11 13:23   ` jacopo mondi
2018-09-11 13:23     ` jacopo mondi
2018-09-13 21:14     ` Laurent Pinchart
2018-09-13 21:14       ` Laurent Pinchart
2018-09-04 12:10 ` [PATCH 06/16] drm: rcar-du: Perform the initial CRTC setup from rcar_du_crtc_get() Laurent Pinchart
2018-09-04 12:10   ` Laurent Pinchart
2018-09-07 18:19   ` jacopo mondi
2018-09-07 18:19     ` jacopo mondi
2018-09-09 16:44     ` Laurent Pinchart
2018-09-09 16:44       ` Laurent Pinchart
2018-09-04 12:10 ` [PATCH 07/16] drm: rcar-du: Use LVDS PLL clock as dot clock when possible Laurent Pinchart
2018-09-04 12:10   ` Laurent Pinchart
2018-09-11 14:59   ` jacopo mondi
2018-09-11 14:59     ` jacopo mondi
2018-09-13 21:17     ` Laurent Pinchart
2018-09-13 21:17       ` Laurent Pinchart
2018-09-04 12:10 ` [PATCH 08/16] drm: rcar-du: Enable configurable DPAD0 routing on Gen3 Laurent Pinchart
2018-09-04 12:10   ` Laurent Pinchart
2018-09-11 15:46   ` jacopo mondi
2018-09-11 15:46     ` jacopo mondi
2018-09-13 21:25     ` Laurent Pinchart
2018-09-13 21:25       ` Laurent Pinchart
2018-09-04 12:10 ` [PATCH 09/16] drm: rcar-du: Cache DSYSR value to ensure known initial value Laurent Pinchart
2018-09-04 12:10   ` Laurent Pinchart
2018-09-04 12:10 ` [PATCH 10/16] drm: rcar-du: Don't use TV sync mode when not supported by the hardware Laurent Pinchart
2018-09-04 12:10   ` Laurent Pinchart
2018-09-04 12:10 ` [PATCH 11/16] drm: rcar-du: Add r8a77990 and r8a77995 device support Laurent Pinchart
2018-09-04 12:10   ` Laurent Pinchart
2018-09-04 12:10 ` [PATCH 12/16] arm64: dts: renesas: r8a77990: Add I2C device nodes Laurent Pinchart
2018-09-04 12:10   ` Laurent Pinchart
2018-09-04 14:32   ` Geert Uytterhoeven
2018-09-04 14:32     ` Geert Uytterhoeven
2018-09-04 14:49     ` jacopo mondi
2018-09-04 14:49       ` jacopo mondi
2018-09-05 13:53       ` Laurent Pinchart
2018-09-05 13:53         ` Laurent Pinchart
2018-09-06  9:26         ` Simon Horman
2018-09-06  9:26           ` Simon Horman
2018-09-06  9:48           ` Laurent Pinchart
2018-09-06  9:48             ` Laurent Pinchart
2018-09-05 13:52     ` Laurent Pinchart
2018-09-05 13:52       ` Laurent Pinchart
2018-09-04 12:10 ` [PATCH 13/16] arm64: dts: renesas: r8a77990: Add display output support Laurent Pinchart
2018-09-04 12:10   ` Laurent Pinchart
2018-09-04 12:10 ` [PATCH 14/16] arm64: dts: renesas: r8a77995: Add LVDS support Laurent Pinchart
2018-09-04 12:10   ` Laurent Pinchart
2018-09-04 12:10 ` [PATCH 15/16] arm64: dts: renesas: r8a77990: ebisu: Enable VGA and HDMI outputs Laurent Pinchart
2018-09-04 12:10   ` Laurent Pinchart
2018-09-04 12:10 ` [PATCH 16/16] arm64: dts: renesas: r8a77995: draak: Enable HDMI display output Laurent Pinchart
2018-09-04 12:10   ` Laurent Pinchart
2018-09-05 16:22 ` [PATCH 00/16] R-Car D3/E3 display support (with LVDS PLL) jacopo mondi
2018-09-05 16:22   ` jacopo mondi

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.