linux-renesas-soc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] R-Car DU DPAD support for D3 and E3
@ 2019-01-17  1:49 Laurent Pinchart
  2019-01-17  1:49 ` [PATCH 1/6] drm: rcar-du: Simplify encoder registration Laurent Pinchart
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Laurent Pinchart @ 2019-01-17  1:49 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Kieran Bingham

Hello,

This series adds support for the DPAD0 output for the D3 and E3 SoCs. On
the Draak and Ebisu boards, DPAD0 is used for the VGA output.

Patches 1/6 and 2/6 prepare the grounds by successfully probing LVDS
encoders that have no connected output. This is required in order to
provide a dot clock to the DPAD output, as on the D3 and E3 SoCs the dot
clock is provided by the LVDS encoders.

Patch 3/6 then adds an API to the LVDS encoder driver to control the
LVDS output clock independently of the LVDS encoder itself, and patch
4/6 makes use of that API to control the clock from the DU driver.

Patches 5/6 and 6/6 finally enable the LVDS1 encoders in the Ebisu and
Draak boards DTs, required to operate the HDMI (out of LVDS0) and VGA
(using the LVDS1 dot clock) together.

The patches have been tested on Draak only as I don't have access to an
Ebisu board, but they should work equally well on both boards.

For your convenience the patches are available from

	git://linuxtv.org/pinchartl/media.git drm/du/next

Laurent Pinchart (6):
  drm: rcar-du: Simplify encoder registration
  drm: rcar-du: lvds: Don't fail probe if output is not connected on
    D3/E3
  drm: rcar-du: lvds: Add API to enable/disable clock output
  drm: rcar-du: Turn LVDS clock output on/off for DPAD0 output on D3/E3
  arm64: dts: renesas: r8a77990: ebisu: Enable LVDS1 encoder
  arm64: dts: renesas: r8a77995: draak: Enable LVDS1 encoder

 .../arm64/boot/dts/renesas/r8a77990-ebisu.dts |  2 +
 .../arm64/boot/dts/renesas/r8a77995-draak.dts |  2 +
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c        | 34 +++++++
 drivers/gpu/drm/rcar-du/rcar_du_drv.h         |  3 +
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c     |  4 +-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.h     |  3 +-
 drivers/gpu/drm/rcar-du/rcar_du_kms.c         | 52 +----------
 drivers/gpu/drm/rcar-du/rcar_lvds.c           | 92 ++++++++++++++++---
 drivers/gpu/drm/rcar-du/rcar_lvds.h           | 18 ++++
 9 files changed, 146 insertions(+), 64 deletions(-)
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_lvds.h

-- 
Regards,

Laurent Pinchart


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

* [PATCH 1/6] drm: rcar-du: Simplify encoder registration
  2019-01-17  1:49 [PATCH 0/6] R-Car DU DPAD support for D3 and E3 Laurent Pinchart
@ 2019-01-17  1:49 ` Laurent Pinchart
  2019-01-17  1:49 ` [PATCH 2/6] drm: rcar-du: lvds: Don't fail probe if output is not connected on D3/E3 Laurent Pinchart
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Laurent Pinchart @ 2019-01-17  1:49 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Kieran Bingham

Before the driver fully moved to drm_bridge and drm_panel, it was
necessary to parse DT and locate encoder and connector nodes. The
connector node is now unused and can be removed as a parameter to
rcar_du_encoder_init(). As a consequence rcar_du_encoders_init_one() can
be greatly simplified, removing most of the DT parsing.

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

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index f16209499117..ba2b38f76b54 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -30,8 +30,7 @@ static const struct drm_encoder_funcs encoder_funcs = {
 
 int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 			 enum rcar_du_output output,
-			 struct device_node *enc_node,
-			 struct device_node *con_node)
+			 struct device_node *enc_node)
 {
 	struct rcar_du_encoder *renc;
 	struct drm_encoder *encoder;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
index 552f2a02e5b5..df9be4524301 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
@@ -26,7 +26,6 @@ struct rcar_du_encoder {
 
 int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 			 enum rcar_du_output output,
-			 struct device_node *enc_node,
-			 struct device_node *con_node);
+			 struct device_node *enc_node);
 
 #endif /* __RCAR_DU_ENCODER_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 015c421451dc..1bd75187d039 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -330,17 +330,10 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
 				     enum rcar_du_output output,
 				     struct of_endpoint *ep)
 {
-	struct device_node *connector = NULL;
-	struct device_node *encoder = NULL;
-	struct device_node *ep_node = NULL;
-	struct device_node *entity_ep_node;
 	struct device_node *entity;
 	int ret;
 
-	/*
-	 * Locate the connected entity and infer its type from the number of
-	 * endpoints.
-	 */
+	/* Locate the connected entity and initialize the encoder. */
 	entity = of_graph_get_remote_port_parent(ep->local_node);
 	if (!entity) {
 		dev_dbg(rcdu->dev, "unconnected endpoint %pOF, skipping\n",
@@ -356,50 +349,13 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
 		return -ENODEV;
 	}
 
-	entity_ep_node = of_graph_get_remote_endpoint(ep->local_node);
-
-	for_each_endpoint_of_node(entity, ep_node) {
-		if (ep_node == entity_ep_node)
-			continue;
-
-		/*
-		 * We've found one endpoint other than the input, this must
-		 * be an encoder. Locate the connector.
-		 */
-		encoder = entity;
-		connector = of_graph_get_remote_port_parent(ep_node);
-		of_node_put(ep_node);
-
-		if (!connector) {
-			dev_warn(rcdu->dev,
-				 "no connector for encoder %pOF, skipping\n",
-				 encoder);
-			of_node_put(entity_ep_node);
-			of_node_put(encoder);
-			return -ENODEV;
-		}
-
-		break;
-	}
-
-	of_node_put(entity_ep_node);
-
-	if (!encoder) {
-		dev_warn(rcdu->dev,
-			 "no encoder found for endpoint %pOF, skipping\n",
-			 ep->local_node);
-		of_node_put(entity);
-		return -ENODEV;
-	}
-
-	ret = rcar_du_encoder_init(rcdu, output, encoder, connector);
+	ret = rcar_du_encoder_init(rcdu, output, entity);
 	if (ret && ret != -EPROBE_DEFER)
 		dev_warn(rcdu->dev,
 			 "failed to initialize encoder %pOF on output %u (%d), skipping\n",
-			 encoder, output, ret);
+			 entity, output, ret);
 
-	of_node_put(encoder);
-	of_node_put(connector);
+	of_node_put(entity);
 
 	return ret;
 }
-- 
Regards,

Laurent Pinchart


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

* [PATCH 2/6] drm: rcar-du: lvds: Don't fail probe if output is not connected on D3/E3
  2019-01-17  1:49 [PATCH 0/6] R-Car DU DPAD support for D3 and E3 Laurent Pinchart
  2019-01-17  1:49 ` [PATCH 1/6] drm: rcar-du: Simplify encoder registration Laurent Pinchart
