LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH 00/15] Add support for R40 HDMI pipeline
@ 2018-05-19 18:31 Jernej Skrabec
  2018-05-19 18:31 ` [PATCH 01/15] clk: sunxi-ng: r40: Add minimal rate for video PLLs Jernej Skrabec
                   ` (14 more replies)
  0 siblings, 15 replies; 46+ messages in thread
From: Jernej Skrabec @ 2018-05-19 18:31 UTC (permalink / raw)
  To: maxime.ripard, wens, robh+dt
  Cc: mark.rutland, dri-devel, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-sunxi

This series adds support for R40 HDMI pipeline. It is a bit special
than other already supported pipelines because it has additional unit
called TCON TOP responsible for relationship configuration between
mixers, TCONs and HDMI. Additionally, it has additional gates for DSI
and TV TCONs, TV encoder clock settings and pin muxing between LCD
and TV encoders.

However, it seems that TCON TOP will become a norm, since newer
Allwinner SoCs like H6 also have this unit.

I tested different possible configurations:
- mixer0 <> TCON-TV0 <> HDMI
- mixer0 <> TCON-TV1 <> HDMI
- mixer1 <> TCON-TV0 <> HDMI
- mixer1 <> TCON-TV1 <> HDMI

Please review.

Best regards,
Jernej

Jernej Skrabec (15):
  clk: sunxi-ng: r40: Add minimal rate for video PLLs
  clk: sunxi-ng: r40: Allow setting parent rate to display related
    clocks
  clk: sunxi-ng: r40: Export video PLLs
  dt-bindings: display: sunxi-drm: Add TCON TOP description
  drm/sun4i: Add TCON TOP driver
  drm/sun4i: tcon: Add support for tcon-top
  dt-bindings: display: sun4i-drm: Add R40 HDMI pipeline
  drm/sun4i: DE2 mixer: Add index quirk
  drm/sun4i: Add support for R40 mixers
  drm/sun4i: Add support for R40 TV TCONs
  drm/sun4i: DW HDMI PHY: Add support for second PLL
  drm/sun4i: Add support for second clock parent to DW HDMI PHY clk
    driver
  drm/sun4i: Add support for A64 HDMI PHY
  ARM: dts: sun8i: r40: Add HDMI pipeline
  ARM: dts: sun8i: r40: Enable HDMI output on BananaPi M2 Ultra

 .../bindings/display/sunxi/sun4i-drm.txt      |  36 ++-
 .../boot/dts/sun8i-r40-bananapi-m2-ultra.dts  |  50 ++++
 arch/arm/boot/dts/sun8i-r40.dtsi              | 166 ++++++++++++
 drivers/clk/sunxi-ng/ccu-sun8i-r40.c          |  58 ++--
 drivers/clk/sunxi-ng/ccu-sun8i-r40.h          |   8 +-
 drivers/gpu/drm/sun4i/Makefile                |   3 +-
 drivers/gpu/drm/sun4i/sun4i_tcon.c            |  67 +++++
 drivers/gpu/drm/sun4i/sun4i_tcon.h            |   8 +
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h         |   8 +-
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c        |  61 ++++-
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c    |  90 ++++--
 drivers/gpu/drm/sun4i/sun8i_mixer.c           |  30 +-
 drivers/gpu/drm/sun4i/sun8i_mixer.h           |   2 +
 drivers/gpu/drm/sun4i/sun8i_tcon_top.c        | 256 ++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_tcon_top.h        |  20 ++
 include/dt-bindings/clock/sun8i-r40-ccu.h     |   4 +
 include/dt-bindings/clock/sun8i-tcon-top.h    |  11 +
 17 files changed, 813 insertions(+), 65 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_tcon_top.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_tcon_top.h
 create mode 100644 include/dt-bindings/clock/sun8i-tcon-top.h

-- 
2.17.0

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

* [PATCH 01/15] clk: sunxi-ng: r40: Add minimal rate for video PLLs
  2018-05-19 18:31 [PATCH 00/15] Add support for R40 HDMI pipeline Jernej Skrabec
@ 2018-05-19 18:31 ` Jernej Skrabec
  2018-05-19 18:31 ` [PATCH 02/15] clk: sunxi-ng: r40: Allow setting parent rate to display related clocks Jernej Skrabec
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 46+ messages in thread
From: Jernej Skrabec @ 2018-05-19 18:31 UTC (permalink / raw)
  To: maxime.ripard, wens, robh+dt
  Cc: mark.rutland, dri-devel, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-sunxi

According to documentation and experience with other similar SoCs, video
PLLs don't work stable if their output frequency is set below 192 MHz.

Because of that, set minimal rate to both R40 video PLLs to 192 MHz.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/clk/sunxi-ng/ccu-sun8i-r40.c | 46 +++++++++++++++-------------
 1 file changed, 24 insertions(+), 22 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
index 933f2e68f42a..c16a62a7bdbd 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
@@ -65,17 +65,18 @@ static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
 				   CLK_SET_RATE_UNGATE);
 
 /* TODO: The result of N/M is required to be in [8, 25] range. */
-static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0",
-					"osc24M", 0x0010,
-					8, 7,		/* N */
-					0, 4,		/* M */
-					BIT(24),	/* frac enable */
-					BIT(25),	/* frac select */
-					270000000,	/* frac rate 0 */
-					297000000,	/* frac rate 1 */
-					BIT(31),	/* gate */
-					BIT(28),	/* lock */
-					CLK_SET_RATE_UNGATE);
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video0_clk, "pll-video0",
+					    "osc24M", 0x0010,
+					    192000000,	/* Minimum rate */
+					    8, 7,	/* N */
+					    0, 4,	/* M */
+					    BIT(24),	/* frac enable */
+					    BIT(25),	/* frac select */
+					    270000000,	/* frac rate 0 */
+					    297000000,	/* frac rate 1 */
+					    BIT(31),	/* gate */
+					    BIT(28),	/* lock */
+					    CLK_SET_RATE_UNGATE);
 
 /* TODO: The result of N/M is required to be in [8, 25] range. */
 static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
@@ -151,17 +152,18 @@ static struct ccu_nk pll_periph1_clk = {
 };
 
 /* TODO: The result of N/M is required to be in [8, 25] range. */
-static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video1_clk, "pll-video1",
-					"osc24M", 0x030,
-					8, 7,		/* N */
-					0, 4,		/* M */
-					BIT(24),	/* frac enable */
-					BIT(25),	/* frac select */
-					270000000,	/* frac rate 0 */
-					297000000,	/* frac rate 1 */
-					BIT(31),	/* gate */
-					BIT(28),	/* lock */
-					CLK_SET_RATE_UNGATE);
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video1_clk, "pll-video1",
+					    "osc24M", 0x030,
+					    192000000,	/* Minimum rate */
+					    8, 7,	/* N */
+					    0, 4,	/* M */
+					    BIT(24),	/* frac enable */
+					    BIT(25),	/* frac select */
+					    270000000,	/* frac rate 0 */
+					    297000000,	/* frac rate 1 */
+					    BIT(31),	/* gate */
+					    BIT(28),	/* lock */
+					    CLK_SET_RATE_UNGATE);
 
 static struct ccu_nkm pll_sata_clk = {
 	.enable		= BIT(31),
-- 
2.17.0

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

* [PATCH 02/15] clk: sunxi-ng: r40: Allow setting parent rate to display related clocks
  2018-05-19 18:31 [PATCH 00/15] Add support for R40 HDMI pipeline Jernej Skrabec
  2018-05-19 18:31 ` [PATCH 01/15] clk: sunxi-ng: r40: Add minimal rate for video PLLs Jernej Skrabec
@ 2018-05-19 18:31 ` Jernej Skrabec
  2018-05-19 18:31 ` [PATCH 03/15] clk: sunxi-ng: r40: Export video PLLs Jernej Skrabec
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 46+ messages in thread
From: Jernej Skrabec @ 2018-05-19 18:31 UTC (permalink / raw)
  To: maxime.ripard, wens, robh+dt
  Cc: mark.rutland, dri-devel, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-sunxi

Display related peripherals need precise clocks to operate correctly.

Allow DE2, TCONs and HDMI to set parent clock.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/clk/sunxi-ng/ccu-sun8i-r40.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
index c16a62a7bdbd..fa5317719684 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
@@ -655,7 +655,8 @@ static SUNXI_CCU_GATE(dram_deinterlace_clk,	"dram-deinterlace",	"dram",
 
 static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" };
 static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
-				 0x104, 0, 4, 24, 3, BIT(31), 0);
+				 0x104, 0, 4, 24, 3, BIT(31),
+				 CLK_SET_RATE_PARENT);
 static SUNXI_CCU_M_WITH_MUX_GATE(mp_clk, "mp", de_parents,
 				 0x108, 0, 4, 24, 3, BIT(31), 0);
 
@@ -667,9 +668,11 @@ static SUNXI_CCU_MUX_WITH_GATE(tcon_lcd0_clk, "tcon-lcd0", tcon_parents,
 static SUNXI_CCU_MUX_WITH_GATE(tcon_lcd1_clk, "tcon-lcd1", tcon_parents,
 			       0x114, 24, 3, BIT(31), CLK_SET_RATE_PARENT);
 static SUNXI_CCU_M_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", tcon_parents,
-				 0x118, 0, 4, 24, 3, BIT(31), 0);
+				 0x118, 0, 4, 24, 3, BIT(31),
+				 CLK_SET_RATE_PARENT);
 static SUNXI_CCU_M_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", tcon_parents,
-				 0x11c, 0, 4, 24, 3, BIT(31), 0);
+				 0x11c, 0, 4, 24, 3, BIT(31),
+				 CLK_SET_RATE_PARENT);
 
 static const char * const deinterlace_parents[] = { "pll-periph0",
 						    "pll-periph1" };
@@ -699,7 +702,8 @@ static SUNXI_CCU_GATE(avs_clk,		"avs",		"osc24M",
 
 static const char * const hdmi_parents[] = { "pll-video0", "pll-video1" };
 static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents,
-				 0x150, 0, 4, 24, 2, BIT(31), 0);
+				 0x150, 0, 4, 24, 2, BIT(31),
+				 CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_GATE(hdmi_slow_clk,	"hdmi-slow",	"osc24M",
 		      0x154, BIT(31), 0);
-- 
2.17.0

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

* [PATCH 03/15] clk: sunxi-ng: r40: Export video PLLs
  2018-05-19 18:31 [PATCH 00/15] Add support for R40 HDMI pipeline Jernej Skrabec
  2018-05-19 18:31 ` [PATCH 01/15] clk: sunxi-ng: r40: Add minimal rate for video PLLs Jernej Skrabec
  2018-05-19 18:31 ` [PATCH 02/15] clk: sunxi-ng: r40: Allow setting parent rate to display related clocks Jernej Skrabec
@ 2018-05-19 18:31 ` Jernej Skrabec
  2018-05-23 18:20   ` Rob Herring
  2018-05-19 18:31 ` [PATCH 04/15] dt-bindings: display: sunxi-drm: Add TCON TOP description Jernej Skrabec
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 46+ messages in thread
From: Jernej Skrabec @ 2018-05-19 18:31 UTC (permalink / raw)
  To: maxime.ripard, wens, robh+dt
  Cc: mark.rutland, dri-devel, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-sunxi

Video PLLs need to be referenced in R40 DT as possible HDMI PHY parent.

Export them.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/clk/sunxi-ng/ccu-sun8i-r40.h      | 8 ++++++--
 include/dt-bindings/clock/sun8i-r40-ccu.h | 4 ++++
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.h b/drivers/clk/sunxi-ng/ccu-sun8i-r40.h
index 0db8e1e97af8..db2a1243f9ff 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-r40.h
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.h
@@ -25,7 +25,9 @@
 #define CLK_PLL_AUDIO_2X	4
 #define CLK_PLL_AUDIO_4X	5
 #define CLK_PLL_AUDIO_8X	6
-#define CLK_PLL_VIDEO0		7
+
+/* PLL_VIDEO0 is exported */
+
 #define CLK_PLL_VIDEO0_2X	8
 #define CLK_PLL_VE		9
 #define CLK_PLL_DDR0		10
@@ -34,7 +36,9 @@
 #define CLK_PLL_PERIPH0_2X	13
 #define CLK_PLL_PERIPH1		14
 #define CLK_PLL_PERIPH1_2X	15
-#define CLK_PLL_VIDEO1		16
+
+/* PLL_VIDEO1 is exported */
+
 #define CLK_PLL_VIDEO1_2X	17
 #define CLK_PLL_SATA		18
 #define CLK_PLL_SATA_OUT	19
diff --git a/include/dt-bindings/clock/sun8i-r40-ccu.h b/include/dt-bindings/clock/sun8i-r40-ccu.h
index 4fa5f69fc297..f9e15a235626 100644
--- a/include/dt-bindings/clock/sun8i-r40-ccu.h
+++ b/include/dt-bindings/clock/sun8i-r40-ccu.h
@@ -43,6 +43,10 @@
 #ifndef _DT_BINDINGS_CLK_SUN8I_R40_H_
 #define _DT_BINDINGS_CLK_SUN8I_R40_H_
 
+#define CLK_PLL_VIDEO0		7
+
+#define CLK_PLL_VIDEO1		16
+
 #define CLK_CPU			24
 
 #define CLK_BUS_MIPI_DSI	29
-- 
2.17.0

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

* [PATCH 04/15] dt-bindings: display: sunxi-drm: Add TCON TOP description
  2018-05-19 18:31 [PATCH 00/15] Add support for R40 HDMI pipeline Jernej Skrabec
                   ` (2 preceding siblings ...)
  2018-05-19 18:31 ` [PATCH 03/15] clk: sunxi-ng: r40: Export video PLLs Jernej Skrabec
@ 2018-05-19 18:31 ` Jernej Skrabec
  2018-05-21  8:01   ` Maxime Ripard
  2018-05-19 18:31 ` [PATCH 05/15] drm/sun4i: Add TCON TOP driver Jernej Skrabec
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 46+ messages in thread
From: Jernej Skrabec @ 2018-05-19 18:31 UTC (permalink / raw)
  To: maxime.ripard, wens, robh+dt
  Cc: mark.rutland, dri-devel, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-sunxi

TCON TOP main purpose is to configure whole display pipeline. It
determines relationships between mixers and TCONs, selects source TCON
for HDMI, muxes LCD and TV encoder GPIO output, selects TV encoder
clock source and contains additional TV TCON and DSI gates.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 .../bindings/display/sunxi/sun4i-drm.txt      | 20 +++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 3346c1e2a7a0..a099957ab62a 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -187,6 +187,26 @@ And on the A23, A31, A31s and A33, you need one more clock line:
    - 'lvds-alt': An alternative clock source, separate from the TCON channel 0
                  clock, that can be used to drive the LVDS clock
 
+TCON TOP
+--------
+
+TCON TOPs main purpose is to configure whole display pipeline. It determines
+relationships between mixers and TCONs, selects source TCON for HDMI, muxes
+LCD and TV encoder GPIO output, selects TV encoder clock source and contains
+additional TV TCON and DSI gates.
+
+Required properties:
+  - compatible: value must be one of:
+    * allwinner,sun8i-r40-tcon-top
+  - reg: base address and size of the memory-mapped region.
+  - clocks: phandle to the clocks feeding the TCON TOP
+    * bus: TCON TOP interface clock
+  - clock-names: clock name mentioned above
+  - resets: phandle to the reset line driving the DRC
+    * rst: TCON TOP reset line
+  - reset-names: reset name mentioned above
+  - #clock-cells : must contain 1
+
 DRC
 ---
 
-- 
2.17.0

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

* [PATCH 05/15] drm/sun4i: Add TCON TOP driver
  2018-05-19 18:31 [PATCH 00/15] Add support for R40 HDMI pipeline Jernej Skrabec
                   ` (3 preceding siblings ...)
  2018-05-19 18:31 ` [PATCH 04/15] dt-bindings: display: sunxi-drm: Add TCON TOP description Jernej Skrabec
@ 2018-05-19 18:31 ` Jernej Skrabec
  2018-05-21  8:05   ` Maxime Ripard
                     ` (2 more replies)
  2018-05-19 18:31 ` [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top Jernej Skrabec
                   ` (9 subsequent siblings)
  14 siblings, 3 replies; 46+ messages in thread
From: Jernej Skrabec @ 2018-05-19 18:31 UTC (permalink / raw)
  To: maxime.ripard, wens, robh+dt
  Cc: mark.rutland, dri-devel, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-sunxi

As already described in DT binding, TCON TOP is responsible for
configuring display pipeline. In this initial driver focus is on HDMI
pipeline, so TVE and LCD configuration is not implemented.

Implemented features:
- HDMI source selection
- clock driver (TCON and DSI gating)
- connecting mixers and TCONS

Something similar also existed in previous SoCs, except that it was part
of first TCON.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/Makefile             |   3 +-
 drivers/gpu/drm/sun4i/sun8i_tcon_top.c     | 256 +++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun8i_tcon_top.h     |  20 ++
 include/dt-bindings/clock/sun8i-tcon-top.h |  11 +
 4 files changed, 289 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_tcon_top.c
 create mode 100644 drivers/gpu/drm/sun4i/sun8i_tcon_top.h
 create mode 100644 include/dt-bindings/clock/sun8i-tcon-top.h

diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 2589f4acd5ae..09fbfd6304ba 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -16,7 +16,8 @@ sun8i-drm-hdmi-y		+= sun8i_hdmi_phy_clk.o
 
 sun8i-mixer-y			+= sun8i_mixer.o sun8i_ui_layer.o \
 				   sun8i_vi_layer.o sun8i_ui_scaler.o \
-				   sun8i_vi_scaler.o sun8i_csc.o
+				   sun8i_vi_scaler.o sun8i_csc.o \
+				   sun8i_tcon_top.o
 
 sun4i-tcon-y			+= sun4i_crtc.o
 sun4i-tcon-y			+= sun4i_dotclock.o
diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
new file mode 100644
index 000000000000..075a356a6dfa
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
@@ -0,0 +1,256 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (c) 2018 Jernej Skrabec <jernej.skrabec@siol.net> */
+
+#include <drm/drmP.h>
+
+#include <dt-bindings/clock/sun8i-tcon-top.h>
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+
+#include "sun8i_tcon_top.h"
+
+#define TCON_TOP_PORT_SEL_REG		0x1C
+#define TCON_TOP_PORT_DE0_MSK			GENMASK(1, 0)
+#define TCON_TOP_PORT_DE1_MSK			GENMASK(5, 4)
+#define TCON_TOP_PORT_TCON_LCD0			0
+#define TCON_TOP_PORT_TCON_LCD1			1
+#define TCON_TOP_PORT_TCON_TV0			2
+#define TCON_TOP_PORT_TCON_TV1			3
+
+#define TCON_TOP_GATE_SRC_REG		0x20
+#define TCON_TOP_HDMI_SRC_MSK			GENMASK(29, 28)
+#define TCON_TOP_HDMI_SRC_NONE			0
+#define TCON_TOP_HDMI_SRC_TCON_TV0		1
+#define TCON_TOP_HDMI_SRC_TCON_TV1		2
+#define TCON_TOP_TCON_TV1_GATE			24
+#define TCON_TOP_TCON_TV0_GATE			20
+#define TCON_TOP_TCON_DSI_GATE			16
+
+#define CLK_NUM					3
+
+struct sun8i_tcon_top {
+	struct clk		*bus;
+	void __iomem		*regs;
+	struct reset_control	*rst;
+
+	/*
+	 * spinlock is used for locking access to registers from different
+	 * places - tcon driver and clk subsystem.
+	 */
+	spinlock_t		reg_lock;
+};
+
+struct sun8i_tcon_top_gate {
+	const char	*name;
+	u8		bit;
+	int		index;
+};
+
+static const struct sun8i_tcon_top_gate gates[] = {
+	{"bus-tcon-top-dsi", TCON_TOP_TCON_DSI_GATE, CLK_BUS_TCON_TOP_DSI},
+	{"bus-tcon-top-tv0", TCON_TOP_TCON_TV0_GATE, CLK_BUS_TCON_TOP_TV0},
+	{"bus-tcon-top-tv1", TCON_TOP_TCON_TV1_GATE, CLK_BUS_TCON_TOP_TV1},
+};
+
+void sun8i_tcon_top_set_hdmi_src(struct sun8i_tcon_top *tcon_top, int tcon)
+{
+	unsigned long flags;
+	u32 val;
+
+	if (tcon > 1) {
+		DRM_ERROR("TCON index is too high!\n");
+		return;
+	}
+
+	spin_lock_irqsave(&tcon_top->reg_lock, flags);
+
+	val = readl(tcon_top->regs + TCON_TOP_GATE_SRC_REG);
+	val &= ~TCON_TOP_HDMI_SRC_MSK;
+	val |= FIELD_PREP(TCON_TOP_HDMI_SRC_MSK,
+			  TCON_TOP_HDMI_SRC_TCON_TV0 + tcon);
+	writel(val, tcon_top->regs + TCON_TOP_GATE_SRC_REG);
+
+	spin_unlock_irqrestore(&tcon_top->reg_lock, flags);
+}
+
+void sun8i_tcon_top_de_config(struct sun8i_tcon_top *tcon_top,
+			      int mixer, enum tcon_type tcon_type, int tcon)
+{
+	unsigned long flags;
+	u32 val, reg;
+
+	if (mixer > 1) {
+		DRM_ERROR("Mixer index is too high!\n");
+		return;
+	}
+
+	if (tcon > 1) {
+		DRM_ERROR("TCON index is too high!\n");
+		return;
+	}
+
+	switch (tcon_type) {
+	case tcon_type_lcd:
+		val = TCON_TOP_PORT_TCON_LCD0 + tcon;
+		break;
+	case tcon_type_tv:
+		val = TCON_TOP_PORT_TCON_TV0 + tcon;
+		break;
+	default:
+		DRM_ERROR("Invalid TCON type!\n");
+		return;
+	}
+
+	spin_lock_irqsave(&tcon_top->reg_lock, flags);
+
+	reg = readl(tcon_top->regs + TCON_TOP_PORT_SEL_REG);
+	if (mixer == 0) {
+		reg &= ~TCON_TOP_PORT_DE0_MSK;
+		reg |= FIELD_PREP(TCON_TOP_PORT_DE0_MSK, val);
+	} else {
+		reg &= ~TCON_TOP_PORT_DE1_MSK;
+		reg |= FIELD_PREP(TCON_TOP_PORT_DE1_MSK, val);
+	}
+	writel(reg, tcon_top->regs + TCON_TOP_PORT_SEL_REG);
+
+	spin_unlock_irqrestore(&tcon_top->reg_lock, flags);
+}
+
+static int sun8i_tcon_top_probe(struct platform_device *pdev)
+{
+	struct clk_hw_onecell_data *clk_data;
+	struct sun8i_tcon_top *tcon_top;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	int ret, i;
+
+	tcon_top = devm_kzalloc(dev, sizeof(*tcon_top), GFP_KERNEL);
+	if (!tcon_top)
+		return -ENOMEM;
+
+	clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data) +
+				sizeof(*clk_data->hws) * CLK_NUM,
+				GFP_KERNEL);
+	if (!clk_data)
+		return -ENOMEM;
+
+	spin_lock_init(&tcon_top->reg_lock);
+
+	tcon_top->rst = devm_reset_control_get(dev, "rst");
+	if (IS_ERR(tcon_top->rst)) {
+		dev_err(dev, "Couldn't get our reset line\n");
+		return PTR_ERR(tcon_top->rst);
+	}
+
+	tcon_top->bus = devm_clk_get(dev, "bus");
+	if (IS_ERR(tcon_top->bus)) {
+		dev_err(dev, "Couldn't get the bus clock\n");
+		return PTR_ERR(tcon_top->bus);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	tcon_top->regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(tcon_top->regs))
+		return PTR_ERR(tcon_top->regs);
+
+	ret = reset_control_deassert(tcon_top->rst);
+	if (ret) {
+		dev_err(dev, "Could not deassert ctrl reset control\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(tcon_top->bus);
+	if (ret) {
+		dev_err(dev, "Could not enable bus clock\n");
+		goto err_assert_reset;
+	}
+
+	/*
+	 * Default register values might have some reserved bits set, which
+	 * prevents TCON TOP from working properly. Set them to 0 here.
+	 */
+	writel(0, tcon_top->regs + TCON_TOP_PORT_SEL_REG);
+	writel(0, tcon_top->regs + TCON_TOP_GATE_SRC_REG);
+
+	for (i = 0; i < CLK_NUM; i++) {
+		const char *parent_name = "bus-tcon-top";
+		struct clk_init_data init;
+		struct clk_gate *gate;
+
+		gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
+		if (!gate) {
+			ret = -ENOMEM;
+			goto err_disable_clock;
+		}
+
+		init.name = gates[i].name;
+		init.ops = &clk_gate_ops;
+		init.flags = CLK_IS_BASIC;
+		init.parent_names = &parent_name;
+		init.num_parents = 1;
+
+		gate->reg = tcon_top->regs + TCON_TOP_GATE_SRC_REG;
+		gate->bit_idx = gates[i].bit;
+		gate->lock = &tcon_top->reg_lock;
+		gate->hw.init = &init;
+
+		ret = devm_clk_hw_register(dev, &gate->hw);
+		if (ret)
+			goto err_disable_clock;
+
+		clk_data->hws[gates[i].index] = &gate->hw;
+	}
+
+	clk_data->num = CLK_NUM;
+
+	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
+	if (ret)
+		goto err_disable_clock;
+
+	platform_set_drvdata(pdev, tcon_top);
+
+	return 0;
+
+err_disable_clock:
+	clk_disable_unprepare(tcon_top->bus);
+err_assert_reset:
+	reset_control_assert(tcon_top->rst);
+
+	return ret;
+}
+
+static int sun8i_tcon_top_remove(struct platform_device *pdev)
+{
+	struct sun8i_tcon_top *tcon_top = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(tcon_top->bus);
+	reset_control_assert(tcon_top->rst);
+
+	return 0;
+}
+
+const struct of_device_id sun8i_tcon_top_of_table[] = {
+	{ .compatible = "allwinner,sun8i-r40-tcon-top" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sun8i_tcon_top_of_table);
+
+static struct platform_driver sun8i_tcon_top_platform_driver = {
+	.probe		= sun8i_tcon_top_probe,
+	.remove		= sun8i_tcon_top_remove,
+	.driver		= {
+		.name		= "sun8i-tcon-top",
+		.of_match_table	= sun8i_tcon_top_of_table,
+	},
+};
+module_platform_driver(sun8i_tcon_top_platform_driver);
+
+MODULE_AUTHOR("Jernej Skrabec <jernej.skrabec@siol.net>");
+MODULE_DESCRIPTION("Allwinner R40 TCON TOP driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.h b/drivers/gpu/drm/sun4i/sun8i_tcon_top.h
new file mode 100644
index 000000000000..19126e07d2a6
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2018 Jernej Skrabec <jernej.skrabec@siol.net> */
+
+#ifndef _SUN8I_TCON_TOP_H_
+#define _SUN8I_TCON_TOP_H_
+
+#include <linux/device.h>
+
+struct sun8i_tcon_top;
+
+enum tcon_type {
+	tcon_type_lcd,
+	tcon_type_tv,
+};
+
+void sun8i_tcon_top_set_hdmi_src(struct sun8i_tcon_top *tcon_top, int tcon);
+void sun8i_tcon_top_de_config(struct sun8i_tcon_top *tcon_top,
+			      int mixer, enum tcon_type tcon_type, int tcon);
+
+#endif /* _SUN8I_TCON_TOP_H_ */
diff --git a/include/dt-bindings/clock/sun8i-tcon-top.h b/include/dt-bindings/clock/sun8i-tcon-top.h
new file mode 100644
index 000000000000..c05e92770402
--- /dev/null
+++ b/include/dt-bindings/clock/sun8i-tcon-top.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/* Copyright (C) 2018 Jernej Skrabec <jernej.skrabec@siol.net> */
+
+#ifndef _DT_BINDINGS_CLOCK_SUN8I_TCON_TOP_H_
+#define _DT_BINDINGS_CLOCK_SUN8I_TCON_TOP_H_
+
+#define CLK_BUS_TCON_TOP_DSI	0
+#define CLK_BUS_TCON_TOP_TV0	1
+#define CLK_BUS_TCON_TOP_TV1	2
+
+#endif /* _DT_BINDINGS_CLOCK_SUN8I_TCON_TOP_H_ */
-- 
2.17.0

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

* [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top
  2018-05-19 18:31 [PATCH 00/15] Add support for R40 HDMI pipeline Jernej Skrabec
                   ` (4 preceding siblings ...)
  2018-05-19 18:31 ` [PATCH 05/15] drm/sun4i: Add TCON TOP driver Jernej Skrabec
@ 2018-05-19 18:31 ` Jernej Skrabec
  2018-05-21  8:07   ` Maxime Ripard
  2018-05-19 18:31 ` [PATCH 07/15] dt-bindings: display: sun4i-drm: Add R40 HDMI pipeline Jernej Skrabec
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 46+ messages in thread
From: Jernej Skrabec @ 2018-05-19 18:31 UTC (permalink / raw)
  To: maxime.ripard, wens, robh+dt
  Cc: mark.rutland, dri-devel, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-sunxi

If SoC has TCON TOP unit, it has to be configured from TCON, since it
has all information needed. Additionally, if it is TCON TV, it must also
enable bus gate inside TCON TOP unit.

Add support for such TCONs.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 28 ++++++++++++++++++++++++++++
 drivers/gpu/drm/sun4i/sun4i_tcon.h |  8 ++++++++
 2 files changed, 36 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 08747fc3ee71..e0c562ce1c22 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -688,6 +688,16 @@ static int sun4i_tcon_init_clocks(struct device *dev,
 		dev_err(dev, "Couldn't get the TCON bus clock\n");
 		return PTR_ERR(tcon->clk);
 	}
+
+	if (tcon->quirks->needs_tcon_top && tcon->quirks->has_channel_1) {
+		tcon->top_clk = devm_clk_get(dev, "tcon-top");
+		if (IS_ERR(tcon->top_clk)) {
+			dev_err(dev, "Couldn't get the TCON TOP bus clock\n");
+			return PTR_ERR(tcon->top_clk);
+		}
+		clk_prepare_enable(tcon->top_clk);
+	}
+
 	clk_prepare_enable(tcon->clk);
 
 	if (tcon->quirks->has_channel_0) {
@@ -712,6 +722,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
 static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
 {
 	clk_disable_unprepare(tcon->clk);
+	clk_disable_unprepare(tcon->top_clk);
 }
 
 static int sun4i_tcon_init_irq(struct device *dev,
@@ -980,6 +991,23 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
 	tcon->id = engine->id;
 	tcon->quirks = of_device_get_match_data(dev);
 
+	if (tcon->quirks->needs_tcon_top) {
+		struct device_node *np;
+
+		np = of_parse_phandle(dev->of_node, "allwinner,tcon-top", 0);
+		if (np) {
+			struct platform_device *pdev;
+
+			pdev = of_find_device_by_node(np);
+			if (pdev)
+				tcon->tcon_top = platform_get_drvdata(pdev);
+			of_node_put(np);
+
+			if (!tcon->tcon_top)
+				return -EPROBE_DEFER;
+		}
+	}
+
 	tcon->lcd_rst = devm_reset_control_get(dev, "lcd");
 	if (IS_ERR(tcon->lcd_rst)) {
 		dev_err(dev, "Couldn't get our reset line\n");
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index f6a071cd5a6f..26be0d317a38 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -20,6 +20,8 @@
 #include <linux/list.h>
 #include <linux/reset.h>
 
+#include "sun8i_tcon_top.h"
+
 #define SUN4I_TCON_GCTL_REG			0x0
 #define SUN4I_TCON_GCTL_TCON_ENABLE			BIT(31)
 #define SUN4I_TCON_GCTL_IOMAP_MASK			BIT(0)
@@ -224,6 +226,7 @@ struct sun4i_tcon_quirks {
 	bool	needs_de_be_mux; /* sun6i needs mux to select backend */
 	bool    needs_edp_reset; /* a80 edp reset needed for tcon0 access */
 	bool	supports_lvds;   /* Does the TCON support an LVDS output? */
+	bool	needs_tcon_top;  /* TCON TOP holds additional muxing configuration */
 
 	/* callback to handle tcon muxing options */
 	int	(*set_mux)(struct sun4i_tcon *, const struct drm_encoder *);
@@ -249,6 +252,9 @@ struct sun4i_tcon {
 	u8				dclk_max_div;
 	u8				dclk_min_div;
 
+	/* TCON TOP clock */
+	struct clk			*top_clk;
+
 	/* Reset control */
 	struct reset_control		*lcd_rst;
 	struct reset_control		*lvds_rst;
@@ -263,6 +269,8 @@ struct sun4i_tcon {
 
 	int				id;
 
+	struct sun8i_tcon_top		*tcon_top;
+
 	/* TCON list management */
 	struct list_head		list;
 };
-- 
2.17.0

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

* [PATCH 07/15] dt-bindings: display: sun4i-drm: Add R40 HDMI pipeline
  2018-05-19 18:31 [PATCH 00/15] Add support for R40 HDMI pipeline Jernej Skrabec
                   ` (5 preceding siblings ...)
  2018-05-19 18:31 ` [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top Jernej Skrabec
@ 2018-05-19 18:31 ` Jernej Skrabec
  2018-05-20  1:50   ` [linux-sunxi] " Julian Calaby
  2018-05-19 18:31 ` [PATCH 08/15] drm/sun4i: DE2 mixer: Add index quirk Jernej Skrabec
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 46+ messages in thread
From: Jernej Skrabec @ 2018-05-19 18:31 UTC (permalink / raw)
  To: maxime.ripard, wens, robh+dt
  Cc: mark.rutland, dri-devel, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-sunxi

Missing compatibles and descriptions needed to implement R40 HDMI
pipeline are added.

For mixers only compatibles are added.

TCON description is expanded with R40 TV TCON compatibles. If the SoC
has TCON TOP unit, phandle to that unit has to be specified. Additional
clock has to be specified if SoC has TCON TOP and TCON is TV TCON.

New compatible is added for DWC HDMI PHY, which has additional clock
specified.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 .../bindings/display/sunxi/sun4i-drm.txt         | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index a099957ab62a..634276f713e8 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -101,6 +101,7 @@ DWC HDMI PHY
 
 Required properties:
   - compatible: value must be one of:
+    * allwinner,sun50i-a64-hdmi-phy
     * allwinner,sun8i-a83t-hdmi-phy
     * allwinner,sun8i-h3-hdmi-phy
   - reg: base address and size of memory-mapped region
@@ -111,8 +112,9 @@ Required properties:
   - resets: phandle to the reset controller driving the PHY
   - reset-names: must be "phy"
 
-H3 HDMI PHY requires additional clock:
+H3 and A64 HDMI PHY requires additional clocks:
   - pll-0: parent of phy clock
+  - pll-1: second possible phy clock parent (A64 only)
 
 TV Encoder
 ----------
@@ -145,6 +147,8 @@ Required properties:
    * allwinner,sun8i-a33-tcon
    * allwinner,sun8i-a83t-tcon-lcd
    * allwinner,sun8i-a83t-tcon-tv
+   * allwinner,sun8i-r40-tcon-tv-0
+   * allwinner,sun8i-r40-tcon-tv-1
    * allwinner,sun8i-v3s-tcon
    * allwinner,sun9i-a80-tcon-lcd
    * allwinner,sun9i-a80-tcon-tv
@@ -179,7 +183,7 @@ For TCONs with channel 0, there is one more clock required:
 For TCONs with channel 1, there is one more clock required:
    - 'tcon-ch1': The clock driving the TCON channel 1
 
-When TCON support LVDS (all TCONs except TV TCON on A83T and those found
+When TCON support LVDS (all TCONs except TV TCONs on A83T, R40 and those found
 in A13, H3, H5 and V3s SoCs), you need one more reset line:
    - 'lvds': The reset line driving the LVDS logic
 
@@ -187,6 +191,12 @@ And on the A23, A31, A31s and A33, you need one more clock line:
    - 'lvds-alt': An alternative clock source, separate from the TCON channel 0
                  clock, that can be used to drive the LVDS clock
 
+If SoC has TCON TOP, like R40, TCON has to have phandle to TCON TOP:
+   - 'allwinner,tcon-top': Phandle to TCON TOP unit
+
+TV TCONs which have phandle to TCON TOP need one more clock:
+   - 'tcon-top': TV TCON gate found in TCON TOP unit
+
 TCON TOP
 --------
 
@@ -330,6 +340,8 @@ Required properties:
     * allwinner,sun8i-a83t-de2-mixer-0
     * allwinner,sun8i-a83t-de2-mixer-1
     * allwinner,sun8i-h3-de2-mixer-0
+    * allwinner,sun8i-r40-de2-mixer-0
+    * allwinner,sun8i-r40-de2-mixer-1
     * allwinner,sun8i-v3s-de2-mixer
   - reg: base address and size of the memory-mapped region.
   - clocks: phandles to the clocks feeding the mixer
-- 
2.17.0

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

* [PATCH 08/15] drm/sun4i: DE2 mixer: Add index quirk
  2018-05-19 18:31 [PATCH 00/15] Add support for R40 HDMI pipeline Jernej Skrabec
                   ` (6 preceding siblings ...)
  2018-05-19 18:31 ` [PATCH 07/15] dt-bindings: display: sun4i-drm: Add R40 HDMI pipeline Jernej Skrabec
@ 2018-05-19 18:31 ` Jernej Skrabec
  2018-05-19 18:31 ` [PATCH 09/15] drm/sun4i: Add support for R40 mixers Jernej Skrabec
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 46+ messages in thread
From: Jernej Skrabec @ 2018-05-19 18:31 UTC (permalink / raw)
  To: maxime.ripard, wens, robh+dt
  Cc: mark.rutland, dri-devel, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-sunxi

When TCON sets up TCON TOP, it needs to know mixer index. Here we do that
by setting engine ID to number provided in mixer index quirk.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 4 ++--
 drivers/gpu/drm/sun4i/sun8i_mixer.h | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 126899d6f0d3..36d90c76317a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -353,13 +353,13 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
 	dev_set_drvdata(dev, mixer);
 	mixer->engine.ops = &sun8i_engine_ops;
 	mixer->engine.node = dev->of_node;
-	/* The ID of the mixer currently doesn't matter */
-	mixer->engine.id = -1;
 
 	mixer->cfg = of_device_get_match_data(dev);
 	if (!mixer->cfg)
 		return -EINVAL;
 
+	mixer->engine.id = mixer->cfg->index;
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	regs = devm_ioremap_resource(dev, res);
 	if (IS_ERR(regs))
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index f34e70c42adf..aeda6e9a7627 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -123,6 +123,7 @@ struct de2_fmt_info {
  *	are invalid.
  * @mod_rate: module clock rate that needs to be set in order to have
  *	a functional block.
+ * @index: mixer index, needed to properly set TCON TOP
  */
 struct sun8i_mixer_cfg {
 	int		vi_num;
@@ -130,6 +131,7 @@ struct sun8i_mixer_cfg {
 	int		scaler_mask;
 	int		ccsc;
 	unsigned long	mod_rate;
+	int		index;
 };
 
 struct sun8i_mixer {
-- 
2.17.0

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

* [PATCH 09/15] drm/sun4i: Add support for R40 mixers
  2018-05-19 18:31 [PATCH 00/15] Add support for R40 HDMI pipeline Jernej Skrabec
                   ` (7 preceding siblings ...)
  2018-05-19 18:31 ` [PATCH 08/15] drm/sun4i: DE2 mixer: Add index quirk Jernej Skrabec
@ 2018-05-19 18:31 ` Jernej Skrabec
  2018-05-19 18:31 ` [PATCH 10/15] drm/sun4i: Add support for R40 TV TCONs Jernej Skrabec
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 46+ messages in thread
From: Jernej Skrabec @ 2018-05-19 18:31 UTC (permalink / raw)
  To: maxime.ripard, wens, robh+dt
  Cc: mark.rutland, dri-devel, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-sunxi

Both mixers have similar capabilities as others SoCs with DE2.

First mixer has 1 VI and 3 UI planes and supports HW scaling on all
planes.

Second mixer has 1 VI and 1 UI planes and also supports HW scaling on
all planes.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_mixer.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 36d90c76317a..78aa878e305c 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -500,6 +500,24 @@ static const struct sun8i_mixer_cfg sun8i_h3_mixer0_cfg = {
 	.vi_num		= 1,
 };
 
+static const struct sun8i_mixer_cfg sun8i_r40_mixer0_cfg = {
+	.ccsc		= 0,
+	.index		= 0,
+	.mod_rate	= 297000000,
+	.scaler_mask	= 0xf,
+	.ui_num		= 3,
+	.vi_num		= 1,
+};
+
+static const struct sun8i_mixer_cfg sun8i_r40_mixer1_cfg = {
+	.ccsc		= 1,
+	.index		= 1,
+	.mod_rate	= 297000000,
+	.scaler_mask	= 0x3,
+	.ui_num		= 1,
+	.vi_num		= 1,
+};
+
 static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
 	.vi_num = 2,
 	.ui_num = 1,
@@ -521,6 +539,14 @@ static const struct of_device_id sun8i_mixer_of_table[] = {
 		.compatible = "allwinner,sun8i-h3-de2-mixer-0",
 		.data = &sun8i_h3_mixer0_cfg,
 	},
+	{
+		.compatible = "allwinner,sun8i-r40-de2-mixer-0",
+		.data = &sun8i_r40_mixer0_cfg,
+	},
+	{
+		.compatible = "allwinner,sun8i-r40-de2-mixer-1",
+		.data = &sun8i_r40_mixer1_cfg,
+	},
 	{
 		.compatible = "allwinner,sun8i-v3s-de2-mixer",
 		.data = &sun8i_v3s_mixer_cfg,
-- 
2.17.0

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

* [PATCH 10/15] drm/sun4i: Add support for R40 TV TCONs
  2018-05-19 18:31 [PATCH 00/15] Add support for R40 HDMI pipeline Jernej Skrabec
                   ` (8 preceding siblings ...)
  2018-05-19 18:31 ` [PATCH 09/15] drm/sun4i: Add support for R40 mixers Jernej Skrabec
@ 2018-05-19 18:31 ` Jernej Skrabec
  2018-05-20  1:57   ` [linux-sunxi] " Julian Calaby
  2018-05-19 18:31 ` [PATCH 11/15] drm/sun4i: DW HDMI PHY: Add support for second PLL Jernej Skrabec
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 46+ messages in thread
From: Jernej Skrabec @ 2018-05-19 18:31 UTC (permalink / raw)
  To: maxime.ripard, wens, robh+dt
  Cc: mark.rutland, dri-devel, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-sunxi

R40 display pipeline has a lot of possible configurations. HDMI can be
connected to 2 different TCONs (out of 4) and mixers can be connected to
any TCON. All this must be configured in TCON TOP.

Along with definition of TCON capabilities also add mux callback, which
can configure this complex pipeline.

For now, only TCON TV is supported.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 39 ++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index e0c562ce1c22..81b9551e4f78 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -1274,6 +1274,31 @@ static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon,
 	return 0;
 }
 
+static int sun8i_r40_tcon_tv_set_mux(struct sun4i_tcon *tcon,
+				     const struct drm_encoder *encoder,
+				     int index)
+{
+	if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
+		sun8i_tcon_top_set_hdmi_src(tcon->tcon_top, index);
+
+	sun8i_tcon_top_de_config(tcon->tcon_top, tcon->id,
+				 tcon_type_tv, index);
+
+	return 0;
+}
+
+static int sun8i_r40_tcon_tv_set_mux_0(struct sun4i_tcon *tcon,
+				       const struct drm_encoder *encoder)
+{
+	return sun8i_r40_tcon_tv_set_mux(tcon, encoder, 0);
+}
+
+static int sun8i_r40_tcon_tv_set_mux_1(struct sun4i_tcon *tcon,
+				       const struct drm_encoder *encoder)
+{
+	return sun8i_r40_tcon_tv_set_mux(tcon, encoder, 1);
+}
+
 static const struct sun4i_tcon_quirks sun4i_a10_quirks = {
 	.has_channel_0		= true,
 	.has_channel_1		= true,
@@ -1321,6 +1346,18 @@ static const struct sun4i_tcon_quirks sun8i_a83t_tv_quirks = {
 	.has_channel_1		= true,
 };
 
+static const struct sun4i_tcon_quirks sun8i_r40_tv_0_quirks = {
+	.has_channel_1		= true,
+	.needs_tcon_top		= true,
+	.set_mux		= sun8i_r40_tcon_tv_set_mux_0,
+};
+
+static const struct sun4i_tcon_quirks sun8i_r40_tv_1_quirks = {
+	.has_channel_1		= true,
+	.needs_tcon_top		= true,
+	.set_mux		= sun8i_r40_tcon_tv_set_mux_1,
+};
+
 static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
 	.has_channel_0		= true,
 };
@@ -1345,6 +1382,8 @@ const struct of_device_id sun4i_tcon_of_table[] = {
 	{ .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
 	{ .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data = &sun8i_a83t_lcd_quirks },
 	{ .compatible = "allwinner,sun8i-a83t-tcon-tv", .data = &sun8i_a83t_tv_quirks },
+	{ .compatible = "allwinner,sun8i-r40-tcon-tv-0", .data = &sun8i_r40_tv_0_quirks },
+	{ .compatible = "allwinner,sun8i-r40-tcon-tv-1", .data = &sun8i_r40_tv_1_quirks },
 	{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
 	{ .compatible = "allwinner,sun9i-a80-tcon-lcd", .data = &sun9i_a80_tcon_lcd_quirks },
 	{ .compatible = "allwinner,sun9i-a80-tcon-tv", .data = &sun9i_a80_tcon_tv_quirks },
-- 
2.17.0

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

* [PATCH 11/15] drm/sun4i: DW HDMI PHY: Add support for second PLL
  2018-05-19 18:31 [PATCH 00/15] Add support for R40 HDMI pipeline Jernej Skrabec
                   ` (9 preceding siblings ...)
  2018-05-19 18:31 ` [PATCH 10/15] drm/sun4i: Add support for R40 TV TCONs Jernej Skrabec
@ 2018-05-19 18:31 ` Jernej Skrabec
  2018-05-19 18:31 ` [PATCH 12/15] drm/sun4i: Add support for second clock parent to DW HDMI PHY clk driver Jernej Skrabec
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 46+ messages in thread
From: Jernej Skrabec @ 2018-05-19 18:31 UTC (permalink / raw)
  To: maxime.ripard, wens, robh+dt
  Cc: mark.rutland, dri-devel, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-sunxi

Some DW HDMI PHYs like those found in A64 and R40 SoCs, can select
between two clock parents.

Add code which reads second PLL from DT.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h  |  2 ++
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 22 ++++++++++++++++------
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index 79154f0f674a..801a17222762 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -147,6 +147,7 @@ struct sun8i_hdmi_phy;
 
 struct sun8i_hdmi_phy_variant {
 	bool has_phy_clk;
+	bool has_second_pll;
 	void (*phy_init)(struct sun8i_hdmi_phy *phy);
 	void (*phy_disable)(struct dw_hdmi *hdmi,
 			    struct sun8i_hdmi_phy *phy);
@@ -160,6 +161,7 @@ struct sun8i_hdmi_phy {
 	struct clk			*clk_mod;
 	struct clk			*clk_phy;
 	struct clk			*clk_pll0;
+	struct clk			*clk_pll1;
 	unsigned int			rcal;
 	struct regmap			*regs;
 	struct reset_control		*rst_phy;
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 5a52fc489a9d..deba47ed69d8 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -472,10 +472,19 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
 			goto err_put_clk_mod;
 		}
 
+		if (phy->variant->has_second_pll) {
+			phy->clk_pll1 = of_clk_get_by_name(node, "pll-1");
+			if (IS_ERR(phy->clk_pll1)) {
+				dev_err(dev, "Could not get pll-1 clock\n");
+				ret = PTR_ERR(phy->clk_pll1);
+				goto err_put_clk_pll0;
+			}
+		}
+
 		ret = sun8i_phy_clk_create(phy, dev);
 		if (ret) {
 			dev_err(dev, "Couldn't create the PHY clock\n");
-			goto err_put_clk_pll0;
+			goto err_put_clk_pll1;
 		}
 	}
 
@@ -483,7 +492,7 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
 	if (IS_ERR(phy->rst_phy)) {
 		dev_err(dev, "Could not get phy reset control\n");
 		ret = PTR_ERR(phy->rst_phy);
-		goto err_put_clk_pll0;
+		goto err_put_clk_pll1;
 	}
 
 	ret = reset_control_deassert(phy->rst_phy);
@@ -514,9 +523,10 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
 	reset_control_assert(phy->rst_phy);
 err_put_rst_phy:
 	reset_control_put(phy->rst_phy);
+err_put_clk_pll1:
+	clk_put(phy->clk_pll1);
 err_put_clk_pll0:
-	if (phy->variant->has_phy_clk)
-		clk_put(phy->clk_pll0);
+	clk_put(phy->clk_pll0);
 err_put_clk_mod:
 	clk_put(phy->clk_mod);
 err_put_clk_bus:
@@ -536,8 +546,8 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi)
 
 	reset_control_put(phy->rst_phy);
 
-	if (phy->variant->has_phy_clk)
-		clk_put(phy->clk_pll0);
+	clk_put(phy->clk_pll0);
+	clk_put(phy->clk_pll1);
 	clk_put(phy->clk_mod);
 	clk_put(phy->clk_bus);
 }
-- 
2.17.0

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

* [PATCH 12/15] drm/sun4i: Add support for second clock parent to DW HDMI PHY clk driver
  2018-05-19 18:31 [PATCH 00/15] Add support for R40 HDMI pipeline Jernej Skrabec
                   ` (10 preceding siblings ...)
  2018-05-19 18:31 ` [PATCH 11/15] drm/sun4i: DW HDMI PHY: Add support for second PLL Jernej Skrabec
@ 2018-05-19 18:31 ` Jernej Skrabec
  2018-05-21  7:47   ` kbuild test robot
  2018-05-21  8:12   ` Maxime Ripard
  2018-05-19 18:31 ` [PATCH 13/15] drm/sun4i: Add support for A64 HDMI PHY Jernej Skrabec
                   ` (2 subsequent siblings)
  14 siblings, 2 replies; 46+ messages in thread
From: Jernej Skrabec @ 2018-05-19 18:31 UTC (permalink / raw)
  To: maxime.ripard, wens, robh+dt
  Cc: mark.rutland, dri-devel, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-sunxi

Expand HDMI PHY clock driver to support second clock parent.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h      |  6 +-
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c     | 29 ++++++-
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c | 90 ++++++++++++++++------
 3 files changed, 98 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index 801a17222762..aadbe0a10b0c 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -98,7 +98,8 @@
 #define SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN		BIT(29)
 #define SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN		BIT(28)
 #define SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33	BIT(27)
-#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL	BIT(26)
+#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK	BIT(26)
+#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT	26
 #define SUN8I_HDMI_PHY_PLL_CFG1_PLLEN		BIT(25)
 #define SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(x)	((x) << 22)
 #define SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(x)	((x) << 20)
@@ -190,6 +191,7 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi);
 void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
 const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void);
 
-int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev);
+int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev,
+			 bool second_parent);
 
 #endif /* _SUN8I_DW_HDMI_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index deba47ed69d8..7a911f0a3ae3 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -183,7 +183,13 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi,
 	regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
 			   SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK, 0);
 
-	regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, pll_cfg1_init);
+	/*
+	 * NOTE: We have to be careful not to overwrite PHY parent
+	 * clock selection bit and clock divider.
+	 */
+	regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
+			   ~SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
+			   pll_cfg1_init);
 	regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG,
 			   (u32)~SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK,
 			   pll_cfg2_init);
@@ -352,6 +358,10 @@ static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy *phy)
 			   SUN8I_HDMI_PHY_ANA_CFG3_SCLEN |
 			   SUN8I_HDMI_PHY_ANA_CFG3_SDAEN);
 
+	/* reset PLL clock configuration */
+	regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, 0);
+	regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG, 0);
+
 	/* set HW control of CEC pins */
 	regmap_write(phy->regs, SUN8I_HDMI_PHY_CEC_REG, 0);
 
@@ -481,18 +491,28 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
 			}
 		}
 
-		ret = sun8i_phy_clk_create(phy, dev);
+		ret = sun8i_phy_clk_create(phy, dev,
+					   phy->variant->has_second_pll);
 		if (ret) {
 			dev_err(dev, "Couldn't create the PHY clock\n");
 			goto err_put_clk_pll1;
 		}
+
+		/*
+		 * Even though HDMI PHY clock doesn't have enable/disable
+		 * handlers, we have to enable it. Otherwise it could happen
+		 * that parent PLL is not enabled by clock framework in a
+		 * highly unlikely event when parent PLL is used solely for
+		 * HDMI PHY clock.
+		 */
+		clk_prepare_enable(phy->clk_phy);
 	}
 
 	phy->rst_phy = of_reset_control_get_shared(node, "phy");
 	if (IS_ERR(phy->rst_phy)) {
 		dev_err(dev, "Could not get phy reset control\n");
 		ret = PTR_ERR(phy->rst_phy);
-		goto err_put_clk_pll1;
+		goto err_disable_clk_phy;
 	}
 
 	ret = reset_control_deassert(phy->rst_phy);
@@ -523,6 +543,8 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
 	reset_control_assert(phy->rst_phy);
 err_put_rst_phy:
 	reset_control_put(phy->rst_phy);
+err_disable_clk_phy:
+	clk_disable_unprepare(phy->clk_phy);
 err_put_clk_pll1:
 	clk_put(phy->clk_pll1);
 err_put_clk_pll0:
@@ -541,6 +563,7 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi)
 
 	clk_disable_unprepare(phy->clk_mod);
 	clk_disable_unprepare(phy->clk_bus);
+	clk_disable_unprepare(phy->clk_phy);
 
 	reset_control_assert(phy->rst_phy);
 
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
index faea449812f8..a4d31fe3abff 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c
@@ -22,35 +22,45 @@ static int sun8i_phy_clk_determine_rate(struct clk_hw *hw,
 {
 	unsigned long rate = req->rate;
 	unsigned long best_rate = 0;
+	struct clk_hw *best_parent = NULL;
 	struct clk_hw *parent;
 	int best_div = 1;
-	int i;
+	int i, p;
 
-	parent = clk_hw_get_parent(hw);
-
-	for (i = 1; i <= 16; i++) {
-		unsigned long ideal = rate * i;
-		unsigned long rounded;
-
-		rounded = clk_hw_round_rate(parent, ideal);
+	for (p = 0; p < clk_hw_get_num_parents(hw); p++) {
+		parent = clk_hw_get_parent_by_index(hw, p);
+		if (!parent)
+			continue;
 
-		if (rounded == ideal) {
-			best_rate = rounded;
-			best_div = i;
-			break;
+		for (i = 1; i <= 16; i++) {
+			unsigned long ideal = rate * i;
+			unsigned long rounded;
+
+			rounded = clk_hw_round_rate(parent, ideal);
+
+			if (rounded == ideal) {
+				best_rate = rounded;
+				best_div = i;
+				best_parent = parent;
+				break;
+			}
+
+			if (!best_rate ||
+			    abs(rate - rounded / i) <
+			    abs(rate - best_rate / best_div)) {
+				best_rate = rounded;
+				best_div = i;
+				best_parent = parent;
+			}
 		}
 
-		if (!best_rate ||
-		    abs(rate - rounded / i) <
-		    abs(rate - best_rate / best_div)) {
-			best_rate = rounded;
-			best_div = i;
-		}
+		if (best_rate / best_div == rate)
+			break;
 	}
 
 	req->rate = best_rate / best_div;
 	req->best_parent_rate = best_rate;
-	req->best_parent_hw = parent;
+	req->best_parent_hw = best_parent;
 
 	return 0;
 }
@@ -95,22 +105,58 @@ static int sun8i_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 	return 0;
 }
 
+static u8 sun8i_phy_clk_get_parent(struct clk_hw *hw)
+{
+	struct sun8i_phy_clk *priv = hw_to_phy_clk(hw);
+	u32 reg;
+
+	regmap_read(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, &reg);
+	reg = (reg & SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK) >>
+	      SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT;
+
+	return reg;
+}
+
+static int sun8i_phy_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct sun8i_phy_clk *priv = hw_to_phy_clk(hw);
+
+	if (index > 1)
+		return -EINVAL;
+
+	regmap_update_bits(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
+			   SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
+			   index << SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT);
+
+	return 0;
+}
+
 static const struct clk_ops sun8i_phy_clk_ops = {
 	.determine_rate	= sun8i_phy_clk_determine_rate,
 	.recalc_rate	= sun8i_phy_clk_recalc_rate,
 	.set_rate	= sun8i_phy_clk_set_rate,
+
+	.get_parent	= sun8i_phy_clk_get_parent,
+	.set_parent	= sun8i_phy_clk_set_parent,
 };
 
-int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev)
+int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev,
+			 bool second_parent)
 {
 	struct clk_init_data init;
 	struct sun8i_phy_clk *priv;
-	const char *parents[1];
+	const char *parents[2];
 
 	parents[0] = __clk_get_name(phy->clk_pll0);
 	if (!parents[0])
 		return -ENODEV;
 
+	if (second_parent) {
+		parents[1] = __clk_get_name(phy->clk_pll1);
+		if (!parents[1])
+			return -ENODEV;
+	}
+
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
@@ -118,7 +164,7 @@ int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev)
 	init.name = "hdmi-phy-clk";
 	init.ops = &sun8i_phy_clk_ops;
 	init.parent_names = parents;
-	init.num_parents = 1;
+	init.num_parents = second_parent ? 2 : 1;
 	init.flags = CLK_SET_RATE_PARENT;
 
 	priv->phy = phy;
-- 
2.17.0

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

* [PATCH 13/15] drm/sun4i: Add support for A64 HDMI PHY
  2018-05-19 18:31 [PATCH 00/15] Add support for R40 HDMI pipeline Jernej Skrabec
                   ` (11 preceding siblings ...)
  2018-05-19 18:31 ` [PATCH 12/15] drm/sun4i: Add support for second clock parent to DW HDMI PHY clk driver Jernej Skrabec
@ 2018-05-19 18:31 ` Jernej Skrabec
  2018-05-19 18:31 ` [PATCH 14/15] ARM: dts: sun8i: r40: Add HDMI pipeline Jernej Skrabec
  2018-05-19 18:31 ` [PATCH 15/15] ARM: dts: sun8i: r40: Enable HDMI output on BananaPi M2 Ultra Jernej Skrabec
  14 siblings, 0 replies; 46+ messages in thread
From: Jernej Skrabec @ 2018-05-19 18:31 UTC (permalink / raw)
  To: maxime.ripard, wens, robh+dt
  Cc: mark.rutland, dri-devel, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-sunxi

PHY is the same as in H3, except it can switch between two clock
parents.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 7a911f0a3ae3..0c9d67bb1007 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -396,6 +396,14 @@ static struct regmap_config sun8i_hdmi_phy_regmap_config = {
 	.name		= "phy"
 };
 
+static const struct sun8i_hdmi_phy_variant sun50i_a64_hdmi_phy = {
+	.has_phy_clk = true,
+	.has_second_pll = true,
+	.phy_init = &sun8i_hdmi_phy_init_h3,
+	.phy_disable = &sun8i_hdmi_phy_disable_h3,
+	.phy_config = &sun8i_hdmi_phy_config_h3,
+};
+
 static const struct sun8i_hdmi_phy_variant sun8i_a83t_hdmi_phy = {
 	.phy_init = &sun8i_hdmi_phy_init_a83t,
 	.phy_disable = &sun8i_hdmi_phy_disable_a83t,
@@ -410,6 +418,10 @@ static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = {
 };
 
 static const struct of_device_id sun8i_hdmi_phy_of_table[] = {
+	{
+		.compatible = "allwinner,sun50i-a64-hdmi-phy",
+		.data = &sun50i_a64_hdmi_phy,
+	},
 	{
 		.compatible = "allwinner,sun8i-a83t-hdmi-phy",
 		.data = &sun8i_a83t_hdmi_phy,
-- 
2.17.0

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

* [PATCH 14/15] ARM: dts: sun8i: r40: Add HDMI pipeline
  2018-05-19 18:31 [PATCH 00/15] Add support for R40 HDMI pipeline Jernej Skrabec
                   ` (12 preceding siblings ...)
  2018-05-19 18:31 ` [PATCH 13/15] drm/sun4i: Add support for A64 HDMI PHY Jernej Skrabec
@ 2018-05-19 18:31 ` Jernej Skrabec
  2018-05-19 18:31 ` [PATCH 15/15] ARM: dts: sun8i: r40: Enable HDMI output on BananaPi M2 Ultra Jernej Skrabec
  14 siblings, 0 replies; 46+ messages in thread
From: Jernej Skrabec @ 2018-05-19 18:31 UTC (permalink / raw)
  To: maxime.ripard, wens, robh+dt
  Cc: mark.rutland, dri-devel, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-sunxi

Add all entries needed for HDMI to function properly.

Since R40 has highly configurable pipeline, both mixers and both TCON
TVs are added. Board specific DT should then connect them together to
best fit the purpose of the board.

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 arch/arm/boot/dts/sun8i-r40.dtsi | 166 +++++++++++++++++++++++++++++++
 1 file changed, 166 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi
index 173dcc1652d2..6d5407964997 100644
--- a/arch/arm/boot/dts/sun8i-r40.dtsi
+++ b/arch/arm/boot/dts/sun8i-r40.dtsi
@@ -42,8 +42,11 @@
  */
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun8i-de2.h>
 #include <dt-bindings/clock/sun8i-r40-ccu.h>
+#include <dt-bindings/clock/sun8i-tcon-top.h>
 #include <dt-bindings/reset/sun8i-r40-ccu.h>
+#include <dt-bindings/reset/sun8i-de2.h>
 
 / {
 	#address-cells = <1>;
@@ -99,12 +102,70 @@
 		};
 	};
 
+	de: display-engine {
+		compatible = "allwinner,sun8i-r40-display-engine",
+			     "allwinner,sun8i-h3-display-engine";
+		allwinner,pipelines = <&mixer0>, <&mixer1>;
+		status = "disabled";
+	};
+
 	soc {
 		compatible = "simple-bus";
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
 
+		display_clocks: clock@1000000 {
+			compatible = "allwinner,sun8i-r40-de2-clk",
+				     "allwinner,sun8i-h3-de2-clk";
+			reg = <0x01000000 0x100000>;
+			clocks = <&ccu CLK_DE>,
+				 <&ccu CLK_BUS_DE>;
+			clock-names = "mod",
+				      "bus";
+			resets = <&ccu RST_BUS_DE>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		mixer0: mixer@1100000 {
+			compatible = "allwinner,sun8i-r40-de2-mixer-0";
+			reg = <0x01100000 0x100000>;
+			clocks = <&display_clocks CLK_BUS_MIXER0>,
+				 <&display_clocks CLK_MIXER0>;
+			clock-names = "bus",
+				      "mod";
+			resets = <&display_clocks RST_MIXER0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				mixer0_out: port@1 {
+					reg = <1>;
+				};
+			};
+		};
+
+		mixer1: mixer@1200000 {
+			compatible = "allwinner,sun8i-r40-de2-mixer-1";
+			reg = <0x01200000 0x100000>;
+			clocks = <&display_clocks CLK_BUS_MIXER1>,
+				 <&display_clocks CLK_MIXER1>;
+			clock-names = "bus",
+				      "mod";
+			resets = <&display_clocks RST_WB>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				mixer1_out: port@1 {
+					reg = <1>;
+				};
+			};
+		};
+
 		nmi_intc: interrupt-controller@1c00030 {
 			compatible = "allwinner,sun7i-a20-sc-nmi";
 			interrupt-controller;
@@ -451,6 +512,70 @@
 			#size-cells = <0>;
 		};
 
+		tcon_top: tcon-top@1c70000 {
+			compatible = "allwinner,sun8i-r40-tcon-top";
+			reg = <0x01c70000 0x1000>;
+			clocks = <&ccu CLK_BUS_TCON_TOP>;
+			clock-names = "bus";
+			resets = <&ccu RST_BUS_TCON_TOP>;
+			reset-names = "rst";
+			#clock-cells = <1>;
+		};
+
+		tcon_tv0: lcd-controller@1c73000 {
+			compatible = "allwinner,sun8i-r40-tcon-tv-0";
+			reg = <0x01c73000 0x1000>;
+			interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_TCON_TV0>, <&ccu CLK_TCON_TV0>,
+				 <&tcon_top 1>;
+			clock-names = "ahb", "tcon-ch1", "tcon-top";
+			resets = <&ccu RST_BUS_TCON_TV0>;
+			reset-names = "lcd";
+			allwinner,tcon-top = <&tcon_top>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tcon_tv0_in: port@0 {
+					reg = <0>;
+				};
+
+				tcon_tv0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+			};
+		};
+
+		tcon_tv1: lcd-controller@1c74000 {
+			compatible = "allwinner,sun8i-r40-tcon-tv-1";
+			reg = <0x01c74000 0x1000>;
+			interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_TCON_TV1>, <&ccu CLK_TCON_TV1>,
+				 <&tcon_top 2>;
+			clock-names = "ahb", "tcon-ch1", "tcon-top";
+			resets = <&ccu RST_BUS_TCON_TV1>;
+			reset-names = "lcd";
+			allwinner,tcon-top = <&tcon_top>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tcon_tv1_in: port@0 {
+					reg = <0>;
+				};
+
+				tcon_tv1_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+			};
+		};
+
 		gic: interrupt-controller@1c81000 {
 			compatible = "arm,gic-400";
 			reg = <0x01c81000 0x1000>,
@@ -461,6 +586,47 @@
 			#interrupt-cells = <3>;
 			interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
 		};
+
+		hdmi: hdmi@1ee0000 {
+			compatible = "allwinner,sun8i-r40-dw-hdmi",
+				     "allwinner,sun8i-a83t-dw-hdmi";
+			reg = <0x01ee0000 0x10000>;
+			reg-io-width = <1>;
+			interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_HDMI0>, <&ccu CLK_HDMI_SLOW>,
+				 <&ccu CLK_HDMI>;
+			clock-names = "iahb", "isfr", "tmds";
+			resets = <&ccu RST_BUS_HDMI1>;
+			reset-names = "ctrl";
+			phys = <&hdmi_phy>;
+			phy-names = "hdmi-phy";
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				hdmi_in: port@0 {
+					reg = <0>;
+				};
+
+				hdmi_out: port@1 {
+					reg = <1>;
+				};
+			};
+		};
+
+		hdmi_phy: hdmi-phy@1ef0000 {
+			compatible = "allwinner,sun8i-r40-hdmi-phy",
+				     "allwinner,sun50i-a64-hdmi-phy";
+			reg = <0x01ef0000 0x10000>;
+			clocks = <&ccu CLK_BUS_HDMI1>, <&ccu CLK_HDMI_SLOW>,
+				 <&ccu 7>, <&ccu 16>;
+			clock-names = "bus", "mod", "pll-0", "pll-1";
+			resets = <&ccu RST_BUS_HDMI0>;
+			reset-names = "phy";
+			#phy-cells = <0>;
+		};
 	};
 
 	timer {
-- 
2.17.0

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

* [PATCH 15/15] ARM: dts: sun8i: r40: Enable HDMI output on BananaPi M2 Ultra
  2018-05-19 18:31 [PATCH 00/15] Add support for R40 HDMI pipeline Jernej Skrabec
                   ` (13 preceding siblings ...)
  2018-05-19 18:31 ` [PATCH 14/15] ARM: dts: sun8i: r40: Add HDMI pipeline Jernej Skrabec
@ 2018-05-19 18:31 ` Jernej Skrabec
  14 siblings, 0 replies; 46+ messages in thread
From: Jernej Skrabec @ 2018-05-19 18:31 UTC (permalink / raw)
  To: maxime.ripard, wens, robh+dt
  Cc: mark.rutland, dri-devel, devicetree, linux-arm-kernel,
	linux-kernel, linux-clk, linux-sunxi

Since HDMI can be considered as main output, most capable mixer is
connected to it (mixer0).

Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
 .../boot/dts/sun8i-r40-bananapi-m2-ultra.dts  | 50 +++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
index 27d9ccd0ef2f..66b492ad5847 100644
--- a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
+++ b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
@@ -58,6 +58,17 @@
 		stdout-path = "serial0:115200n8";
 	};
 
+	connector {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_con_in: endpoint {
+				remote-endpoint = <&hdmi_out_con>;
+			};
+		};
+	};
+
 	leds {
 		compatible = "gpio-leds";
 
@@ -93,6 +104,10 @@
 	};
 };
 
+&de {
+	status = "okay";
+};
+
 &ehci1 {
 	status = "okay";
 };
@@ -101,6 +116,22 @@
 	status = "okay";
 };
 
+&hdmi {
+	status = "okay";
+};
+
+&hdmi_in {
+	hdmi_in_tcon_tv0: endpoint {
+		remote-endpoint = <&tcon_tv0_out_hdmi>;
+	};
+};
+
+&hdmi_out {
+	hdmi_out_con: endpoint {
+		remote-endpoint = <&hdmi_con_in>;
+	};
+};
+
 &i2c0 {
 	status = "okay";
 
@@ -161,6 +192,12 @@
 	regulator-name = "vcc-wifi";
 };
 
+&mixer0_out {
+	mixer0_out_tcon_tv0: endpoint {
+		remote-endpoint = <&tcon_tv0_in_mixer0>;
+	};
+};
+
 &mmc0 {
 	vmmc-supply = <&reg_dcdc1>;
 	bus-width = <4>;
@@ -195,6 +232,19 @@
 	status = "okay";
 };
 