@ 2019-01-17  1:49 ` Laurent Pinchart
  2019-01-17  8:23   ` Sergei Shtylyov
  2019-01-17  1:49 ` [PATCH 3/6] drm: rcar-du: lvds: Add API to enable/disable clock output Laurent Pinchart
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 10+ messages in thread
From: Laurent Pinchart @ 2019-01-17  1:49 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Kieran Bingham

On the D3 and E3 SoCs the LVDS encoder has an extended internal PLL and
supplies a clock to the DU. That clock is used not only for the LVDS
outputs but also for the DPAD output. The LVDS encoder thus needs to be
available to the DU even when its output is disabled. Don't fail probe
in that cose on D3 and E3.

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

diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
index 96d749a35b25..a8ec6c6fa983 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
@@ -544,7 +544,10 @@ static int rcar_lvds_attach(struct drm_bridge *bridge)
 		return drm_bridge_attach(bridge->encoder, lvds->next_bridge,
 					 bridge);
 
-	/* Otherwise we have a panel, create a connector. */
+	/* Otherwise if we have a panel, create a connector. */
+	if (!lvds->panel)
+		return 0;
+
 	ret = drm_connector_init(bridge->dev, connector, &rcar_lvds_conn_funcs,
 				 DRM_MODE_CONNECTOR_LVDS);
 	if (ret < 0)
@@ -592,7 +595,8 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
 	local_output = of_graph_get_endpoint_by_regs(lvds->dev->of_node, 1, 0);
 	if (!local_output) {
 		dev_dbg(lvds->dev, "unconnected port@1\n");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto done;
 	}
 
 	/*
@@ -642,6 +646,15 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
 	of_node_put(remote_input);
 	of_node_put(remote);
 
+	/*
+	 * On D3/E3 the LVDS encoder provides a clock to the DU, which can be
+	 * used for the DPAD output even when the LVDS output is not connected.
+	 * Don't fail probe in that case as the DU will need the bridge to
+	 * control the clock.
+	 */
+	if (lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)
+		return ret == -ENODEV ? 0 : ret;
+
 	return ret;
 }
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH 3/6] drm: rcar-du: lvds: Add API to enable/disable clock output
  2019-01-17  1:49 [PATCH 0/6] R-Car DU DPAD support for D3 and E3 Laurent Pinchart
  2019-01-17  1:49 ` [PATCH 1/6] drm: rcar-du: Simplify encoder registration Laurent Pinchart
  2019-01-17  1:49 ` [PATCH 2/6] drm: rcar-du: lvds: Don't fail probe if output is not connected on D3/E3 Laurent Pinchart
@ 2019-01-17  1:49 ` Laurent Pinchart
  2019-01-17  1:49 ` [PATCH 4/6] drm: rcar-du: Turn LVDS clock output on/off for DPAD0 output on D3/E3 Laurent Pinchart
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Laurent Pinchart @ 2019-01-17  1:49 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Kieran Bingham

On the D3 and E3 platforms, the LVDS internal PLL supplies the pixel
clock to the DU. This works automatically for LVDS outputs as the LVDS
encoder is enabled through the bridge API, enabling the internal PLL and
clock output. However, when using the DU DPAD output with the LVDS
outputs turned off, the LVDS PLL needs to be controlled manually. Add an
API to do so, to be called by the DU driver.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_lvds.c | 75 +++++++++++++++++++++++++----
 drivers/gpu/drm/rcar-du/rcar_lvds.h | 18 +++++++
 2 files changed, 83 insertions(+), 10 deletions(-)
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_lvds.h

diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
index a8ec6c6fa983..c5371127ff94 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
@@ -22,6 +22,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_panel.h>
 
+#include "rcar_lvds.h"
 #include "rcar_lvds_regs.h"
 
 struct rcar_lvds;
@@ -182,8 +183,9 @@ struct pll_info {
 
 static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk,
 				     unsigned long target, struct pll_info *pll,
-				     u32 clksel)
+				     u32 clksel, bool dot_clock_only)
 {
+	unsigned int div7 = dot_clock_only ? 1 : 7;
 	unsigned long output;
 	unsigned long fin;
 	unsigned int m_min;
@@ -217,9 +219,9 @@ static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk,
 	 *                     `------------> | |
 	 *                                    |/
 	 *
-	 * 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 /7 divider is optional, it is enabled when the LVDS PLL is used
+	 * to drive the LVDS encoder, and disabled when  used to generate a dot
+	 * clock for the DU RGB output, without using the LVDS encoder.
 	 *
 	 * The PLL allowed input frequency range is 12 MHz to 192 MHz.
 	 */
@@ -279,7 +281,7 @@ static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk,
 				 * the PLL, followed by a an optional fixed /7
 				 * divider.
 				 */
-				fout = fvco / (1 << e) / 7;
+				fout = fvco / (1 << e) / div7;
 				div = DIV_ROUND_CLOSEST(fout, target);
 				diff = abs(fout / div - target);
 
@@ -300,7 +302,7 @@ static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk,
 
 done:
 	output = fin * pll->pll_n / pll->pll_m / (1 << pll->pll_e)
-	       / 7 / pll->div;
+	       / div7 / pll->div;
 	error = (long)(output - target) * 10000 / (long)target;
 
 	dev_dbg(lvds->dev,
@@ -310,17 +312,18 @@ static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk,
 		pll->pll_m, pll->pll_n, pll->pll_e, pll->div);
 }
 
-static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned int freq)
+static void __rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds,
+					unsigned int freq, bool dot_clock_only)
 {
 	struct pll_info pll = { .diff = (unsigned long)-1 };
 	u32 lvdpllcr;
 
 	rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[0], freq, &pll,
-				 LVDPLLCR_CKSEL_DU_DOTCLKIN(0));
+				 LVDPLLCR_CKSEL_DU_DOTCLKIN(0), dot_clock_only);
 	rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.dotclkin[1], freq, &pll,