+&tcon_tv0_in {
+	tcon_tv0_in_mixer0: endpoint {
+		remote-endpoint = <&mixer0_out_tcon_tv0>;
+	};
+};
+
+&tcon_tv0_out {
+	tcon_tv0_out_hdmi: endpoint@1 {
+		reg = <1>;
+		remote-endpoint = <&hdmi_in_tcon_tv0>;
+	};
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pb_pins>;
-- 
2.17.0

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

* Re: [linux-sunxi] [PATCH 07/15] dt-bindings: display: sun4i-drm: Add R40 HDMI pipeline
  2018-05-19 18:31 ` [PATCH 07/15] dt-bindings: display: sun4i-drm: Add R40 HDMI pipeline Jernej Skrabec
@ 2018-05-20  1:50   ` Julian Calaby
  0 siblings, 0 replies; 46+ messages in thread
From: Julian Calaby @ 2018-05-20  1:50 UTC (permalink / raw)
  To: jernej.skrabec
  Cc: Maxime Ripard, Chen-Yu Tsai, Rob Herring, Mark Rutland,
	dri-devel, devicetree, Mailing List, Arm, linux-kernel,
	open list:COMMON CLK FRAMEWORK, linux-sunxi

Hi Jernej,

On Sun, May 20, 2018 at 4:31 AM, Jernej Skrabec <jernej.skrabec@siol.net> wrote:
> Missing compatibles and descriptions needed to implement R40 HDMI
> pipeline are added.
>
> For mixers only compatibles are added.
>
> TCON description is expanded with R40 TV TCON compatibles. If the SoC
> has TCON TOP unit, phandle to that unit has to be specified. Additional
> clock has to be specified if SoC has TCON TOP and TCON is TV TCON.
>
> New compatible is added for DWC HDMI PHY, which has additional clock
> specified.

There's a bunch of A64 related stuff mixed in here, is the R40
compatible with the A64's parts? If so, you should probably mention
that in the commit log.

> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  .../bindings/display/sunxi/sun4i-drm.txt         | 16 ++++++++++++++--
>  1 file changed, 14 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> index a099957ab62a..634276f713e8 100644
> --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> @@ -111,8 +112,9 @@ Required properties:
>    - resets: phandle to the reset controller driving the PHY
>    - reset-names: must be "phy"
>
> -H3 HDMI PHY requires additional clock:
> +H3 and A64 HDMI PHY requires additional clocks:
>    - pll-0: parent of phy clock
> +  - pll-1: second possible phy clock parent (A64 only)

Maybe split this into two:

H3 HDMI PHY ...
   - pll-0: ...

A64 HDMI PHY ...
   - pll-0: ...
   - pll-1: ...

At the moment a quick reading implies that H3 needs pll-1.

Thanks,

-- 
Julian Calaby

Email: julian.calaby@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/

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

* Re: [linux-sunxi] [PATCH 10/15] drm/sun4i: Add support for R40 TV TCONs
  2018-05-19 18:31 ` [PATCH 10/15] drm/sun4i: Add support for R40 TV TCONs Jernej Skrabec
@ 2018-05-20  1:57   ` Julian Calaby
  2018-05-20  2:09     ` Julian Calaby
  0 siblings, 1 reply; 46+ messages in thread
From: Julian Calaby @ 2018-05-20  1:57 UTC (permalink / raw)
  To: jernej.skrabec
  Cc: Maxime Ripard, Chen-Yu Tsai, Rob Herring, Mark Rutland,
	dri-devel, devicetree, Mailing List, Arm, linux-kernel,
	open list:COMMON CLK FRAMEWORK, linux-sunxi

Hi Jernej,

On Sun, May 20, 2018 at 4:31 AM, Jernej Skrabec <jernej.skrabec@siol.net> wrote:
> R40 display pipeline has a lot of possible configurations. HDMI can be
> connected to 2 different TCONs (out of 4) and mixers can be connected to
> any TCON. All this must be configured in TCON TOP.
>
> Along with definition of TCON capabilities also add mux callback, which
> can configure this complex pipeline.
>
> For now, only TCON TV is supported.
>
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 39 ++++++++++++++++++++++++++++++
>  1 file changed, 39 insertions(+)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index e0c562ce1c22..81b9551e4f78 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -1274,6 +1274,31 @@ static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon,
>         return 0;
>  }
>
> +static int sun8i_r40_tcon_tv_set_mux(struct sun4i_tcon *tcon,
> +                                    const struct drm_encoder *encoder,
> +                                    int index)
> +{
> +       if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
> +               sun8i_tcon_top_set_hdmi_src(tcon->tcon_top, index);
> +
> +       sun8i_tcon_top_de_config(tcon->tcon_top, tcon->id,
> +                                tcon_type_tv, index);
> +
> +       return 0;
> +}
> +
> +static int sun8i_r40_tcon_tv_set_mux_0(struct sun4i_tcon *tcon,
> +                                      const struct drm_encoder *encoder)
> +{
> +       return sun8i_r40_tcon_tv_set_mux(tcon, encoder, 0);
> +}
> +
> +static int sun8i_r40_tcon_tv_set_mux_1(struct sun4i_tcon *tcon,
> +                                      const struct drm_encoder *encoder)
> +{
> +       return sun8i_r40_tcon_tv_set_mux(tcon, encoder, 1);
> +}

Are TCON-TOPs going to be a common thing in new SoCs from Allwinner?
If so, maybe we should add an index to the TCON quirks and have a
common TCON-TOP set_mux function.

Thanks,

-- 
Julian Calaby

Email: julian.calaby@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/

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

* Re: [linux-sunxi] [PATCH 10/15] drm/sun4i: Add support for R40 TV TCONs
  2018-05-20  1:57   ` [linux-sunxi] " Julian Calaby
@ 2018-05-20  2:09     ` Julian Calaby
  2018-05-20  7:30       ` Jernej Škrabec
  0 siblings, 1 reply; 46+ messages in thread
From: Julian Calaby @ 2018-05-20  2:09 UTC (permalink / raw)
  To: jernej.skrabec
  Cc: Maxime Ripard, Chen-Yu Tsai, Rob Herring, Mark Rutland,
	dri-devel, devicetree, Mailing List, Arm, linux-kernel,
	open list:COMMON CLK FRAMEWORK, linux-sunxi

Hi Jernej,

On Sun, May 20, 2018 at 11:57 AM, Julian Calaby <julian.calaby@gmail.com> wrote:
> Hi Jernej,
>
> On Sun, May 20, 2018 at 4:31 AM, Jernej Skrabec <jernej.skrabec@siol.net> wrote:
>> R40 display pipeline has a lot of possible configurations. HDMI can be
>> connected to 2 different TCONs (out of 4) and mixers can be connected to
>> any TCON. All this must be configured in TCON TOP.
>>
>> Along with definition of TCON capabilities also add mux callback, which
>> can configure this complex pipeline.
>>
>> For now, only TCON TV is supported.
>>
>> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
>> ---
>>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 39 ++++++++++++++++++++++++++++++
>>  1 file changed, 39 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
>> index e0c562ce1c22..81b9551e4f78 100644
>> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
>> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
>> @@ -1274,6 +1274,31 @@ static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon,
>>         return 0;
>>  }
>>
>> +static int sun8i_r40_tcon_tv_set_mux(struct sun4i_tcon *tcon,
>> +                                    const struct drm_encoder *encoder,
>> +                                    int index)
>> +{
>> +       if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
>> +               sun8i_tcon_top_set_hdmi_src(tcon->tcon_top, index);
>> +
>> +       sun8i_tcon_top_de_config(tcon->tcon_top, tcon->id,
>> +                                tcon_type_tv, index);
>> +
>> +       return 0;
>> +}
>> +
>> +static int sun8i_r40_tcon_tv_set_mux_0(struct sun4i_tcon *tcon,
>> +                                      const struct drm_encoder *encoder)
>> +{
>> +       return sun8i_r40_tcon_tv_set_mux(tcon, encoder, 0);
>> +}
>> +
>> +static int sun8i_r40_tcon_tv_set_mux_1(struct sun4i_tcon *tcon,
>> +                                      const struct drm_encoder *encoder)
>> +{
>> +       return sun8i_r40_tcon_tv_set_mux(tcon, encoder, 1);
>> +}
>
> Are TCON-TOPs going to be a common thing in new SoCs from Allwinner?
> If so, maybe we should add an index to the TCON quirks and have a
> common TCON-TOP set_mux function.

Actually, that only moves it up a level. Should it be a devicetree property?

Thanks,

-- 
Julian Calaby

Email: julian.calaby@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/

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

* Re: [linux-sunxi] [PATCH 10/15] drm/sun4i: Add support for R40 TV TCONs
  2018-05-20  2:09     ` Julian Calaby
@ 2018-05-20  7:30       ` Jernej Škrabec
  0 siblings, 0 replies; 46+ messages in thread
From: Jernej Škrabec @ 2018-05-20  7:30 UTC (permalink / raw)
  To: Julian Calaby
  Cc: Maxime Ripard, Chen-Yu Tsai, Rob Herring, Mark Rutland,
	dri-devel, devicetree, Mailing List, Arm, linux-kernel,
	open list:COMMON CLK FRAMEWORK, linux-sunxi

Hi,

Dne nedelja, 20. maj 2018 ob 04:09:52 CEST je Julian Calaby napisal(a):
> Hi Jernej,
> 
> On Sun, May 20, 2018 at 11:57 AM, Julian Calaby <julian.calaby@gmail.com> 
wrote:
> > Hi Jernej,
> > 
> > On Sun, May 20, 2018 at 4:31 AM, Jernej Skrabec <jernej.skrabec@siol.net> 
wrote:
> >> R40 display pipeline has a lot of possible configurations. HDMI can be
> >> connected to 2 different TCONs (out of 4) and mixers can be connected to
> >> any TCON. All this must be configured in TCON TOP.
> >> 
> >> Along with definition of TCON capabilities also add mux callback, which
> >> can configure this complex pipeline.
> >> 
> >> For now, only TCON TV is supported.
> >> 
> >> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> >> ---
> >> 
> >>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 39 ++++++++++++++++++++++++++++++
> >>  1 file changed, 39 insertions(+)
> >> 
> >> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> >> b/drivers/gpu/drm/sun4i/sun4i_tcon.c index e0c562ce1c22..81b9551e4f78
> >> 100644
> >> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> >> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> >> @@ -1274,6 +1274,31 @@ static int sun6i_tcon_set_mux(struct sun4i_tcon
> >> *tcon,>> 
> >>         return 0;
> >>  
> >>  }
> >> 
> >> +static int sun8i_r40_tcon_tv_set_mux(struct sun4i_tcon *tcon,
> >> +                                    const struct drm_encoder *encoder,
> >> +                                    int index)
> >> +{
> >> +       if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
> >> +               sun8i_tcon_top_set_hdmi_src(tcon->tcon_top, index);
> >> +
> >> +       sun8i_tcon_top_de_config(tcon->tcon_top, tcon->id,
> >> +                                tcon_type_tv, index);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static int sun8i_r40_tcon_tv_set_mux_0(struct sun4i_tcon *tcon,
> >> +                                      const struct drm_encoder *encoder)
> >> +{
> >> +       return sun8i_r40_tcon_tv_set_mux(tcon, encoder, 0);
> >> +}
> >> +
> >> +static int sun8i_r40_tcon_tv_set_mux_1(struct sun4i_tcon *tcon,
> >> +                                      const struct drm_encoder *encoder)
> >> +{
> >> +       return sun8i_r40_tcon_tv_set_mux(tcon, encoder, 1);
> >> +}
> > 
> > Are TCON-TOPs going to be a common thing in new SoCs from Allwinner?
> > If so, maybe we should add an index to the TCON quirks and have a
> > common TCON-TOP set_mux function.
> 
> Actually, that only moves it up a level. Should it be a devicetree property?
> 

TCON-TOP is besides R40 part of two newest Allwinner SoCs, H6 and A63. 
However, they have only one TV TCON and one LCD TCON, so indexes are not 
needed for them (always 0). This makes R40 somewhat special. I don't think it 
makes sense to expand everything just for one SoC.

Best regards,
Jernej

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

* Re: [PATCH 12/15] drm/sun4i: Add support for second clock parent to DW HDMI PHY clk driver
  2018-05-19 18:31 ` [PATCH 12/15] drm/sun4i: Add support for second clock parent to DW HDMI PHY clk driver Jernej Skrabec
@ 2018-05-21  7:47   ` kbuild test robot
  2018-05-21  8:12   ` Maxime Ripard
  1 sibling, 0 replies; 46+ messages in thread
From: kbuild test robot @ 2018-05-21  7:47 UTC (permalink / raw)
  To: Jernej Skrabec
  Cc: kbuild-all, maxime.ripard, wens, robh+dt, mark.rutland,
	dri-devel, devicetree, linux-arm-kernel, linux-kernel, linux-clk,
	linux-sunxi

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

Hi Jernej,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm/drm-next]
[also build test WARNING on v4.17-rc6 next-20180517]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Jernej-Skrabec/Add-support-for-R40-HDMI-pipeline/20180521-131839
base:   git://people.freedesktop.org/~airlied/linux.git drm-next
config: arm64-allmodconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All warnings (new ones prefixed by >>):

   In file included from drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h:12:0,
                    from drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c:9:
   drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c: In function 'sun8i_hdmi_phy_config_h3':
>> drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c:191:7: warning: large integer implicitly truncated to unsigned type [-Woverflow]
          ~SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
          ^
   include/linux/regmap.h:76:36: note: in definition of macro 'regmap_update_bits'
     regmap_update_bits_base(map, reg, mask, val, NULL, false, false)
                                       ^~~~

vim +191 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c

     8	
   > 9	#include "sun8i_dw_hdmi.h"
    10	
    11	/*
    12	 * Address can be actually any value. Here is set to same value as
    13	 * it is set in BSP driver.
    14	 */
    15	#define I2C_ADDR	0x69
    16	
    17	static int sun8i_hdmi_phy_config_a83t(struct dw_hdmi *hdmi,
    18					      struct sun8i_hdmi_phy *phy,
    19					      unsigned int clk_rate)
    20	{
    21		regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG,
    22				   SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN,
    23				   SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN);
    24	
    25		/* power down */
    26		dw_hdmi_phy_gen2_txpwron(hdmi, 0);
    27		dw_hdmi_phy_gen2_pddq(hdmi, 1);
    28	
    29		dw_hdmi_phy_reset(hdmi);
    30	
    31		dw_hdmi_phy_gen2_pddq(hdmi, 0);
    32	
    33		dw_hdmi_phy_i2c_set_addr(hdmi, I2C_ADDR);
    34	
    35		/*
    36		 * Values are taken from BSP HDMI driver. Although AW didn't
    37		 * release any documentation, explanation of this values can
    38		 * be found in i.MX 6Dual/6Quad Reference Manual.
    39		 */
    40		if (clk_rate <= 27000000) {
    41			dw_hdmi_phy_i2c_write(hdmi, 0x01e0, 0x06);
    42			dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x15);
    43			dw_hdmi_phy_i2c_write(hdmi, 0x08da, 0x10);
    44			dw_hdmi_phy_i2c_write(hdmi, 0x0007, 0x19);
    45			dw_hdmi_phy_i2c_write(hdmi, 0x0318, 0x0e);
    46			dw_hdmi_phy_i2c_write(hdmi, 0x8009, 0x09);
    47		} else if (clk_rate <= 74250000) {
    48			dw_hdmi_phy_i2c_write(hdmi, 0x0540, 0x06);
    49			dw_hdmi_phy_i2c_write(hdmi, 0x0005, 0x15);
    50			dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10);
    51			dw_hdmi_phy_i2c_write(hdmi, 0x0007, 0x19);
    52			dw_hdmi_phy_i2c_write(hdmi, 0x02b5, 0x0e);
    53			dw_hdmi_phy_i2c_write(hdmi, 0x8009, 0x09);
    54		} else if (clk_rate <= 148500000) {
    55			dw_hdmi_phy_i2c_write(hdmi, 0x04a0, 0x06);
    56			dw_hdmi_phy_i2c_write(hdmi, 0x000a, 0x15);
    57			dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10);
    58			dw_hdmi_phy_i2c_write(hdmi, 0x0002, 0x19);
    59			dw_hdmi_phy_i2c_write(hdmi, 0x0021, 0x0e);
    60			dw_hdmi_phy_i2c_write(hdmi, 0x8029, 0x09);
    61		} else {
    62			dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x06);
    63			dw_hdmi_phy_i2c_write(hdmi, 0x000f, 0x15);
    64			dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10);
    65			dw_hdmi_phy_i2c_write(hdmi, 0x0002, 0x19);
    66			dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x0e);
    67			dw_hdmi_phy_i2c_write(hdmi, 0x802b, 0x09);
    68		}
    69	
    70		dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x1e);
    71		dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x13);
    72		dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x17);
    73	
    74		dw_hdmi_phy_gen2_txpwron(hdmi, 1);
    75	
    76		return 0;
    77	}
    78	
    79	static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi,
    80					    struct sun8i_hdmi_phy *phy,
    81					    unsigned int clk_rate)
    82	{
    83		u32 pll_cfg1_init;
    84		u32 pll_cfg2_init;
    85		u32 ana_cfg1_end;
    86		u32 ana_cfg2_init;
    87		u32 ana_cfg3_init;
    88		u32 b_offset = 0;
    89		u32 val;
    90	
    91		/* bandwidth / frequency independent settings */
    92	
    93		pll_cfg1_init = SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN |
    94				SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN |
    95				SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(7) |
    96				SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(1) |
    97				SUN8I_HDMI_PHY_PLL_CFG1_PLLDBEN |
    98				SUN8I_HDMI_PHY_PLL_CFG1_CS |
    99				SUN8I_HDMI_PHY_PLL_CFG1_CP_S(2) |
   100				SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(63) |
   101				SUN8I_HDMI_PHY_PLL_CFG1_BWS;
   102	
   103		pll_cfg2_init = SUN8I_HDMI_PHY_PLL_CFG2_SV_H |
   104				SUN8I_HDMI_PHY_PLL_CFG2_VCOGAIN_EN |
   105				SUN8I_HDMI_PHY_PLL_CFG2_SDIV2;
   106	
   107		ana_cfg1_end = SUN8I_HDMI_PHY_ANA_CFG1_REG_SVBH(1) |
   108			       SUN8I_HDMI_PHY_ANA_CFG1_AMP_OPT |
   109			       SUN8I_HDMI_PHY_ANA_CFG1_EMP_OPT |
   110			       SUN8I_HDMI_PHY_ANA_CFG1_AMPCK_OPT |
   111			       SUN8I_HDMI_PHY_ANA_CFG1_EMPCK_OPT |
   112			       SUN8I_HDMI_PHY_ANA_CFG1_ENRCAL |
   113			       SUN8I_HDMI_PHY_ANA_CFG1_ENCALOG |
   114			       SUN8I_HDMI_PHY_ANA_CFG1_REG_SCKTMDS |
   115			       SUN8I_HDMI_PHY_ANA_CFG1_TMDSCLK_EN |
   116			       SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK |
   117			       SUN8I_HDMI_PHY_ANA_CFG1_TXEN_ALL |
   118			       SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDSCLK |
   119			       SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS2 |
   120			       SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS1 |
   121			       SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS0 |
   122			       SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS2 |
   123			       SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS1 |
   124			       SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS0 |
   125			       SUN8I_HDMI_PHY_ANA_CFG1_CKEN |
   126			       SUN8I_HDMI_PHY_ANA_CFG1_LDOEN |
   127			       SUN8I_HDMI_PHY_ANA_CFG1_ENVBS |
   128			       SUN8I_HDMI_PHY_ANA_CFG1_ENBI;
   129	
   130		ana_cfg2_init = SUN8I_HDMI_PHY_ANA_CFG2_M_EN |
   131				SUN8I_HDMI_PHY_ANA_CFG2_REG_DENCK |
   132				SUN8I_HDMI_PHY_ANA_CFG2_REG_DEN |
   133				SUN8I_HDMI_PHY_ANA_CFG2_REG_CKSS(1) |
   134				SUN8I_HDMI_PHY_ANA_CFG2_REG_CSMPS(1);
   135	
   136		ana_cfg3_init = SUN8I_HDMI_PHY_ANA_CFG3_REG_WIRE(0x3e0) |
   137				SUN8I_HDMI_PHY_ANA_CFG3_SDAEN |
   138				SUN8I_HDMI_PHY_ANA_CFG3_SCLEN;
   139	
   140		/* bandwidth / frequency dependent settings */
   141		if (clk_rate <= 27000000) {
   142			pll_cfg1_init |= SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 |
   143					 SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(32);
   144			pll_cfg2_init |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(4) |
   145					 SUN8I_HDMI_PHY_PLL_CFG2_S(4);
   146			ana_cfg1_end |= SUN8I_HDMI_PHY_ANA_CFG1_REG_CALSW;
   147			ana_cfg2_init |= SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4) |
   148					 SUN8I_HDMI_PHY_ANA_CFG2_REG_RESDI(phy->rcal);
   149			ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(3) |
   150					 SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(5);
   151		} else if (clk_rate <= 74250000) {
   152			pll_cfg1_init |= SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 |
   153					 SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(32);
   154			pll_cfg2_init |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(4) |
   155					 SUN8I_HDMI_PHY_PLL_CFG2_S(5);
   156			ana_cfg1_end |= SUN8I_HDMI_PHY_ANA_CFG1_REG_CALSW;
   157			ana_cfg2_init |= SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4) |
   158					 SUN8I_HDMI_PHY_ANA_CFG2_REG_RESDI(phy->rcal);
   159			ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(5) |
   160					 SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(7);
   161		} else if (clk_rate <= 148500000) {
   162			pll_cfg1_init |= SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 |
   163					 SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(32);
   164			pll_cfg2_init |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(4) |
   165					 SUN8I_HDMI_PHY_PLL_CFG2_S(6);
   166			ana_cfg2_init |= SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSWCK |
   167					 SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSW |
   168					 SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(2);
   169			ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(7) |
   170					 SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(9);
   171		} else {
   172			b_offset = 2;
   173			pll_cfg1_init |= SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(63);
   174			pll_cfg2_init |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(6) |
   175					 SUN8I_HDMI_PHY_PLL_CFG2_S(7);
   176			ana_cfg2_init |= SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSWCK |
   177					 SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSW |
   178					 SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4);
   179			ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(9) |
   180					 SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(13);
   181		}
   182	
   183		regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
   184				   SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK, 0);
   185	
   186		/*
   187		 * NOTE: We have to be careful not to overwrite PHY parent
   188		 * clock selection bit and clock divider.
   189		 */
   190		regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
 > 191				   ~SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
   192				   pll_cfg1_init);
   193		regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG,
   194				   (u32)~SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK,
   195				   pll_cfg2_init);
   196		usleep_range(10000, 15000);
   197		regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG3_REG,
   198			     SUN8I_HDMI_PHY_PLL_CFG3_SOUT_DIV2);
   199		regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
   200				   SUN8I_HDMI_PHY_PLL_CFG1_PLLEN,
   201				   SUN8I_HDMI_PHY_PLL_CFG1_PLLEN);
   202		msleep(100);
   203	
   204		/* get B value */
   205		regmap_read(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, &val);
   206		val = (val & SUN8I_HDMI_PHY_ANA_STS_B_OUT_MSK) >>
   207			SUN8I_HDMI_PHY_ANA_STS_B_OUT_SHIFT;
   208		val = min(val + b_offset, (u32)0x3f);
   209	
   210		regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
   211				   SUN8I_HDMI_PHY_PLL_CFG1_REG_OD1 |
   212				   SUN8I_HDMI_PHY_PLL_CFG1_REG_OD,
   213				   SUN8I_HDMI_PHY_PLL_CFG1_REG_OD1 |
   214				   SUN8I_HDMI_PHY_PLL_CFG1_REG_OD);
   215		regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
   216				   SUN8I_HDMI_PHY_PLL_CFG1_B_IN_MSK,
   217				   val << SUN8I_HDMI_PHY_PLL_CFG1_B_IN_SHIFT);
   218		msleep(100);
   219		regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, ana_cfg1_end);
   220		regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG2_REG, ana_cfg2_init);
   221		regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG3_REG, ana_cfg3_init);
   222	
   223		return 0;
   224	}
   225	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 59031 bytes --]

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

* Re: [PATCH 04/15] dt-bindings: display: sunxi-drm: Add TCON TOP description
  2018-05-19 18:31 ` [PATCH 04/15] dt-bindings: display: sunxi-drm: Add TCON TOP description Jernej Skrabec
@ 2018-05-21  8:01   ` Maxime Ripard
  2018-05-21 15:10     ` Jernej Škrabec
  0 siblings, 1 reply; 46+ messages in thread
From: Maxime Ripard @ 2018-05-21  8:01 UTC (permalink / raw)
  To: Jernej Skrabec
  Cc: wens, robh+dt, mark.rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, linux-sunxi

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

Hi,

On Sat, May 19, 2018 at 08:31:16PM +0200, Jernej Skrabec wrote:
> TCON TOP main purpose is to configure whole display pipeline. It
> determines relationships between mixers and TCONs, selects source TCON
> for HDMI, muxes LCD and TV encoder GPIO output,

I'm not sure you mean GPIO here, but rather pin?

> selects TV encoder clock source and contains additional TV TCON and
> DSI gates.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  .../bindings/display/sunxi/sun4i-drm.txt      | 20 +++++++++++++++++++
>  1 file changed, 20 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> index 3346c1e2a7a0..a099957ab62a 100644
> --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> @@ -187,6 +187,26 @@ And on the A23, A31, A31s and A33, you need one more clock line:
>     - 'lvds-alt': An alternative clock source, separate from the TCON channel 0
>                   clock, that can be used to drive the LVDS clock
>  
> +TCON TOP
> +--------
> +
> +TCON TOPs main purpose is to configure whole display pipeline. It determines
> +relationships between mixers and TCONs, selects source TCON for HDMI, muxes
> +LCD and TV encoder GPIO output, selects TV encoder clock source and contains
> +additional TV TCON and DSI gates.
> +
> +Required properties:
> +  - compatible: value must be one of:
> +    * allwinner,sun8i-r40-tcon-top
> +  - reg: base address and size of the memory-mapped region.
> +  - clocks: phandle to the clocks feeding the TCON TOP
> +    * bus: TCON TOP interface clock
> +  - clock-names: clock name mentioned above
> +  - resets: phandle to the reset line driving the DRC
> +    * rst: TCON TOP reset line
> +  - reset-names: reset name mentioned above
> +  - #clock-cells : must contain 1
> +

I guess you should better describe the OF-graph endpoints, and the
clocks output. Just using the binding additions here doesn't allow to
get a clear idea of how the DT should look like.

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

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

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

* Re: [PATCH 05/15] drm/sun4i: Add TCON TOP driver
  2018-05-19 18:31 ` [PATCH 05/15] drm/sun4i: Add TCON TOP driver Jernej Skrabec
@ 2018-05-21  8:05   ` Maxime Ripard
  2018-05-21 15:15     ` Jernej Škrabec
  2018-05-22  2:25   ` kbuild test robot
  2018-05-23 18:23   ` Rob Herring
  2 siblings, 1 reply; 46+ messages in thread
From: Maxime Ripard @ 2018-05-21  8:05 UTC (permalink / raw)
  To: Jernej Skrabec
  Cc: wens, robh+dt, mark.rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, linux-sunxi

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

On Sat, May 19, 2018 at 08:31:17PM +0200, Jernej Skrabec wrote:
> As already described in DT binding, TCON TOP is responsible for
> configuring display pipeline. In this initial driver focus is on HDMI
> pipeline, so TVE and LCD configuration is not implemented.
> 
> Implemented features:
> - HDMI source selection
> - clock driver (TCON and DSI gating)
> - connecting mixers and TCONS
> 
> Something similar also existed in previous SoCs, except that it was part
> of first TCON.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  drivers/gpu/drm/sun4i/Makefile             |   3 +-
>  drivers/gpu/drm/sun4i/sun8i_tcon_top.c     | 256 +++++++++++++++++++++
>  drivers/gpu/drm/sun4i/sun8i_tcon_top.h     |  20 ++
>  include/dt-bindings/clock/sun8i-tcon-top.h |  11 +
>  4 files changed, 289 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_tcon_top.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_tcon_top.h
>  create mode 100644 include/dt-bindings/clock/sun8i-tcon-top.h
> 
> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
> index 2589f4acd5ae..09fbfd6304ba 100644
> --- a/drivers/gpu/drm/sun4i/Makefile
> +++ b/drivers/gpu/drm/sun4i/Makefile
> @@ -16,7 +16,8 @@ sun8i-drm-hdmi-y		+= sun8i_hdmi_phy_clk.o
>  
>  sun8i-mixer-y			+= sun8i_mixer.o sun8i_ui_layer.o \
>  				   sun8i_vi_layer.o sun8i_ui_scaler.o \
> -				   sun8i_vi_scaler.o sun8i_csc.o
> +				   sun8i_vi_scaler.o sun8i_csc.o \
> +				   sun8i_tcon_top.o
>  
>  sun4i-tcon-y			+= sun4i_crtc.o
>  sun4i-tcon-y			+= sun4i_dotclock.o
> diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
> new file mode 100644
> index 000000000000..075a356a6dfa
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
> @@ -0,0 +1,256 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/* Copyright (c) 2018 Jernej Skrabec <jernej.skrabec@siol.net> */
> +
> +#include <drm/drmP.h>
> +
> +#include <dt-bindings/clock/sun8i-tcon-top.h>
> +
> +#include <linux/bitfield.h>
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/spinlock.h>
> +
> +#include "sun8i_tcon_top.h"
> +
> +#define TCON_TOP_PORT_SEL_REG		0x1C
> +#define TCON_TOP_PORT_DE0_MSK			GENMASK(1, 0)
> +#define TCON_TOP_PORT_DE1_MSK			GENMASK(5, 4)
> +#define TCON_TOP_PORT_TCON_LCD0			0
> +#define TCON_TOP_PORT_TCON_LCD1			1
> +#define TCON_TOP_PORT_TCON_TV0			2
> +#define TCON_TOP_PORT_TCON_TV1			3
> +
> +#define TCON_TOP_GATE_SRC_REG		0x20
> +#define TCON_TOP_HDMI_SRC_MSK			GENMASK(29, 28)
> +#define TCON_TOP_HDMI_SRC_NONE			0
> +#define TCON_TOP_HDMI_SRC_TCON_TV0		1
> +#define TCON_TOP_HDMI_SRC_TCON_TV1		2
> +#define TCON_TOP_TCON_TV1_GATE			24
> +#define TCON_TOP_TCON_TV0_GATE			20
> +#define TCON_TOP_TCON_DSI_GATE			16
> +
> +#define CLK_NUM					3
> +
> +struct sun8i_tcon_top {
> +	struct clk		*bus;
> +	void __iomem		*regs;
> +	struct reset_control	*rst;
> +
> +	/*
> +	 * spinlock is used for locking access to registers from different
> +	 * places - tcon driver and clk subsystem.
> +	 */
> +	spinlock_t		reg_lock;
> +};
> +
> +struct sun8i_tcon_top_gate {
> +	const char	*name;
> +	u8		bit;
> +	int		index;
> +};
> +
> +static const struct sun8i_tcon_top_gate gates[] = {
> +	{"bus-tcon-top-dsi", TCON_TOP_TCON_DSI_GATE, CLK_BUS_TCON_TOP_DSI},
> +	{"bus-tcon-top-tv0", TCON_TOP_TCON_TV0_GATE, CLK_BUS_TCON_TOP_TV0},
> +	{"bus-tcon-top-tv1", TCON_TOP_TCON_TV1_GATE, CLK_BUS_TCON_TOP_TV1},
> +};
> +
> +void sun8i_tcon_top_set_hdmi_src(struct sun8i_tcon_top *tcon_top, int tcon)
> +{
> +	unsigned long flags;
> +	u32 val;
> +
> +	if (tcon > 1) {
> +		DRM_ERROR("TCON index is too high!\n");
> +		return;
> +	}
> +
> +	spin_lock_irqsave(&tcon_top->reg_lock, flags);
> +
> +	val = readl(tcon_top->regs + TCON_TOP_GATE_SRC_REG);
> +	val &= ~TCON_TOP_HDMI_SRC_MSK;
> +	val |= FIELD_PREP(TCON_TOP_HDMI_SRC_MSK,
> +			  TCON_TOP_HDMI_SRC_TCON_TV0 + tcon);
> +	writel(val, tcon_top->regs + TCON_TOP_GATE_SRC_REG);
> +
> +	spin_unlock_irqrestore(&tcon_top->reg_lock, flags);
> +}
> +
> +void sun8i_tcon_top_de_config(struct sun8i_tcon_top *tcon_top,
> +			      int mixer, enum tcon_type tcon_type, int tcon)
> +{
> +	unsigned long flags;
> +	u32 val, reg;
> +
> +	if (mixer > 1) {
> +		DRM_ERROR("Mixer index is too high!\n");
> +		return;
> +	}
> +
> +	if (tcon > 1) {
> +		DRM_ERROR("TCON index is too high!\n");
> +		return;
> +	}
> +
> +	switch (tcon_type) {
> +	case tcon_type_lcd:
> +		val = TCON_TOP_PORT_TCON_LCD0 + tcon;
> +		break;
> +	case tcon_type_tv:
> +		val = TCON_TOP_PORT_TCON_TV0 + tcon;
> +		break;
> +	default:
> +		DRM_ERROR("Invalid TCON type!\n");
> +		return;
> +	}
> +
> +	spin_lock_irqsave(&tcon_top->reg_lock, flags);
> +
> +	reg = readl(tcon_top->regs + TCON_TOP_PORT_SEL_REG);
> +	if (mixer == 0) {
> +		reg &= ~TCON_TOP_PORT_DE0_MSK;
> +		reg |= FIELD_PREP(TCON_TOP_PORT_DE0_MSK, val);
> +	} else {
> +		reg &= ~TCON_TOP_PORT_DE1_MSK;
> +		reg |= FIELD_PREP(TCON_TOP_PORT_DE1_MSK, val);
> +	}
> +	writel(reg, tcon_top->regs + TCON_TOP_PORT_SEL_REG);
> +
> +	spin_unlock_irqrestore(&tcon_top->reg_lock, flags);
> +}
> +
> +static int sun8i_tcon_top_probe(struct platform_device *pdev)
> +{
> +	struct clk_hw_onecell_data *clk_data;
> +	struct sun8i_tcon_top *tcon_top;
> +	struct device *dev = &pdev->dev;
> +	struct resource *res;
> +	int ret, i;
> +
> +	tcon_top = devm_kzalloc(dev, sizeof(*tcon_top), GFP_KERNEL);
> +	if (!tcon_top)
> +		return -ENOMEM;
> +
> +	clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data) +
> +				sizeof(*clk_data->hws) * CLK_NUM,
> +				GFP_KERNEL);
> +	if (!clk_data)
> +		return -ENOMEM;
> +
> +	spin_lock_init(&tcon_top->reg_lock);
> +
> +	tcon_top->rst = devm_reset_control_get(dev, "rst");
> +	if (IS_ERR(tcon_top->rst)) {
> +		dev_err(dev, "Couldn't get our reset line\n");
> +		return PTR_ERR(tcon_top->rst);
> +	}
> +
> +	tcon_top->bus = devm_clk_get(dev, "bus");
> +	if (IS_ERR(tcon_top->bus)) {
> +		dev_err(dev, "Couldn't get the bus clock\n");
> +		return PTR_ERR(tcon_top->bus);
> +	}
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	tcon_top->regs = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(tcon_top->regs))
> +		return PTR_ERR(tcon_top->regs);
> +
> +	ret = reset_control_deassert(tcon_top->rst);
> +	if (ret) {
> +		dev_err(dev, "Could not deassert ctrl reset control\n");
> +		return ret;
> +	}
> +
> +	ret = clk_prepare_enable(tcon_top->bus);
> +	if (ret) {
> +		dev_err(dev, "Could not enable bus clock\n");
> +		goto err_assert_reset;
> +	}
> +
> +	/*
> +	 * Default register values might have some reserved bits set, which
> +	 * prevents TCON TOP from working properly. Set them to 0 here.
> +	 */
> +	writel(0, tcon_top->regs + TCON_TOP_PORT_SEL_REG);
> +	writel(0, tcon_top->regs + TCON_TOP_GATE_SRC_REG);
> +
> +	for (i = 0; i < CLK_NUM; i++) {
> +		const char *parent_name = "bus-tcon-top";

I guess retrieving the parent's clock name at runtime would be more
flexible.

> +		struct clk_init_data init;
> +		struct clk_gate *gate;
> +
> +		gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
> +		if (!gate) {
> +			ret = -ENOMEM;
> +			goto err_disable_clock;
> +		}
> +
> +		init.name = gates[i].name;
> +		init.ops = &clk_gate_ops;
> +		init.flags = CLK_IS_BASIC;
> +		init.parent_names = &parent_name;
> +		init.num_parents = 1;
> +
> +		gate->reg = tcon_top->regs + TCON_TOP_GATE_SRC_REG;
> +		gate->bit_idx = gates[i].bit;
> +		gate->lock = &tcon_top->reg_lock;
> +		gate->hw.init = &init;
> +
> +		ret = devm_clk_hw_register(dev, &gate->hw);
> +		if (ret)
> +			goto err_disable_clock;

Isn't it what clk_hw_register_gate is doing?

> +		clk_data->hws[gates[i].index] = &gate->hw;
> +	}
> +
> +	clk_data->num = CLK_NUM;
> +
> +	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
> +	if (ret)
> +		goto err_disable_clock;
> +
> +	platform_set_drvdata(pdev, tcon_top);
> +
> +	return 0;
> +
> +err_disable_clock:
> +	clk_disable_unprepare(tcon_top->bus);
> +err_assert_reset:
> +	reset_control_assert(tcon_top->rst);
> +
> +	return ret;
> +}
> +
> +static int sun8i_tcon_top_remove(struct platform_device *pdev)
> +{
> +	struct sun8i_tcon_top *tcon_top = platform_get_drvdata(pdev);
> +
> +	clk_disable_unprepare(tcon_top->bus);
> +	reset_control_assert(tcon_top->rst);
> +
> +	return 0;
> +}
> +
> +const struct of_device_id sun8i_tcon_top_of_table[] = {
> +	{ .compatible = "allwinner,sun8i-r40-tcon-top" },
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, sun8i_tcon_top_of_table);
> +
> +static struct platform_driver sun8i_tcon_top_platform_driver = {
> +	.probe		= sun8i_tcon_top_probe,
> +	.remove		= sun8i_tcon_top_remove,
> +	.driver		= {
> +		.name		= "sun8i-tcon-top",
> +		.of_match_table	= sun8i_tcon_top_of_table,
> +	},
> +};
> +module_platform_driver(sun8i_tcon_top_platform_driver);
> +
> +MODULE_AUTHOR("Jernej Skrabec <jernej.skrabec@siol.net>");
> +MODULE_DESCRIPTION("Allwinner R40 TCON TOP driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.h b/drivers/gpu/drm/sun4i/sun8i_tcon_top.h
> new file mode 100644
> index 000000000000..19126e07d2a6
> --- /dev/null
> +++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.h
> @@ -0,0 +1,20 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/* Copyright (c) 2018 Jernej Skrabec <jernej.skrabec@siol.net> */
> +
> +#ifndef _SUN8I_TCON_TOP_H_
> +#define _SUN8I_TCON_TOP_H_
> +
> +#include <linux/device.h>
> +
> +struct sun8i_tcon_top;
> +
> +enum tcon_type {
> +	tcon_type_lcd,
> +	tcon_type_tv,

The usual practice is to have the enum values upper-case.

Thanks!
Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

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

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

* Re: [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top
  2018-05-19 18:31 ` [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top Jernej Skrabec
@ 2018-05-21  8:07   ` Maxime Ripard
  2018-05-21 17:27     ` Jernej Škrabec
  0 siblings, 1 reply; 46+ messages in thread
From: Maxime Ripard @ 2018-05-21  8:07 UTC (permalink / raw)
  To: Jernej Skrabec
  Cc: wens, robh+dt, mark.rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, linux-sunxi

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

On Sat, May 19, 2018 at 08:31:18PM +0200, Jernej Skrabec wrote:
> If SoC has TCON TOP unit, it has to be configured from TCON, since it
> has all information needed. Additionally, if it is TCON TV, it must also
> enable bus gate inside TCON TOP unit.

Why?

> Add support for such TCONs.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 28 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/sun4i/sun4i_tcon.h |  8 ++++++++
>  2 files changed, 36 insertions(+)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 08747fc3ee71..e0c562ce1c22 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -688,6 +688,16 @@ static int sun4i_tcon_init_clocks(struct device *dev,
>  		dev_err(dev, "Couldn't get the TCON bus clock\n");
>  		return PTR_ERR(tcon->clk);
>  	}
> +
> +	if (tcon->quirks->needs_tcon_top && tcon->quirks->has_channel_1) {
> +		tcon->top_clk = devm_clk_get(dev, "tcon-top");
> +		if (IS_ERR(tcon->top_clk)) {
> +			dev_err(dev, "Couldn't get the TCON TOP bus clock\n");
> +			return PTR_ERR(tcon->top_clk);
> +		}
> +		clk_prepare_enable(tcon->top_clk);
> +	}
> +
>  	clk_prepare_enable(tcon->clk);
>  
>  	if (tcon->quirks->has_channel_0) {
> @@ -712,6 +722,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
>  static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
>  {
>  	clk_disable_unprepare(tcon->clk);
> +	clk_disable_unprepare(tcon->top_clk);
>  }
>  
>  static int sun4i_tcon_init_irq(struct device *dev,
> @@ -980,6 +991,23 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
>  	tcon->id = engine->id;
>  	tcon->quirks = of_device_get_match_data(dev);
>  
> +	if (tcon->quirks->needs_tcon_top) {
> +		struct device_node *np;
> +
> +		np = of_parse_phandle(dev->of_node, "allwinner,tcon-top", 0);
> +		if (np) {
> +			struct platform_device *pdev;
> +
> +			pdev = of_find_device_by_node(np);
> +			if (pdev)
> +				tcon->tcon_top = platform_get_drvdata(pdev);
> +			of_node_put(np);
> +
> +			if (!tcon->tcon_top)
> +				return -EPROBE_DEFER;
> +		}
> +	}
> +

I might have missed it, but I've not seen the bindings additions for
that property. This shouldn't really be done that way anyway, instead
of using a direct phandle, you should be using the of-graph, with the
TCON-top sitting where it belongs in the flow of data.

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

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

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

* Re: [PATCH 12/15] drm/sun4i: Add support for second clock parent to DW HDMI PHY clk driver
  2018-05-19 18:31 ` [PATCH 12/15] drm/sun4i: Add support for second clock parent to DW HDMI PHY clk driver Jernej Skrabec
  2018-05-21  7:47   ` kbuild test robot
@ 2018-05-21  8:12   ` Maxime Ripard
  2018-05-21 15:02     ` [linux-sunxi] " Jernej Škrabec
  1 sibling, 1 reply; 46+ messages in thread
From: Maxime Ripard @ 2018-05-21  8:12 UTC (permalink / raw)
  To: Jernej Skrabec
  Cc: wens, robh+dt, mark.rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, linux-sunxi

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

On Sat, May 19, 2018 at 08:31:24PM +0200, Jernej Skrabec wrote:
> Expand HDMI PHY clock driver to support second clock parent.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h      |  6 +-
>  drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c     | 29 ++++++-
>  drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c | 90 ++++++++++++++++------
>  3 files changed, 98 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> index 801a17222762..aadbe0a10b0c 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> @@ -98,7 +98,8 @@
>  #define SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN		BIT(29)
>  #define SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN		BIT(28)
>  #define SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33	BIT(27)
> -#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL	BIT(26)
> +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK	BIT(26)
> +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT	26
>  #define SUN8I_HDMI_PHY_PLL_CFG1_PLLEN		BIT(25)
>  #define SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(x)	((x) << 22)
>  #define SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(x)	((x) << 20)
> @@ -190,6 +191,7 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi);
>  void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
>  const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void);
>  
> -int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev);
> +int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev,
> +			 bool second_parent);
>  
>  #endif /* _SUN8I_DW_HDMI_H_ */
> diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> index deba47ed69d8..7a911f0a3ae3 100644
> --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> @@ -183,7 +183,13 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi,
>  	regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
>  			   SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK, 0);
>  
> -	regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, pll_cfg1_init);
> +	/*
> +	 * NOTE: We have to be careful not to overwrite PHY parent
> +	 * clock selection bit and clock divider.
> +	 */
> +	regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
> +			   ~SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
> +			   pll_cfg1_init);