-				 LVDPLLCR_CKSEL_DU_DOTCLKIN(1));
+				 LVDPLLCR_CKSEL_DU_DOTCLKIN(1), dot_clock_only);
 	rcar_lvds_d3_e3_pll_calc(lvds, lvds->clocks.extal, freq, &pll,
-				 LVDPLLCR_CKSEL_EXTAL);
+				 LVDPLLCR_CKSEL_EXTAL, dot_clock_only);
 
 	lvdpllcr = LVDPLLCR_PLLON | pll.clksel | LVDPLLCR_CLKOUT
 		 | LVDPLLCR_PLLN(pll.pll_n - 1) | LVDPLLCR_PLLM(pll.pll_m - 1);
@@ -329,6 +332,9 @@ static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned int freq)
 		lvdpllcr |= LVDPLLCR_STP_CLKOUTE | LVDPLLCR_OUTCLKSEL
 			 |  LVDPLLCR_PLLE(pll.pll_e - 1);
 
+	if (dot_clock_only)
+		lvdpllcr |= LVDPLLCR_OCKSEL;
+
 	rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
 
 	if (pll.div > 1)
@@ -342,6 +348,55 @@ static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned int freq)
 		rcar_lvds_write(lvds, LVDDIV, 0);
 }
 
+static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned int freq)
+{
+	__rcar_lvds_pll_setup_d3_e3(lvds, freq, false);
+}
+
+/* -----------------------------------------------------------------------------
+ * Clock - D3/E3 only
+ */
+
+int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq)
+{
+	struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
+	int ret;
+
+	if (WARN_ON(!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)))
+		return -ENODEV;
+
+	dev_dbg(lvds->dev, "enabling LVDS PLL, freq=%luHz\n", freq);
+
+	WARN_ON(lvds->enabled);
+
+	ret = clk_prepare_enable(lvds->clocks.mod);
+	if (ret < 0)
+		return ret;
+
+	__rcar_lvds_pll_setup_d3_e3(lvds, freq, true);
+
+	lvds->enabled = true;
+	return 0;
+}
+
+void rcar_lvds_clk_disable(struct drm_bridge *bridge)
+{
+	struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
+
+	if (WARN_ON(!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)))
+		return;
+
+	dev_dbg(lvds->dev, "disabling LVDS PLL\n");
+
+	WARN_ON(!lvds->enabled);
+
+	rcar_lvds_write(lvds, LVDPLLCR, 0);
+
+	clk_disable_unprepare(lvds->clocks.mod);
+
+	lvds->enabled = false;
+}
+
 /* -----------------------------------------------------------------------------
  * Bridge
  */
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.h b/drivers/gpu/drm/rcar-du/rcar_lvds.h
new file mode 100644
index 000000000000..89f6a9032424
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * rcar_lvds.h  --  R-Car LVDS Encoder
+ *
+ * Copyright (C) 2013-2018 Renesas Electronics Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ */
+
+#ifndef __RCAR_LVDS_H__
+#define __RCAR_LVDS_H__
+
+struct drm_bridge;
+
+int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq);
+void rcar_lvds_clk_disable(struct drm_bridge *bridge);
+
+#endif /* __RCAR_LVDS_H__ */
-- 
Regards,

Laurent Pinchart


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

* [PATCH 4/6] drm: rcar-du: Turn LVDS clock output on/off for DPAD0 output on D3/E3
  2019-01-17  1:49 [PATCH 0/6] R-Car DU DPAD support for D3 and E3 Laurent Pinchart
                   ` (2 preceding siblings ...)
  2019-01-17  1:49 ` [PATCH 3/6] drm: rcar-du: lvds: Add API to enable/disable clock output Laurent Pinchart
@ 2019-01-17  1:49 ` Laurent Pinchart
  2019-01-17  1:49 ` [PATCH 5/6] arm64: dts: renesas: r8a77990: ebisu: Enable LVDS1 encoder Laurent Pinchart
  2019-01-17  1:49 ` [PATCH 6/6] arm64: dts: renesas: r8a77995: draak: " Laurent Pinchart
  5 siblings, 0 replies; 10+ messages in thread
From: Laurent Pinchart @ 2019-01-17  1:49 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Kieran Bingham

On the D3 and E3 SoCs the LVDS PLL clock output provides the dot clock
to the DU channels, even when the LVDS outputs are not in use. Enable
and disable the LVDS clock output when enabling or disabling a CRTC
connected to the DPAD0 output.

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

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 771b460c7216..3018e4500aa1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -26,6 +26,7 @@
 #include "rcar_du_plane.h"
 #include "rcar_du_regs.h"
 #include "rcar_du_vsp.h"
+#include "rcar_lvds.h"
 
 static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg)
 {
@@ -657,8 +658,27 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
 				       struct drm_crtc_state *old_state)
 {
 	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+	struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(crtc->state);
+	struct rcar_du_device *rcdu = rcrtc->group->dev;
 
 	rcar_du_crtc_get(rcrtc);
+
+	/*
+	 * On D3/E3 the dot clock is provided by the LVDS encoder attached to
+	 * the DU channel. We need to enable its clock output explicitly if
+	 * the LVDS output is disabled.
+	 */
+	if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index) &&
+	    rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0)) {
+		struct rcar_du_encoder *encoder =
+			rcdu->encoders[RCAR_DU_OUTPUT_LVDS0 + rcrtc->index];
+		const struct drm_display_mode *mode =
+			&crtc->state->adjusted_mode;
+
+		rcar_lvds_clk_enable(encoder->base.bridge,
+				     mode->clock * 1000);
+	}
+
 	rcar_du_crtc_start(rcrtc);
 }
 
@@ -666,10 +686,24 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
 					struct drm_crtc_state *old_state)
 {
 	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+	struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(old_state);
+	struct rcar_du_device *rcdu = rcrtc->group->dev;
 
 	rcar_du_crtc_stop(rcrtc);
 	rcar_du_crtc_put(rcrtc);
 
+	if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index) &&
+	    rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0)) {
+		struct rcar_du_encoder *encoder =
+			rcdu->encoders[RCAR_DU_OUTPUT_LVDS0 + rcrtc->index];
+
+		/*
+		 * Disable the LVDS clock output, see
+		 * rcar_du_crtc_atomic_enable().
+		 */
+		rcar_lvds_clk_disable(encoder->base.bridge);
+	}
+
 	spin_lock_irq(&crtc->dev->event_lock);
 	if (crtc->state->event) {
 		drm_crtc_send_vblank_event(crtc, crtc->state->event);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index 6c187d0bf7c2..1327cd0df90a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -22,6 +22,7 @@ struct device;
 struct drm_device;
 struct drm_property;
 struct rcar_du_device;
+struct rcar_du_encoder;
 
 #define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK	BIT(0)	/* Per-CRTC IRQ and clock */
 #define RCAR_DU_FEATURE_VSP1_SOURCE	BIT(1)	/* Has inputs from VSP1 */
@@ -81,6 +82,8 @@ struct rcar_du_device {
 	struct rcar_du_crtc crtcs[RCAR_DU_MAX_CRTCS];
 	unsigned int num_crtcs;
 
+	struct rcar_du_encoder *encoders[RCAR_DU_OUTPUT_MAX];
+
 	struct rcar_du_group groups[RCAR_DU_MAX_GROUPS];
 	struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS];
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index ba2b38f76b54..13c3c7382514 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -41,6 +41,7 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 	if (renc == NULL)
 		return -ENOMEM;
 
+	rcdu->encoders[output] = renc;
 	renc->output = output;
 	encoder = rcar_encoder_to_drm_encoder(renc);
 
-- 
Regards,

Laurent Pinchart


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

* [PATCH 5/6] arm64: dts: renesas: r8a77990: ebisu: Enable LVDS1 encoder
  2019-01-17  1:49 [PATCH 0/6] R-Car DU DPAD support for D3 and E3 Laurent Pinchart
                   ` (3 preceding siblings ...)
  2019-01-17  1:49 ` [PATCH 4/6] drm: rcar-du: Turn LVDS clock output on/off for DPAD0 output on D3/E3 Laurent Pinchart
@ 2019-01-17  1:49 ` Laurent Pinchart
  2019-01-17 10:21   ` Geert Uytterhoeven
  2019-01-17  1:49 ` [PATCH 6/6] arm64: dts: renesas: r8a77995: draak: " Laurent Pinchart
  5 siblings, 1 reply; 10+ messages in thread