It feels like it belongs in a separate patch.

>  	regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG,
>  			   (u32)~SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK,
>  			   pll_cfg2_init);
> @@ -352,6 +358,10 @@ static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy *phy)
>  			   SUN8I_HDMI_PHY_ANA_CFG3_SCLEN |
>  			   SUN8I_HDMI_PHY_ANA_CFG3_SDAEN);
>  
> +	/* reset PLL clock configuration */
> +	regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, 0);
> +	regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG, 0);
> +

Ditto,

> +
> +		/*
> +		 * Even though HDMI PHY clock doesn't have enable/disable
> +		 * handlers, we have to enable it. Otherwise it could happen
> +		 * that parent PLL is not enabled by clock framework in a
> +		 * highly unlikely event when parent PLL is used solely for
> +		 * HDMI PHY clock.
> +		 */
> +		clk_prepare_enable(phy->clk_phy);

The implementation of the clock doesn't really matter in our API
usage. If we're using a clock, we have to call
clk_prepare_enable. That's documented everywhere, and mentionning how
the clock is implemented is an abstraction leakage and it's
irrelevant. I'd simply remove the comment here.

And it should be in a separate patch as well.

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

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

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

* Re: [linux-sunxi] Re: [PATCH 12/15] drm/sun4i: Add support for second clock parent to DW HDMI PHY clk driver
  2018-05-21  8:12   ` Maxime Ripard
@ 2018-05-21 15:02     ` Jernej Škrabec
  2018-05-24  8:27       ` Maxime Ripard
  0 siblings, 1 reply; 46+ messages in thread
From: Jernej Škrabec @ 2018-05-21 15:02 UTC (permalink / raw)
  To: linux-sunxi, maxime.ripard
  Cc: wens, robh+dt, mark.rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk

Hi,

Dne ponedeljek, 21. maj 2018 ob 10:12:53 CEST je Maxime Ripard napisal(a):
> On Sat, May 19, 2018 at 08:31:24PM +0200, Jernej Skrabec wrote:
> > Expand HDMI PHY clock driver to support second clock parent.
> > 
> > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > ---
> > 
> >  drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h      |  6 +-
> >  drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c     | 29 ++++++-
> >  drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c | 90 ++++++++++++++++------
> >  3 files changed, 98 insertions(+), 27 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> > b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h index 801a17222762..aadbe0a10b0c
> > 100644
> > --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> > +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> > @@ -98,7 +98,8 @@
> > 
> >  #define SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN		BIT(29)
> >  #define SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN		BIT(28)
> >  #define SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33	BIT(27)
> > 
> > -#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL	BIT(26)
> > +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK	BIT(26)
> > +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT	26
> > 
> >  #define SUN8I_HDMI_PHY_PLL_CFG1_PLLEN		BIT(25)
> >  #define SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(x)	((x) << 22)
> >  #define SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(x)	((x) << 20)
> > 
> > @@ -190,6 +191,7 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi
> > *hdmi);
> > 
> >  void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
> >  const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void);
> > 
> > -int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev);
> > +int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev,
> > +			 bool second_parent);
> > 
> >  #endif /* _SUN8I_DW_HDMI_H_ */
> > 
> > diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> > b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c index deba47ed69d8..7a911f0a3ae3
> > 100644
> > --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> > +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> > @@ -183,7 +183,13 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi
> > *hdmi,> 
> >  	regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
> >  	
> >  			   SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK, 0);
> > 
> > -	regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, pll_cfg1_init);
> > +	/*
> > +	 * NOTE: We have to be careful not to overwrite PHY parent
> > +	 * clock selection bit and clock divider.
> > +	 */
> > +	regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
> > +			   ~SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
> > +			   pll_cfg1_init);
> 
> It feels like it belongs in a separate patch.

Why? clk_set_rate() on HDMI PHY clock is called before this function, so 
SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL bit is already set to correct value. Original 
code doesn't take this into account and sets it to 0 here in all cases, which 
obviously is not right.

If you insist on splitting this in new patch, it has to be applied before 
clock changes. It would also need to include "reset PLL clock configuration" 
chunk (next change in this patch), otherwise other SoCs with only one parent 
could get 1 there, which is obviously wrong. Note that I didn't really tested 
if default value of this bit is 0 or 1, but I wouldn't really like to depend 
on default values.

> 
> >  	regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG,
> >  	
> >  			   (u32)~SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK,
> >  			   pll_cfg2_init);
> > 
> > @@ -352,6 +358,10 @@ static void sun8i_hdmi_phy_init_h3(struct
> > sun8i_hdmi_phy *phy)> 
> >  			   SUN8I_HDMI_PHY_ANA_CFG3_SCLEN |
> >  			   SUN8I_HDMI_PHY_ANA_CFG3_SDAEN);
> > 
> > +	/* reset PLL clock configuration */
> > +	regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, 0);
> > +	regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG, 0);
> > +
> 
> Ditto,
> 
> > +
> > +		/*
> > +		 * Even though HDMI PHY clock doesn't have enable/disable
> > +		 * handlers, we have to enable it. Otherwise it could happen
> > +		 * that parent PLL is not enabled by clock framework in a
> > +		 * highly unlikely event when parent PLL is used solely for
> > +		 * HDMI PHY clock.
> > +		 */
> > +		clk_prepare_enable(phy->clk_phy);
> 
> The implementation of the clock doesn't really matter in our API
> usage. If we're using a clock, we have to call
> clk_prepare_enable. That's documented everywhere, and mentionning how
> the clock is implemented is an abstraction leakage and it's
> irrelevant. I'd simply remove the comment here.
> 
> And it should be in a separate patch as well.

OK. Should I add Fixes tag, since current code obviously is not by the specs? 
It could still get in 4.17...

Best regards,
Jernej

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

* Re: [PATCH 04/15] dt-bindings: display: sunxi-drm: Add TCON TOP description
  2018-05-21  8:01   ` Maxime Ripard
@ 2018-05-21 15:10     ` Jernej Škrabec
  0 siblings, 0 replies; 46+ messages in thread
From: Jernej Škrabec @ 2018-05-21 15:10 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: wens, robh+dt, mark.rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, linux-sunxi

Hi,

Dne ponedeljek, 21. maj 2018 ob 10:01:47 CEST je Maxime Ripard napisal(a):
> Hi,
> 
> On Sat, May 19, 2018 at 08:31:16PM +0200, Jernej Skrabec wrote:
> > TCON TOP main purpose is to configure whole display pipeline. It
> > determines relationships between mixers and TCONs, selects source TCON
> > for HDMI, muxes LCD and TV encoder GPIO output,
> 
> I'm not sure you mean GPIO here, but rather pin?

Right, I'll fix that.

> 
> > selects TV encoder clock source and contains additional TV TCON and
> > DSI gates.
> > 
> > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > ---
> > 
> >  .../bindings/display/sunxi/sun4i-drm.txt      | 20 +++++++++++++++++++
> >  1 file changed, 20 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> > b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt index
> > 3346c1e2a7a0..a099957ab62a 100644
> > --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> > +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> > 
> > @@ -187,6 +187,26 @@ And on the A23, A31, A31s and A33, you need one more 
clock line:
> >     - 'lvds-alt': An alternative clock source, separate from the TCON
> >     channel 0
> >     
> >                   clock, that can be used to drive the LVDS clock
> > 
> > +TCON TOP
> > +--------
> > +
> > +TCON TOPs main purpose is to configure whole display pipeline. It
> > determines +relationships between mixers and TCONs, selects source TCON
> > for HDMI, muxes +LCD and TV encoder GPIO output, selects TV encoder clock
> > source and contains +additional TV TCON and DSI gates.
> > +
> > +Required properties:
> > +  - compatible: value must be one of:
> > +    * allwinner,sun8i-r40-tcon-top
> > +  - reg: base address and size of the memory-mapped region.
> > +  - clocks: phandle to the clocks feeding the TCON TOP
> > +    * bus: TCON TOP interface clock
> > +  - clock-names: clock name mentioned above
> > +  - resets: phandle to the reset line driving the DRC
> > +    * rst: TCON TOP reset line
> > +  - reset-names: reset name mentioned above
> > +  - #clock-cells : must contain 1
> > +
> 
> I guess you should better describe the OF-graph endpoints, and the
> clocks output. Just using the binding additions here doesn't allow to
> get a clear idea of how the DT should look like.

With my idea of implementation, OF graph is the same as before, so I didn't 
mention anything about it.

My idea of dependencies (you should view it in fixed width font):
         TCON-TOP
            ^
            |
mixer <-> TCON <-> HDMI

I'll explain my design decision as response to other mail.

Best regards,
Jernej

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

* Re: [PATCH 05/15] drm/sun4i: Add TCON TOP driver
  2018-05-21  8:05   ` Maxime Ripard
@ 2018-05-21 15:15     ` Jernej Škrabec
  2018-05-24  8:43       ` Maxime Ripard
  0 siblings, 1 reply; 46+ messages in thread
From: Jernej Škrabec @ 2018-05-21 15:15 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: wens, robh+dt, mark.rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, linux-sunxi

Hi,