From: Laurent Pinchart @ 2019-01-17  1:49 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Kieran Bingham

The LVDS1 encoder must supply a pixel clock to the DU for the DPAD
output when the LVDS0 encoder is used. Enable it despite its output not
being connected.

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

diff --git a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
index 62bdddcbbae7..df5dc23fd252 100644
--- a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
@@ -443,6 +443,8 @@
 };
 
 &lvds1 {
+	status = "okay";
+
 	clocks = <&cpg CPG_MOD 727>,
 		 <&x13_clk>,
 		 <&extal_clk>;
-- 
Regards,

Laurent Pinchart


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

* [PATCH 6/6] arm64: dts: renesas: r8a77995: draak: Enable LVDS1 encoder
  2019-01-17  1:49 [PATCH 0/6] R-Car DU DPAD support for D3 and E3 Laurent Pinchart
                   ` (4 preceding siblings ...)
  2019-01-17  1:49 ` [PATCH 5/6] arm64: dts: renesas: r8a77990: ebisu: Enable LVDS1 encoder Laurent Pinchart
@ 2019-01-17  1:49 ` Laurent Pinchart
  5 siblings, 0 replies; 10+ messages in thread
From: Laurent Pinchart @ 2019-01-17  1:49 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Kieran Bingham

The LVDS1 encoder must supply a pixel clock to the DU for the DPAD
output when the LVDS0 encoder is used. Enable it despite its output not
being connected.

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

diff --git a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
index 89df9bc844c0..1879f0feaf88 100644
--- a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
@@ -356,6 +356,8 @@
 };
 
 &lvds1 {
+	status = "okay";
+
 	clocks = <&cpg CPG_MOD 727>,
 		 <&x12_clk>,
 		 <&extal_clk>;
-- 
Regards,

Laurent Pinchart


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

* Re: [PATCH 2/6] drm: rcar-du: lvds: Don't fail probe if output is not connected on D3/E3
  2019-01-17  1:49 ` [PATCH 2/6] drm: rcar-du: lvds: Don't fail probe if output is not connected on D3/E3 Laurent Pinchart
@ 2019-01-17  8:23   ` Sergei Shtylyov
  0 siblings, 0 replies; 10+ messages in thread
From: Sergei Shtylyov @ 2019-01-17  8:23 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel; +Cc: linux-renesas-soc, Kieran Bingham

Hello!

On 17.01.2019 4:49, Laurent Pinchart wrote:

> On the D3 and E3 SoCs the LVDS encoder has an extended internal PLL and
> supplies a clock to the DU. That clock is used not only for the LVDS
> outputs but also for the DPAD output. The LVDS encoder thus needs to be
> available to the DU even when its output is disabled. Don't fail probe
> in that cose on D3 and E3.

    Case?

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

[...]

MBR, Sergei

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

* Re: [PATCH 5/6] arm64: dts: renesas: r8a77990: ebisu: Enable LVDS1 encoder
  2019-01-17  1:49 ` [PATCH 5/6] arm64: dts: renesas: r8a77990: ebisu: Enable LVDS1 encoder Laurent Pinchart
@ 2019-01-17 10:21   ` Geert Uytterhoeven
  2019-01-22 20:42     ` Laurent Pinchart
  0 siblings, 1 reply; 10+ messages in thread
From: Geert Uytterhoeven @ 2019-01-17 10:21 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: DRI Development, Linux-Renesas, Kieran Bingham

Hi Laurent,

On Thu, Jan 17, 2019 at 3:07 AM Laurent Pinchart
<laurent.pinchart+renesas@ideasonboard.com> wrote:
> The LVDS1 encoder must supply a pixel clock to the DU for the DPAD
> output when the LVDS0 encoder is used. Enable it despite its output not
> being connected.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Thanks for your patch!

> --- a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
> +++ b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
> @@ -443,6 +443,8 @@
>  };
>
>  &lvds1 {

Would it make sense to add a comment

    /* Must be enabled to supply a pixel clock to the DU for the DPAD
output when lvds0 is used */

also for D3?

> +       status = "okay";
> +
>         clocks = <&cpg CPG_MOD 727>,
>                  <&x13_clk>,
>                  <&extal_clk>;

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

* Re: [PATCH 5/6] arm64: dts: renesas: r8a77990: ebisu: Enable LVDS1 encoder
  2019-01-17 10:21   ` Geert Uytterhoeven
@ 2019-01-22 20:42     ` Laurent Pinchart
  0 siblings, 0 replies; 10+ messages in thread
From: Laurent Pinchart @ 2019-01-22 20:42 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Laurent Pinchart, DRI Development, Linux-Renesas, Kieran Bingham

Hi Geert,

On Thu, Jan 17, 2019 at 11:21:32AM +0100, Geert Uytterhoeven wrote:
> On Thu, Jan 17, 2019 at 3:07 AM Laurent Pinchart
> <laurent.pinchart+renesas@ideasonboard.com> wrote:
> > The LVDS1 encoder must supply a pixel clock to the DU for the DPAD
> > output when the LVDS0 encoder is used. Enable it despite its output not
> > being connected.
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> 
> Thanks for your patch!
> 
> > --- a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
> > +++ b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
> > @@ -443,6 +443,8 @@
> >  };
> >
> >  &lvds1 {
> 
> Would it make sense to add a comment
> 
>     /* Must be enabled to supply a pixel clock to the DU for the DPAD
> output when lvds0 is used */
> 
> also for D3?

Good point, I'll add it for both.

> > +       status = "okay";
> > +
> >         clocks = <&cpg CPG_MOD 727>,
> >                  <&x13_clk>,
> >                  <&extal_clk>;

-- 
Regards,

Laurent Pinchart

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

end of thread, other threads:[~2019-01-22 20:42 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-17  1:49 [PATCH 0/6] R-Car DU DPAD support for D3 and E3 Laurent Pinchart
2019-01-17  1:49 ` [PATCH 1/6] drm: rcar-du: Simplify encoder registration Laurent Pinchart
2019-01-17  1:49 ` [PATCH 2/6] drm: rcar-du: lvds: Don't fail probe if output is not connected on D3/E3 Laurent Pinchart
2019-01-17  8:23   ` Sergei Shtylyov
2019-01-17  1:49 ` [PATCH 3/6] drm: rcar-du: lvds: Add API to enable/disable clock output Laurent Pinchart
2019-01-17  1:49 ` [PATCH 4/6] drm: rcar-du: Turn LVDS clock output on/off for DPAD0 output on D3/E3 Laurent Pinchart
2019-01-17  1:49 ` [PATCH 5/6] arm64: dts: renesas: r8a77990: ebisu: Enable LVDS1 encoder Laurent Pinchart
2019-01-17 10:21   ` Geert Uytterhoeven
2019-01-22 20:42     ` Laurent Pinchart
2019-01-17  1:49 ` [PATCH 6/6] arm64: dts: renesas: r8a77995: draak: " Laurent Pinchart

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