Dne ponedeljek, 21. maj 2018 ob 10:05:17 CEST je Maxime Ripard napisal(a):
> On Sat, May 19, 2018 at 08:31:17PM +0200, Jernej Skrabec wrote:
> > As already described in DT binding, TCON TOP is responsible for
> > configuring display pipeline. In this initial driver focus is on HDMI
> > pipeline, so TVE and LCD configuration is not implemented.
> > 
> > Implemented features:
> > - HDMI source selection
> > - clock driver (TCON and DSI gating)
> > - connecting mixers and TCONS
> > 
> > Something similar also existed in previous SoCs, except that it was part
> > of first TCON.
> > 
> > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > ---
> > 
> >  drivers/gpu/drm/sun4i/Makefile             |   3 +-
> >  drivers/gpu/drm/sun4i/sun8i_tcon_top.c     | 256 +++++++++++++++++++++
> >  drivers/gpu/drm/sun4i/sun8i_tcon_top.h     |  20 ++
> >  include/dt-bindings/clock/sun8i-tcon-top.h |  11 +
> >  4 files changed, 289 insertions(+), 1 deletion(-)
> >  create mode 100644 drivers/gpu/drm/sun4i/sun8i_tcon_top.c
> >  create mode 100644 drivers/gpu/drm/sun4i/sun8i_tcon_top.h
> >  create mode 100644 include/dt-bindings/clock/sun8i-tcon-top.h
> > 
> > diff --git a/drivers/gpu/drm/sun4i/Makefile
> > b/drivers/gpu/drm/sun4i/Makefile index 2589f4acd5ae..09fbfd6304ba 100644
> > --- a/drivers/gpu/drm/sun4i/Makefile
> > +++ b/drivers/gpu/drm/sun4i/Makefile
> > @@ -16,7 +16,8 @@ sun8i-drm-hdmi-y		+= sun8i_hdmi_phy_clk.o
> > 
> >  sun8i-mixer-y			+= sun8i_mixer.o sun8i_ui_layer.o \
> >  
> >  				   sun8i_vi_layer.o sun8i_ui_scaler.o \
> > 
> > -				   sun8i_vi_scaler.o sun8i_csc.o
> > +				   sun8i_vi_scaler.o sun8i_csc.o \
> > +				   sun8i_tcon_top.o
> > 
> >  sun4i-tcon-y			+= sun4i_crtc.o
> >  sun4i-tcon-y			+= sun4i_dotclock.o
> > 
> > diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
> > b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c new file mode 100644
> > index 000000000000..075a356a6dfa
> > --- /dev/null
> > +++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
> > @@ -0,0 +1,256 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/* Copyright (c) 2018 Jernej Skrabec <jernej.skrabec@siol.net> */
> > +
> > +#include <drm/drmP.h>
> > +
> > +#include <dt-bindings/clock/sun8i-tcon-top.h>
> > +
> > +#include <linux/bitfield.h>
> > +#include <linux/clk.h>
> > +#include <linux/clk-provider.h>
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/reset.h>
> > +#include <linux/spinlock.h>
> > +
> > +#include "sun8i_tcon_top.h"
> > +
> > +#define TCON_TOP_PORT_SEL_REG		0x1C
> > +#define TCON_TOP_PORT_DE0_MSK			GENMASK(1, 0)
> > +#define TCON_TOP_PORT_DE1_MSK			GENMASK(5, 4)
> > +#define TCON_TOP_PORT_TCON_LCD0			0
> > +#define TCON_TOP_PORT_TCON_LCD1			1
> > +#define TCON_TOP_PORT_TCON_TV0			2
> > +#define TCON_TOP_PORT_TCON_TV1			3
> > +
> > +#define TCON_TOP_GATE_SRC_REG		0x20
> > +#define TCON_TOP_HDMI_SRC_MSK			GENMASK(29, 28)
> > +#define TCON_TOP_HDMI_SRC_NONE			0
> > +#define TCON_TOP_HDMI_SRC_TCON_TV0		1
> > +#define TCON_TOP_HDMI_SRC_TCON_TV1		2
> > +#define TCON_TOP_TCON_TV1_GATE			24
> > +#define TCON_TOP_TCON_TV0_GATE			20
> > +#define TCON_TOP_TCON_DSI_GATE			16
> > +
> > +#define CLK_NUM					3
> > +
> > +struct sun8i_tcon_top {
> > +	struct clk		*bus;
> > +	void __iomem		*regs;
> > +	struct reset_control	*rst;
> > +
> > +	/*
> > +	 * spinlock is used for locking access to registers from different
> > +	 * places - tcon driver and clk subsystem.
> > +	 */
> > +	spinlock_t		reg_lock;
> > +};
> > +
> > +struct sun8i_tcon_top_gate {
> > +	const char	*name;
> > +	u8		bit;
> > +	int		index;
> > +};
> > +
> > +static const struct sun8i_tcon_top_gate gates[] = {
> > +	{"bus-tcon-top-dsi", TCON_TOP_TCON_DSI_GATE, CLK_BUS_TCON_TOP_DSI},
> > +	{"bus-tcon-top-tv0", TCON_TOP_TCON_TV0_GATE, CLK_BUS_TCON_TOP_TV0},
> > +	{"bus-tcon-top-tv1", TCON_TOP_TCON_TV1_GATE, CLK_BUS_TCON_TOP_TV1},
> > +};
> > +
> > +void sun8i_tcon_top_set_hdmi_src(struct sun8i_tcon_top *tcon_top, int
> > tcon) +{
> > +	unsigned long flags;
> > +	u32 val;
> > +
> > +	if (tcon > 1) {
> > +		DRM_ERROR("TCON index is too high!\n");
> > +		return;
> > +	}
> > +
> > +	spin_lock_irqsave(&tcon_top->reg_lock, flags);
> > +
> > +	val = readl(tcon_top->regs + TCON_TOP_GATE_SRC_REG);
> > +	val &= ~TCON_TOP_HDMI_SRC_MSK;
> > +	val |= FIELD_PREP(TCON_TOP_HDMI_SRC_MSK,
> > +			  TCON_TOP_HDMI_SRC_TCON_TV0 + tcon);
> > +	writel(val, tcon_top->regs + TCON_TOP_GATE_SRC_REG);
> > +
> > +	spin_unlock_irqrestore(&tcon_top->reg_lock, flags);
> > +}
> > +
> > +void sun8i_tcon_top_de_config(struct sun8i_tcon_top *tcon_top,
> > +			      int mixer, enum tcon_type tcon_type, int tcon)
> > +{
> > +	unsigned long flags;
> > +	u32 val, reg;
> > +
> > +	if (mixer > 1) {
> > +		DRM_ERROR("Mixer index is too high!\n");
> > +		return;
> > +	}
> > +
> > +	if (tcon > 1) {
> > +		DRM_ERROR("TCON index is too high!\n");
> > +		return;
> > +	}
> > +
> > +	switch (tcon_type) {
> > +	case tcon_type_lcd:
> > +		val = TCON_TOP_PORT_TCON_LCD0 + tcon;
> > +		break;
> > +	case tcon_type_tv:
> > +		val = TCON_TOP_PORT_TCON_TV0 + tcon;
> > +		break;
> > +	default:
> > +		DRM_ERROR("Invalid TCON type!\n");
> > +		return;
> > +	}
> > +
> > +	spin_lock_irqsave(&tcon_top->reg_lock, flags);
> > +
> > +	reg = readl(tcon_top->regs + TCON_TOP_PORT_SEL_REG);
> > +	if (mixer == 0) {
> > +		reg &= ~TCON_TOP_PORT_DE0_MSK;
> > +		reg |= FIELD_PREP(TCON_TOP_PORT_DE0_MSK, val);
> > +	} else {
> > +		reg &= ~TCON_TOP_PORT_DE1_MSK;
> > +		reg |= FIELD_PREP(TCON_TOP_PORT_DE1_MSK, val);
> > +	}
> > +	writel(reg, tcon_top->regs + TCON_TOP_PORT_SEL_REG);
> > +
> > +	spin_unlock_irqrestore(&tcon_top->reg_lock, flags);
> > +}
> > +
> > +static int sun8i_tcon_top_probe(struct platform_device *pdev)
> > +{
> > +	struct clk_hw_onecell_data *clk_data;
> > +	struct sun8i_tcon_top *tcon_top;
> > +	struct device *dev = &pdev->dev;
> > +	struct resource *res;
> > +	int ret, i;
> > +
> > +	tcon_top = devm_kzalloc(dev, sizeof(*tcon_top), GFP_KERNEL);
> > +	if (!tcon_top)
> > +		return -ENOMEM;
> > +
> > +	clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data) +
> > +				sizeof(*clk_data->hws) * CLK_NUM,
> > +				GFP_KERNEL);
> > +	if (!clk_data)
> > +		return -ENOMEM;
> > +
> > +	spin_lock_init(&tcon_top->reg_lock);
> > +
> > +	tcon_top->rst = devm_reset_control_get(dev, "rst");
> > +	if (IS_ERR(tcon_top->rst)) {
> > +		dev_err(dev, "Couldn't get our reset line\n");
> > +		return PTR_ERR(tcon_top->rst);
> > +	}
> > +
> > +	tcon_top->bus = devm_clk_get(dev, "bus");
> > +	if (IS_ERR(tcon_top->bus)) {
> > +		dev_err(dev, "Couldn't get the bus clock\n");
> > +		return PTR_ERR(tcon_top->bus);
> > +	}
> > +
> > +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	tcon_top->regs = devm_ioremap_resource(dev, res);
> > +	if (IS_ERR(tcon_top->regs))
> > +		return PTR_ERR(tcon_top->regs);
> > +
> > +	ret = reset_control_deassert(tcon_top->rst);
> > +	if (ret) {
> > +		dev_err(dev, "Could not deassert ctrl reset control\n");
> > +		return ret;
> > +	}
> > +
> > +	ret = clk_prepare_enable(tcon_top->bus);
> > +	if (ret) {
> > +		dev_err(dev, "Could not enable bus clock\n");
> > +		goto err_assert_reset;
> > +	}
> > +
> > +	/*
> > +	 * Default register values might have some reserved bits set, which
> > +	 * prevents TCON TOP from working properly. Set them to 0 here.
> > +	 */
> > +	writel(0, tcon_top->regs + TCON_TOP_PORT_SEL_REG);
> > +	writel(0, tcon_top->regs + TCON_TOP_GATE_SRC_REG);
> > +
> > +	for (i = 0; i < CLK_NUM; i++) {
> > +		const char *parent_name = "bus-tcon-top";
> 
> I guess retrieving the parent's clock name at runtime would be more
> flexible.
> 

It is, but will it ever be anything else?

> > +		struct clk_init_data init;
> > +		struct clk_gate *gate;
> > +
> > +		gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
> > +		if (!gate) {
> > +			ret = -ENOMEM;
> > +			goto err_disable_clock;
> > +		}
> > +
> > +		init.name = gates[i].name;
> > +		init.ops = &clk_gate_ops;
> > +		init.flags = CLK_IS_BASIC;
> > +		init.parent_names = &parent_name;
> > +		init.num_parents = 1;
> > +
> > +		gate->reg = tcon_top->regs + TCON_TOP_GATE_SRC_REG;
> > +		gate->bit_idx = gates[i].bit;
> > +		gate->lock = &tcon_top->reg_lock;
> > +		gate->hw.init = &init;
> > +
> > +		ret = devm_clk_hw_register(dev, &gate->hw);
> > +		if (ret)
> > +			goto err_disable_clock;
> 
> Isn't it what clk_hw_register_gate is doing?
> 

Almost, but not exactly. My goal was to use devm_* functions, so there is no 
need to do any special cleanup.

> > +		clk_data->hws[gates[i].index] = &gate->hw;
> > +	}
> > +
> > +	clk_data->num = CLK_NUM;
> > +
> > +	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, 
clk_data);
> > +	if (ret)
> > +		goto err_disable_clock;
> > +
> > +	platform_set_drvdata(pdev, tcon_top);
> > +
> > +	return 0;
> > +
> > +err_disable_clock:
> > +	clk_disable_unprepare(tcon_top->bus);
> > +err_assert_reset:
> > +	reset_control_assert(tcon_top->rst);
> > +
> > +	return ret;
> > +}
> > +
> > +static int sun8i_tcon_top_remove(struct platform_device *pdev)
> > +{
> > +	struct sun8i_tcon_top *tcon_top = platform_get_drvdata(pdev);
> > +
> > +	clk_disable_unprepare(tcon_top->bus);
> > +	reset_control_assert(tcon_top->rst);
> > +
> > +	return 0;
> > +}
> > +
> > +const struct of_device_id sun8i_tcon_top_of_table[] = {
> > +	{ .compatible = "allwinner,sun8i-r40-tcon-top" },
> > +	{ /* sentinel */ }
> > +};
> > +MODULE_DEVICE_TABLE(of, sun8i_tcon_top_of_table);
> > +
> > +static struct platform_driver sun8i_tcon_top_platform_driver = {
> > +	.probe		= sun8i_tcon_top_probe,
> > +	.remove		= sun8i_tcon_top_remove,
> > +	.driver		= {
> > +		.name		= "sun8i-tcon-top",
> > +		.of_match_table	= sun8i_tcon_top_of_table,
> > +	},
> > +};
> > +module_platform_driver(sun8i_tcon_top_platform_driver);
> > +
> > +MODULE_AUTHOR("Jernej Skrabec <jernej.skrabec@siol.net>");
> > +MODULE_DESCRIPTION("Allwinner R40 TCON TOP driver");
> > +MODULE_LICENSE("GPL");
> > diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.h
> > b/drivers/gpu/drm/sun4i/sun8i_tcon_top.h new file mode 100644
> > index 000000000000..19126e07d2a6
> > --- /dev/null
> > +++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.h
> > @@ -0,0 +1,20 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/* Copyright (c) 2018 Jernej Skrabec <jernej.skrabec@siol.net> */
> > +
> > +#ifndef _SUN8I_TCON_TOP_H_
> > +#define _SUN8I_TCON_TOP_H_
> > +
> > +#include <linux/device.h>
> > +
> > +struct sun8i_tcon_top;
> > +
> > +enum tcon_type {
> > +	tcon_type_lcd,
> > +	tcon_type_tv,
> 
> The usual practice is to have the enum values upper-case.

Ok.

Best regards,
Jernej

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

* Re: [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top
  2018-05-21  8:07   ` Maxime Ripard
@ 2018-05-21 17:27     ` Jernej Škrabec
  2018-05-24  8:50       ` Maxime Ripard
  0 siblings, 1 reply; 46+ messages in thread
From: Jernej Škrabec @ 2018-05-21 17:27 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: wens, robh+dt, mark.rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, linux-sunxi

Hi,

Dne ponedeljek, 21. maj 2018 ob 10:07:59 CEST je Maxime Ripard napisal(a):
> On Sat, May 19, 2018 at 08:31:18PM +0200, Jernej Skrabec wrote:
> > If SoC has TCON TOP unit, it has to be configured from TCON, since it
> > has all information needed. Additionally, if it is TCON TV, it must also
> > enable bus gate inside TCON TOP unit.
> 
> Why?

I'll explain my design decision below.

> 
> > Add support for such TCONs.
> > 
> > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > ---
> > 
> >  drivers/gpu/drm/sun4i/sun4i_tcon.c | 28 ++++++++++++++++++++++++++++
> >  drivers/gpu/drm/sun4i/sun4i_tcon.h |  8 ++++++++
> >  2 files changed, 36 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 08747fc3ee71..e0c562ce1c22
> > 100644
> > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > @@ -688,6 +688,16 @@ static int sun4i_tcon_init_clocks(struct device *dev,
> > 
> >  		dev_err(dev, "Couldn't get the TCON bus clock\n");
> >  		return PTR_ERR(tcon->clk);
> >  	
> >  	}
> > 
> > +
> > +	if (tcon->quirks->needs_tcon_top && tcon->quirks->has_channel_1) {
> > +		tcon->top_clk = devm_clk_get(dev, "tcon-top");
> > +		if (IS_ERR(tcon->top_clk)) {
> > +			dev_err(dev, "Couldn't get the TCON TOP bus clock\n");
> > +			return PTR_ERR(tcon->top_clk);
> > +		}
> > +		clk_prepare_enable(tcon->top_clk);
> > +	}
> > +
> > 
> >  	clk_prepare_enable(tcon->clk);
> >  	
> >  	if (tcon->quirks->has_channel_0) {
> > 
> > @@ -712,6 +722,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
> > 
> >  static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
> >  {
> >  
> >  	clk_disable_unprepare(tcon->clk);
> > 
> > +	clk_disable_unprepare(tcon->top_clk);
> > 
> >  }
> >  
> >  static int sun4i_tcon_init_irq(struct device *dev,
> > 
> > @@ -980,6 +991,23 @@ static int sun4i_tcon_bind(struct device *dev, struct
> > device *master,> 
> >  	tcon->id = engine->id;
> >  	tcon->quirks = of_device_get_match_data(dev);
> > 
> > +	if (tcon->quirks->needs_tcon_top) {
> > +		struct device_node *np;
> > +
> > +		np = of_parse_phandle(dev->of_node, "allwinner,tcon-top", 0);
> > +		if (np) {
> > +			struct platform_device *pdev;
> > +
> > +			pdev = of_find_device_by_node(np);
> > +			if (pdev)
> > +				tcon->tcon_top = platform_get_drvdata(pdev);
> > +			of_node_put(np);
> > +
> > +			if (!tcon->tcon_top)
> > +				return -EPROBE_DEFER;
> > +		}
> > +	}
> > +
> 
> I might have missed it, but I've not seen the bindings additions for
> that property. This shouldn't really be done that way anyway, instead
> of using a direct phandle, you should be using the of-graph, with the
> TCON-top sitting where it belongs in the flow of data.

Just to answer to the first question, it did describe it in "[PATCH 07/15] dt-
bindings: display: sun4i-drm: Add R40 HDMI pipeline".

As why I designed it that way - HW representation could be described that way 
(ASCII art makes sense when fixed width font is used to view it):

                            / LCD0/LVDS0
                / TCON-LCD0
                |           \ MIPI DSI
mixer0          |
       \        / TCON-LCD1 - LCD1/LVDS1
        TCON-TOP
       /        \ TCON-TV0 - TVE0/RGB
mixer1          |          \
                |           TCON-TOP - HDMI
                |          /
                \ TCON-TV1 - TVE1/RGB

This is a bit simplified, since there is also TVE-TOP, which is responsible 
for sharing 4 DACs between both TVE encoders. You can have two TV outs (PAL/
NTSC) or TVE0 as TV out and TVE1 as RGB or vice versa. It even seems that you 
can arbitrarly choose which DAC is responsible for which signal, so there is a 
ton of possible end combinations, but I'm not 100% sure.

Even though I wrote TCON-TOP twice, this is same unit in HW. R40 manual 
suggest more possibilities, although some of them seem wrong, like RGB feeding 
from LCD TCON. That is confirmed to be wrong when checking BSP code. 

Additionally, TCON-TOP comes in the middle of TVE0 and LCD0, TVE1 and LCD1 for 
pin muxing, although I'm not sure why is that needed at all, since according 
to R40 datasheet, TVE0 and TVE1 pins are dedicated and not on PORT D and PORT 
H, respectively, as TCON-TOP documentation suggest. However, HSYNC and PSYNC 
lines might be shared between TVE (when it works in RGB mode) and LCD. But 
that is just my guess since I'm not really familiar with RGB and LCD 
interfaces.

I'm really not sure what would be the best representation in OF-graph. Can you 
suggest one?

On the other hand, mux callback in TCON driver has all available informations 
at hand. It knows mixer ID, TCON ID and most importantly, encoder type. Based 
on all that informations, it's easy to configure TCON TOP.

I hope you understand. If you have better idea, I'm all ears, since phandle 
seems a bit weird to me too, but I think it's the only future proof, when 
adding LVDS, RGB, TVE or LCD support.

Best regards,
Jernej

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

* Re: [PATCH 05/15] drm/sun4i: Add TCON TOP driver
  2018-05-19 18:31 ` [PATCH 05/15] drm/sun4i: Add TCON TOP driver Jernej Skrabec
  2018-05-21  8:05   ` Maxime Ripard
@ 2018-05-22  2:25   ` kbuild test robot
  2018-05-23 18:23   ` Rob Herring
  2 siblings, 0 replies; 46+ messages in thread
From: kbuild test robot @ 2018-05-22  2:25 UTC (permalink / raw)
  To: Jernej Skrabec
  Cc: kbuild-all, maxime.ripard, wens, robh+dt, mark.rutland,
	dri-devel, devicetree, linux-arm-kernel, linux-kernel, linux-clk,
	linux-sunxi

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

Hi Jernej,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm/drm-next]
[also build test ERROR on v4.17-rc6 next-20180517]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Jernej-Skrabec/Add-support-for-R40-HDMI-pipeline/20180521-131839
base:   git://people.freedesktop.org/~airlied/linux.git drm-next
config: arm-multi_v7_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   drivers/gpu/drm/sun4i/sun8i_tcon_top.o: In function `init_module':
>> sun8i_tcon_top.c:(.init.text+0x0): multiple definition of `init_module'
   drivers/gpu/drm/sun4i/sun8i_mixer.o:sun8i_mixer.c:(.init.text+0x0): first defined here
   drivers/gpu/drm/sun4i/sun8i_tcon_top.o: In function `cleanup_module':
>> sun8i_tcon_top.c:(.exit.text+0x0): multiple definition of `cleanup_module'
   drivers/gpu/drm/sun4i/sun8i_mixer.o:sun8i_mixer.c:(.exit.text+0x0): first defined here

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 43346 bytes --]

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

* Re: [PATCH 03/15] clk: sunxi-ng: r40: Export video PLLs
  2018-05-19 18:31 ` [PATCH 03/15] clk: sunxi-ng: r40: Export video PLLs Jernej Skrabec
@ 2018-05-23 18:20   ` Rob Herring
  0 siblings, 0 replies; 46+ messages in thread
From: Rob Herring @ 2018-05-23 18:20 UTC (permalink / raw)
  To: Jernej Skrabec
  Cc: maxime.ripard, wens, mark.rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, linux-sunxi

On Sat, May 19, 2018 at 08:31:15PM +0200, Jernej Skrabec wrote:
> Video PLLs need to be referenced in R40 DT as possible HDMI PHY parent.
> 
> Export them.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  drivers/clk/sunxi-ng/ccu-sun8i-r40.h      | 8 ++++++--
>  include/dt-bindings/clock/sun8i-r40-ccu.h | 4 ++++
>  2 files changed, 10 insertions(+), 2 deletions(-)

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

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

* Re: [PATCH 05/15] drm/sun4i: Add TCON TOP driver
  2018-05-19 18:31 ` [PATCH 05/15] drm/sun4i: Add TCON TOP driver Jernej Skrabec
  2018-05-21  8:05   ` Maxime Ripard
  2018-05-22  2:25   ` kbuild test robot
@ 2018-05-23 18:23   ` Rob Herring
  2 siblings, 0 replies; 46+ messages in thread
From: Rob Herring @ 2018-05-23 18:23 UTC (permalink / raw)
  To: Jernej Skrabec
  Cc: maxime.ripard, wens, mark.rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, linux-sunxi

On Sat, May 19, 2018 at 08:31:17PM +0200, Jernej Skrabec wrote:
> As already described in DT binding, TCON TOP is responsible for
> configuring display pipeline. In this initial driver focus is on HDMI
> pipeline, so TVE and LCD configuration is not implemented.
> 
> Implemented features:
> - HDMI source selection
> - clock driver (TCON and DSI gating)
> - connecting mixers and TCONS
> 
> Something similar also existed in previous SoCs, except that it was part
> of first TCON.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
>  drivers/gpu/drm/sun4i/Makefile             |   3 +-
>  drivers/gpu/drm/sun4i/sun8i_tcon_top.c     | 256 +++++++++++++++++++++
>  drivers/gpu/drm/sun4i/sun8i_tcon_top.h     |  20 ++
>  include/dt-bindings/clock/sun8i-tcon-top.h |  11 +

This belongs with the binding doc patch.

>  4 files changed, 289 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_tcon_top.c
>  create mode 100644 drivers/gpu/drm/sun4i/sun8i_tcon_top.h
>  create mode 100644 include/dt-bindings/clock/sun8i-tcon-top.h

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

* Re: [linux-sunxi] Re: [PATCH 12/15] drm/sun4i: Add support for second clock parent to DW HDMI PHY clk driver
  2018-05-21 15:02     ` [linux-sunxi] " Jernej Škrabec
@ 2018-05-24  8:27       ` Maxime Ripard
  0 siblings, 0 replies; 46+ messages in thread
From: Maxime Ripard @ 2018-05-24  8:27 UTC (permalink / raw)
  To: Jernej Škrabec
  Cc: linux-sunxi, wens, robh+dt, mark.rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk

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

On Mon, May 21, 2018 at 05:02:23PM +0200, Jernej Škrabec wrote:
> Hi,
> 
> Dne ponedeljek, 21. maj 2018 ob 10:12:53 CEST je Maxime Ripard napisal(a):
> > On Sat, May 19, 2018 at 08:31:24PM +0200, Jernej Skrabec wrote:
> > > Expand HDMI PHY clock driver to support second clock parent.
> > > 
> > > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > > ---
> > > 
> > >  drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h      |  6 +-
> > >  drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c     | 29 ++++++-
> > >  drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c | 90 ++++++++++++++++------
> > >  3 files changed, 98 insertions(+), 27 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> > > b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h index 801a17222762..aadbe0a10b0c
> > > 100644
> > > --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> > > +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
> > > @@ -98,7 +98,8 @@
> > > 
> > >  #define SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN		BIT(29)
> > >  #define SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN		BIT(28)
> > >  #define SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33	BIT(27)
> > > 
> > > -#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL	BIT(26)
> > > +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK	BIT(26)
> > > +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT	26
> > > 
> > >  #define SUN8I_HDMI_PHY_PLL_CFG1_PLLEN		BIT(25)
> > >  #define SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(x)	((x) << 22)
> > >  #define SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(x)	((x) << 20)
> > > 
> > > @@ -190,6 +191,7 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi
> > > *hdmi);
> > > 
> > >  void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
> > >  const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void);
> > > 
> > > -int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev);
> > > +int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev,
> > > +			 bool second_parent);
> > > 
> > >  #endif /* _SUN8I_DW_HDMI_H_ */
> > > 
> > > diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> > > b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c index deba47ed69d8..7a911f0a3ae3
> > > 100644
> > > --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> > > +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
> > > @@ -183,7 +183,13 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi
> > > *hdmi,> 
> > >  	regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG,
> > >  	
> > >  			   SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK, 0);
> > > 
> > > -	regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, pll_cfg1_init);
> > > +	/*
> > > +	 * NOTE: We have to be careful not to overwrite PHY parent
> > > +	 * clock selection bit and clock divider.
> > > +	 */
> > > +	regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG,
> > > +			   ~SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK,
> > > +			   pll_cfg1_init);
> > 
> > It feels like it belongs in a separate patch.
> 
> Why? clk_set_rate() on HDMI PHY clock is called before this function, so 
> SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL bit is already set to correct value. Original 
> code doesn't take this into account and sets it to 0 here in all cases, which 
> obviously is not right.
> 
> If you insist on splitting this in new patch, it has to be applied before 
> clock changes. It would also need to include "reset PLL clock configuration" 
> chunk (next change in this patch), otherwise other SoCs with only one parent 
> could get 1 there, which is obviously wrong. Note that I didn't really tested 
> if default value of this bit is 0 or 1, but I wouldn't really like to depend 
> on default values.

I don't have a strong feeling about this, but to me, the fact that you
don't want to overwrite the muxing bit because the clock might use it
is sensible in itself, disregarding the fact that the clock *will* use
it.

> 
> > 
> > >  	regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG,
> > >  	
> > >  			   (u32)~SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK,
> > >  			   pll_cfg2_init);
> > > 
> > > @@ -352,6 +358,10 @@ static void sun8i_hdmi_phy_init_h3(struct
> > > sun8i_hdmi_phy *phy)> 
> > >  			   SUN8I_HDMI_PHY_ANA_CFG3_SCLEN |
> > >  			   SUN8I_HDMI_PHY_ANA_CFG3_SDAEN);
> > > 
> > > +	/* reset PLL clock configuration */
> > > +	regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, 0);
> > > +	regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG, 0);
> > > +
> > 
> > Ditto,
> > 
> > > +
> > > +		/*
> > > +		 * Even though HDMI PHY clock doesn't have enable/disable
> > > +		 * handlers, we have to enable it. Otherwise it could happen
> > > +		 * that parent PLL is not enabled by clock framework in a
> > > +		 * highly unlikely event when parent PLL is used solely for
> > > +		 * HDMI PHY clock.
> > > +		 */
> > > +		clk_prepare_enable(phy->clk_phy);
> > 
> > The implementation of the clock doesn't really matter in our API
> > usage. If we're using a clock, we have to call
> > clk_prepare_enable. That's documented everywhere, and mentionning how
> > the clock is implemented is an abstraction leakage and it's
> > irrelevant. I'd simply remove the comment here.
> > 
> > And it should be in a separate patch as well.
> 
> OK. Should I add Fixes tag, since current code obviously is not by the specs? 
> It could still get in 4.17...

Yep!

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

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

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

* Re: [PATCH 05/15] drm/sun4i: Add TCON TOP driver
  2018-05-21 15:15     ` Jernej Škrabec
@ 2018-05-24  8:43       ` Maxime Ripard
  2018-05-24 20:33         ` [linux-sunxi] " Jernej Škrabec
  0 siblings, 1 reply; 46+ messages in thread
From: Maxime Ripard @ 2018-05-24  8:43 UTC (permalink / raw)
  To: Jernej Škrabec
  Cc: wens, robh+dt, mark.rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, linux-sunxi

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

Hi,

On Mon, May 21, 2018 at 05:15:15PM +0200, Jernej Škrabec wrote:
> > > +	/*
> > > +	 * Default register values might have some reserved bits set, which
> > > +	 * prevents TCON TOP from working properly. Set them to 0 here.
> > > +	 */
> > > +	writel(0, tcon_top->regs + TCON_TOP_PORT_SEL_REG);
> > > +	writel(0, tcon_top->regs + TCON_TOP_GATE_SRC_REG);
> > > +
> > > +	for (i = 0; i < CLK_NUM; i++) {
> > > +		const char *parent_name = "bus-tcon-top";
> > 
> > I guess retrieving the parent's clock name at runtime would be more
> > flexible.
> 
> It is, but will it ever be anything else?

Probably not, but when the complexity is exactly the same (using
__clk_get_name), we'd better use the more appropriate solution. If we
ever need to change that clock name, or to use the driver with an SoC
that wouldn't have the same clock name for whatever reason, it will
just work.

> > > +		struct clk_init_data init;
> > > +		struct clk_gate *gate;
> > > +
> > > +		gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
> > > +		if (!gate) {
> > > +			ret = -ENOMEM;
> > > +			goto err_disable_clock;
> > > +		}
> > > +
> > > +		init.name = gates[i].name;
> > > +		init.ops = &clk_gate_ops;
> > > +		init.flags = CLK_IS_BASIC;
> > > +		init.parent_names = &parent_name;
> > > +		init.num_parents = 1;
> > > +
> > > +		gate->reg = tcon_top->regs + TCON_TOP_GATE_SRC_REG;
> > > +		gate->bit_idx = gates[i].bit;
> > > +		gate->lock = &tcon_top->reg_lock;
> > > +		gate->hw.init = &init;
> > > +
> > > +		ret = devm_clk_hw_register(dev, &gate->hw);
> > > +		if (ret)
> > > +			goto err_disable_clock;
> > 
> > Isn't it what clk_hw_register_gate is doing?
> 
> Almost, but not exactly. My goal was to use devm_* functions, so there is no 
> need to do any special cleanup.

Is it the only difference? If so, you can just create a
devm_clk_hw_register gate.

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

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

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

* Re: [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top
  2018-05-21 17:27     ` Jernej Škrabec
@ 2018-05-24  8:50       ` Maxime Ripard
  2018-05-24 22:01         ` Chen-Yu Tsai
  0 siblings, 1 reply; 46+ messages in thread
From: Maxime Ripard @ 2018-05-24  8:50 UTC (permalink / raw)
  To: Jernej Škrabec
  Cc: wens, robh+dt, mark.rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, linux-sunxi

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

On Mon, May 21, 2018 at 07:27:46PM +0200, Jernej Škrabec wrote:
> Hi,
> 
> Dne ponedeljek, 21. maj 2018 ob 10:07:59 CEST je Maxime Ripard napisal(a):
> > On Sat, May 19, 2018 at 08:31:18PM +0200, Jernej Skrabec wrote:
> > > If SoC has TCON TOP unit, it has to be configured from TCON, since it
> > > has all information needed. Additionally, if it is TCON TV, it must also
> > > enable bus gate inside TCON TOP unit.
> > 
> > Why?
> 
> I'll explain my design decision below.
> 
> > 
> > > Add support for such TCONs.
> > > 
> > > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > > ---
> > > 
> > >  drivers/gpu/drm/sun4i/sun4i_tcon.c | 28 ++++++++++++++++++++++++++++
> > >  drivers/gpu/drm/sun4i/sun4i_tcon.h |  8 ++++++++
> > >  2 files changed, 36 insertions(+)
> > > 
> > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 08747fc3ee71..e0c562ce1c22
> > > 100644
> > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > @@ -688,6 +688,16 @@ static int sun4i_tcon_init_clocks(struct device *dev,
> > > 
> > >  		dev_err(dev, "Couldn't get the TCON bus clock\n");
> > >  		return PTR_ERR(tcon->clk);
> > >  	
> > >  	}
> > > 
> > > +
> > > +	if (tcon->quirks->needs_tcon_top && tcon->quirks->has_channel_1) {
> > > +		tcon->top_clk = devm_clk_get(dev, "tcon-top");
> > > +		if (IS_ERR(tcon->top_clk)) {
> > > +			dev_err(dev, "Couldn't get the TCON TOP bus clock\n");
> > > +			return PTR_ERR(tcon->top_clk);
> > > +		}
> > > +		clk_prepare_enable(tcon->top_clk);
> > > +	}
> > > +
> > > 
> > >  	clk_prepare_enable(tcon->clk);
> > >  	
> > >  	if (tcon->quirks->has_channel_0) {
> > > 
> > > @@ -712,6 +722,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
> > > 
> > >  static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
> > >  {
> > >  
> > >  	clk_disable_unprepare(tcon->clk);
> > > 
> > > +	clk_disable_unprepare(tcon->top_clk);
> > > 
> > >  }
> > >  
> > >  static int sun4i_tcon_init_irq(struct device *dev,
> > > 
> > > @@ -980,6 +991,23 @@ static int sun4i_tcon_bind(struct device *dev, struct
> > > device *master,> 
> > >  	tcon->id = engine->id;
> > >  	tcon->quirks = of_device_get_match_data(dev);
> > > 
> > > +	if (tcon->quirks->needs_tcon_top) {
> > > +		struct device_node *np;
> > > +
> > > +		np = of_parse_phandle(dev->of_node, "allwinner,tcon-top", 0);
> > > +		if (np) {
> > > +			struct platform_device *pdev;
> > > +
> > > +			pdev = of_find_device_by_node(np);
> > > +			if (pdev)
> > > +				tcon->tcon_top = platform_get_drvdata(pdev);
> > > +			of_node_put(np);
> > > +
> > > +			if (!tcon->tcon_top)
> > > +				return -EPROBE_DEFER;
> > > +		}
> > > +	}
> > > +
> > 
> > I might have missed it, but I've not seen the bindings additions for
> > that property. This shouldn't really be done that way anyway, instead
> > of using a direct phandle, you should be using the of-graph, with the
> > TCON-top sitting where it belongs in the flow of data.
> 
> Just to answer to the first question, it did describe it in "[PATCH 07/15] dt-
> bindings: display: sun4i-drm: Add R40 HDMI pipeline".
> 
> As why I designed it that way - HW representation could be described that way 
> (ASCII art makes sense when fixed width font is used to view it):
> 
>                             / LCD0/LVDS0
>                 / TCON-LCD0
>                 |           \ MIPI DSI
> mixer0          |
>        \        / TCON-LCD1 - LCD1/LVDS1
>         TCON-TOP
>        /        \ TCON-TV0 - TVE0/RGB
> mixer1          |          \
>                 |           TCON-TOP - HDMI
>                 |          /
>                 \ TCON-TV1 - TVE1/RGB
> 
> This is a bit simplified, since there is also TVE-TOP, which is responsible 
> for sharing 4 DACs between both TVE encoders. You can have two TV outs (PAL/
> NTSC) or TVE0 as TV out and TVE1 as RGB or vice versa. It even seems that you 
> can arbitrarly choose which DAC is responsible for which signal, so there is a 
> ton of possible end combinations, but I'm not 100% sure.
> 
> Even though I wrote TCON-TOP twice, this is same unit in HW. R40 manual 
> suggest more possibilities, although some of them seem wrong, like RGB feeding 
> from LCD TCON. That is confirmed to be wrong when checking BSP code. 
> 
> Additionally, TCON-TOP comes in the middle of TVE0 and LCD0, TVE1 and LCD1 for 
> pin muxing, although I'm not sure why is that needed at all, since according 
> to R40 datasheet, TVE0 and TVE1 pins are dedicated and not on PORT D and PORT 
> H, respectively, as TCON-TOP documentation suggest. However, HSYNC and PSYNC 
> lines might be shared between TVE (when it works in RGB mode) and LCD. But 
> that is just my guess since I'm not really familiar with RGB and LCD 
> interfaces.
> 
> I'm really not sure what would be the best representation in OF-graph. Can you 
> suggest one?

Rob might disagree on this one, but I don't see anything wrong with
having loops in the graph. If the TCON-TOP can be both the input and
output of the TCONs, then so be it, and have it described that way in
the graph.

The code is already able to filter out nodes that have already been
added to the list of devices we need to wait for in the component
framework, so that should work as well.

And we'd need to describe TVE-TOP as well, even though we don't have a
driver for it yet. That will simplify the backward compatibility later
on.

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

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

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

* Re: [linux-sunxi] Re: [PATCH 05/15] drm/sun4i: Add TCON TOP driver
  2018-05-24  8:43       ` Maxime Ripard
@ 2018-05-24 20:33         ` Jernej Škrabec
  0 siblings, 0 replies; 46+ messages in thread
From: Jernej Škrabec @ 2018-05-24 20:33 UTC (permalink / raw)
  To: linux-sunxi, maxime.ripard
  Cc: wens, robh+dt, mark.rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk

Hi,

Dne četrtek, 24. maj 2018 ob 10:43:51 CEST je Maxime Ripard napisal(a):
> Hi,
> 
> On Mon, May 21, 2018 at 05:15:15PM +0200, Jernej Škrabec wrote:
> > > > +	/*
> > > > +	 * Default register values might have some reserved bits set, 
which
> > > > +	 * prevents TCON TOP from working properly. Set them to 0 here.
> > > > +	 */
> > > > +	writel(0, tcon_top->regs + TCON_TOP_PORT_SEL_REG);
> > > > +	writel(0, tcon_top->regs + TCON_TOP_GATE_SRC_REG);
> > > > +
> > > > +	for (i = 0; i < CLK_NUM; i++) {
> > > > +		const char *parent_name = "bus-tcon-top";
> > > 
> > > I guess retrieving the parent's clock name at runtime would be more
> > > flexible.
> > 
> > It is, but will it ever be anything else?
> 
> Probably not, but when the complexity is exactly the same (using
> __clk_get_name), we'd better use the more appropriate solution. If we
> ever need to change that clock name, or to use the driver with an SoC
> that wouldn't have the same clock name for whatever reason, it will
> just work.
> 
> > > > +		struct clk_init_data init;
> > > > +		struct clk_gate *gate;
> > > > +
> > > > +		gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL);
> > > > +		if (!gate) {
> > > > +			ret = -ENOMEM;
> > > > +			goto err_disable_clock;
> > > > +		}
> > > > +
> > > > +		init.name = gates[i].name;
> > > > +		init.ops = &clk_gate_ops;
> > > > +		init.flags = CLK_IS_BASIC;
> > > > +		init.parent_names = &parent_name;
> > > > +		init.num_parents = 1;
> > > > +
> > > > +		gate->reg = tcon_top->regs + TCON_TOP_GATE_SRC_REG;
> > > > +		gate->bit_idx = gates[i].bit;
> > > > +		gate->lock = &tcon_top->reg_lock;
> > > > +		gate->hw.init = &init;
> > > > +
> > > > +		ret = devm_clk_hw_register(dev, &gate->hw);
> > > > +		if (ret)
> > > > +			goto err_disable_clock;
> > > 
> > > Isn't it what clk_hw_register_gate is doing?
> > 
> > Almost, but not exactly. My goal was to use devm_* functions, so there is
> > no need to do any special cleanup.
> 
> Is it the only difference? If so, you can just create a
> devm_clk_hw_register gate.

I checked around and it seems that in clk core there are only non devm_* 
helpers like clk_hw_register_gate() for some reason. I guess I'll just use 
that and manually unregister all the clocks in cleanup function.

Best regards,
Jernej

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

* Re: [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top
  2018-05-24  8:50       ` Maxime Ripard
@ 2018-05-24 22:01         ` Chen-Yu Tsai
  2018-05-31  9:21           ` Maxime Ripard
  0 siblings, 1 reply; 46+ messages in thread
From: Chen-Yu Tsai @ 2018-05-24 22:01 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Jernej Škrabec, Rob Herring, Mark Rutland, dri-devel,
	devicetree, linux-arm-kernel, linux-kernel, linux-clk,
	linux-sunxi

On Thu, May 24, 2018 at 1:50 AM, Maxime Ripard
<maxime.ripard@bootlin.com> wrote:
> On Mon, May 21, 2018 at 07:27:46PM +0200, Jernej Škrabec wrote:
>> Hi,
>>
>> Dne ponedeljek, 21. maj 2018 ob 10:07:59 CEST je Maxime Ripard napisal(a):
>> > On Sat, May 19, 2018 at 08:31:18PM +0200, Jernej Skrabec wrote:
>> > > If SoC has TCON TOP unit, it has to be configured from TCON, since it
>> > > has all information needed. Additionally, if it is TCON TV, it must also
>> > > enable bus gate inside TCON TOP unit.
>> >
>> > Why?
>>
>> I'll explain my design decision below.
>>
>> >
>> > > Add support for such TCONs.
>> > >
>> > > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
>> > > ---
>> > >
>> > >  drivers/gpu/drm/sun4i/sun4i_tcon.c | 28 ++++++++++++++++++++++++++++
>> > >  drivers/gpu/drm/sun4i/sun4i_tcon.h |  8 ++++++++
>> > >  2 files changed, 36 insertions(+)
>> > >
>> > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
>> > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 08747fc3ee71..e0c562ce1c22
>> > > 100644
>> > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
>> > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
>> > > @@ -688,6 +688,16 @@ static int sun4i_tcon_init_clocks(struct device *dev,
>> > >
>> > >           dev_err(dev, "Couldn't get the TCON bus clock\n");
>> > >           return PTR_ERR(tcon->clk);
>> > >
>> > >   }
>> > >
>> > > +
>> > > + if (tcon->quirks->needs_tcon_top && tcon->quirks->has_channel_1) {
>> > > +         tcon->top_clk = devm_clk_get(dev, "tcon-top");
>> > > +         if (IS_ERR(tcon->top_clk)) {
>> > > +                 dev_err(dev, "Couldn't get the TCON TOP bus clock\n");
>> > > +                 return PTR_ERR(tcon->top_clk);
>> > > +         }
>> > > +         clk_prepare_enable(tcon->top_clk);
>> > > + }
>> > > +
>> > >
>> > >   clk_prepare_enable(tcon->clk);
>> > >
>> > >   if (tcon->quirks->has_channel_0) {
>> > >
>> > > @@ -712,6 +722,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
>> > >
>> > >  static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
>> > >  {
>> > >
>> > >   clk_disable_unprepare(tcon->clk);
>> > >
>> > > + clk_disable_unprepare(tcon->top_clk);
>> > >
>> > >  }
>> > >
>> > >  static int sun4i_tcon_init_irq(struct device *dev,
>> > >
>> > > @@ -980,6 +991,23 @@ static int sun4i_tcon_bind(struct device *dev, struct
>> > > device *master,>
>> > >   tcon->id = engine->id;
>> > >   tcon->quirks = of_device_get_match_data(dev);
>> > >
>> > > + if (tcon->quirks->needs_tcon_top) {
>> > > +         struct device_node *np;
>> > > +
>> > > +         np = of_parse_phandle(dev->of_node, "allwinner,tcon-top", 0);
>> > > +         if (np) {
>> > > +                 struct platform_device *pdev;
>> > > +
>> > > +                 pdev = of_find_device_by_node(np);
>> > > +                 if (pdev)
>> > > +                         tcon->tcon_top = platform_get_drvdata(pdev);
>> > > +                 of_node_put(np);
>> > > +
>> > > +                 if (!tcon->tcon_top)
>> > > +                         return -EPROBE_DEFER;
>> > > +         }
>> > > + }
>> > > +
>> >
>> > I might have missed it, but I've not seen the bindings additions for
>> > that property. This shouldn't really be done that way anyway, instead
>> > of using a direct phandle, you should be using the of-graph, with the
>> > TCON-top sitting where it belongs in the flow of data.
>>
>> Just to answer to the first question, it did describe it in "[PATCH 07/15] dt-
>> bindings: display: sun4i-drm: Add R40 HDMI pipeline".
>>
>> As why I designed it that way - HW representation could be described that way
>> (ASCII art makes sense when fixed width font is used to view it):
>>
>>                             / LCD0/LVDS0
>>                 / TCON-LCD0
>>                 |           \ MIPI DSI
>> mixer0          |
>>        \        / TCON-LCD1 - LCD1/LVDS1
>>         TCON-TOP
>>        /        \ TCON-TV0 - TVE0/RGB
>> mixer1          |          \
>>                 |           TCON-TOP - HDMI
>>                 |          /
>>                 \ TCON-TV1 - TVE1/RGB
>>
>> This is a bit simplified, since there is also TVE-TOP, which is responsible
>> for sharing 4 DACs between both TVE encoders. You can have two TV outs (PAL/
>> NTSC) or TVE0 as TV out and TVE1 as RGB or vice versa. It even seems that you
>> can arbitrarly choose which DAC is responsible for which signal, so there is a
>> ton of possible end combinations, but I'm not 100% sure.
>>
>> Even though I wrote TCON-TOP twice, this is same unit in HW. R40 manual
>> suggest more possibilities, although some of them seem wrong, like RGB feeding
>> from LCD TCON. That is confirmed to be wrong when checking BSP code.
>>
>> Additionally, TCON-TOP comes in the middle of TVE0 and LCD0, TVE1 and LCD1 for
>> pin muxing, although I'm not sure why is that needed at all, since according
>> to R40 datasheet, TVE0 and TVE1 pins are dedicated and not on PORT D and PORT
>> H, respectively, as TCON-TOP documentation suggest. However, HSYNC and PSYNC
>> lines might be shared between TVE (when it works in RGB mode) and LCD. But
>> that is just my guess since I'm not really familiar with RGB and LCD
>> interfaces.
>>
>> I'm really not sure what would be the best representation in OF-graph. Can you
>> suggest one?
>
> Rob might disagree on this one, but I don't see anything wrong with
> having loops in the graph. If the TCON-TOP can be both the input and
> output of the TCONs, then so be it, and have it described that way in
> the graph.
>
> The code is already able to filter out nodes that have already been
> added to the list of devices we need to wait for in the component
> framework, so that should work as well.
>
> And we'd need to describe TVE-TOP as well, even though we don't have a
> driver for it yet. That will simplify the backward compatibility later
> on.

I'm getting the feeling that TCON-TOP / TVE-TOP is the glue layer that
binds everything together, and provides signal routing, kind of like
DE-TOP on A64. So the signal mux controls that were originally found
in TCON0 and TVE0 were moved out.

The driver needs to know about that, but the graph about doesn't make
much sense directly. Without looking at the manual, I understand it to
likely be one mux between the mixers and TCONs, and one between the
TCON-TVs and HDMI. Would it make more sense to just have the graph
connections between the muxed components, and remove TCON-TOP from
it, like we had in the past? A phandle could be used to reference
the TCON-TOP for mux controls, in addition to the clocks and resets.

For TVE, we would need something to represent each of the output pins,
so the device tree can actually describe what kind of signal, be it
each component of RGB/YUV or composite video, is wanted on each pin,
if any. This is also needed on the A20 for the Cubietruck, so we can
describe which pins are tied to the VGA connector, and which one does
R, G, or B.


Regards
ChenYu

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

* Re: [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top
  2018-05-24 22:01         ` Chen-Yu Tsai
@ 2018-05-31  9:21           ` Maxime Ripard
  2018-05-31 17:54             ` Jernej Škrabec
  0 siblings, 1 reply; 46+ messages in thread
From: Maxime Ripard @ 2018-05-31  9:21 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Jernej Škrabec, Rob Herring, Mark Rutland, dri-devel,
	devicetree, linux-arm-kernel, linux-kernel, linux-clk,
	linux-sunxi

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

On Thu, May 24, 2018 at 03:01:09PM -0700, Chen-Yu Tsai wrote:
> >> > > + if (tcon->quirks->needs_tcon_top) {
> >> > > +         struct device_node *np;
> >> > > +
> >> > > +         np = of_parse_phandle(dev->of_node, "allwinner,tcon-top", 0);
> >> > > +         if (np) {
> >> > > +                 struct platform_device *pdev;
> >> > > +
> >> > > +                 pdev = of_find_device_by_node(np);
> >> > > +                 if (pdev)
> >> > > +                         tcon->tcon_top = platform_get_drvdata(pdev);
> >> > > +                 of_node_put(np);
> >> > > +
> >> > > +                 if (!tcon->tcon_top)
> >> > > +                         return -EPROBE_DEFER;
> >> > > +         }
> >> > > + }
> >> > > +
> >> >
> >> > I might have missed it, but I've not seen the bindings additions for
> >> > that property. This shouldn't really be done that way anyway, instead
> >> > of using a direct phandle, you should be using the of-graph, with the
> >> > TCON-top sitting where it belongs in the flow of data.
> >>
> >> Just to answer to the first question, it did describe it in "[PATCH 07/15] dt-
> >> bindings: display: sun4i-drm: Add R40 HDMI pipeline".
> >>
> >> As why I designed it that way - HW representation could be described that way
> >> (ASCII art makes sense when fixed width font is used to view it):
> >>
> >>                             / LCD0/LVDS0
> >>                 / TCON-LCD0
> >>                 |           \ MIPI DSI
> >> mixer0          |
> >>        \        / TCON-LCD1 - LCD1/LVDS1
> >>         TCON-TOP
> >>        /        \ TCON-TV0 - TVE0/RGB
> >> mixer1          |          \
> >>                 |           TCON-TOP - HDMI
> >>                 |          /
> >>                 \ TCON-TV1 - TVE1/RGB
> >>
> >> This is a bit simplified, since there is also TVE-TOP, which is responsible
> >> for sharing 4 DACs between both TVE encoders. You can have two TV outs (PAL/
> >> NTSC) or TVE0 as TV out and TVE1 as RGB or vice versa. It even seems that you
> >> can arbitrarly choose which DAC is responsible for which signal, so there is a
> >> ton of possible end combinations, but I'm not 100% sure.
> >>
> >> Even though I wrote TCON-TOP twice, this is same unit in HW. R40 manual
> >> suggest more possibilities, although some of them seem wrong, like RGB feeding
> >> from LCD TCON. That is confirmed to be wrong when checking BSP code.
> >>
> >> Additionally, TCON-TOP comes in the middle of TVE0 and LCD0, TVE1 and LCD1 for
> >> pin muxing, although I'm not sure why is that needed at all, since according
> >> to R40 datasheet, TVE0 and TVE1 pins are dedicated and not on PORT D and PORT
> >> H, respectively, as TCON-TOP documentation suggest. However, HSYNC and PSYNC
> >> lines might be shared between TVE (when it works in RGB mode) and LCD. But
> >> that is just my guess since I'm not really familiar with RGB and LCD
> >> interfaces.
> >>
> >> I'm really not sure what would be the best representation in OF-graph. Can you
> >> suggest one?
> >
> > Rob might disagree on this one, but I don't see anything wrong with
> > having loops in the graph. If the TCON-TOP can be both the input and
> > output of the TCONs, then so be it, and have it described that way in
> > the graph.
> >
> > The code is already able to filter out nodes that have already been
> > added to the list of devices we need to wait for in the component
> > framework, so that should work as well.
> >
> > And we'd need to describe TVE-TOP as well, even though we don't have a
> > driver for it yet. That will simplify the backward compatibility later
> > on.
> 
> I'm getting the feeling that TCON-TOP / TVE-TOP is the glue layer that
> binds everything together, and provides signal routing, kind of like
> DE-TOP on A64. So the signal mux controls that were originally found
> in TCON0 and TVE0 were moved out.
> 
> The driver needs to know about that, but the graph about doesn't make
> much sense directly. Without looking at the manual, I understand it to
> likely be one mux between the mixers and TCONs, and one between the
> TCON-TVs and HDMI. Would it make more sense to just have the graph
> connections between the muxed components, and remove TCON-TOP from
> it, like we had in the past? A phandle could be used to reference
> the TCON-TOP for mux controls, in addition to the clocks and resets.
> 
> For TVE, we would need something to represent each of the output pins,
> so the device tree can actually describe what kind of signal, be it
> each component of RGB/YUV or composite video, is wanted on each pin,
> if any. This is also needed on the A20 for the Cubietruck, so we can
> describe which pins are tied to the VGA connector, and which one does
> R, G, or B.

I guess we'll see how the DT maintainers feel about this, but my
impression is that the OF graph should model the flow of data between
the devices. If there's a mux somewhere, then the data is definitely
going through it, and as such it should be part of the graph.

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

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

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

* Re: [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top
  2018-05-31  9:21           ` Maxime Ripard
@ 2018-05-31 17:54             ` Jernej Škrabec
  2018-06-01 15:29               ` Maxime Ripard
  0 siblings, 1 reply; 46+ messages in thread
From: Jernej Škrabec @ 2018-05-31 17:54 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Chen-Yu Tsai, Rob Herring, Mark Rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, linux-sunxi

Dne četrtek, 31. maj 2018 ob 11:21:33 CEST je Maxime Ripard napisal(a):
> On Thu, May 24, 2018 at 03:01:09PM -0700, Chen-Yu Tsai wrote:
> > >> > > + if (tcon->quirks->needs_tcon_top) {
> > >> > > +         struct device_node *np;
> > >> > > +
> > >> > > +         np = of_parse_phandle(dev->of_node, "allwinner,tcon-top",
> > >> > > 0);
> > >> > > +         if (np) {
> > >> > > +                 struct platform_device *pdev;
> > >> > > +
> > >> > > +                 pdev = of_find_device_by_node(np);
> > >> > > +                 if (pdev)
> > >> > > +                         tcon->tcon_top =
> > >> > > platform_get_drvdata(pdev);
> > >> > > +                 of_node_put(np);
> > >> > > +
> > >> > > +                 if (!tcon->tcon_top)
> > >> > > +                         return -EPROBE_DEFER;
> > >> > > +         }
> > >> > > + }
> > >> > > +
> > >> > 
> > >> > I might have missed it, but I've not seen the bindings additions for
> > >> > that property. This shouldn't really be done that way anyway, instead
> > >> > of using a direct phandle, you should be using the of-graph, with the
> > >> > TCON-top sitting where it belongs in the flow of data.
> > >> 
> > >> Just to answer to the first question, it did describe it in "[PATCH
> > >> 07/15] dt- bindings: display: sun4i-drm: Add R40 HDMI pipeline".
> > >> 
> > >> As why I designed it that way - HW representation could be described
> > >> that way> >> 
> > >> (ASCII art makes sense when fixed width font is used to view it):
> > >>                             / LCD0/LVDS0
> > >>                 
> > >>                 / TCON-LCD0
> > >>                 
> > >>                 |           \ MIPI DSI
> > >> 
> > >> mixer0          |
> > >> 
> > >>        \        / TCON-LCD1 - LCD1/LVDS1
> > >>        
> > >>         TCON-TOP
> > >>        
> > >>        /        \ TCON-TV0 - TVE0/RGB
> > >> 
> > >> mixer1          |          \
> > >> 
> > >>                 |           TCON-TOP - HDMI
> > >>                 |          
> > >>                 |          /
> > >>                 
> > >>                 \ TCON-TV1 - TVE1/RGB
> > >> 
> > >> This is a bit simplified, since there is also TVE-TOP, which is
> > >> responsible
> > >> for sharing 4 DACs between both TVE encoders. You can have two TV outs
> > >> (PAL/ NTSC) or TVE0 as TV out and TVE1 as RGB or vice versa. It even
> > >> seems that you can arbitrarly choose which DAC is responsible for
> > >> which signal, so there is a ton of possible end combinations, but I'm
> > >> not 100% sure.
> > >> 
> > >> Even though I wrote TCON-TOP twice, this is same unit in HW. R40 manual
> > >> suggest more possibilities, although some of them seem wrong, like RGB
> > >> feeding from LCD TCON. That is confirmed to be wrong when checking BSP
> > >> code.
> > >> 
> > >> Additionally, TCON-TOP comes in the middle of TVE0 and LCD0, TVE1 and
> > >> LCD1 for pin muxing, although I'm not sure why is that needed at all,
> > >> since according to R40 datasheet, TVE0 and TVE1 pins are dedicated and
> > >> not on PORT D and PORT H, respectively, as TCON-TOP documentation
> > >> suggest. However, HSYNC and PSYNC lines might be shared between TVE
> > >> (when it works in RGB mode) and LCD. But that is just my guess since
> > >> I'm not really familiar with RGB and LCD interfaces.
> > >> 
> > >> I'm really not sure what would be the best representation in OF-graph.
> > >> Can you suggest one?
> > > 
> > > Rob might disagree on this one, but I don't see anything wrong with
> > > having loops in the graph. If the TCON-TOP can be both the input and
> > > output of the TCONs, then so be it, and have it described that way in
> > > the graph.
> > > 
> > > The code is already able to filter out nodes that have already been
> > > added to the list of devices we need to wait for in the component
> > > framework, so that should work as well.
> > > 
> > > And we'd need to describe TVE-TOP as well, even though we don't have a
> > > driver for it yet. That will simplify the backward compatibility later
> > > on.
> > 
> > I'm getting the feeling that TCON-TOP / TVE-TOP is the glue layer that
> > binds everything together, and provides signal routing, kind of like
> > DE-TOP on A64. So the signal mux controls that were originally found
> > in TCON0 and TVE0 were moved out.
> > 
> > The driver needs to know about that, but the graph about doesn't make
> > much sense directly. Without looking at the manual, I understand it to
> > likely be one mux between the mixers and TCONs, and one between the
> > TCON-TVs and HDMI. Would it make more sense to just have the graph
> > connections between the muxed components, and remove TCON-TOP from
> > it, like we had in the past? A phandle could be used to reference
> > the TCON-TOP for mux controls, in addition to the clocks and resets.
> > 
> > For TVE, we would need something to represent each of the output pins,
> > so the device tree can actually describe what kind of signal, be it
> > each component of RGB/YUV or composite video, is wanted on each pin,
> > if any. This is also needed on the A20 for the Cubietruck, so we can
> > describe which pins are tied to the VGA connector, and which one does
> > R, G, or B.
> 
> I guess we'll see how the DT maintainers feel about this, but my
> impression is that the OF graph should model the flow of data between
> the devices. If there's a mux somewhere, then the data is definitely
> going through it, and as such it should be part of the graph.

I concur, but I spent few days thinking how to represent this sanely in graph, 
but I didn't find any good solution. I'll represent here my idea and please 
tell your opinion before I start implementing it.

First, let me be clear that mixer0 and mixer1 don't have same capabilities 
(different number of planes, mixer0 supports writeback, mixer1 does not, 
etc.). Thus, it does matter which mixer is connected to which TCON/encoder. 
mixer0 is meant to be connected to main display and mixer1 to auxiliary. That 
obviously depends on end system.

So, TCON TOP has 3 muxes, which have to be represented in graph. Two of them 
are for mixer/TCON relationship (each of them 1 input and 4 possible outputs) 
and one for TV TCON/HDMI pair selection (2 possible inputs, 1 output).

According to current practice in sun4i-drm driver, graph has to have port 0, 
representing input and port 1, representing output. This would mean that graph 
looks something like that:

tcon_top: tcon-top@1c70000 {
	compatible = "allwinner,sun8i-r40-tcon-top";
	...
	ports {
		#address-cells = <1>;
		#size-cells = <0>;

		tcon_top_in: port@0 {
			#address-cells = <1>;
			#size-cells = <0>;
			reg = <0>;

			tcon_top_in_mixer0: endpoint@0 {
				reg = <0>;
				remote-endpoint = <&mixer0_out_tcon_top>;
			};

			tcon_top_in_mixer1: endpoint@1 {
				reg = <1>;
				remote-endpoint = <&mixer1_out_tcon_top>;
			};

			tcon_top_in_tcon_tv: endpoint@2 {
				reg = <2>;
				// here is HDMI input connection, part of board DTS
				remote-endpoint = <board specific phandle to TV TCON output>;
			};
		};

		tcon_top_out: port@1 {
			#address-cells = <1>;
			#size-cells = <0>;
			reg = <1>;

			tcon_top_out_tcon0: endpoint@0 {
				reg = <0>;
				// here is mixer0 output connection, part of board DTS
				remote-endpoint = <board specific phandle to TCON>;
			};

			tcon_top_out_tcon1: endpoint@1 {
				reg = <1>;
				// here is mixer1 output connection, part of board DTS
				remote-endpoint = <board specific phandle to TCON>;
			};

			tcon_top_out_hdmi: endpoint@2 {
				reg = <2>;
				remote-endpoint = <&hdmi_in_tcon_top>;
			};
		};
	};
};

tcon_tv0: lcd-controller@1c73000 {
	compatible = "allwinner,sun8i-r40-tcon-tv-0";
	...
	ports {
		#address-cells = <1>;
		#size-cells = <0>;

		tcon_tv0_in: port@0 {
			reg = <0>;

			tcon_tv0_in_tcon_top: endpoint {
				// endpoint depends on board, part of board DTS
				remote-endpoint = <phandle to one of tcon_top_out_tcon>;
			};
		};

		tcon_tv0_out: port@1 {
			#address-cells = <1>;
			#size-cells = <0>;
			reg = <1>;

			// endpoints to TV TOP and TCON TOP HDMI input
			...
		};
	};
};

tcon_tv1: lcd-controller@1c74000 {
	compatible = "allwinner,sun8i-r40-tcon-tv-1";
	...
	ports {
		#address-cells = <1>;
		#size-cells = <0>;

		tcon_tv1_in: port@0 {
			reg = <0>;

			tcon_tv1_in_tcon_top: endpoint {
				// endpoint depends on board, part of board DTS
				remote-endpoint = <phandle to one of tcon_top_out_tcon>;
			};
		};

		tcon_tv1_out: port@1 {
			#address-cells = <1>;
			#size-cells = <0>;
			reg = <1>;

			// endpoints to TV TOP and TCON TOP HDMI input
			...
		};
	};
};

tcon_lcd0 and tcon_lcd1 would have similar connections, except that for 
outputs would be LCD or LVDS panels or MIPI DSI encoder.

Please note that each TCON (there are 4 of them) would need to have unique 
compatible and have HW index stored in quirks data. It would be used by TCON 
TOP driver for configuring muxes.

What do you think about above suggestion?

Best regards,
Jernej

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

* Re: [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top
  2018-05-31 17:54             ` Jernej Škrabec
@ 2018-06-01 15:29               ` Maxime Ripard
  2018-06-01 16:19                 ` Chen-Yu Tsai
  0 siblings, 1 reply; 46+ messages in thread
From: Maxime Ripard @ 2018-06-01 15:29 UTC (permalink / raw)
  To: Jernej Škrabec
  Cc: Chen-Yu Tsai, Rob Herring, Mark Rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, linux-sunxi

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

On Thu, May 31, 2018 at 07:54:08PM +0200, Jernej Škrabec wrote:
> Dne četrtek, 31. maj 2018 ob 11:21:33 CEST je Maxime Ripard napisal(a):
> > On Thu, May 24, 2018 at 03:01:09PM -0700, Chen-Yu Tsai wrote:
> > > >> > > + if (tcon->quirks->needs_tcon_top) {
> > > >> > > +         struct device_node *np;
> > > >> > > +
> > > >> > > +         np = of_parse_phandle(dev->of_node, "allwinner,tcon-top",
> > > >> > > 0);
> > > >> > > +         if (np) {
> > > >> > > +                 struct platform_device *pdev;
> > > >> > > +
> > > >> > > +                 pdev = of_find_device_by_node(np);
> > > >> > > +                 if (pdev)
> > > >> > > +                         tcon->tcon_top =
> > > >> > > platform_get_drvdata(pdev);
> > > >> > > +                 of_node_put(np);
> > > >> > > +
> > > >> > > +                 if (!tcon->tcon_top)
> > > >> > > +                         return -EPROBE_DEFER;
> > > >> > > +         }
> > > >> > > + }
> > > >> > > +
> > > >> > 
> > > >> > I might have missed it, but I've not seen the bindings additions for
> > > >> > that property. This shouldn't really be done that way anyway, instead
> > > >> > of using a direct phandle, you should be using the of-graph, with the
> > > >> > TCON-top sitting where it belongs in the flow of data.
> > > >> 
> > > >> Just to answer to the first question, it did describe it in "[PATCH
> > > >> 07/15] dt- bindings: display: sun4i-drm: Add R40 HDMI pipeline".
> > > >> 
> > > >> As why I designed it that way - HW representation could be described
> > > >> that way> >> 
> > > >> (ASCII art makes sense when fixed width font is used to view it):
> > > >>                             / LCD0/LVDS0
> > > >>                 
> > > >>                 / TCON-LCD0
> > > >>                 
> > > >>                 |           \ MIPI DSI
> > > >> 
> > > >> mixer0          |
> > > >> 
> > > >>        \        / TCON-LCD1 - LCD1/LVDS1
> > > >>        
> > > >>         TCON-TOP
> > > >>        
> > > >>        /        \ TCON-TV0 - TVE0/RGB
> > > >> 
> > > >> mixer1          |          \
> > > >> 
> > > >>                 |           TCON-TOP - HDMI
> > > >>                 |          
> > > >>                 |          /
> > > >>                 
> > > >>                 \ TCON-TV1 - TVE1/RGB
> > > >> 
> > > >> This is a bit simplified, since there is also TVE-TOP, which is
> > > >> responsible
> > > >> for sharing 4 DACs between both TVE encoders. You can have two TV outs
> > > >> (PAL/ NTSC) or TVE0 as TV out and TVE1 as RGB or vice versa. It even
> > > >> seems that you can arbitrarly choose which DAC is responsible for
> > > >> which signal, so there is a ton of possible end combinations, but I'm
> > > >> not 100% sure.
> > > >> 
> > > >> Even though I wrote TCON-TOP twice, this is same unit in HW. R40 manual
> > > >> suggest more possibilities, although some of them seem wrong, like RGB
> > > >> feeding from LCD TCON. That is confirmed to be wrong when checking BSP
> > > >> code.
> > > >> 
> > > >> Additionally, TCON-TOP comes in the middle of TVE0 and LCD0, TVE1 and
> > > >> LCD1 for pin muxing, although I'm not sure why is that needed at all,
> > > >> since according to R40 datasheet, TVE0 and TVE1 pins are dedicated and
> > > >> not on PORT D and PORT H, respectively, as TCON-TOP documentation
> > > >> suggest. However, HSYNC and PSYNC lines might be shared between TVE
> > > >> (when it works in RGB mode) and LCD. But that is just my guess since
> > > >> I'm not really familiar with RGB and LCD interfaces.
> > > >> 
> > > >> I'm really not sure what would be the best representation in OF-graph.
> > > >> Can you suggest one?
> > > > 
> > > > Rob might disagree on this one, but I don't see anything wrong with
> > > > having loops in the graph. If the TCON-TOP can be both the input and
> > > > output of the TCONs, then so be it, and have it described that way in
> > > > the graph.
> > > > 
> > > > The code is already able to filter out nodes that have already been
> > > > added to the list of devices we need to wait for in the component
> > > > framework, so that should work as well.
> > > > 
> > > > And we'd need to describe TVE-TOP as well, even though we don't have a
> > > > driver for it yet. That will simplify the backward compatibility later
> > > > on.
> > > 
> > > I'm getting the feeling that TCON-TOP / TVE-TOP is the glue layer that
> > > binds everything together, and provides signal routing, kind of like
> > > DE-TOP on A64. So the signal mux controls that were originally found
> > > in TCON0 and TVE0 were moved out.
> > > 
> > > The driver needs to know about that, but the graph about doesn't make
> > > much sense directly. Without looking at the manual, I understand it to
> > > likely be one mux between the mixers and TCONs, and one between the
> > > TCON-TVs and HDMI. Would it make more sense to just have the graph
> > > connections between the muxed components, and remove TCON-TOP from
> > > it, like we had in the past? A phandle could be used to reference
> > > the TCON-TOP for mux controls, in addition to the clocks and resets.
> > > 
> > > For TVE, we would need something to represent each of the output pins,
> > > so the device tree can actually describe what kind of signal, be it
> > > each component of RGB/YUV or composite video, is wanted on each pin,
> > > if any. This is also needed on the A20 for the Cubietruck, so we can
> > > describe which pins are tied to the VGA connector, and which one does
> > > R, G, or B.
> > 
> > I guess we'll see how the DT maintainers feel about this, but my
> > impression is that the OF graph should model the flow of data between
> > the devices. If there's a mux somewhere, then the data is definitely
> > going through it, and as such it should be part of the graph.
> 
> I concur, but I spent few days thinking how to represent this sanely in graph, 
> but I didn't find any good solution. I'll represent here my idea and please 
> tell your opinion before I start implementing it.
> 
> First, let me be clear that mixer0 and mixer1 don't have same capabilities 
> (different number of planes, mixer0 supports writeback, mixer1 does not, 
> etc.). Thus, it does matter which mixer is connected to which TCON/encoder. 
> mixer0 is meant to be connected to main display and mixer1 to auxiliary. That 
> obviously depends on end system.
> 
> So, TCON TOP has 3 muxes, which have to be represented in graph. Two of them 
> are for mixer/TCON relationship (each of them 1 input and 4 possible outputs) 
> and one for TV TCON/HDMI pair selection (2 possible inputs, 1 output).
> 
> According to current practice in sun4i-drm driver, graph has to have port 0, 
> representing input and port 1, representing output. This would mean that graph 
> looks something like that:
> 
> tcon_top: tcon-top@1c70000 {
> 	compatible = "allwinner,sun8i-r40-tcon-top";
> 	...
> 	ports {
> 		#address-cells = <1>;
> 		#size-cells = <0>;
> 
> 		tcon_top_in: port@0 {
> 			#address-cells = <1>;
> 			#size-cells = <0>;
> 			reg = <0>;
> 
> 			tcon_top_in_mixer0: endpoint@0 {
> 				reg = <0>;
> 				remote-endpoint = <&mixer0_out_tcon_top>;
> 			};
> 
> 			tcon_top_in_mixer1: endpoint@1 {
> 				reg = <1>;
> 				remote-endpoint = <&mixer1_out_tcon_top>;
> 			};
> 
> 			tcon_top_in_tcon_tv: endpoint@2 {
> 				reg = <2>;
> 				// here is HDMI input connection, part of board DTS
> 				remote-endpoint = <board specific phandle to TV TCON output>;
> 			};
> 		};
> 
> 		tcon_top_out: port@1 {
> 			#address-cells = <1>;
> 			#size-cells = <0>;
> 			reg = <1>;
> 
> 			tcon_top_out_tcon0: endpoint@0 {
> 				reg = <0>;
> 				// here is mixer0 output connection, part of board DTS
> 				remote-endpoint = <board specific phandle to TCON>;
> 			};
> 
> 			tcon_top_out_tcon1: endpoint@1 {
> 				reg = <1>;
> 				// here is mixer1 output connection, part of board DTS
> 				remote-endpoint = <board specific phandle to TCON>;
> 			};
> 
> 			tcon_top_out_hdmi: endpoint@2 {
> 				reg = <2>;
> 				remote-endpoint = <&hdmi_in_tcon_top>;
> 			};
> 		};
> 	};
> };

IIRC, each port is supposed to be one route for the data, so we would
have multiple ports, one for the mixers in input and for the tcon in
output, and one for the TCON in input and for the HDMI/TV in
output. Rob might correct me here.

> tcon_tv0: lcd-controller@1c73000 {
> 	compatible = "allwinner,sun8i-r40-tcon-tv-0";
> 	...
> 	ports {
> 		#address-cells = <1>;
> 		#size-cells = <0>;
> 
> 		tcon_tv0_in: port@0 {
> 			reg = <0>;
> 
> 			tcon_tv0_in_tcon_top: endpoint {
> 				// endpoint depends on board, part of board DTS
> 				remote-endpoint = <phandle to one of tcon_top_out_tcon>;

Just curious, what would be there?

> 			};
> 		};
> 
> 		tcon_tv0_out: port@1 {
> 			#address-cells = <1>;
> 			#size-cells = <0>;
> 			reg = <1>;
> 
> 			// endpoints to TV TOP and TCON TOP HDMI input
> 			...
> 		};
> 	};
> };
> 
> tcon_tv1: lcd-controller@1c74000 {
> 	compatible = "allwinner,sun8i-r40-tcon-tv-1";
> 	...
> 	ports {
> 		#address-cells = <1>;
> 		#size-cells = <0>;
> 
> 		tcon_tv1_in: port@0 {
> 			reg = <0>;
> 
> 			tcon_tv1_in_tcon_top: endpoint {
> 				// endpoint depends on board, part of board DTS
> 				remote-endpoint = <phandle to one of tcon_top_out_tcon>;
> 			};
> 		};
> 
> 		tcon_tv1_out: port@1 {
> 			#address-cells = <1>;
> 			#size-cells = <0>;
> 			reg = <1>;
> 
> 			// endpoints to TV TOP and TCON TOP HDMI input
> 			...
> 		};
> 	};
> };
> 
> tcon_lcd0 and tcon_lcd1 would have similar connections, except that for 
> outputs would be LCD or LVDS panels or MIPI DSI encoder.
> 
> Please note that each TCON (there are 4 of them) would need to have unique 
> compatible and have HW index stored in quirks data. It would be used by TCON 
> TOP driver for configuring muxes.

Can't we use the port/endpoint ID instead? If the mux is the only
thing that changes, the compatible has no reason to. It's the same IP,
and the only thing that changes is something that is not part of that
IP.

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

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

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

* Re: [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top
  2018-06-01 15:29               ` Maxime Ripard
@ 2018-06-01 16:19                 ` Chen-Yu Tsai
  2018-06-04 11:50                   ` Maxime Ripard
  0 siblings, 1 reply; 46+ messages in thread
From: Chen-Yu Tsai @ 2018-06-01 16:19 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Jernej Škrabec, Rob Herring, Mark Rutland, dri-devel,
	devicetree, linux-arm-kernel, linux-kernel, linux-clk,
	linux-sunxi

On Fri, Jun 1, 2018 at 8:29 AM, Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> On Thu, May 31, 2018 at 07:54:08PM +0200, Jernej Škrabec wrote:
>> Dne četrtek, 31. maj 2018 ob 11:21:33 CEST je Maxime Ripard napisal(a):
>> > On Thu, May 24, 2018 at 03:01:09PM -0700, Chen-Yu Tsai wrote:
>> > > >> > > + if (tcon->quirks->needs_tcon_top) {
>> > > >> > > +         struct device_node *np;
>> > > >> > > +
>> > > >> > > +         np = of_parse_phandle(dev->of_node, "allwinner,tcon-top",
>> > > >> > > 0);
>> > > >> > > +         if (np) {
>> > > >> > > +                 struct platform_device *pdev;
>> > > >> > > +
>> > > >> > > +                 pdev = of_find_device_by_node(np);
>> > > >> > > +                 if (pdev)
>> > > >> > > +                         tcon->tcon_top =
>> > > >> > > platform_get_drvdata(pdev);
>> > > >> > > +                 of_node_put(np);
>> > > >> > > +
>> > > >> > > +                 if (!tcon->tcon_top)
>> > > >> > > +                         return -EPROBE_DEFER;
>> > > >> > > +         }
>> > > >> > > + }
>> > > >> > > +
>> > > >> >
>> > > >> > I might have missed it, but I've not seen the bindings additions for
>> > > >> > that property. This shouldn't really be done that way anyway, instead
>> > > >> > of using a direct phandle, you should be using the of-graph, with the
>> > > >> > TCON-top sitting where it belongs in the flow of data.
>> > > >>
>> > > >> Just to answer to the first question, it did describe it in "[PATCH
>> > > >> 07/15] dt- bindings: display: sun4i-drm: Add R40 HDMI pipeline".
>> > > >>
>> > > >> As why I designed it that way - HW representation could be described
>> > > >> that way> >>
>> > > >> (ASCII art makes sense when fixed width font is used to view it):
>> > > >>                             / LCD0/LVDS0
>> > > >>
>> > > >>                 / TCON-LCD0
>> > > >>
>> > > >>                 |           \ MIPI DSI
>> > > >>
>> > > >> mixer0          |
>> > > >>
>> > > >>        \        / TCON-LCD1 - LCD1/LVDS1
>> > > >>
>> > > >>         TCON-TOP
>> > > >>
>> > > >>        /        \ TCON-TV0 - TVE0/RGB
>> > > >>
>> > > >> mixer1          |          \
>> > > >>
>> > > >>                 |           TCON-TOP - HDMI
>> > > >>                 |
>> > > >>                 |          /
>> > > >>
>> > > >>                 \ TCON-TV1 - TVE1/RGB
>> > > >>
>> > > >> This is a bit simplified, since there is also TVE-TOP, which is
>> > > >> responsible
>> > > >> for sharing 4 DACs between both TVE encoders. You can have two TV outs
>> > > >> (PAL/ NTSC) or TVE0 as TV out and TVE1 as RGB or vice versa. It even
>> > > >> seems that you can arbitrarly choose which DAC is responsible for
>> > > >> which signal, so there is a ton of possible end combinations, but I'm
>> > > >> not 100% sure.
>> > > >>
>> > > >> Even though I wrote TCON-TOP twice, this is same unit in HW. R40 manual
>> > > >> suggest more possibilities, although some of them seem wrong, like RGB
>> > > >> feeding from LCD TCON. That is confirmed to be wrong when checking BSP
>> > > >> code.
>> > > >>
>> > > >> Additionally, TCON-TOP comes in the middle of TVE0 and LCD0, TVE1 and
>> > > >> LCD1 for pin muxing, although I'm not sure why is that needed at all,
>> > > >> since according to R40 datasheet, TVE0 and TVE1 pins are dedicated and
>> > > >> not on PORT D and PORT H, respectively, as TCON-TOP documentation
>> > > >> suggest. However, HSYNC and PSYNC lines might be shared between TVE
>> > > >> (when it works in RGB mode) and LCD. But that is just my guess since
>> > > >> I'm not really familiar with RGB and LCD interfaces.
>> > > >>
>> > > >> I'm really not sure what would be the best representation in OF-graph.
>> > > >> Can you suggest one?
>> > > >
>> > > > Rob might disagree on this one, but I don't see anything wrong with
>> > > > having loops in the graph. If the TCON-TOP can be both the input and
>> > > > output of the TCONs, then so be it, and have it described that way in
>> > > > the graph.
>> > > >
>> > > > The code is already able to filter out nodes that have already been
>> > > > added to the list of devices we need to wait for in the component
>> > > > framework, so that should work as well.
>> > > >
>> > > > And we'd need to describe TVE-TOP as well, even though we don't have a
>> > > > driver for it yet. That will simplify the backward compatibility later
>> > > > on.
>> > >
>> > > I'm getting the feeling that TCON-TOP / TVE-TOP is the glue layer that
>> > > binds everything together, and provides signal routing, kind of like
>> > > DE-TOP on A64. So the signal mux controls that were originally found
>> > > in TCON0 and TVE0 were moved out.
>> > >
>> > > The driver needs to know about that, but the graph about doesn't make
>> > > much sense directly. Without looking at the manual, I understand it to
>> > > likely be one mux between the mixers and TCONs, and one between the
>> > > TCON-TVs and HDMI. Would it make more sense to just have the graph
>> > > connections between the muxed components, and remove TCON-TOP from
>> > > it, like we had in the past? A phandle could be used to reference
>> > > the TCON-TOP for mux controls, in addition to the clocks and resets.
>> > >
>> > > For TVE, we would need something to represent each of the output pins,
>> > > so the device tree can actually describe what kind of signal, be it
>> > > each component of RGB/YUV or composite video, is wanted on each pin,
>> > > if any. This is also needed on the A20 for the Cubietruck, so we can
>> > > describe which pins are tied to the VGA connector, and which one does
>> > > R, G, or B.
>> >
>> > I guess we'll see how the DT maintainers feel about this, but my
>> > impression is that the OF graph should model the flow of data between
>> > the devices. If there's a mux somewhere, then the data is definitely
>> > going through it, and as such it should be part of the graph.
>>
>> I concur, but I spent few days thinking how to represent this sanely in graph,
>> but I didn't find any good solution. I'll represent here my idea and please
>> tell your opinion before I start implementing it.
>>
>> First, let me be clear that mixer0 and mixer1 don't have same capabilities
>> (different number of planes, mixer0 supports writeback, mixer1 does not,
>> etc.). Thus, it does matter which mixer is connected to which TCON/encoder.
>> mixer0 is meant to be connected to main display and mixer1 to auxiliary. That
>> obviously depends on end system.
>>
>> So, TCON TOP has 3 muxes, which have to be represented in graph. Two of them
>> are for mixer/TCON relationship (each of them 1 input and 4 possible outputs)
>> and one for TV TCON/HDMI pair selection (2 possible inputs, 1 output).
>>
>> According to current practice in sun4i-drm driver, graph has to have port 0,
>> representing input and port 1, representing output. This would mean that graph
>> looks something like that:
>>
>> tcon_top: tcon-top@1c70000 {
>>       compatible = "allwinner,sun8i-r40-tcon-top";
>>       ...
>>       ports {
>>               #address-cells = <1>;
>>               #size-cells = <0>;
>>
>>               tcon_top_in: port@0 {
>>                       #address-cells = <1>;
>>                       #size-cells = <0>;
>>                       reg = <0>;
>>
>>                       tcon_top_in_mixer0: endpoint@0 {
>>                               reg = <0>;
>>                               remote-endpoint = <&mixer0_out_tcon_top>;
>>                       };
>>
>>                       tcon_top_in_mixer1: endpoint@1 {
>>                               reg = <1>;
>>                               remote-endpoint = <&mixer1_out_tcon_top>;
>>                       };
>>
>>                       tcon_top_in_tcon_tv: endpoint@2 {
>>                               reg = <2>;
>>                               // here is HDMI input connection, part of board DTS
>>                               remote-endpoint = <board specific phandle to TV TCON output>;
>>                       };
>>               };
>>
>>               tcon_top_out: port@1 {
>>                       #address-cells = <1>;
>>                       #size-cells = <0>;
>>                       reg = <1>;
>>
>>                       tcon_top_out_tcon0: endpoint@0 {
>>                               reg = <0>;
>>                               // here is mixer0 output connection, part of board DTS
>>                               remote-endpoint = <board specific phandle to TCON>;
>>                       };
>>
>>                       tcon_top_out_tcon1: endpoint@1 {
>>                               reg = <1>;
>>                               // here is mixer1 output connection, part of board DTS
>>                               remote-endpoint = <board specific phandle to TCON>;
>>                       };
>>
>>                       tcon_top_out_hdmi: endpoint@2 {
>>                               reg = <2>;
>>                               remote-endpoint = <&hdmi_in_tcon_top>;
>>                       };
>>               };
>>       };
>> };
>
> IIRC, each port is supposed to be one route for the data, so we would
> have multiple ports, one for the mixers in input and for the tcon in
> output, and one for the TCON in input and for the HDMI/TV in
> output. Rob might correct me here.
>
>> tcon_tv0: lcd-controller@1c73000 {
>>       compatible = "allwinner,sun8i-r40-tcon-tv-0";
>>       ...
>>       ports {
>>               #address-cells = <1>;
>>               #size-cells = <0>;
>>
>>               tcon_tv0_in: port@0 {
>>                       reg = <0>;
>>
>>                       tcon_tv0_in_tcon_top: endpoint {
>>                               // endpoint depends on board, part of board DTS
>>                               remote-endpoint = <phandle to one of tcon_top_out_tcon>;
>
> Just curious, what would be there?
>
>>                       };
>>               };
>>
>>               tcon_tv0_out: port@1 {
>>                       #address-cells = <1>;
>>                       #size-cells = <0>;
>>                       reg = <1>;
>>
>>                       // endpoints to TV TOP and TCON TOP HDMI input
>>                       ...
>>               };
>>       };
>> };
>>
>> tcon_tv1: lcd-controller@1c74000 {
>>       compatible = "allwinner,sun8i-r40-tcon-tv-1";
>>       ...
>>       ports {
>>               #address-cells = <1>;
>>               #size-cells = <0>;
>>
>>               tcon_tv1_in: port@0 {
>>                       reg = <0>;
>>
>>                       tcon_tv1_in_tcon_top: endpoint {
>>                               // endpoint depends on board, part of board DTS
>>                               remote-endpoint = <phandle to one of tcon_top_out_tcon>;
>>                       };
>>               };
>>
>>               tcon_tv1_out: port@1 {
>>                       #address-cells = <1>;
>>                       #size-cells = <0>;
>>                       reg = <1>;
>>
>>                       // endpoints to TV TOP and TCON TOP HDMI input
>>                       ...
>>               };
>>       };
>> };
>>
>> tcon_lcd0 and tcon_lcd1 would have similar connections, except that for
>> outputs would be LCD or LVDS panels or MIPI DSI encoder.
>>
>> Please note that each TCON (there are 4 of them) would need to have unique
>> compatible and have HW index stored in quirks data. It would be used by TCON
>> TOP driver for configuring muxes.
>
> Can't we use the port/endpoint ID instead? If the mux is the only
> thing that changes, the compatible has no reason to. It's the same IP,
> and the only thing that changes is something that is not part of that
> IP.

I agree. Endpoint IDs should provide that information. I'm still not
sure How to encode multiple in/out mux groups in a device node though.

ChenYu

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

* Re: [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top
  2018-06-01 16:19                 ` Chen-Yu Tsai
@ 2018-06-04 11:50                   ` Maxime Ripard
  2018-06-04 15:09                     ` Jernej Škrabec
  0 siblings, 1 reply; 46+ messages in thread
From: Maxime Ripard @ 2018-06-04 11:50 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Jernej Škrabec, Rob Herring, Mark Rutland, dri-devel,
	devicetree, linux-arm-kernel, linux-kernel, linux-clk,
	linux-sunxi

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

On Fri, Jun 01, 2018 at 09:19:43AM -0700, Chen-Yu Tsai wrote:
> On Fri, Jun 1, 2018 at 8:29 AM, Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > On Thu, May 31, 2018 at 07:54:08PM +0200, Jernej Škrabec wrote:
> >> Dne četrtek, 31. maj 2018 ob 11:21:33 CEST je Maxime Ripard napisal(a):
> >> > On Thu, May 24, 2018 at 03:01:09PM -0700, Chen-Yu Tsai wrote:
> >> > > >> > > + if (tcon->quirks->needs_tcon_top) {
> >> > > >> > > +         struct device_node *np;
> >> > > >> > > +
> >> > > >> > > +         np = of_parse_phandle(dev->of_node, "allwinner,tcon-top",
> >> > > >> > > 0);
> >> > > >> > > +         if (np) {
> >> > > >> > > +                 struct platform_device *pdev;
> >> > > >> > > +
> >> > > >> > > +                 pdev = of_find_device_by_node(np);
> >> > > >> > > +                 if (pdev)
> >> > > >> > > +                         tcon->tcon_top =
> >> > > >> > > platform_get_drvdata(pdev);
> >> > > >> > > +                 of_node_put(np);
> >> > > >> > > +
> >> > > >> > > +                 if (!tcon->tcon_top)
> >> > > >> > > +                         return -EPROBE_DEFER;
> >> > > >> > > +         }
> >> > > >> > > + }
> >> > > >> > > +
> >> > > >> >
> >> > > >> > I might have missed it, but I've not seen the bindings additions for
> >> > > >> > that property. This shouldn't really be done that way anyway, instead
> >> > > >> > of using a direct phandle, you should be using the of-graph, with the
> >> > > >> > TCON-top sitting where it belongs in the flow of data.
> >> > > >>
> >> > > >> Just to answer to the first question, it did describe it in "[PATCH
> >> > > >> 07/15] dt- bindings: display: sun4i-drm: Add R40 HDMI pipeline".
> >> > > >>
> >> > > >> As why I designed it that way - HW representation could be described
> >> > > >> that way> >>
> >> > > >> (ASCII art makes sense when fixed width font is used to view it):
> >> > > >>                             / LCD0/LVDS0
> >> > > >>
> >> > > >>                 / TCON-LCD0
> >> > > >>
> >> > > >>                 |           \ MIPI DSI
> >> > > >>
> >> > > >> mixer0          |
> >> > > >>
> >> > > >>        \        / TCON-LCD1 - LCD1/LVDS1
> >> > > >>
> >> > > >>         TCON-TOP
> >> > > >>
> >> > > >>        /        \ TCON-TV0 - TVE0/RGB
> >> > > >>
> >> > > >> mixer1          |          \
> >> > > >>
> >> > > >>                 |           TCON-TOP - HDMI
> >> > > >>                 |
> >> > > >>                 |          /
> >> > > >>
> >> > > >>                 \ TCON-TV1 - TVE1/RGB
> >> > > >>
> >> > > >> This is a bit simplified, since there is also TVE-TOP, which is
> >> > > >> responsible
> >> > > >> for sharing 4 DACs between both TVE encoders. You can have two TV outs
> >> > > >> (PAL/ NTSC) or TVE0 as TV out and TVE1 as RGB or vice versa. It even
> >> > > >> seems that you can arbitrarly choose which DAC is responsible for
> >> > > >> which signal, so there is a ton of possible end combinations, but I'm
> >> > > >> not 100% sure.
> >> > > >>
> >> > > >> Even though I wrote TCON-TOP twice, this is same unit in HW. R40 manual
> >> > > >> suggest more possibilities, although some of them seem wrong, like RGB
> >> > > >> feeding from LCD TCON. That is confirmed to be wrong when checking BSP
> >> > > >> code.
> >> > > >>
> >> > > >> Additionally, TCON-TOP comes in the middle of TVE0 and LCD0, TVE1 and
> >> > > >> LCD1 for pin muxing, although I'm not sure why is that needed at all,
> >> > > >> since according to R40 datasheet, TVE0 and TVE1 pins are dedicated and
> >> > > >> not on PORT D and PORT H, respectively, as TCON-TOP documentation
> >> > > >> suggest. However, HSYNC and PSYNC lines might be shared between TVE
> >> > > >> (when it works in RGB mode) and LCD. But that is just my guess since
> >> > > >> I'm not really familiar with RGB and LCD interfaces.
> >> > > >>
> >> > > >> I'm really not sure what would be the best representation in OF-graph.
> >> > > >> Can you suggest one?
> >> > > >
> >> > > > Rob might disagree on this one, but I don't see anything wrong with
> >> > > > having loops in the graph. If the TCON-TOP can be both the input and
> >> > > > output of the TCONs, then so be it, and have it described that way in
> >> > > > the graph.
> >> > > >
> >> > > > The code is already able to filter out nodes that have already been
> >> > > > added to the list of devices we need to wait for in the component
> >> > > > framework, so that should work as well.
> >> > > >
> >> > > > And we'd need to describe TVE-TOP as well, even though we don't have a
> >> > > > driver for it yet. That will simplify the backward compatibility later
> >> > > > on.
> >> > >
> >> > > I'm getting the feeling that TCON-TOP / TVE-TOP is the glue layer that
> >> > > binds everything together, and provides signal routing, kind of like
> >> > > DE-TOP on A64. So the signal mux controls that were originally found
> >> > > in TCON0 and TVE0 were moved out.
> >> > >
> >> > > The driver needs to know about that, but the graph about doesn't make
> >> > > much sense directly. Without looking at the manual, I understand it to
> >> > > likely be one mux between the mixers and TCONs, and one between the
> >> > > TCON-TVs and HDMI. Would it make more sense to just have the graph
> >> > > connections between the muxed components, and remove TCON-TOP from
> >> > > it, like we had in the past? A phandle could be used to reference
> >> > > the TCON-TOP for mux controls, in addition to the clocks and resets.
> >> > >
> >> > > For TVE, we would need something to represent each of the output pins,
> >> > > so the device tree can actually describe what kind of signal, be it
> >> > > each component of RGB/YUV or composite video, is wanted on each pin,
> >> > > if any. This is also needed on the A20 for the Cubietruck, so we can
> >> > > describe which pins are tied to the VGA connector, and which one does
> >> > > R, G, or B.
> >> >
> >> > I guess we'll see how the DT maintainers feel about this, but my
> >> > impression is that the OF graph should model the flow of data between
> >> > the devices. If there's a mux somewhere, then the data is definitely
> >> > going through it, and as such it should be part of the graph.
> >>
> >> I concur, but I spent few days thinking how to represent this sanely in graph,
> >> but I didn't find any good solution. I'll represent here my idea and please
> >> tell your opinion before I start implementing it.
> >>
> >> First, let me be clear that mixer0 and mixer1 don't have same capabilities
> >> (different number of planes, mixer0 supports writeback, mixer1 does not,
> >> etc.). Thus, it does matter which mixer is connected to which TCON/encoder.
> >> mixer0 is meant to be connected to main display and mixer1 to auxiliary. That
> >> obviously depends on end system.
> >>
> >> So, TCON TOP has 3 muxes, which have to be represented in graph. Two of them
> >> are for mixer/TCON relationship (each of them 1 input and 4 possible outputs)
> >> and one for TV TCON/HDMI pair selection (2 possible inputs, 1 output).
> >>
> >> According to current practice in sun4i-drm driver, graph has to have port 0,
> >> representing input and port 1, representing output. This would mean that graph
> >> looks something like that:
> >>
> >> tcon_top: tcon-top@1c70000 {
> >>       compatible = "allwinner,sun8i-r40-tcon-top";
> >>       ...
> >>       ports {
> >>               #address-cells = <1>;
> >>               #size-cells = <0>;
> >>
> >>               tcon_top_in: port@0 {
> >>                       #address-cells = <1>;
> >>                       #size-cells = <0>;
> >>                       reg = <0>;
> >>
> >>                       tcon_top_in_mixer0: endpoint@0 {
> >>                               reg = <0>;
> >>                               remote-endpoint = <&mixer0_out_tcon_top>;
> >>                       };
> >>
> >>                       tcon_top_in_mixer1: endpoint@1 {
> >>                               reg = <1>;
> >>                               remote-endpoint = <&mixer1_out_tcon_top>;
> >>                       };
> >>
> >>                       tcon_top_in_tcon_tv: endpoint@2 {
> >>                               reg = <2>;
> >>                               // here is HDMI input connection, part of board DTS
> >>                               remote-endpoint = <board specific phandle to TV TCON output>;
> >>                       };
> >>               };
> >>
> >>               tcon_top_out: port@1 {
> >>                       #address-cells = <1>;
> >>                       #size-cells = <0>;
> >>                       reg = <1>;
> >>
> >>                       tcon_top_out_tcon0: endpoint@0 {
> >>                               reg = <0>;
> >>                               // here is mixer0 output connection, part of board DTS
> >>                               remote-endpoint = <board specific phandle to TCON>;
> >>                       };
> >>
> >>                       tcon_top_out_tcon1: endpoint@1 {
> >>                               reg = <1>;
> >>                               // here is mixer1 output connection, part of board DTS
> >>                               remote-endpoint = <board specific phandle to TCON>;
> >>                       };
> >>
> >>                       tcon_top_out_hdmi: endpoint@2 {
> >>                               reg = <2>;
> >>                               remote-endpoint = <&hdmi_in_tcon_top>;
> >>                       };
> >>               };
> >>       };
> >> };
> >
> > IIRC, each port is supposed to be one route for the data, so we would
> > have multiple ports, one for the mixers in input and for the tcon in
> > output, and one for the TCON in input and for the HDMI/TV in
> > output. Rob might correct me here.
> >
> >> tcon_tv0: lcd-controller@1c73000 {
> >>       compatible = "allwinner,sun8i-r40-tcon-tv-0";
> >>       ...
> >>       ports {
> >>               #address-cells = <1>;
> >>               #size-cells = <0>;
> >>
> >>               tcon_tv0_in: port@0 {
> >>                       reg = <0>;
> >>
> >>                       tcon_tv0_in_tcon_top: endpoint {
> >>                               // endpoint depends on board, part of board DTS
> >>                               remote-endpoint = <phandle to one of tcon_top_out_tcon>;
> >
> > Just curious, what would be there?
> >
> >>                       };
> >>               };
> >>
> >>               tcon_tv0_out: port@1 {
> >>                       #address-cells = <1>;
> >>                       #size-cells = <0>;
> >>                       reg = <1>;
> >>
> >>                       // endpoints to TV TOP and TCON TOP HDMI input
> >>                       ...
> >>               };
> >>       };
> >> };
> >>
> >> tcon_tv1: lcd-controller@1c74000 {
> >>       compatible = "allwinner,sun8i-r40-tcon-tv-1";
> >>       ...
> >>       ports {
> >>               #address-cells = <1>;
> >>               #size-cells = <0>;
> >>
> >>               tcon_tv1_in: port@0 {
> >>                       reg = <0>;
> >>
> >>                       tcon_tv1_in_tcon_top: endpoint {
> >>                               // endpoint depends on board, part of board DTS
> >>                               remote-endpoint = <phandle to one of tcon_top_out_tcon>;
> >>                       };
> >>               };
> >>
> >>               tcon_tv1_out: port@1 {
> >>                       #address-cells = <1>;
> >>                       #size-cells = <0>;
> >>                       reg = <1>;
> >>
> >>                       // endpoints to TV TOP and TCON TOP HDMI input
> >>                       ...
> >>               };
> >>       };
> >> };
> >>
> >> tcon_lcd0 and tcon_lcd1 would have similar connections, except that for
> >> outputs would be LCD or LVDS panels or MIPI DSI encoder.
> >>
> >> Please note that each TCON (there are 4 of them) would need to have unique
> >> compatible and have HW index stored in quirks data. It would be used by TCON
> >> TOP driver for configuring muxes.
> >
> > Can't we use the port/endpoint ID instead? If the mux is the only
> > thing that changes, the compatible has no reason to. It's the same IP,
> > and the only thing that changes is something that is not part of that
> > IP.
> 
> I agree. Endpoint IDs should provide that information. I'm still not
> sure How to encode multiple in/out mux groups in a device node though.

I guess we can do that through different ports?

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

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

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

* Re: [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top
  2018-06-04 11:50                   ` Maxime Ripard
@ 2018-06-04 15:09                     ` Jernej Škrabec
  2018-06-04 16:23                       ` Maxime Ripard
  0 siblings, 1 reply; 46+ messages in thread
From: Jernej Škrabec @ 2018-06-04 15:09 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Chen-Yu Tsai, Rob Herring, Mark Rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, linux-sunxi

Dne ponedeljek, 04. junij 2018 ob 13:50:34 CEST je Maxime Ripard napisal(a):
> On Fri, Jun 01, 2018 at 09:19:43AM -0700, Chen-Yu Tsai wrote:
> > On Fri, Jun 1, 2018 at 8:29 AM, Maxime Ripard <maxime.ripard@bootlin.com> 
wrote:
> > > On Thu, May 31, 2018 at 07:54:08PM +0200, Jernej Škrabec wrote:
> > >> Dne četrtek, 31. maj 2018 ob 11:21:33 CEST je Maxime Ripard napisal(a):
> > >> > On Thu, May 24, 2018 at 03:01:09PM -0700, Chen-Yu Tsai wrote:
> > >> > > >> > > + if (tcon->quirks->needs_tcon_top) {
> > >> > > >> > > +         struct device_node *np;
> > >> > > >> > > +
> > >> > > >> > > +         np = of_parse_phandle(dev->of_node,
> > >> > > >> > > "allwinner,tcon-top",
> > >> > > >> > > 0);
> > >> > > >> > > +         if (np) {
> > >> > > >> > > +                 struct platform_device *pdev;
> > >> > > >> > > +
> > >> > > >> > > +                 pdev = of_find_device_by_node(np);
> > >> > > >> > > +                 if (pdev)
> > >> > > >> > > +                         tcon->tcon_top =
> > >> > > >> > > platform_get_drvdata(pdev);
> > >> > > >> > > +                 of_node_put(np);
> > >> > > >> > > +
> > >> > > >> > > +                 if (!tcon->tcon_top)
> > >> > > >> > > +                         return -EPROBE_DEFER;
> > >> > > >> > > +         }
> > >> > > >> > > + }
> > >> > > >> > > +
> > >> > > >> > 
> > >> > > >> > I might have missed it, but I've not seen the bindings
> > >> > > >> > additions for
> > >> > > >> > that property. This shouldn't really be done that way anyway,
> > >> > > >> > instead
> > >> > > >> > of using a direct phandle, you should be using the of-graph,
> > >> > > >> > with the
> > >> > > >> > TCON-top sitting where it belongs in the flow of data.
> > >> > > >> 
> > >> > > >> Just to answer to the first question, it did describe it in
> > >> > > >> "[PATCH
> > >> > > >> 07/15] dt- bindings: display: sun4i-drm: Add R40 HDMI pipeline".
> > >> > > >> 
> > >> > > >> As why I designed it that way - HW representation could be
> > >> > > >> described
> > >> > > >> that way> >>
> > >> > > >> 
> > >> > > >> (ASCII art makes sense when fixed width font is used to view 
it):
> > >> > > >>                             / LCD0/LVDS0
> > >> > > >>                 
> > >> > > >>                 / TCON-LCD0
> > >> > > >>                 
> > >> > > >>                 |           \ MIPI DSI
> > >> > > >> 
> > >> > > >> mixer0          |
> > >> > > >> 
> > >> > > >>        \        / TCON-LCD1 - LCD1/LVDS1
> > >> > > >>        
> > >> > > >>         TCON-TOP
> > >> > > >>        
> > >> > > >>        /        \ TCON-TV0 - TVE0/RGB
> > >> > > >> 
> > >> > > >> mixer1          |          \
> > >> > > >> 
> > >> > > >>                 |           TCON-TOP - HDMI
> > >> > > >>                 |          
> > >> > > >>                 |          /
> > >> > > >>                 
> > >> > > >>                 \ TCON-TV1 - TVE1/RGB
> > >> > > >> 
> > >> > > >> This is a bit simplified, since there is also TVE-TOP, which is
> > >> > > >> responsible
> > >> > > >> for sharing 4 DACs between both TVE encoders. You can have two
> > >> > > >> TV outs
> > >> > > >> (PAL/ NTSC) or TVE0 as TV out and TVE1 as RGB or vice versa. It
> > >> > > >> even
> > >> > > >> seems that you can arbitrarly choose which DAC is responsible
> > >> > > >> for
> > >> > > >> which signal, so there is a ton of possible end combinations,
> > >> > > >> but I'm
> > >> > > >> not 100% sure.
> > >> > > >> 
> > >> > > >> Even though I wrote TCON-TOP twice, this is same unit in HW. R40
> > >> > > >> manual
> > >> > > >> suggest more possibilities, although some of them seem wrong,
> > >> > > >> like RGB
> > >> > > >> feeding from LCD TCON. That is confirmed to be wrong when
> > >> > > >> checking BSP
> > >> > > >> code.
> > >> > > >> 
> > >> > > >> Additionally, TCON-TOP comes in the middle of TVE0 and LCD0,
> > >> > > >> TVE1 and
> > >> > > >> LCD1 for pin muxing, although I'm not sure why is that needed at
> > >> > > >> all,
> > >> > > >> since according to R40 datasheet, TVE0 and TVE1 pins are
> > >> > > >> dedicated and
> > >> > > >> not on PORT D and PORT H, respectively, as TCON-TOP
> > >> > > >> documentation
> > >> > > >> suggest. However, HSYNC and PSYNC lines might be shared between
> > >> > > >> TVE
> > >> > > >> (when it works in RGB mode) and LCD. But that is just my guess
> > >> > > >> since
> > >> > > >> I'm not really familiar with RGB and LCD interfaces.
> > >> > > >> 
> > >> > > >> I'm really not sure what would be the best representation in
> > >> > > >> OF-graph.
> > >> > > >> Can you suggest one?
> > >> > > > 
> > >> > > > Rob might disagree on this one, but I don't see anything wrong
> > >> > > > with
> > >> > > > having loops in the graph. If the TCON-TOP can be both the input
> > >> > > > and
> > >> > > > output of the TCONs, then so be it, and have it described that
> > >> > > > way in
> > >> > > > the graph.
> > >> > > > 
> > >> > > > The code is already able to filter out nodes that have already
> > >> > > > been
> > >> > > > added to the list of devices we need to wait for in the component
> > >> > > > framework, so that should work as well.
> > >> > > > 
> > >> > > > And we'd need to describe TVE-TOP as well, even though we don't
> > >> > > > have a
> > >> > > > driver for it yet. That will simplify the backward compatibility
> > >> > > > later
> > >> > > > on.
> > >> > > 
> > >> > > I'm getting the feeling that TCON-TOP / TVE-TOP is the glue layer
> > >> > > that
> > >> > > binds everything together, and provides signal routing, kind of
> > >> > > like
> > >> > > DE-TOP on A64. So the signal mux controls that were originally
> > >> > > found
> > >> > > in TCON0 and TVE0 were moved out.
> > >> > > 
> > >> > > The driver needs to know about that, but the graph about doesn't
> > >> > > make
> > >> > > much sense directly. Without looking at the manual, I understand it
> > >> > > to
> > >> > > likely be one mux between the mixers and TCONs, and one between the
> > >> > > TCON-TVs and HDMI. Would it make more sense to just have the graph
> > >> > > connections between the muxed components, and remove TCON-TOP from
> > >> > > it, like we had in the past? A phandle could be used to reference
> > >> > > the TCON-TOP for mux controls, in addition to the clocks and
> > >> > > resets.
> > >> > > 
> > >> > > For TVE, we would need something to represent each of the output
> > >> > > pins,
> > >> > > so the device tree can actually describe what kind of signal, be it
> > >> > > each component of RGB/YUV or composite video, is wanted on each
> > >> > > pin,
> > >> > > if any. This is also needed on the A20 for the Cubietruck, so we
> > >> > > can
> > >> > > describe which pins are tied to the VGA connector, and which one
> > >> > > does
> > >> > > R, G, or B.
> > >> > 
> > >> > I guess we'll see how the DT maintainers feel about this, but my
> > >> > impression is that the OF graph should model the flow of data between
> > >> > the devices. If there's a mux somewhere, then the data is definitely
> > >> > going through it, and as such it should be part of the graph.
> > >> 
> > >> I concur, but I spent few days thinking how to represent this sanely in
> > >> graph, but I didn't find any good solution. I'll represent here my
> > >> idea and please tell your opinion before I start implementing it.
> > >> 
> > >> First, let me be clear that mixer0 and mixer1 don't have same
> > >> capabilities
> > >> (different number of planes, mixer0 supports writeback, mixer1 does
> > >> not,
> > >> etc.). Thus, it does matter which mixer is connected to which
> > >> TCON/encoder.
> > >> mixer0 is meant to be connected to main display and mixer1 to
> > >> auxiliary. That obviously depends on end system.
> > >> 
> > >> So, TCON TOP has 3 muxes, which have to be represented in graph. Two of
> > >> them are for mixer/TCON relationship (each of them 1 input and 4
> > >> possible outputs) and one for TV TCON/HDMI pair selection (2 possible
> > >> inputs, 1 output).
> > >> 
> > >> According to current practice in sun4i-drm driver, graph has to have
> > >> port 0, representing input and port 1, representing output. This would
> > >> mean that graph looks something like that:
> > >> 
> > >> tcon_top: tcon-top@1c70000 {
> > >> 
> > >>       compatible = "allwinner,sun8i-r40-tcon-top";
> > >>       ...
> > >>       ports {
> > >>       
> > >>               #address-cells = <1>;
> > >>               #size-cells = <0>;
> > >>               
> > >>               tcon_top_in: port@0 {
> > >>               
> > >>                       #address-cells = <1>;
> > >>                       #size-cells = <0>;
> > >>                       reg = <0>;
> > >>                       
> > >>                       tcon_top_in_mixer0: endpoint@0 {
> > >>                       
> > >>                               reg = <0>;
> > >>                               remote-endpoint = <&mixer0_out_tcon_top>;
> > >>                       
> > >>                       };
> > >>                       
> > >>                       tcon_top_in_mixer1: endpoint@1 {
> > >>                       
> > >>                               reg = <1>;
> > >>                               remote-endpoint = <&mixer1_out_tcon_top>;
> > >>                       
> > >>                       };
> > >>                       
> > >>                       tcon_top_in_tcon_tv: endpoint@2 {
> > >>                       
> > >>                               reg = <2>;
> > >>                               // here is HDMI input connection, part of
> > >>                               board DTS
> > >>                               remote-endpoint = <board specific phandle
> > >>                               to TV TCON output>;
> > >>                       
> > >>                       };
> > >>               
> > >>               };
> > >>               
> > >>               tcon_top_out: port@1 {
> > >>               
> > >>                       #address-cells = <1>;
> > >>                       #size-cells = <0>;
> > >>                       reg = <1>;
> > >>                       
> > >>                       tcon_top_out_tcon0: endpoint@0 {
> > >>                       
> > >>                               reg = <0>;
> > >>                               // here is mixer0 output connection, part
> > >>                               of board DTS
> > >>                               remote-endpoint = <board specific phandle
> > >>                               to TCON>;
> > >>                       
> > >>                       };
> > >>                       
> > >>                       tcon_top_out_tcon1: endpoint@1 {
> > >>                       
> > >>                               reg = <1>;
> > >>                               // here is mixer1 output connection, part
> > >>                               of board DTS
> > >>                               remote-endpoint = <board specific phandle
> > >>                               to TCON>;
> > >>                       
> > >>                       };
> > >>                       
> > >>                       tcon_top_out_hdmi: endpoint@2 {
> > >>                       
> > >>                               reg = <2>;
> > >>                               remote-endpoint = <&hdmi_in_tcon_top>;
> > >>                       
> > >>                       };
> > >>               
> > >>               };
> > >>       
> > >>       };
> > >> 
> > >> };
> > > 
> > > IIRC, each port is supposed to be one route for the data, so we would
> > > have multiple ports, one for the mixers in input and for the tcon in
> > > output, and one for the TCON in input and for the HDMI/TV in
> > > output. Rob might correct me here.

Ok, that seems more clean approach. I'll have to extend graph traversing 
algorithm in sun4i_drv.c, but that's no problem.

Just to be clear, you have in mind 3 pairs of ports (0/1 for mixer0 mux, 2/3 
for mixer1 and 4/5 for HDMI input), right? That way each mux is represented 
with one pair of ports, even numbered for input and odd numbered for output.

> > > 
> > >> tcon_tv0: lcd-controller@1c73000 {
> > >> 
> > >>       compatible = "allwinner,sun8i-r40-tcon-tv-0";
> > >>       ...
> > >>       ports {
> > >>       
> > >>               #address-cells = <1>;
> > >>               #size-cells = <0>;
> > >>               
> > >>               tcon_tv0_in: port@0 {
> > >>               
> > >>                       reg = <0>;
> > >>                       
> > >>                       tcon_tv0_in_tcon_top: endpoint {
> > >>                       
> > >>                               // endpoint depends on board, part of
> > >>                               board DTS
> > >>                               remote-endpoint = <phandle to one of
> > >>                               tcon_top_out_tcon>;
> > > 
> > > Just curious, what would be there?

Either phandle to tcon_top_out_tcon0 or tcon_top_out_tcon1.

> > > 
> > >>                       };
> > >>               
> > >>               };
> > >>               
> > >>               tcon_tv0_out: port@1 {
> > >>               
> > >>                       #address-cells = <1>;
> > >>                       #size-cells = <0>;
> > >>                       reg = <1>;
> > >>                       
> > >>                       // endpoints to TV TOP and TCON TOP HDMI input
> > >>                       ...
> > >>               
> > >>               };
> > >>       
> > >>       };
> > >> 
> > >> };
> > >> 
> > >> tcon_tv1: lcd-controller@1c74000 {
> > >> 
> > >>       compatible = "allwinner,sun8i-r40-tcon-tv-1";
> > >>       ...
> > >>       ports {
> > >>       
> > >>               #address-cells = <1>;
> > >>               #size-cells = <0>;
> > >>               
> > >>               tcon_tv1_in: port@0 {
> > >>               
> > >>                       reg = <0>;
> > >>                       
> > >>                       tcon_tv1_in_tcon_top: endpoint {
> > >>                       
> > >>                               // endpoint depends on board, part of
> > >>                               board DTS
> > >>                               remote-endpoint = <phandle to one of
> > >>                               tcon_top_out_tcon>;
> > >>                       
> > >>                       };
> > >>               
> > >>               };
> > >>               
> > >>               tcon_tv1_out: port@1 {
> > >>               
> > >>                       #address-cells = <1>;
> > >>                       #size-cells = <0>;
> > >>                       reg = <1>;
> > >>                       
> > >>                       // endpoints to TV TOP and TCON TOP HDMI input
> > >>                       ...
> > >>               
> > >>               };
> > >>       
> > >>       };
> > >> 
> > >> };
> > >> 
> > >> tcon_lcd0 and tcon_lcd1 would have similar connections, except that for
> > >> outputs would be LCD or LVDS panels or MIPI DSI encoder.
> > >> 
> > >> Please note that each TCON (there are 4 of them) would need to have
> > >> unique
> > >> compatible and have HW index stored in quirks data. It would be used by
> > >> TCON TOP driver for configuring muxes.
> > > 
> > > Can't we use the port/endpoint ID instead? If the mux is the only
> > > thing that changes, the compatible has no reason to. It's the same IP,
> > > and the only thing that changes is something that is not part of that
> > > IP.
> > 
> > I agree. Endpoint IDs should provide that information. I'm still not
> > sure How to encode multiple in/out mux groups in a device node though.
> 
> I guess we can do that through different ports?

Ok, I'll try to do something with "reg" property.

Best regards,
Jernej

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

* Re: [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top
  2018-06-04 15:09                     ` Jernej Škrabec
@ 2018-06-04 16:23                       ` Maxime Ripard
  2018-06-06 22:30                         ` Jernej Škrabec
  0 siblings, 1 reply; 46+ messages in thread
From: Maxime Ripard @ 2018-06-04 16:23 UTC (permalink / raw)
  To: Jernej Škrabec
  Cc: Chen-Yu Tsai, Rob Herring, Mark Rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, linux-sunxi

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

On Mon, Jun 04, 2018 at 05:09:56PM +0200, Jernej Škrabec wrote:
> Dne ponedeljek, 04. junij 2018 ob 13:50:34 CEST je Maxime Ripard napisal(a):
> > On Fri, Jun 01, 2018 at 09:19:43AM -0700, Chen-Yu Tsai wrote:
> > > On Fri, Jun 1, 2018 at 8:29 AM, Maxime Ripard <maxime.ripard@bootlin.com> 
> wrote:
> > > > On Thu, May 31, 2018 at 07:54:08PM +0200, Jernej Škrabec wrote:
> > > >> Dne četrtek, 31. maj 2018 ob 11:21:33 CEST je Maxime Ripard napisal(a):
> > > >> > On Thu, May 24, 2018 at 03:01:09PM -0700, Chen-Yu Tsai wrote:
> > > >> > > >> > > + if (tcon->quirks->needs_tcon_top) {
> > > >> > > >> > > +         struct device_node *np;
> > > >> > > >> > > +
> > > >> > > >> > > +         np = of_parse_phandle(dev->of_node,
> > > >> > > >> > > "allwinner,tcon-top",
> > > >> > > >> > > 0);
> > > >> > > >> > > +         if (np) {
> > > >> > > >> > > +                 struct platform_device *pdev;
> > > >> > > >> > > +
> > > >> > > >> > > +                 pdev = of_find_device_by_node(np);
> > > >> > > >> > > +                 if (pdev)
> > > >> > > >> > > +                         tcon->tcon_top =
> > > >> > > >> > > platform_get_drvdata(pdev);
> > > >> > > >> > > +                 of_node_put(np);
> > > >> > > >> > > +
> > > >> > > >> > > +                 if (!tcon->tcon_top)
> > > >> > > >> > > +                         return -EPROBE_DEFER;
> > > >> > > >> > > +         }
> > > >> > > >> > > + }
> > > >> > > >> > > +
> > > >> > > >> > 
> > > >> > > >> > I might have missed it, but I've not seen the bindings
> > > >> > > >> > additions for
> > > >> > > >> > that property. This shouldn't really be done that way anyway,
> > > >> > > >> > instead
> > > >> > > >> > of using a direct phandle, you should be using the of-graph,
> > > >> > > >> > with the
> > > >> > > >> > TCON-top sitting where it belongs in the flow of data.
> > > >> > > >> 
> > > >> > > >> Just to answer to the first question, it did describe it in
> > > >> > > >> "[PATCH
> > > >> > > >> 07/15] dt- bindings: display: sun4i-drm: Add R40 HDMI pipeline".
> > > >> > > >> 
> > > >> > > >> As why I designed it that way - HW representation could be
> > > >> > > >> described
> > > >> > > >> that way> >>
> > > >> > > >> 
> > > >> > > >> (ASCII art makes sense when fixed width font is used to view 
> it):
> > > >> > > >>                             / LCD0/LVDS0
> > > >> > > >>                 
> > > >> > > >>                 / TCON-LCD0
> > > >> > > >>                 
> > > >> > > >>                 |           \ MIPI DSI
> > > >> > > >> 
> > > >> > > >> mixer0          |
> > > >> > > >> 
> > > >> > > >>        \        / TCON-LCD1 - LCD1/LVDS1
> > > >> > > >>        
> > > >> > > >>         TCON-TOP
> > > >> > > >>        
> > > >> > > >>        /        \ TCON-TV0 - TVE0/RGB
> > > >> > > >> 
> > > >> > > >> mixer1          |          \
> > > >> > > >> 
> > > >> > > >>                 |           TCON-TOP - HDMI
> > > >> > > >>                 |          
> > > >> > > >>                 |          /
> > > >> > > >>                 
> > > >> > > >>                 \ TCON-TV1 - TVE1/RGB
> > > >> > > >> 
> > > >> > > >> This is a bit simplified, since there is also TVE-TOP, which is
> > > >> > > >> responsible
> > > >> > > >> for sharing 4 DACs between both TVE encoders. You can have two
> > > >> > > >> TV outs
> > > >> > > >> (PAL/ NTSC) or TVE0 as TV out and TVE1 as RGB or vice versa. It
> > > >> > > >> even
> > > >> > > >> seems that you can arbitrarly choose which DAC is responsible
> > > >> > > >> for
> > > >> > > >> which signal, so there is a ton of possible end combinations,
> > > >> > > >> but I'm
> > > >> > > >> not 100% sure.
> > > >> > > >> 
> > > >> > > >> Even though I wrote TCON-TOP twice, this is same unit in HW. R40
> > > >> > > >> manual
> > > >> > > >> suggest more possibilities, although some of them seem wrong,
> > > >> > > >> like RGB
> > > >> > > >> feeding from LCD TCON. That is confirmed to be wrong when
> > > >> > > >> checking BSP
> > > >> > > >> code.
> > > >> > > >> 
> > > >> > > >> Additionally, TCON-TOP comes in the middle of TVE0 and LCD0,
> > > >> > > >> TVE1 and
> > > >> > > >> LCD1 for pin muxing, although I'm not sure why is that needed at
> > > >> > > >> all,
> > > >> > > >> since according to R40 datasheet, TVE0 and TVE1 pins are
> > > >> > > >> dedicated and
> > > >> > > >> not on PORT D and PORT H, respectively, as TCON-TOP
> > > >> > > >> documentation
> > > >> > > >> suggest. However, HSYNC and PSYNC lines might be shared between
> > > >> > > >> TVE
> > > >> > > >> (when it works in RGB mode) and LCD. But that is just my guess
> > > >> > > >> since
> > > >> > > >> I'm not really familiar with RGB and LCD interfaces.
> > > >> > > >> 
> > > >> > > >> I'm really not sure what would be the best representation in
> > > >> > > >> OF-graph.
> > > >> > > >> Can you suggest one?
> > > >> > > > 
> > > >> > > > Rob might disagree on this one, but I don't see anything wrong
> > > >> > > > with
> > > >> > > > having loops in the graph. If the TCON-TOP can be both the input
> > > >> > > > and
> > > >> > > > output of the TCONs, then so be it, and have it described that
> > > >> > > > way in
> > > >> > > > the graph.
> > > >> > > > 
> > > >> > > > The code is already able to filter out nodes that have already
> > > >> > > > been
> > > >> > > > added to the list of devices we need to wait for in the component
> > > >> > > > framework, so that should work as well.
> > > >> > > > 
> > > >> > > > And we'd need to describe TVE-TOP as well, even though we don't
> > > >> > > > have a
> > > >> > > > driver for it yet. That will simplify the backward compatibility
> > > >> > > > later
> > > >> > > > on.
> > > >> > > 
> > > >> > > I'm getting the feeling that TCON-TOP / TVE-TOP is the glue layer
> > > >> > > that
> > > >> > > binds everything together, and provides signal routing, kind of
> > > >> > > like
> > > >> > > DE-TOP on A64. So the signal mux controls that were originally
> > > >> > > found
> > > >> > > in TCON0 and TVE0 were moved out.
> > > >> > > 
> > > >> > > The driver needs to know about that, but the graph about doesn't
> > > >> > > make
> > > >> > > much sense directly. Without looking at the manual, I understand it
> > > >> > > to
> > > >> > > likely be one mux between the mixers and TCONs, and one between the
> > > >> > > TCON-TVs and HDMI. Would it make more sense to just have the graph
> > > >> > > connections between the muxed components, and remove TCON-TOP from
> > > >> > > it, like we had in the past? A phandle could be used to reference
> > > >> > > the TCON-TOP for mux controls, in addition to the clocks and
> > > >> > > resets.
> > > >> > > 
> > > >> > > For TVE, we would need something to represent each of the output
> > > >> > > pins,
> > > >> > > so the device tree can actually describe what kind of signal, be it
> > > >> > > each component of RGB/YUV or composite video, is wanted on each
> > > >> > > pin,
> > > >> > > if any. This is also needed on the A20 for the Cubietruck, so we
> > > >> > > can
> > > >> > > describe which pins are tied to the VGA connector, and which one
> > > >> > > does
> > > >> > > R, G, or B.
> > > >> > 
> > > >> > I guess we'll see how the DT maintainers feel about this, but my
> > > >> > impression is that the OF graph should model the flow of data between
> > > >> > the devices. If there's a mux somewhere, then the data is definitely
> > > >> > going through it, and as such it should be part of the graph.
> > > >> 
> > > >> I concur, but I spent few days thinking how to represent this sanely in
> > > >> graph, but I didn't find any good solution. I'll represent here my
> > > >> idea and please tell your opinion before I start implementing it.
> > > >> 
> > > >> First, let me be clear that mixer0 and mixer1 don't have same
> > > >> capabilities
> > > >> (different number of planes, mixer0 supports writeback, mixer1 does
> > > >> not,
> > > >> etc.). Thus, it does matter which mixer is connected to which
> > > >> TCON/encoder.
> > > >> mixer0 is meant to be connected to main display and mixer1 to
> > > >> auxiliary. That obviously depends on end system.
> > > >> 
> > > >> So, TCON TOP has 3 muxes, which have to be represented in graph. Two of
> > > >> them are for mixer/TCON relationship (each of them 1 input and 4
> > > >> possible outputs) and one for TV TCON/HDMI pair selection (2 possible
> > > >> inputs, 1 output).
> > > >> 
> > > >> According to current practice in sun4i-drm driver, graph has to have
> > > >> port 0, representing input and port 1, representing output. This would
> > > >> mean that graph looks something like that:
> > > >> 
> > > >> tcon_top: tcon-top@1c70000 {
> > > >> 
> > > >>       compatible = "allwinner,sun8i-r40-tcon-top";
> > > >>       ...
> > > >>       ports {
> > > >>       
> > > >>               #address-cells = <1>;
> > > >>               #size-cells = <0>;
> > > >>               
> > > >>               tcon_top_in: port@0 {
> > > >>               
> > > >>                       #address-cells = <1>;
> > > >>                       #size-cells = <0>;
> > > >>                       reg = <0>;
> > > >>                       
> > > >>                       tcon_top_in_mixer0: endpoint@0 {
> > > >>                       
> > > >>                               reg = <0>;
> > > >>                               remote-endpoint = <&mixer0_out_tcon_top>;
> > > >>                       
> > > >>                       };
> > > >>                       
> > > >>                       tcon_top_in_mixer1: endpoint@1 {
> > > >>                       
> > > >>                               reg = <1>;
> > > >>                               remote-endpoint = <&mixer1_out_tcon_top>;
> > > >>                       
> > > >>                       };
> > > >>                       
> > > >>                       tcon_top_in_tcon_tv: endpoint@2 {
> > > >>                       
> > > >>                               reg = <2>;
> > > >>                               // here is HDMI input connection, part of
> > > >>                               board DTS
> > > >>                               remote-endpoint = <board specific phandle
> > > >>                               to TV TCON output>;
> > > >>                       
> > > >>                       };
> > > >>               
> > > >>               };
> > > >>               
> > > >>               tcon_top_out: port@1 {
> > > >>               
> > > >>                       #address-cells = <1>;
> > > >>                       #size-cells = <0>;
> > > >>                       reg = <1>;
> > > >>                       
> > > >>                       tcon_top_out_tcon0: endpoint@0 {
> > > >>                       
> > > >>                               reg = <0>;
> > > >>                               // here is mixer0 output connection, part
> > > >>                               of board DTS
> > > >>                               remote-endpoint = <board specific phandle
> > > >>                               to TCON>;
> > > >>                       
> > > >>                       };
> > > >>                       
> > > >>                       tcon_top_out_tcon1: endpoint@1 {
> > > >>                       
> > > >>                               reg = <1>;
> > > >>                               // here is mixer1 output connection, part
> > > >>                               of board DTS
> > > >>                               remote-endpoint = <board specific phandle
> > > >>                               to TCON>;
> > > >>                       
> > > >>                       };
> > > >>                       
> > > >>                       tcon_top_out_hdmi: endpoint@2 {
> > > >>                       
> > > >>                               reg = <2>;
> > > >>                               remote-endpoint = <&hdmi_in_tcon_top>;
> > > >>                       
> > > >>                       };
> > > >>               
> > > >>               };
> > > >>       
> > > >>       };
> > > >> 
> > > >> };
> > > > 
> > > > IIRC, each port is supposed to be one route for the data, so we would
> > > > have multiple ports, one for the mixers in input and for the tcon in
> > > > output, and one for the TCON in input and for the HDMI/TV in
> > > > output. Rob might correct me here.
> 
> Ok, that seems more clean approach. I'll have to extend graph traversing 
> algorithm in sun4i_drv.c, but that's no problem.
> 
> Just to be clear, you have in mind 3 pairs of ports (0/1 for mixer0 mux, 2/3 
> for mixer1 and 4/5 for HDMI input), right? That way each mux is represented 
> with one pair of ports, even numbered for input and odd numbered for output.

Yep, unless Rob feels otherwise.

Maxime

-- 
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

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

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

* Re: [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top
  2018-06-04 16:23                       ` Maxime Ripard
@ 2018-06-06 22:30                         ` Jernej Škrabec
  2018-06-08  5:17                           ` [linux-sunxi] " Jernej Škrabec
  0 siblings, 1 reply; 46+ messages in thread
From: Jernej Škrabec @ 2018-06-06 22:30 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Chen-Yu Tsai, Rob Herring, Mark Rutland, dri-devel, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, linux-sunxi

Dne ponedeljek, 04. junij 2018 ob 18:23:57 CEST je Maxime Ripard napisal(a):
> On Mon, Jun 04, 2018 at 05:09:56PM +0200, Jernej Škrabec wrote:
> > Dne ponedeljek, 04. junij 2018 ob 13:50:34 CEST je Maxime Ripard 
napisal(a):
> > > On Fri, Jun 01, 2018 at 09:19:43AM -0700, Chen-Yu Tsai wrote:
> > > > On Fri, Jun 1, 2018 at 8:29 AM, Maxime Ripard
> > > > <maxime.ripard@bootlin.com>
> > 
> > wrote:
> > > > > On Thu, May 31, 2018 at 07:54:08PM +0200, Jernej Škrabec wrote:
> > > > >> Dne četrtek, 31. maj 2018 ob 11:21:33 CEST je Maxime Ripard 
napisal(a):
> > > > >> > On Thu, May 24, 2018 at 03:01:09PM -0700, Chen-Yu Tsai wrote:
> > > > >> > > >> > > + if (tcon->quirks->needs_tcon_top) {
> > > > >> > > >> > > +         struct device_node *np;
> > > > >> > > >> > > +
> > > > >> > > >> > > +         np = of_parse_phandle(dev->of_node,
> > > > >> > > >> > > "allwinner,tcon-top",
> > > > >> > > >> > > 0);
> > > > >> > > >> > > +         if (np) {
> > > > >> > > >> > > +                 struct platform_device *pdev;
> > > > >> > > >> > > +
> > > > >> > > >> > > +                 pdev = of_find_device_by_node(np);
> > > > >> > > >> > > +                 if (pdev)
> > > > >> > > >> > > +                         tcon->tcon_top =
> > > > >> > > >> > > platform_get_drvdata(pdev);
> > > > >> > > >> > > +                 of_node_put(np);
> > > > >> > > >> > > +
> > > > >> > > >> > > +                 if (!tcon->tcon_top)
> > > > >> > > >> > > +                         return -EPROBE_DEFER;
> > > > >> > > >> > > +         }
> > > > >> > > >> > > + }
> > > > >> > > >> > > +
> > > > >> > > >> > 
> > > > >> > > >> > I might have missed it, but I've not seen the bindings
> > > > >> > > >> > additions for
> > > > >> > > >> > that property. This shouldn't really be done that way
> > > > >> > > >> > anyway,
> > > > >> > > >> > instead
> > > > >> > > >> > of using a direct phandle, you should be using the
> > > > >> > > >> > of-graph,
> > > > >> > > >> > with the
> > > > >> > > >> > TCON-top sitting where it belongs in the flow of data.
> > > > >> > > >> 
> > > > >> > > >> Just to answer to the first question, it did describe it in
> > > > >> > > >> "[PATCH
> > > > >> > > >> 07/15] dt- bindings: display: sun4i-drm: Add R40 HDMI
> > > > >> > > >> pipeline".
> > > > >> > > >> 
> > > > >> > > >> As why I designed it that way - HW representation could be
> > > > >> > > >> described
> > > > >> > > >> that way> >>
> > > > >> > > >> 
> > > > >> > > >> (ASCII art makes sense when fixed width font is used to view
> > 
> > it):
> > > > >> > > >>                             / LCD0/LVDS0
> > > > >> > > >>                 
> > > > >> > > >>                 / TCON-LCD0
> > > > >> > > >>                 
> > > > >> > > >>                 |           \ MIPI DSI
> > > > >> > > >> 
> > > > >> > > >> mixer0          |
> > > > >> > > >> 
> > > > >> > > >>        \        / TCON-LCD1 - LCD1/LVDS1
> > > > >> > > >>        
> > > > >> > > >>         TCON-TOP
> > > > >> > > >>        
> > > > >> > > >>        /        \ TCON-TV0 - TVE0/RGB
> > > > >> > > >> 
> > > > >> > > >> mixer1          |          \
> > > > >> > > >> 
> > > > >> > > >>                 |           TCON-TOP - HDMI
> > > > >> > > >>                 |          
> > > > >> > > >>                 |          /
> > > > >> > > >>                 
> > > > >> > > >>                 \ TCON-TV1 - TVE1/RGB
> > > > >> > > >> 
> > > > >> > > >> This is a bit simplified, since there is also TVE-TOP, which
> > > > >> > > >> is
> > > > >> > > >> responsible
> > > > >> > > >> for sharing 4 DACs between both TVE encoders. You can have
> > > > >> > > >> two
> > > > >> > > >> TV outs
> > > > >> > > >> (PAL/ NTSC) or TVE0 as TV out and TVE1 as RGB or vice versa.
> > > > >> > > >> It
> > > > >> > > >> even
> > > > >> > > >> seems that you can arbitrarly choose which DAC is
> > > > >> > > >> responsible
> > > > >> > > >> for
> > > > >> > > >> which signal, so there is a ton of possible end
> > > > >> > > >> combinations,
> > > > >> > > >> but I'm
> > > > >> > > >> not 100% sure.
> > > > >> > > >> 
> > > > >> > > >> Even though I wrote TCON-TOP twice, this is same unit in HW.
> > > > >> > > >> R40
> > > > >> > > >> manual
> > > > >> > > >> suggest more possibilities, although some of them seem
> > > > >> > > >> wrong,
> > > > >> > > >> like RGB
> > > > >> > > >> feeding from LCD TCON. That is confirmed to be wrong when
> > > > >> > > >> checking BSP
> > > > >> > > >> code.
> > > > >> > > >> 
> > > > >> > > >> Additionally, TCON-TOP comes in the middle of TVE0 and LCD0,
> > > > >> > > >> TVE1 and
> > > > >> > > >> LCD1 for pin muxing, although I'm not sure why is that
> > > > >> > > >> needed at
> > > > >> > > >> all,
> > > > >> > > >> since according to R40 datasheet, TVE0 and TVE1 pins are
> > > > >> > > >> dedicated and
> > > > >> > > >> not on PORT D and PORT H, respectively, as TCON-TOP
> > > > >> > > >> documentation
> > > > >> > > >> suggest. However, HSYNC and PSYNC lines might be shared
> > > > >> > > >> between
> > > > >> > > >> TVE
> > > > >> > > >> (when it works in RGB mode) and LCD. But that is just my
> > > > >> > > >> guess
> > > > >> > > >> since
> > > > >> > > >> I'm not really familiar with RGB and LCD interfaces.
> > > > >> > > >> 
> > > > >> > > >> I'm really not sure what would be the best representation in
> > > > >> > > >> OF-graph.
> > > > >> > > >> Can you suggest one?
> > > > >> > > > 
> > > > >> > > > Rob might disagree on this one, but I don't see anything
> > > > >> > > > wrong
> > > > >> > > > with
> > > > >> > > > having loops in the graph. If the TCON-TOP can be both the
> > > > >> > > > input
> > > > >> > > > and
> > > > >> > > > output of the TCONs, then so be it, and have it described
> > > > >> > > > that
> > > > >> > > > way in
> > > > >> > > > the graph.
> > > > >> > > > 
> > > > >> > > > The code is already able to filter out nodes that have
> > > > >> > > > already
> > > > >> > > > been
> > > > >> > > > added to the list of devices we need to wait for in the
> > > > >> > > > component
> > > > >> > > > framework, so that should work as well.
> > > > >> > > > 
> > > > >> > > > And we'd need to describe TVE-TOP as well, even though we
> > > > >> > > > don't
> > > > >> > > > have a
> > > > >> > > > driver for it yet. That will simplify the backward
> > > > >> > > > compatibility
> > > > >> > > > later
> > > > >> > > > on.
> > > > >> > > 
> > > > >> > > I'm getting the feeling that TCON-TOP / TVE-TOP is the glue
> > > > >> > > layer
> > > > >> > > that
> > > > >> > > binds everything together, and provides signal routing, kind of
> > > > >> > > like
> > > > >> > > DE-TOP on A64. So the signal mux controls that were originally
> > > > >> > > found
> > > > >> > > in TCON0 and TVE0 were moved out.
> > > > >> > > 
> > > > >> > > The driver needs to know about that, but the graph about
> > > > >> > > doesn't
> > > > >> > > make
> > > > >> > > much sense directly. Without looking at the manual, I
> > > > >> > > understand it
> > > > >> > > to
> > > > >> > > likely be one mux between the mixers and TCONs, and one between
> > > > >> > > the
> > > > >> > > TCON-TVs and HDMI. Would it make more sense to just have the
> > > > >> > > graph
> > > > >> > > connections between the muxed components, and remove TCON-TOP
> > > > >> > > from
> > > > >> > > it, like we had in the past? A phandle could be used to
> > > > >> > > reference
> > > > >> > > the TCON-TOP for mux controls, in addition to the clocks and
> > > > >> > > resets.
> > > > >> > > 
> > > > >> > > For TVE, we would need something to represent each of the
> > > > >> > > output
> > > > >> > > pins,
> > > > >> > > so the device tree can actually describe what kind of signal,
> > > > >> > > be it
> > > > >> > > each component of RGB/YUV or composite video, is wanted on each
> > > > >> > > pin,
> > > > >> > > if any. This is also needed on the A20 for the Cubietruck, so
> > > > >> > > we
> > > > >> > > can
> > > > >> > > describe which pins are tied to the VGA connector, and which
> > > > >> > > one
> > > > >> > > does
> > > > >> > > R, G, or B.
> > > > >> > 
> > > > >> > I guess we'll see how the DT maintainers feel about this, but my
> > > > >> > impression is that the OF graph should model the flow of data
> > > > >> > between
> > > > >> > the devices. If there's a mux somewhere, then the data is
> > > > >> > definitely
> > > > >> > going through it, and as such it should be part of the graph.
> > > > >> 
> > > > >> I concur, but I spent few days thinking how to represent this
> > > > >> sanely in
> > > > >> graph, but I didn't find any good solution. I'll represent here my
> > > > >> idea and please tell your opinion before I start implementing it.
> > > > >> 
> > > > >> First, let me be clear that mixer0 and mixer1 don't have same
> > > > >> capabilities
> > > > >> (different number of planes, mixer0 supports writeback, mixer1 does
> > > > >> not,
> > > > >> etc.). Thus, it does matter which mixer is connected to which
> > > > >> TCON/encoder.
> > > > >> mixer0 is meant to be connected to main display and mixer1 to
> > > > >> auxiliary. That obviously depends on end system.
> > > > >> 
> > > > >> So, TCON TOP has 3 muxes, which have to be represented in graph.
> > > > >> Two of
> > > > >> them are for mixer/TCON relationship (each of them 1 input and 4
> > > > >> possible outputs) and one for TV TCON/HDMI pair selection (2
> > > > >> possible
> > > > >> inputs, 1 output).
> > > > >> 
> > > > >> According to current practice in sun4i-drm driver, graph has to
> > > > >> have
> > > > >> port 0, representing input and port 1, representing output. This
> > > > >> would
> > > > >> mean that graph looks something like that:
> > > > >> 
> > > > >> tcon_top: tcon-top@1c70000 {
> > > > >> 
> > > > >>       compatible = "allwinner,sun8i-r40-tcon-top";
> > > > >>       ...
> > > > >>       ports {
> > > > >>       
> > > > >>               #address-cells = <1>;
> > > > >>               #size-cells = <0>;
> > > > >>               
> > > > >>               tcon_top_in: port@0 {
> > > > >>               
> > > > >>                       #address-cells = <1>;
> > > > >>                       #size-cells = <0>;
> > > > >>                       reg = <0>;
> > > > >>                       
> > > > >>                       tcon_top_in_mixer0: endpoint@0 {
> > > > >>                       
> > > > >>                               reg = <0>;
> > > > >>                               remote-endpoint =
> > > > >>                               <&mixer0_out_tcon_top>;
> > > > >>                       
> > > > >>                       };
> > > > >>                       
> > > > >>                       tcon_top_in_mixer1: endpoint@1 {
> > > > >>                       
> > > > >>                               reg = <1>;
> > > > >>                               remote-endpoint =
> > > > >>                               <&mixer1_out_tcon_top>;
> > > > >>                       
> > > > >>                       };
> > > > >>                       
> > > > >>                       tcon_top_in_tcon_tv: endpoint@2 {
> > > > >>                       
> > > > >>                               reg = <2>;
> > > > >>                               // here is HDMI input connection,
> > > > >>                               part of
> > > > >>                               board DTS
> > > > >>                               remote-endpoint = <board specific
> > > > >>                               phandle
> > > > >>                               to TV TCON output>;
> > > > >>                       
> > > > >>                       };
> > > > >>               
> > > > >>               };
> > > > >>               
> > > > >>               tcon_top_out: port@1 {
> > > > >>               
> > > > >>                       #address-cells = <1>;
> > > > >>                       #size-cells = <0>;
> > > > >>                       reg = <1>;
> > > > >>                       
> > > > >>                       tcon_top_out_tcon0: endpoint@0 {
> > > > >>                       
> > > > >>                               reg = <0>;
> > > > >>                               // here is mixer0 output connection,
> > > > >>                               part
> > > > >>                               of board DTS
> > > > >>                               remote-endpoint = <board specific
> > > > >>                               phandle
> > > > >>                               to TCON>;
> > > > >>                       
> > > > >>                       };
> > > > >>                       
> > > > >>                       tcon_top_out_tcon1: endpoint@1 {
> > > > >>                       
> > > > >>                               reg = <1>;
> > > > >>                               // here is mixer1 output connection,
> > > > >>                               part
> > > > >>                               of board DTS
> > > > >>                               remote-endpoint = <board specific
> > > > >>                               phandle
> > > > >>                               to TCON>;
> > > > >>                       
> > > > >>                       };
> > > > >>                       
> > > > >>                       tcon_top_out_hdmi: endpoint@2 {
> > > > >>                       
> > > > >>                               reg = <2>;
> > > > >>                               remote-endpoint =
> > > > >>                               <&hdmi_in_tcon_top>;
> > > > >>                       
> > > > >>                       };
> > > > >>               
> > > > >>               };
> > > > >>       
> > > > >>       };
> > > > >> 
> > > > >> };
> > > > > 
> > > > > IIRC, each port is supposed to be one route for the data, so we
> > > > > would
> > > > > have multiple ports, one for the mixers in input and for the tcon in
> > > > > output, and one for the TCON in input and for the HDMI/TV in
> > > > > output. Rob might correct me here.
> > 
> > Ok, that seems more clean approach. I'll have to extend graph traversing
> > algorithm in sun4i_drv.c, but that's no problem.
> > 
> > Just to be clear, you have in mind 3 pairs of ports (0/1 for mixer0 mux,
> > 2/3 for mixer1 and 4/5 for HDMI input), right? That way each mux is
> > represented with one pair of ports, even numbered for input and odd
> > numbered for output.
> Yep, unless Rob feels otherwise.

I found an issue with this concept.

HDMI driver (sun8i_dw_hdmi.c) uses drm_of_find_possible_crtcs() to find 
connected crtcs (TCONs) to HDMI. This function assumes that crtc and encoder 
are directly connected through of_graph, but that is not the case with TCON 
TOP HDMI mux anymore. 
I could give TCON TOP node as an input to this function, but that won't work, 
since TCON TOP can have connections to other crtcs, not only that of HDMI and 
they will also be picked up by drm_of_find_possible_crtcs().

Any suggestion how to solve this nicely? I think creating my own version of 
drm_of_find_possible_crtcs() which considers that case is one way, but not 
very nice solution. Alternatively, we can fix possible_crtcs to BIT(0), since 
it always has only one input. This is done in meson_dw_hdmi.c for example. 

Best regards,
Jernej

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

* Re: [linux-sunxi] Re: [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top
  2018-06-06 22:30                         ` Jernej Škrabec
@ 2018-06-08  5:17                           ` Jernej Škrabec
  0 siblings, 0 replies; 46+ messages in thread
From: Jernej Škrabec @ 2018-06-08  5:17 UTC (permalink / raw)
  To: linux-sunxi
  Cc: Maxime Ripard, Chen-Yu Tsai, Rob Herring, Mark Rutland,
	dri-devel, devicetree, linux-arm-kernel, linux-kernel, linux-clk

Dne četrtek, 07. junij 2018 ob 00:30:24 CEST je Jernej Škrabec napisal(a):
> Dne ponedeljek, 04. junij 2018 ob 18:23:57 CEST je Maxime Ripard napisal(a):
> > On Mon, Jun 04, 2018 at 05:09:56PM +0200, Jernej Škrabec wrote:
> > > Dne ponedeljek, 04. junij 2018 ob 13:50:34 CEST je Maxime Ripard
> 
> napisal(a):
> > > > On Fri, Jun 01, 2018 at 09:19:43AM -0700, Chen-Yu Tsai wrote:
> > > > > On Fri, Jun 1, 2018 at 8:29 AM, Maxime Ripard
> > > > > <maxime.ripard@bootlin.com>
> > > 
> > > wrote:
> > > > > > On Thu, May 31, 2018 at 07:54:08PM +0200, Jernej Škrabec wrote:
> > > > > >> Dne četrtek, 31. maj 2018 ob 11:21:33 CEST je Maxime Ripard
> 
> napisal(a):
> > > > > >> > On Thu, May 24, 2018 at 03:01:09PM -0700, Chen-Yu Tsai wrote:
> > > > > >> > > >> > > + if (tcon->quirks->needs_tcon_top) {
> > > > > >> > > >> > > +         struct device_node *np;
> > > > > >> > > >> > > +
> > > > > >> > > >> > > +         np = of_parse_phandle(dev->of_node,
> > > > > >> > > >> > > "allwinner,tcon-top",
> > > > > >> > > >> > > 0);
> > > > > >> > > >> > > +         if (np) {
> > > > > >> > > >> > > +                 struct platform_device *pdev;
> > > > > >> > > >> > > +
> > > > > >> > > >> > > +                 pdev = of_find_device_by_node(np);
> > > > > >> > > >> > > +                 if (pdev)
> > > > > >> > > >> > > +                         tcon->tcon_top =
> > > > > >> > > >> > > platform_get_drvdata(pdev);
> > > > > >> > > >> > > +                 of_node_put(np);
> > > > > >> > > >> > > +
> > > > > >> > > >> > > +                 if (!tcon->tcon_top)
> > > > > >> > > >> > > +                         return -EPROBE_DEFER;
> > > > > >> > > >> > > +         }
> > > > > >> > > >> > > + }
> > > > > >> > > >> > > +
> > > > > >> > > >> > 
> > > > > >> > > >> > I might have missed it, but I've not seen the bindings
> > > > > >> > > >> > additions for
> > > > > >> > > >> > that property. This shouldn't really be done that way
> > > > > >> > > >> > anyway,
> > > > > >> > > >> > instead
> > > > > >> > > >> > of using a direct phandle, you should be using the
> > > > > >> > > >> > of-graph,
> > > > > >> > > >> > with the
> > > > > >> > > >> > TCON-top sitting where it belongs in the flow of data.
> > > > > >> > > >> 
> > > > > >> > > >> Just to answer to the first question, it did describe it
> > > > > >> > > >> in
> > > > > >> > > >> "[PATCH
> > > > > >> > > >> 07/15] dt- bindings: display: sun4i-drm: Add R40 HDMI
> > > > > >> > > >> pipeline".
> > > > > >> > > >> 
> > > > > >> > > >> As why I designed it that way - HW representation could be
> > > > > >> > > >> described
> > > > > >> > > >> that way> >>
> > > > > >> > > >> 
> > > > > >> > > >> (ASCII art makes sense when fixed width font is used to
> > > > > >> > > >> view
> > > 
> > > it):
> > > > > >> > > >>                             / LCD0/LVDS0
> > > > > >> > > >>                 
> > > > > >> > > >>                 / TCON-LCD0
> > > > > >> > > >>                 
> > > > > >> > > >>                 |           \ MIPI DSI
> > > > > >> > > >> 
> > > > > >> > > >> mixer0          |
> > > > > >> > > >> 
> > > > > >> > > >>        \        / TCON-LCD1 - LCD1/LVDS1
> > > > > >> > > >>        
> > > > > >> > > >>         TCON-TOP
> > > > > >> > > >>        
> > > > > >> > > >>        /        \ TCON-TV0 - TVE0/RGB
> > > > > >> > > >> 
> > > > > >> > > >> mixer1          |          \
> > > > > >> > > >> 
> > > > > >> > > >>                 |           TCON-TOP - HDMI
> > > > > >> > > >>                 |          
> > > > > >> > > >>                 |          /
> > > > > >> > > >>                 
> > > > > >> > > >>                 \ TCON-TV1 - TVE1/RGB
> > > > > >> > > >> 
> > > > > >> > > >> This is a bit simplified, since there is also TVE-TOP,
> > > > > >> > > >> which
> > > > > >> > > >> is
> > > > > >> > > >> responsible
> > > > > >> > > >> for sharing 4 DACs between both TVE encoders. You can have
> > > > > >> > > >> two
> > > > > >> > > >> TV outs
> > > > > >> > > >> (PAL/ NTSC) or TVE0 as TV out and TVE1 as RGB or vice
> > > > > >> > > >> versa.
> > > > > >> > > >> It
> > > > > >> > > >> even
> > > > > >> > > >> seems that you can arbitrarly choose which DAC is
> > > > > >> > > >> responsible
> > > > > >> > > >> for
> > > > > >> > > >> which signal, so there is a ton of possible end
> > > > > >> > > >> combinations,
> > > > > >> > > >> but I'm
> > > > > >> > > >> not 100% sure.
> > > > > >> > > >> 
> > > > > >> > > >> Even though I wrote TCON-TOP twice, this is same unit in
> > > > > >> > > >> HW.
> > > > > >> > > >> R40
> > > > > >> > > >> manual
> > > > > >> > > >> suggest more possibilities, although some of them seem
> > > > > >> > > >> wrong,
> > > > > >> > > >> like RGB
> > > > > >> > > >> feeding from LCD TCON. That is confirmed to be wrong when
> > > > > >> > > >> checking BSP
> > > > > >> > > >> code.
> > > > > >> > > >> 
> > > > > >> > > >> Additionally, TCON-TOP comes in the middle of TVE0 and
> > > > > >> > > >> LCD0,
> > > > > >> > > >> TVE1 and
> > > > > >> > > >> LCD1 for pin muxing, although I'm not sure why is that
> > > > > >> > > >> needed at
> > > > > >> > > >> all,
> > > > > >> > > >> since according to R40 datasheet, TVE0 and TVE1 pins are
> > > > > >> > > >> dedicated and
> > > > > >> > > >> not on PORT D and PORT H, respectively, as TCON-TOP
> > > > > >> > > >> documentation
> > > > > >> > > >> suggest. However, HSYNC and PSYNC lines might be shared
> > > > > >> > > >> between
> > > > > >> > > >> TVE
> > > > > >> > > >> (when it works in RGB mode) and LCD. But that is just my
> > > > > >> > > >> guess
> > > > > >> > > >> since
> > > > > >> > > >> I'm not really familiar with RGB and LCD interfaces.
> > > > > >> > > >> 
> > > > > >> > > >> I'm really not sure what would be the best representation
> > > > > >> > > >> in
> > > > > >> > > >> OF-graph.
> > > > > >> > > >> Can you suggest one?
> > > > > >> > > > 
> > > > > >> > > > Rob might disagree on this one, but I don't see anything
> > > > > >> > > > wrong
> > > > > >> > > > with
> > > > > >> > > > having loops in the graph. If the TCON-TOP can be both the
> > > > > >> > > > input
> > > > > >> > > > and
> > > > > >> > > > output of the TCONs, then so be it, and have it described
> > > > > >> > > > that
> > > > > >> > > > way in
> > > > > >> > > > the graph.
> > > > > >> > > > 
> > > > > >> > > > The code is already able to filter out nodes that have
> > > > > >> > > > already
> > > > > >> > > > been
> > > > > >> > > > added to the list of devices we need to wait for in the
> > > > > >> > > > component
> > > > > >> > > > framework, so that should work as well.
> > > > > >> > > > 
> > > > > >> > > > And we'd need to describe TVE-TOP as well, even though we
> > > > > >> > > > don't
> > > > > >> > > > have a
> > > > > >> > > > driver for it yet. That will simplify the backward
> > > > > >> > > > compatibility
> > > > > >> > > > later
> > > > > >> > > > on.
> > > > > >> > > 
> > > > > >> > > I'm getting the feeling that TCON-TOP / TVE-TOP is the glue
> > > > > >> > > layer
> > > > > >> > > that
> > > > > >> > > binds everything together, and provides signal routing, kind
> > > > > >> > > of
> > > > > >> > > like
> > > > > >> > > DE-TOP on A64. So the signal mux controls that were
> > > > > >> > > originally
> > > > > >> > > found
> > > > > >> > > in TCON0 and TVE0 were moved out.
> > > > > >> > > 
> > > > > >> > > The driver needs to know about that, but the graph about
> > > > > >> > > doesn't
> > > > > >> > > make
> > > > > >> > > much sense directly. Without looking at the manual, I
> > > > > >> > > understand it
> > > > > >> > > to
> > > > > >> > > likely be one mux between the mixers and TCONs, and one
> > > > > >> > > between
> > > > > >> > > the
> > > > > >> > > TCON-TVs and HDMI. Would it make more sense to just have the
> > > > > >> > > graph
> > > > > >> > > connections between the muxed components, and remove TCON-TOP
> > > > > >> > > from
> > > > > >> > > it, like we had in the past? A phandle could be used to
> > > > > >> > > reference
> > > > > >> > > the TCON-TOP for mux controls, in addition to the clocks and
> > > > > >> > > resets.
> > > > > >> > > 
> > > > > >> > > For TVE, we would need something to represent each of the
> > > > > >> > > output
> > > > > >> > > pins,
> > > > > >> > > so the device tree can actually describe what kind of signal,
> > > > > >> > > be it
> > > > > >> > > each component of RGB/YUV or composite video, is wanted on
> > > > > >> > > each
> > > > > >> > > pin,
> > > > > >> > > if any. This is also needed on the A20 for the Cubietruck, so
> > > > > >> > > we
> > > > > >> > > can
> > > > > >> > > describe which pins are tied to the VGA connector, and which
> > > > > >> > > one
> > > > > >> > > does
> > > > > >> > > R, G, or B.
> > > > > >> > 
> > > > > >> > I guess we'll see how the DT maintainers feel about this, but
> > > > > >> > my
> > > > > >> > impression is that the OF graph should model the flow of data
> > > > > >> > between
> > > > > >> > the devices. If there's a mux somewhere, then the data is
> > > > > >> > definitely
> > > > > >> > going through it, and as such it should be part of the graph.
> > > > > >> 
> > > > > >> I concur, but I spent few days thinking how to represent this
> > > > > >> sanely in
> > > > > >> graph, but I didn't find any good solution. I'll represent here
> > > > > >> my
> > > > > >> idea and please tell your opinion before I start implementing it.
> > > > > >> 
> > > > > >> First, let me be clear that mixer0 and mixer1 don't have same
> > > > > >> capabilities
> > > > > >> (different number of planes, mixer0 supports writeback, mixer1
> > > > > >> does
> > > > > >> not,
> > > > > >> etc.). Thus, it does matter which mixer is connected to which
> > > > > >> TCON/encoder.
> > > > > >> mixer0 is meant to be connected to main display and mixer1 to
> > > > > >> auxiliary. That obviously depends on end system.
> > > > > >> 
> > > > > >> So, TCON TOP has 3 muxes, which have to be represented in graph.
> > > > > >> Two of
> > > > > >> them are for mixer/TCON relationship (each of them 1 input and 4
> > > > > >> possible outputs) and one for TV TCON/HDMI pair selection (2
> > > > > >> possible
> > > > > >> inputs, 1 output).
> > > > > >> 
> > > > > >> According to current practice in sun4i-drm driver, graph has to
> > > > > >> have
> > > > > >> port 0, representing input and port 1, representing output. This
> > > > > >> would
> > > > > >> mean that graph looks something like that:
> > > > > >> 
> > > > > >> tcon_top: tcon-top@1c70000 {
> > > > > >> 
> > > > > >>       compatible = "allwinner,sun8i-r40-tcon-top";
> > > > > >>       ...
> > > > > >>       ports {
> > > > > >>       
> > > > > >>               #address-cells = <1>;
> > > > > >>               #size-cells = <0>;
> > > > > >>               
> > > > > >>               tcon_top_in: port@0 {
> > > > > >>               
> > > > > >>                       #address-cells = <1>;
> > > > > >>                       #size-cells = <0>;
> > > > > >>                       reg = <0>;
> > > > > >>                       
> > > > > >>                       tcon_top_in_mixer0: endpoint@0 {
> > > > > >>                       
> > > > > >>                               reg = <0>;
> > > > > >>                               remote-endpoint =
> > > > > >>                               <&mixer0_out_tcon_top>;
> > > > > >>                       
> > > > > >>                       };
> > > > > >>                       
> > > > > >>                       tcon_top_in_mixer1: endpoint@1 {
> > > > > >>                       
> > > > > >>                               reg = <1>;
> > > > > >>                               remote-endpoint =
> > > > > >>                               <&mixer1_out_tcon_top>;
> > > > > >>                       
> > > > > >>                       };
> > > > > >>                       
> > > > > >>                       tcon_top_in_tcon_tv: endpoint@2 {
> > > > > >>                       
> > > > > >>                               reg = <2>;
> > > > > >>                               // here is HDMI input connection,
> > > > > >>                               part of
> > > > > >>                               board DTS
> > > > > >>                               remote-endpoint = <board specific
> > > > > >>                               phandle
> > > > > >>                               to TV TCON output>;
> > > > > >>                       
> > > > > >>                       };
> > > > > >>               
> > > > > >>               };
> > > > > >>               
> > > > > >>               tcon_top_out: port@1 {
> > > > > >>               
> > > > > >>                       #address-cells = <1>;
> > > > > >>                       #size-cells = <0>;
> > > > > >>                       reg = <1>;
> > > > > >>                       
> > > > > >>                       tcon_top_out_tcon0: endpoint@0 {
> > > > > >>                       
> > > > > >>                               reg = <0>;
> > > > > >>                               // here is mixer0 output
> > > > > >>                               connection,
> > > > > >>                               part
> > > > > >>                               of board DTS
> > > > > >>                               remote-endpoint = <board specific
> > > > > >>                               phandle
> > > > > >>                               to TCON>;
> > > > > >>                       
> > > > > >>                       };
> > > > > >>                       
> > > > > >>                       tcon_top_out_tcon1: endpoint@1 {
> > > > > >>                       
> > > > > >>                               reg = <1>;
> > > > > >>                               // here is mixer1 output
> > > > > >>                               connection,
> > > > > >>                               part
> > > > > >>                               of board DTS
> > > > > >>                               remote-endpoint = <board specific
> > > > > >>                               phandle
> > > > > >>                               to TCON>;
> > > > > >>                       
> > > > > >>                       };
> > > > > >>                       
> > > > > >>                       tcon_top_out_hdmi: endpoint@2 {
> > > > > >>                       
> > > > > >>                               reg = <2>;
> > > > > >>                               remote-endpoint =
> > > > > >>                               <&hdmi_in_tcon_top>;
> > > > > >>                       
> > > > > >>                       };
> > > > > >>               
> > > > > >>               };
> > > > > >>       
> > > > > >>       };
> > > > > >> 
> > > > > >> };
> > > > > > 
> > > > > > IIRC, each port is supposed to be one route for the data, so we
> > > > > > would
> > > > > > have multiple ports, one for the mixers in input and for the tcon
> > > > > > in
> > > > > > output, and one for the TCON in input and for the HDMI/TV in
> > > > > > output. Rob might correct me here.
> > > 
> > > Ok, that seems more clean approach. I'll have to extend graph traversing
> > > algorithm in sun4i_drv.c, but that's no problem.
> > > 
> > > Just to be clear, you have in mind 3 pairs of ports (0/1 for mixer0 mux,
> > > 2/3 for mixer1 and 4/5 for HDMI input), right? That way each mux is
> > > represented with one pair of ports, even numbered for input and odd
> > > numbered for output.
> > 
> > Yep, unless Rob feels otherwise.
> 
> I found an issue with this concept.
> 
> HDMI driver (sun8i_dw_hdmi.c) uses drm_of_find_possible_crtcs() to find
> connected crtcs (TCONs) to HDMI. This function assumes that crtc and encoder
> are directly connected through of_graph, but that is not the case with TCON
> TOP HDMI mux anymore.
> I could give TCON TOP node as an input to this function, but that won't
> work, since TCON TOP can have connections to other crtcs, not only that of
> HDMI and they will also be picked up by drm_of_find_possible_crtcs().
> 
> Any suggestion how to solve this nicely? I think creating my own version of
> drm_of_find_possible_crtcs() which considers that case is one way, but not
> very nice solution. Alternatively, we can fix possible_crtcs to BIT(0),

This doesn't seem like a good solution, since it doesn't work in dual head 
system. I'll take first approach.

Best regards,
Jernej

> since it always has only one input. This is done in meson_dw_hdmi.c for
> example.

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

end of thread, other threads:[~2018-06-08  5:18 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-19 18:31 [PATCH 00/15] Add support for R40 HDMI pipeline Jernej Skrabec
2018-05-19 18:31 ` [PATCH 01/15] clk: sunxi-ng: r40: Add minimal rate for video PLLs Jernej Skrabec
2018-05-19 18:31 ` [PATCH 02/15] clk: sunxi-ng: r40: Allow setting parent rate to display related clocks Jernej Skrabec
2018-05-19 18:31 ` [PATCH 03/15] clk: sunxi-ng: r40: Export video PLLs Jernej Skrabec
2018-05-23 18:20   ` Rob Herring
2018-05-19 18:31 ` [PATCH 04/15] dt-bindings: display: sunxi-drm: Add TCON TOP description Jernej Skrabec
2018-05-21  8:01   ` Maxime Ripard
2018-05-21 15:10     ` Jernej Škrabec
2018-05-19 18:31 ` [PATCH 05/15] drm/sun4i: Add TCON TOP driver Jernej Skrabec
2018-05-21  8:05   ` Maxime Ripard
2018-05-21 15:15     ` Jernej Škrabec
2018-05-24  8:43       ` Maxime Ripard
2018-05-24 20:33         ` [linux-sunxi] " Jernej Škrabec
2018-05-22  2:25   ` kbuild test robot
2018-05-23 18:23   ` Rob Herring
2018-05-19 18:31 ` [PATCH 06/15] drm/sun4i: tcon: Add support for tcon-top Jernej Skrabec
2018-05-21  8:07   ` Maxime Ripard
2018-05-21 17:27     ` Jernej Škrabec
2018-05-24  8:50       ` Maxime Ripard
2018-05-24 22:01         ` Chen-Yu Tsai
2018-05-31  9:21           ` Maxime Ripard
2018-05-31 17:54             ` Jernej Škrabec
2018-06-01 15:29               ` Maxime Ripard
2018-06-01 16:19                 ` Chen-Yu Tsai
2018-06-04 11:50                   ` Maxime Ripard
2018-06-04 15:09                     ` Jernej Škrabec
2018-06-04 16:23                       ` Maxime Ripard
2018-06-06 22:30                         ` Jernej Škrabec
2018-06-08  5:17                           ` [linux-sunxi] " Jernej Škrabec
2018-05-19 18:31 ` [PATCH 07/15] dt-bindings: display: sun4i-drm: Add R40 HDMI pipeline Jernej Skrabec
2018-05-20  1:50   ` [linux-sunxi] " Julian Calaby
2018-05-19 18:31 ` [PATCH 08/15] drm/sun4i: DE2 mixer: Add index quirk Jernej Skrabec
2018-05-19 18:31 ` [PATCH 09/15] drm/sun4i: Add support for R40 mixers Jernej Skrabec
2018-05-19 18:31 ` [PATCH 10/15] drm/sun4i: Add support for R40 TV TCONs Jernej Skrabec
2018-05-20  1:57   ` [linux-sunxi] " Julian Calaby
2018-05-20  2:09     ` Julian Calaby
2018-05-20  7:30       ` Jernej Škrabec
2018-05-19 18:31 ` [PATCH 11/15] drm/sun4i: DW HDMI PHY: Add support for second PLL Jernej Skrabec
2018-05-19 18:31 ` [PATCH 12/15] drm/sun4i: Add support for second clock parent to DW HDMI PHY clk driver Jernej Skrabec
2018-05-21  7:47   ` kbuild test robot
2018-05-21  8:12   ` Maxime Ripard
2018-05-21 15:02     ` [linux-sunxi] " Jernej Škrabec
2018-05-24  8:27       ` Maxime Ripard
2018-05-19 18:31 ` [PATCH 13/15] drm/sun4i: Add support for A64 HDMI PHY Jernej Skrabec
2018-05-19 18:31 ` [PATCH 14/15] ARM: dts: sun8i: r40: Add HDMI pipeline Jernej Skrabec
2018-05-19 18:31 ` [PATCH 15/15] ARM: dts: sun8i: r40: Enable HDMI output on BananaPi M2 Ultra Jernej Skrabec

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