2017-09-20 20:01:39

by Jernej Skrabec

[permalink] [raw]
Subject: [RESEND RFC PATCH 0/7] sun8i H3 HDMI glue driver for DW HDMI

[added media mailing list due to CEC question]

This patch series adds a HDMI glue driver for Allwinner H3 SoC. For now, only
video and CEC functionality is supported. Audio needs more tweaks.

Series is based on the H3 DE2 patch series available on mailing list:
http://lists.infradead.org/pipermail/linux-arm-kernel/2017-August/522697.html
(ignore patches marked with [NOT FOR REVIEW NOW] tag)

Patch 1 adds support for polling plug detection since custom PHY used here
doesn't support HPD interrupt.

Patch 2 enables overflow workaround for v1.32a. This HDMI controller exhibits
same issues as HDMI controller used in iMX6 SoCs.

Patch 3 adds CLK_SET_RATE_PARENT to hdmi clock.

Patch 4 adds dt bindings documentation.

Patch 5 adds actual H3 HDMI glue driver.

Patch 6 and 7 add HDMI node to DT and enable it where needed.

Allwinner used DW HDMI controller in a non standard way:
- register offsets obfuscation layer, which can fortunately be turned off
- register read lock, which has to be disabled by magic number
- custom PHY, which have to be initialized before DW HDMI controller
- non standard clocks
- no HPD interrupt

Because of that, I have two questions:
- Since HPD have to be polled, is it enough just to enable poll mode? I'm
mainly concerned about invalidating CEC address here.
- PHY has to be initialized before DW HDMI controller to disable offset
obfuscation and read lock among other things. This means that all clocks have
to be enabled in glue driver. This poses a problem, since when using
component model, dw-hdmi bridge uses drvdata for it's own private data and
prevents glue layer to pass a pointer to unbind function, where clocks should
be disabled. I noticed same issue in meson DW HDMI glue driver, where clocks
are also not disabled when unbind callback is called. I noticed that when H3
SoC is shutdown, HDMI output is still enabled and lastest image is shown on
monitor until it is unplugged from power supply. Is there any simple solution
to this?

Chen-Yu,
TL Lim was unable to obtain any answer from Allwinner about HDMI clocks. I think
it is safe to assume that divider in HDMI clock doesn't have any effect.

Branch based on linux-next from 1. September with integrated patches is
available here:
https://github.com/jernejsk/linux-1/tree/h3_hdmi_rfc

Some additonal info about H3 HDMI:
https://linux-sunxi.org/DWC_HDMI_Controller

Thanks to Jens Kuske, who figured out that it is actually DW HDMI controller
and mapped scrambled register offsets to original ones.

Icenowy Zheng (1):
ARM: sun8i: h3: Add DesignWare HDMI controller node

Jernej Skrabec (6):
drm: bridge: Enable polling hpd event in dw_hdmi
drm: bridge: Enable workaround in dw_hdmi for v1.32a
clk: sunxi: Add CLK_SET_RATE_PARENT flag for H3 HDMI clock
dt-bindings: Document Allwinner DWC HDMI TX node
drm: sun4i: Add a glue for the DesignWare HDMI controller in H3
ARM: sun8i: h3: Enable HDMI output on H3 boards

.../bindings/display/sunxi/sun4i-drm.txt | 158 ++++++-
arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts | 33 ++
arch/arm/boot/dts/sun8i-h3-beelink-x2.dts | 33 ++
arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts | 33 ++
arch/arm/boot/dts/sun8i-h3-orangepi-2.dts | 33 ++
arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts | 33 ++
arch/arm/boot/dts/sun8i-h3-orangepi-one.dts | 33 ++
arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts | 33 ++
arch/arm/boot/dts/sun8i-h3.dtsi | 5 +
arch/arm/boot/dts/sunxi-h3-h5.dtsi | 36 ++
drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 2 +-
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 14 +-
drivers/gpu/drm/sun4i/Kconfig | 9 +
drivers/gpu/drm/sun4i/Makefile | 1 +
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 500 +++++++++++++++++++++
15 files changed, 950 insertions(+), 6 deletions(-)
create mode 100644 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c

--
2.14.1


2017-09-20 20:01:41

by Jernej Skrabec

[permalink] [raw]
Subject: [RESEND RFC PATCH 1/7] drm: bridge: Enable polling hpd event in dw_hdmi

Some custom phys don't support hpd interrupts. Add support for polling
such events.

Signed-off-by: Jernej Skrabec <[email protected]>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index bf14214fa464..09cb5a3e4c71 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1954,7 +1954,11 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge)
struct drm_connector *connector = &hdmi->connector;

connector->interlace_allowed = 1;
- connector->polled = DRM_CONNECTOR_POLL_HPD;
+ if (hdmi->phy.ops->setup_hpd)
+ connector->polled = DRM_CONNECTOR_POLL_HPD;
+ else
+ connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT;

drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs);

--
2.14.1

2017-09-20 20:01:47

by Jernej Skrabec

[permalink] [raw]
Subject: [RESEND RFC PATCH 3/7] clk: sunxi: Add CLK_SET_RATE_PARENT flag for H3 HDMI clock

When setting the HDMI clock of H3, the PLL_VIDEO clock needs to be set.

Add CLK_SET_RATE_PARENT flag for H3 HDMI clock.

Signed-off-by: Jernej Skrabec <[email protected]>
Signed-off-by: Icenowy Zheng <[email protected]>
---
drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
index 7a222ff1ad0a..36224ba93f9d 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
@@ -474,7 +474,7 @@ static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M",

static const char * const hdmi_parents[] = { "pll-video" };
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_ddc_clk, "hdmi-ddc", "osc24M",
0x154, BIT(31), 0);
--
2.14.1

2017-09-20 20:01:54

by Jernej Skrabec

[permalink] [raw]
Subject: [RESEND RFC PATCH 5/7] drm: sun4i: Add a glue for the DesignWare HDMI controller in H3

Allwinner H3 features DesignWare HDMI Transmitter paired with custom
PHY.

Add a glue driver for it.

For now, only video and CEC are supported. Audio will be supported at
a later time.

Signed-off-by: Jernej Skrabec <[email protected]>
---
drivers/gpu/drm/sun4i/Kconfig | 9 +
drivers/gpu/drm/sun4i/Makefile | 1 +
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 500 ++++++++++++++++++++++++++++++++++
3 files changed, 510 insertions(+)
create mode 100644 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c

diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 06f05302ee75..589502ffe31a 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -40,6 +40,15 @@ config DRM_SUN4I_BACKEND
do some alpha blending and feed graphics to TCON. If M is
selected the module will be called sun4i-backend.

+config DRM_SUN8I_DW_HDMI
+ tristate "Support for Allwinner version of DesignWare HDMI"
+ depends on DRM_SUN4I
+ select DRM_DW_HDMI
+ help
+ Choose this option if you have an Allwinner SoC with the
+ DesignWare HDMI controller with custom HDMI PHY. If M is
+ selected the module will be called sun8i_dw_hdmi.
+
config DRM_SUN8I_MIXER
tristate "Support for Allwinner Display Engine 2.0 Mixer"
default MACH_SUN8I
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 43c753cafc88..9c56173bf140 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o
obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o
obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o
obj-$(CONFIG_DRM_SUN8I_MIXER) += sun8i-mixer.o
+obj-$(CONFIG_DRM_SUN8I_DW_HDMI) += sun8i_dw_hdmi.o
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
new file mode 100644
index 000000000000..65db3e10e311
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -0,0 +1,500 @@
+/*
+ * Copyright (c) 2017, Jernej Skrabec <[email protected]>
+ *
+ * Based on hdmi_bsp_sun8iw7.c which is:
+ * Copyright (c) 2016 Allwinnertech Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include <drm/drm_of.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/bridge/dw_hdmi.h>
+
+#include "sun4i_crtc.h"
+#include "sun4i_tcon.h"
+
+#define SUN8I_HDMI_PHY_REG_POL 0x0000
+
+#define SUN8I_HDMI_PHY_REG_READ_EN 0x0010
+#define SUN8I_HDMI_PHY_REG_READ_EN_MAGIC 0x54524545
+
+#define SUN8I_HDMI_PHY_REG_UNSCRAMBLE 0x0014
+#define SUN8I_HDMI_PHY_REG_UNSCRAMBLE_MAGIC 0x42494E47
+
+#define SUN8I_HDMI_PHY_REG_CTRL 0x0020
+#define SUN8I_HDMI_PHY_REG_UNK1 0x0024
+#define SUN8I_HDMI_PHY_REG_UNK2 0x0028
+#define SUN8I_HDMI_PHY_REG_PLL 0x002c
+#define SUN8I_HDMI_PHY_REG_CLK 0x0030
+#define SUN8I_HDMI_PHY_REG_UNK3 0x0034
+
+#define SUN8I_HDMI_PHY_REG_STATUS 0x0038
+#define SUN8I_HDMI_PHY_REG_STATUS_READY BIT(7)
+#define SUN8I_HDMI_PHY_REG_STATUS_HPD BIT(19)
+
+#define SUN8I_HDMI_PHY_REG_CEC 0x003c
+
+#define to_sun8i_dw_hdmi(x) container_of(x, struct sun8i_dw_hdmi, x)
+#define set_bits(p, v) writel(readl(p) | (v), p)
+
+struct sun8i_dw_hdmi {
+ struct clk *clk_ahb;
+ struct clk *clk_ddc;
+ struct clk *clk_sfr;
+ struct device *dev;
+ struct drm_encoder encoder;
+ void __iomem *phy_base;
+ struct dw_hdmi_plat_data plat_data;
+ struct reset_control *rst_ddc;
+ struct reset_control *rst_hdmi;
+};
+
+static u32 sun8i_dw_hdmi_get_divider(int clk_khz)
+{
+ /*
+ * Due to missing documentation of HDMI PHY, we know correct
+ * settings only for following four PHY dividers. Select one
+ * based on pixel clock.
+ */
+ if (clk_khz <= 27000)
+ return 11;
+ else if (clk_khz <= 74250)
+ return 4;
+ else if (clk_khz <= 148500)
+ return 2;
+ else
+ return 1;
+}
+
+static void sun8i_dw_hdmi_encoder_disable(struct drm_encoder *encoder)
+{
+ struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
+ struct sun4i_tcon *tcon = crtc->tcon;
+
+ DRM_DEBUG_DRIVER("Disabling HDMI Output\n");
+
+ sun4i_tcon_channel_disable(tcon, 1);
+}
+
+static void sun8i_dw_hdmi_encoder_enable(struct drm_encoder *encoder)
+{
+ struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
+ struct sun4i_tcon *tcon = crtc->tcon;
+
+ DRM_DEBUG_DRIVER("Enabling HDMI Output\n");
+
+ sun4i_tcon_channel_enable(tcon, 1);
+}
+
+static void sun8i_dw_hdmi_encoder_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adj_mode)
+{
+ struct sun8i_dw_hdmi *hdmi = to_sun8i_dw_hdmi(encoder);
+ struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
+ struct sun4i_tcon *tcon = crtc->tcon;
+ u32 div;
+
+ sun4i_tcon1_mode_set(tcon, mode);
+
+ div = sun8i_dw_hdmi_get_divider(mode->crtc_clock);
+ clk_set_rate(hdmi->clk_sfr, mode->crtc_clock * 1000 * div);
+ clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
+}
+
+static const struct drm_encoder_helper_funcs
+ sun8i_dw_hdmi_encoder_helper_funcs = {
+ .mode_set = sun8i_dw_hdmi_encoder_mode_set,
+ .enable = sun8i_dw_hdmi_encoder_enable,
+ .disable = sun8i_dw_hdmi_encoder_disable,
+};
+
+static int sun8i_dw_hdmi_phy_init(struct dw_hdmi *hdmi_data, void *data,
+ struct drm_display_mode *mode)
+{
+ struct sun8i_dw_hdmi *hdmi = (struct sun8i_dw_hdmi *)data;
+ u32 div = sun8i_dw_hdmi_get_divider(mode->crtc_clock);
+ u32 val;
+
+ /*
+ * Unfortunately, we don't know much about those magic
+ * numbers. They are taken from Allwinner BSP driver.
+ */
+
+ val = readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+ writel(val & ~0xf000, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+
+ switch (div) {
+ case 1:
+ writel(0x30dc5fc0, hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL);
+ writel(0x800863C0, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CLK);
+ usleep_range(10000, 15000);
+ writel(1, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK3);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, BIT(25));
+ msleep(200);
+ val = readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_STATUS);
+ val = (val & 0x1f800) >> 11;
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL,
+ BIT(31) | BIT(30));
+ if (val < 0x3d)
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL,
+ val + 2);
+ else
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, 0x3f);
+ msleep(100);
+ writel(0x01FFFF7F, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+ writel(0x8063b000, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK1);
+ writel(0x0F8246B5, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK2);
+ break;
+ case 2:
+ writel(0x39dc5040, hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL);
+ writel(0x80084381, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CLK);
+ usleep_range(10000, 15000);
+ writel(1, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK3);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, BIT(25));
+ msleep(100);
+ val = readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_STATUS);
+ val = (val & 0x1f800) >> 11;
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL,
+ BIT(31) | BIT(30));
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, val);
+ writel(0x01FFFF7F, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+ writel(0x8063a800, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK1);
+ writel(0x0F81C485, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK2);
+ break;
+ case 4:
+ writel(0x39dc5040, hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL);
+ writel(0x80084343, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CLK);
+ usleep_range(10000, 15000);
+ writel(1, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK3);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, BIT(25));
+ msleep(100);
+ val = readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_STATUS);
+ val = (val & 0x1f800) >> 11;
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL,
+ BIT(31) | BIT(30));
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, val);
+ writel(0x01FFFF7F, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+ writel(0x8063b000, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK1);
+ writel(0x0F81C405, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK2);
+ break;
+ case 11:
+ writel(0x39dc5040, hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL);
+ writel(0x8008430a, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CLK);
+ usleep_range(10000, 15000);
+ writel(1, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK3);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, BIT(25));
+ msleep(100);
+ val = readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_STATUS);
+ val = (val & 0x1f800) >> 11;
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL,
+ BIT(31) | BIT(30));
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, val);
+ writel(0x01FFFF7F, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+ writel(0x8063b000, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK1);
+ writel(0x0F81C405, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK2);
+ break;
+ }
+
+ /* clear polarity bits */
+ val = readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_POL);
+ val &= ~0x300;
+
+ /*
+ * Set polarity bits if necessary. Condition in original code
+ * is a bit weird. This is attempt to make it more reasonable
+ * and it works. It could be that bits and conditions are
+ * related and should be separated.
+ */
+ if (!(mode->flags & DRM_MODE_FLAG_PHSYNC) ||
+ !(mode->flags & DRM_MODE_FLAG_PVSYNC)) {
+ val |= 0x300;
+ }
+
+ writel(val, hdmi->phy_base + SUN8I_HDMI_PHY_REG_POL);
+
+ return 0;
+}
+
+static void sun8i_dw_hdmi_phy_disable(struct dw_hdmi *hdmi_data, void *data)
+{
+ struct sun8i_dw_hdmi *hdmi = (struct sun8i_dw_hdmi *)data;
+
+ /* Disable output and stop PLL */
+ writel(7, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+ writel(0, hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL);
+}
+
+static enum drm_connector_status
+ sun8i_dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi_data,
+ void *data)
+{
+ struct sun8i_dw_hdmi *hdmi = (struct sun8i_dw_hdmi *)data;
+ u32 reg_val = readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_STATUS);
+
+ return (reg_val & SUN8I_HDMI_PHY_REG_STATUS_HPD) ?
+ connector_status_connected : connector_status_disconnected;
+}
+
+static const struct dw_hdmi_phy_ops sun8i_dw_hdmi_phy_ops = {
+ .init = &sun8i_dw_hdmi_phy_init,
+ .disable = &sun8i_dw_hdmi_phy_disable,
+ .read_hpd = &sun8i_dw_hdmi_phy_read_hpd,
+};
+
+static void sun8i_dw_hdmi_init(struct sun8i_dw_hdmi *hdmi)
+{
+ u32 timeout = 20;
+ u32 val;
+
+ /*
+ * HDMI PHY settings are taken as-is from Allwinner BSP code.
+ * There is no documentation.
+ */
+ writel(0, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, BIT(0));
+ udelay(5);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, BIT(16));
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, BIT(1));
+ usleep_range(10, 20);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, BIT(2));
+ udelay(5);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, BIT(3));
+ usleep_range(40, 100);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, BIT(19));
+ usleep_range(100, 200);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, BIT(18));
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, 7 << 4);
+
+ /* Note that Allwinner code doesn't fail in case of timeout */
+ while (!(readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_STATUS) &
+ SUN8I_HDMI_PHY_REG_STATUS_READY)) {
+ if (!timeout--) {
+ dev_warn(hdmi->dev, "HDMI PHY init timeout!\n");
+ break;
+ }
+ usleep_range(100, 200);
+ }
+
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, 0xf << 8);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL, BIT(7));
+
+ writel(0x39dc5040, hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL);
+ writel(0x80084343, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CLK);
+ usleep_range(10000, 15000);
+ writel(1, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK3);
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, BIT(25));
+ msleep(100);
+ val = readl(hdmi->phy_base + SUN8I_HDMI_PHY_REG_STATUS);
+ val = (val & 0x1f800) >> 11;
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, BIT(31) | BIT(30));
+ set_bits(hdmi->phy_base + SUN8I_HDMI_PHY_REG_PLL, val);
+ writel(0x01FF0F7F, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CTRL);
+ writel(0x80639000, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK1);
+ writel(0x0F81C405, hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNK2);
+
+ /* enable read access to HDMI controller */
+ writel(SUN8I_HDMI_PHY_REG_READ_EN_MAGIC,
+ hdmi->phy_base + SUN8I_HDMI_PHY_REG_READ_EN);
+
+ /* unscramble register offsets */
+ writel(SUN8I_HDMI_PHY_REG_UNSCRAMBLE_MAGIC,
+ hdmi->phy_base + SUN8I_HDMI_PHY_REG_UNSCRAMBLE);
+
+ /* Reset PHY CEC settings. This gives dw hdmi total control over CEC. */
+ writel(0, hdmi->phy_base + SUN8I_HDMI_PHY_REG_CEC);
+}
+
+static const struct drm_encoder_funcs sun8i_dw_hdmi_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct dw_hdmi_plat_data *plat_data;
+ struct drm_device *drm = data;
+ struct drm_encoder *encoder;
+ struct sun8i_dw_hdmi *hdmi;
+ struct resource *res;
+ int ret;
+
+ if (!pdev->dev.of_node)
+ return -ENODEV;
+
+ hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
+ if (!hdmi)
+ return -ENOMEM;
+
+ plat_data = &hdmi->plat_data;
+ hdmi->dev = &pdev->dev;
+ encoder = &hdmi->encoder;
+
+ encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
+ /*
+ * If we failed to find the CRTC(s) which this encoder is
+ * supposed to be connected to, it's because the CRTC has
+ * not been registered yet. Defer probing, and hope that
+ * the required CRTC is added later.
+ */
+ if (encoder->possible_crtcs == 0)
+ return -EPROBE_DEFER;
+
+ /* resource 0 is the memory region for the core controller */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ hdmi->phy_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(hdmi->phy_base))
+ return PTR_ERR(hdmi->phy_base);
+
+ hdmi->clk_ahb = devm_clk_get(dev, "iahb");
+ if (IS_ERR(hdmi->clk_ahb)) {
+ dev_err(dev, "Could not get iahb clock\n");
+ return PTR_ERR(hdmi->clk_ahb);
+ }
+
+ hdmi->clk_sfr = devm_clk_get(dev, "isfr");
+ if (IS_ERR(hdmi->clk_sfr)) {
+ dev_err(dev, "Could not get isfr clock\n");
+ return PTR_ERR(hdmi->clk_sfr);
+ }
+
+ hdmi->clk_ddc = devm_clk_get(dev, "ddc");
+ if (IS_ERR(hdmi->clk_ddc)) {
+ dev_err(dev, "Could not get ddc clock\n");
+ return PTR_ERR(hdmi->clk_ddc);
+ }
+
+ hdmi->rst_hdmi = devm_reset_control_get(dev, "hdmi");
+ if (IS_ERR(hdmi->rst_hdmi)) {
+ dev_err(dev, "Could not get hdmi reset control\n");
+ return PTR_ERR(hdmi->rst_hdmi);
+ }
+
+ hdmi->rst_ddc = devm_reset_control_get(dev, "ddc");
+ if (IS_ERR(hdmi->rst_ddc)) {
+ dev_err(dev, "Could not get ddc reset control\n");
+ return PTR_ERR(hdmi->rst_ddc);
+ }
+
+ ret = clk_prepare_enable(hdmi->clk_ahb);
+ if (ret) {
+ dev_err(dev, "Cannot enable ahb clock: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(hdmi->clk_sfr);
+ if (ret) {
+ dev_err(dev, "Cannot enable isfr clock: %d\n", ret);
+ goto err_ahb_clk;
+ }
+
+ ret = clk_prepare_enable(hdmi->clk_ddc);
+ if (ret) {
+ dev_err(dev, "Cannot enable ddc clock: %d\n", ret);
+ goto err_sfr_clk;
+ }
+
+ ret = reset_control_deassert(hdmi->rst_hdmi);
+ if (ret) {
+ dev_err(dev, "Could not deassert hdmi reset control\n");
+ goto err_ddc_clk;
+ }
+
+ ret = reset_control_deassert(hdmi->rst_ddc);
+ if (ret) {
+ dev_err(dev, "Could not deassert ddc reset control\n");
+ goto err_assert_hdmi_reset;
+ }
+
+ drm_encoder_helper_add(encoder, &sun8i_dw_hdmi_encoder_helper_funcs);
+ drm_encoder_init(drm, encoder, &sun8i_dw_hdmi_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS, NULL);
+
+ sun8i_dw_hdmi_init(hdmi);
+
+ plat_data->phy_ops = &sun8i_dw_hdmi_phy_ops,
+ plat_data->phy_name = "sun8i_dw_hdmi_phy",
+ plat_data->phy_data = hdmi;
+
+ ret = dw_hdmi_bind(pdev, encoder, plat_data);
+
+ /*
+ * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
+ * which would have called the encoder cleanup. Do it manually.
+ */
+ if (ret)
+ goto cleanup_encoder;
+
+ return 0;
+
+cleanup_encoder:
+ drm_encoder_cleanup(encoder);
+ reset_control_assert(hdmi->rst_ddc);
+err_assert_hdmi_reset:
+ reset_control_assert(hdmi->rst_hdmi);
+err_ddc_clk:
+ clk_disable_unprepare(hdmi->clk_ddc);
+err_sfr_clk:
+ clk_disable_unprepare(hdmi->clk_sfr);
+err_ahb_clk:
+ clk_disable_unprepare(hdmi->clk_ahb);
+
+ return ret;
+}
+
+static void sun8i_dw_hdmi_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ return dw_hdmi_unbind(dev);
+}
+
+static const struct component_ops sun8i_dw_hdmi_ops = {
+ .bind = sun8i_dw_hdmi_bind,
+ .unbind = sun8i_dw_hdmi_unbind,
+};
+
+static int sun8i_dw_hdmi_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &sun8i_dw_hdmi_ops);
+}
+
+static int sun8i_dw_hdmi_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &sun8i_dw_hdmi_ops);
+
+ return 0;
+}
+
+static const struct of_device_id sun8i_dw_hdmi_dt_ids[] = {
+ { .compatible = "allwinner,sun8i-h3-dw-hdmi" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, sun8i_dw_hdmi_dt_ids);
+
+struct platform_driver sun8i_dw_hdmi_pltfm_driver = {
+ .probe = sun8i_dw_hdmi_probe,
+ .remove = sun8i_dw_hdmi_remove,
+ .driver = {
+ .name = "sun8i-dw-hdmi",
+ .of_match_table = sun8i_dw_hdmi_dt_ids,
+ },
+};
+module_platform_driver(sun8i_dw_hdmi_pltfm_driver);
+
+MODULE_AUTHOR("Jernej Skrabec <[email protected]>");
+MODULE_DESCRIPTION("Allwinner H3 DW HDMI bridge");
+MODULE_LICENSE("GPL");
--
2.14.1

2017-09-20 20:02:06

by Jernej Skrabec

[permalink] [raw]
Subject: [RESEND RFC PATCH 7/7] ARM: sun8i: h3: Enable HDMI output on H3 boards

Enable HDMI output on all boards which include HDMI connector.

Signed-off-by: Jernej Skrabec <[email protected]>
---
arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts | 33 +++++++++++++++++++++++++
arch/arm/boot/dts/sun8i-h3-beelink-x2.dts | 33 +++++++++++++++++++++++++
arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts | 33 +++++++++++++++++++++++++
arch/arm/boot/dts/sun8i-h3-orangepi-2.dts | 33 +++++++++++++++++++++++++
arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts | 33 +++++++++++++++++++++++++
arch/arm/boot/dts/sun8i-h3-orangepi-one.dts | 33 +++++++++++++++++++++++++
arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts | 33 +++++++++++++++++++++++++
7 files changed, 231 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts b/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts
index d756ff825116..52a0f954df1c 100644
--- a/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts
+++ b/arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts
@@ -61,6 +61,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";
pinctrl-names = "default";
@@ -103,6 +114,10 @@
};
};

+&de {
+ status = "okay";
+};
+
&ehci0 {
status = "okay";
};
@@ -126,6 +141,16 @@
status = "okay";
};

+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
@@ -139,6 +164,10 @@
};
};

+&mixer0 {
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
@@ -212,6 +241,10 @@
status = "okay";
};

+&tcon0 {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
diff --git a/arch/arm/boot/dts/sun8i-h3-beelink-x2.dts b/arch/arm/boot/dts/sun8i-h3-beelink-x2.dts
index 546837ccd8af..8a4ec474f183 100644
--- a/arch/arm/boot/dts/sun8i-h3-beelink-x2.dts
+++ b/arch/arm/boot/dts/sun8i-h3-beelink-x2.dts
@@ -61,6 +61,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";

@@ -100,6 +111,10 @@
};
};

+&de {
+ status = "okay";
+};
+
&ehci0 {
status = "okay";
};
@@ -115,12 +130,26 @@
status = "okay";
};

+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
status = "okay";
};

+&mixer0 {
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
@@ -177,6 +206,10 @@
status = "okay";
};

+&tcon0 {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts b/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts
index ec63d104b404..e6b551bb43e7 100644
--- a/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts
+++ b/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts
@@ -45,6 +45,21 @@
/ {
model = "FriendlyArm NanoPi M1";
compatible = "friendlyarm,nanopi-m1", "allwinner,sun8i-h3";
+
+ connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+};
+
+&de {
+ status = "okay";
};

&ehci1 {
@@ -55,6 +70,20 @@
status = "okay";
};

+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&mixer0 {
+ status = "okay";
+};
+
&ohci1 {
status = "okay";
};
@@ -62,3 +91,7 @@
&ohci2 {
status = "okay";
};
+
+&tcon0 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
index 17cdeae19c6f..586181c4ce8b 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
@@ -62,6 +62,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";
pinctrl-names = "default";
@@ -114,6 +125,10 @@
status = "okay";
};

+&de {
+ status = "okay";
+};
+
&ehci1 {
status = "okay";
};
@@ -125,12 +140,26 @@
status = "okay";
};

+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
status = "okay";
};

+&mixer0 {
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
@@ -188,6 +217,10 @@
status = "okay";
};

+&tcon0 {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
index 9b47a0def740..cecf4af1b743 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
@@ -61,6 +61,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";
pinctrl-names = "default";
@@ -91,6 +102,10 @@
};
};

+&de {
+ status = "okay";
+};
+
&ehci1 {
status = "okay";
};
@@ -99,12 +114,26 @@
status = "okay";
};

+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
status = "okay";
};

+&mixer0 {
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
@@ -159,6 +188,10 @@
};
};

+&tcon0 {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
index 6880268e8b87..ad1739e1d01d 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
@@ -60,6 +60,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";
pinctrl-names = "default";
@@ -90,6 +101,10 @@
};
};

+&de {
+ status = "okay";
+};
+
&ehci0 {
status = "okay";
};
@@ -105,6 +120,20 @@
status = "okay";
};

+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&mixer0 {
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
@@ -147,6 +176,10 @@
status = "okay";
};

+&tcon0 {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
index 998b60f8d295..24ec7376f479 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
@@ -60,6 +60,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";
pinctrl-names = "default";
@@ -98,6 +109,10 @@
status = "okay";
};

+&de {
+ status = "okay";
+};
+
&ehci0 {
status = "okay";
};
@@ -121,12 +136,26 @@
status = "okay";
};

+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
status = "okay";
};

+&mixer0 {
+ status = "okay";
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
@@ -177,6 +206,10 @@
status = "okay";
};

+&tcon0 {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
--
2.14.1

2017-09-20 20:01:53

by Jernej Skrabec

[permalink] [raw]
Subject: [RESEND RFC PATCH 6/7] ARM: sun8i: h3: Add DesignWare HDMI controller node

From: Icenowy Zheng <[email protected]>

The H3 SoC has a DesignWare HDMI controller with some Allwinner-specific
glue and custom PHY.

Since H3 and H5 have same HDMI controller, add related device node in
shared dtsi file.

Signed-off-by: Icenowy Zheng <[email protected]>
Signed-off-by: Jernej Skrabec <[email protected]>
---
arch/arm/boot/dts/sun8i-h3.dtsi | 5 +++++
arch/arm/boot/dts/sunxi-h3-h5.dtsi | 36 ++++++++++++++++++++++++++++++++++++
2 files changed, 41 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index 75ad7b65a7fc..b01f5ac60059 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -197,6 +197,11 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
+
+ tcon0_out_hdmi: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&hdmi_in_tcon0>;
+ };
};
};
};
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index d38282b9e5d4..28f4df82300e 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -592,6 +592,42 @@
interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
};

+ hdmi: hdmi@1ee0000 {
+ compatible = "allwinner,sun8i-h3-dw-hdmi";
+ reg = <0x01ee0000 0x10000>,
+ <0x01ef0000 0x10000>;
+ reg-io-width = <1>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI>,
+ <&ccu CLK_HDMI_DDC>;
+ clock-names = "iahb", "isfr", "ddc";
+ resets = <&ccu RST_BUS_HDMI0>, <&ccu RST_BUS_HDMI1>;
+ reset-names = "hdmi", "ddc";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hdmi_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ hdmi_in_tcon0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon0_out_hdmi>;
+ };
+ };
+
+ hdmi_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+ };
+ };
+
rtc: rtc@01f00000 {
compatible = "allwinner,sun6i-a31-rtc";
reg = <0x01f00000 0x54>;
--
2.14.1

2017-09-20 20:02:41

by Jernej Skrabec

[permalink] [raw]
Subject: [RESEND RFC PATCH 4/7] dt-bindings: Document Allwinner DWC HDMI TX node

Add documentation about Allwinner DWC HDMI TX node, found in H3 SoC.

Signed-off-by: Jernej Skrabec <[email protected]>
---
.../bindings/display/sunxi/sun4i-drm.txt | 158 ++++++++++++++++++++-
1 file changed, 157 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 92512953943e..cb6aee5c486f 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -60,6 +60,40 @@ Required properties:
first port should be the input endpoint. The second should be the
output, usually to an HDMI connector.

+DWC HDMI TX Encoder
+-----------------------------
+
+The HDMI transmitter is a Synopsys DesignWare HDMI 1.4 TX controller IP
+with Allwinner's own PHY IP. It supports audio and video outputs and CEC.
+
+These DT bindings follow the Synopsys DWC HDMI TX bindings defined in
+Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt with the
+following device-specific properties.
+
+Required properties:
+
+ - compatible: value must be one of:
+ * "allwinner,sun8i-h3-dw-hdmi"
+ - reg: two pairs of base address and size of memory-mapped region, first
+ for controller and second for PHY
+ registers.
+ - reg-io-width: See dw_hdmi.txt. Shall be 1.
+ - interrupts: HDMI interrupt number
+ - clocks: phandles to the clocks feeding the HDMI encoder
+ * iahb: the HDMI interface clock
+ * isfr: the HDMI module clock
+ * ddc: the HDMI ddc clock
+ - clock-names: the clock names mentioned above
+ - resets: phandles to the reset controllers driving the encoder
+ * hdmi: the reset line for the HDMI
+ * ddc: the reset line for the DDC
+ - reset-names: the reset names mentioned above
+
+ - ports: A ports node with endpoint definitions as defined in
+ Documentation/devicetree/bindings/media/video-interfaces.txt. The
+ first port should be the input endpoint. The second should be the
+ output, usually to an HDMI connector.
+
TV Encoder
----------

@@ -255,7 +289,7 @@ Required properties:
- allwinner,pipelines: list of phandle to the display engine
frontends (DE 1.0) or mixers (DE 2.0) available.

-Example:
+Example 1:

panel: panel {
compatible = "olimex,lcd-olinuxino-43-ts";
@@ -455,3 +489,125 @@ display-engine {
compatible = "allwinner,sun5i-a13-display-engine";
allwinner,pipelines = <&fe0>;
};
+
+Example 2:
+
+connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+};
+
+de: display-engine {
+ compatible = "allwinner,sun8i-h3-display-engine";
+ allwinner,pipelines = <&mixer0>;
+};
+
+hdmi: hdmi@1ee0000 {
+ compatible = "allwinner,h3-dw-hdmi";
+ reg = <0x01ee0000 0x10000>,
+ <0x01ef0000 0x10000>;
+ reg-io-width = <1>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI>,
+ <&ccu CLK_HDMI_DDC>;
+ clock-names = "iahb", "isfr", "ddc";
+ resets = <&ccu RST_BUS_HDMI0>, <&ccu RST_BUS_HDMI1>;
+ reset-names = "hdmi", "ddc";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hdmi_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ hdmi_in_tcon0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon0_out_hdmi>;
+ };
+ };
+
+ hdmi_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+ };
+ };
+};
+
+mixer0: mixer@1100000 {
+ compatible = "allwinner,sun8i-h3-de2-mixer0";
+ 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 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ mixer0_out_tcon0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon0_in_mixer0>;
+ };
+ };
+ };
+};
+
+tcon0: lcd-controller@1c0c000 {
+ compatible = "allwinner,sun8i-h3-tcon";
+ reg = <0x01c0c000 0x1000>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_TCON0>,
+ <&ccu CLK_TCON0>;
+ clock-names = "ahb",
+ "tcon-ch1";
+ resets = <&ccu RST_BUS_TCON0>;
+ reset-names = "lcd";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon0_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ tcon0_in_mixer0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&mixer0_out_tcon0>;
+ };
+ };
+
+ tcon0_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ tcon0_out_hdmi: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&hdmi_in_tcon0>;
+ };
+ };
+ };
+};
--
2.14.1

2017-09-20 20:03:04

by Jernej Skrabec

[permalink] [raw]
Subject: [RESEND RFC PATCH 2/7] drm: bridge: Enable workaround in dw_hdmi for v1.32a

Allwinner SoCs have dw hdmi controller v1.32a which exhibits same
magenta line issue as i.MX6Q and i.MX6DL. Enable workaround for it.

Allwinner never released any kind of dw hdmi or errata documentation,
so it is not clear how many iterations need to be executed. One
iteration seems to be enough.

Signed-off-by: Jernej Skrabec <[email protected]>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 09cb5a3e4c71..72969240a9d4 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1631,9 +1631,10 @@ static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
* then write one of the FC registers several times.
*
* The number of iterations matters and depends on the HDMI TX revision
- * (and possibly on the platform). So far only i.MX6Q (v1.30a) and
- * i.MX6DL (v1.31a) have been identified as needing the workaround, with
- * 4 and 1 iterations respectively.
+ * (and possibly on the platform). So far i.MX6Q (v1.30a), i.MX6DL
+ * (v1.31a) and multiple Allwinner SoCs (v1.32a) have been identified
+ * as needing the workaround, with 4 iterations for v1.30a and 1
+ * iteration for others.
*/

switch (hdmi->version) {
@@ -1641,6 +1642,7 @@ static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi)
count = 4;
break;
case 0x131a:
+ case 0x132a:
count = 1;
break;
default:
--
2.14.1

2017-09-21 09:40:11

by Jose Abreu

[permalink] [raw]
Subject: Re: [RESEND RFC PATCH 0/7] sun8i H3 HDMI glue driver for DW HDMI

Hi Jernej,

On 20-09-2017 21:01, Jernej Skrabec wrote:
> [added media mailing list due to CEC question]
>
> This patch series adds a HDMI glue driver for Allwinner H3 SoC. For now, only
> video and CEC functionality is supported. Audio needs more tweaks.
>
> Series is based on the H3 DE2 patch series available on mailing list:
> https://urldefense.proofpoint.com/v2/url?u=http-3A__lists.infradead.org_pipermail_linux-2Darm-2Dkernel_2017-2DAugust_522697.html&d=DwIBAg&c=DPL6_X_6JkXFx7AXWqB0tg&r=WHDsc6kcWAl4i96Vm5hJ_19IJiuxx_p_Rzo2g-uHDKw&m=coyfcQKSr2asrHcaCeWFmAP_9nkFkRK8s7Uw5bmVei4&s=JCFaMXK1MmZ3jE745_YcqZhZkaqtc6UapGfSSapcz_s&e=
> (ignore patches marked with [NOT FOR REVIEW NOW] tag)
>
> Patch 1 adds support for polling plug detection since custom PHY used here
> doesn't support HPD interrupt.
>
> Patch 2 enables overflow workaround for v1.32a. This HDMI controller exhibits
> same issues as HDMI controller used in iMX6 SoCs.
>
> Patch 3 adds CLK_SET_RATE_PARENT to hdmi clock.
>
> Patch 4 adds dt bindings documentation.
>
> Patch 5 adds actual H3 HDMI glue driver.
>
> Patch 6 and 7 add HDMI node to DT and enable it where needed.
>
> Allwinner used DW HDMI controller in a non standard way:
> - register offsets obfuscation layer, which can fortunately be turned off
> - register read lock, which has to be disabled by magic number
> - custom PHY, which have to be initialized before DW HDMI controller
> - non standard clocks
> - no HPD interrupt
>
> Because of that, I have two questions:
> - Since HPD have to be polled, is it enough just to enable poll mode? I'm
> mainly concerned about invalidating CEC address here.

You mean you get no interrupt when HPD status changes? Hans can
answer this better but then you will need to invalidate the cec
physical address yourself because right now its invalidated in
the dw-hdmi irq handler (see dw_hdmi_irq()).

> - PHY has to be initialized before DW HDMI controller to disable offset
> obfuscation and read lock among other things. This means that all clocks have
> to be enabled in glue driver. This poses a problem, since when using
> component model, dw-hdmi bridge uses drvdata for it's own private data and
> prevents glue layer to pass a pointer to unbind function, where clocks should
> be disabled. I noticed same issue in meson DW HDMI glue driver, where clocks
> are also not disabled when unbind callback is called. I noticed that when H3
> SoC is shutdown, HDMI output is still enabled and lastest image is shown on
> monitor until it is unplugged from power supply. Is there any simple solution
> to this?

I don't know if you can use an empty platform device created with
platform_device_alloc(). Perhaps it would be better fix this in
the dw-hdmi driver. I see two solutions:

- Either you return the dw-hdmi private structure in the bind
callback, store it and pass it in the unbind
- Or, you pass your own private data to the dw-hdmi bind, the
dw-hdmi stores it and you just create a public function in the
dw-hdmi driver called like dw_hdmi_get_auxdata(struct device
*dev) which returns your private data.

I think first option is nice, maybe anyone else can suggest
something better?

Best regards,
Jose Miguel Abreu

>
> Chen-Yu,
> TL Lim was unable to obtain any answer from Allwinner about HDMI clocks. I think
> it is safe to assume that divider in HDMI clock doesn't have any effect.
>
> Branch based on linux-next from 1. September with integrated patches is
> available here:
> https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_jernejsk_linux-2D1_tree_h3-5Fhdmi-5Frfc&d=DwIBAg&c=DPL6_X_6JkXFx7AXWqB0tg&r=WHDsc6kcWAl4i96Vm5hJ_19IJiuxx_p_Rzo2g-uHDKw&m=coyfcQKSr2asrHcaCeWFmAP_9nkFkRK8s7Uw5bmVei4&s=lDAnd3egsc2sxqVM-Ya_Me9ozWXKWvxxvsdV3Jn3vpA&e=
>
> Some additonal info about H3 HDMI:
> https://urldefense.proofpoint.com/v2/url?u=https-3A__linux-2Dsunxi.org_DWC-5FHDMI-5FController&d=DwIBAg&c=DPL6_X_6JkXFx7AXWqB0tg&r=WHDsc6kcWAl4i96Vm5hJ_19IJiuxx_p_Rzo2g-uHDKw&m=coyfcQKSr2asrHcaCeWFmAP_9nkFkRK8s7Uw5bmVei4&s=d9iEgk23RCLJL4oXJ4kkt6NyYK90_vFy0mCD3WauJDk&e=
>
> Thanks to Jens Kuske, who figured out that it is actually DW HDMI controller
> and mapped scrambled register offsets to original ones.
>
> Icenowy Zheng (1):
> ARM: sun8i: h3: Add DesignWare HDMI controller node
>
> Jernej Skrabec (6):
> drm: bridge: Enable polling hpd event in dw_hdmi
> drm: bridge: Enable workaround in dw_hdmi for v1.32a
> clk: sunxi: Add CLK_SET_RATE_PARENT flag for H3 HDMI clock
> dt-bindings: Document Allwinner DWC HDMI TX node
> drm: sun4i: Add a glue for the DesignWare HDMI controller in H3
> ARM: sun8i: h3: Enable HDMI output on H3 boards
>
> .../bindings/display/sunxi/sun4i-drm.txt | 158 ++++++-
> arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts | 33 ++
> arch/arm/boot/dts/sun8i-h3-beelink-x2.dts | 33 ++
> arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts | 33 ++
> arch/arm/boot/dts/sun8i-h3-orangepi-2.dts | 33 ++
> arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts | 33 ++
> arch/arm/boot/dts/sun8i-h3-orangepi-one.dts | 33 ++
> arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts | 33 ++
> arch/arm/boot/dts/sun8i-h3.dtsi | 5 +
> arch/arm/boot/dts/sunxi-h3-h5.dtsi | 36 ++
> drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 2 +-
> drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 14 +-
> drivers/gpu/drm/sun4i/Kconfig | 9 +
> drivers/gpu/drm/sun4i/Makefile | 1 +
> drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 500 +++++++++++++++++++++
> 15 files changed, 950 insertions(+), 6 deletions(-)
> create mode 100644 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
>

2017-09-21 09:59:32

by Hans Verkuil (hansverk)

[permalink] [raw]
Subject: Re: [RESEND RFC PATCH 0/7] sun8i H3 HDMI glue driver for DW HDMI

On 09/21/17 11:39, Jose Abreu wrote:
> Hi Jernej,
>
> On 20-09-2017 21:01, Jernej Skrabec wrote:
>> [added media mailing list due to CEC question]
>>
>> This patch series adds a HDMI glue driver for Allwinner H3 SoC. For now, only
>> video and CEC functionality is supported. Audio needs more tweaks.
>>
>> Series is based on the H3 DE2 patch series available on mailing list:
>> https://urldefense.proofpoint.com/v2/url?u=http-3A__lists.infradead.org_pipermail_linux-2Darm-2Dkernel_2017-2DAugust_522697.html&d=DwIBAg&c=DPL6_X_6JkXFx7AXWqB0tg&r=WHDsc6kcWAl4i96Vm5hJ_19IJiuxx_p_Rzo2g-uHDKw&m=coyfcQKSr2asrHcaCeWFmAP_9nkFkRK8s7Uw5bmVei4&s=JCFaMXK1MmZ3jE745_YcqZhZkaqtc6UapGfSSapcz_s&e=
>> (ignore patches marked with [NOT FOR REVIEW NOW] tag)
>>
>> Patch 1 adds support for polling plug detection since custom PHY used here
>> doesn't support HPD interrupt.
>>
>> Patch 2 enables overflow workaround for v1.32a. This HDMI controller exhibits
>> same issues as HDMI controller used in iMX6 SoCs.
>>
>> Patch 3 adds CLK_SET_RATE_PARENT to hdmi clock.
>>
>> Patch 4 adds dt bindings documentation.
>>
>> Patch 5 adds actual H3 HDMI glue driver.
>>
>> Patch 6 and 7 add HDMI node to DT and enable it where needed.
>>
>> Allwinner used DW HDMI controller in a non standard way:
>> - register offsets obfuscation layer, which can fortunately be turned off
>> - register read lock, which has to be disabled by magic number
>> - custom PHY, which have to be initialized before DW HDMI controller
>> - non standard clocks
>> - no HPD interrupt
>>
>> Because of that, I have two questions:
>> - Since HPD have to be polled, is it enough just to enable poll mode? I'm
>> mainly concerned about invalidating CEC address here.
>
> You mean you get no interrupt when HPD status changes? Hans can
> answer this better but then you will need to invalidate the cec
> physical address yourself because right now its invalidated in
> the dw-hdmi irq handler (see dw_hdmi_irq()).

That's correct. When the HPD goes low you need to call cec_notifier_phys_addr_invalidate()
to invalidate the physical address. This is not terribly time sensitive, i.e.
checking this once a second would be quick enough.

Regards,

Hans

2017-09-27 21:56:43

by Rob Herring

[permalink] [raw]
Subject: Re: [RESEND RFC PATCH 4/7] dt-bindings: Document Allwinner DWC HDMI TX node

On Wed, Sep 20, 2017 at 10:01:21PM +0200, Jernej Skrabec wrote:
> Add documentation about Allwinner DWC HDMI TX node, found in H3 SoC.
>
> Signed-off-by: Jernej Skrabec <[email protected]>
> ---
> .../bindings/display/sunxi/sun4i-drm.txt | 158 ++++++++++++++++++++-
> 1 file changed, 157 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> index 92512953943e..cb6aee5c486f 100644
> --- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> +++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
> @@ -60,6 +60,40 @@ Required properties:
> first port should be the input endpoint. The second should be the
> output, usually to an HDMI connector.
>
> +DWC HDMI TX Encoder
> +-----------------------------
> +
> +The HDMI transmitter is a Synopsys DesignWare HDMI 1.4 TX controller IP
> +with Allwinner's own PHY IP. It supports audio and video outputs and CEC.
> +
> +These DT bindings follow the Synopsys DWC HDMI TX bindings defined in
> +Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt with the
> +following device-specific properties.
> +
> +Required properties:
> +
> + - compatible: value must be one of:
> + * "allwinner,sun8i-h3-dw-hdmi"
> + - reg: two pairs of base address and size of memory-mapped region, first
> + for controller and second for PHY
> + registers.
> + - reg-io-width: See dw_hdmi.txt. Shall be 1.
> + - interrupts: HDMI interrupt number
> + - clocks: phandles to the clocks feeding the HDMI encoder
> + * iahb: the HDMI interface clock
> + * isfr: the HDMI module clock
> + * ddc: the HDMI ddc clock
> + - clock-names: the clock names mentioned above
> + - resets: phandles to the reset controllers driving the encoder
> + * hdmi: the reset line for the HDMI
> + * ddc: the reset line for the DDC
> + - reset-names: the reset names mentioned above
> +
> + - ports: A ports node with endpoint definitions as defined in
> + Documentation/devicetree/bindings/media/video-interfaces.txt. The
> + first port should be the input endpoint. The second should be the
> + output, usually to an HDMI connector.
> +
> TV Encoder
> ----------
>
> @@ -255,7 +289,7 @@ Required properties:
> - allwinner,pipelines: list of phandle to the display engine
> frontends (DE 1.0) or mixers (DE 2.0) available.
>
> -Example:
> +Example 1:
>
> panel: panel {
> compatible = "olimex,lcd-olinuxino-43-ts";
> @@ -455,3 +489,125 @@ display-engine {
> compatible = "allwinner,sun5i-a13-display-engine";
> allwinner,pipelines = <&fe0>;
> };
> +
> +Example 2:
> +
> +connector {
> + compatible = "hdmi-connector";
> + type = "a";
> +
> + port {
> + hdmi_con_in: endpoint {
> + remote-endpoint = <&hdmi_out_con>;
> + };
> + };
> +};
> +
> +de: display-engine {
> + compatible = "allwinner,sun8i-h3-display-engine";
> + allwinner,pipelines = <&mixer0>;
> +};
> +
> +hdmi: hdmi@1ee0000 {
> + compatible = "allwinner,h3-dw-hdmi";
> + reg = <0x01ee0000 0x10000>,
> + <0x01ef0000 0x10000>;
> + reg-io-width = <1>;
> + interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&ccu CLK_BUS_HDMI>, <&ccu CLK_HDMI>,
> + <&ccu CLK_HDMI_DDC>;
> + clock-names = "iahb", "isfr", "ddc";
> + resets = <&ccu RST_BUS_HDMI0>, <&ccu RST_BUS_HDMI1>;
> + reset-names = "hdmi", "ddc";
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + hdmi_in: port@0 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + reg = <0>;
> +
> + hdmi_in_tcon0: endpoint@0 {
> + reg = <0>;

You don't need reg when there's only one.

Otherwise,

Acked-by: Rob Herring <[email protected]>

2017-09-30 11:58:16

by Alexey Kardashevskiy

[permalink] [raw]
Subject: Re: [RESEND RFC PATCH 0/7] sun8i H3 HDMI glue driver for DW HDMI

On 21/09/17 06:01, Jernej Skrabec wrote:
> [added media mailing list due to CEC question]
>
> This patch series adds a HDMI glue driver for Allwinner H3 SoC. For now, only
> video and CEC functionality is supported. Audio needs more tweaks.
>
> Series is based on the H3 DE2 patch series available on mailing list:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2017-August/522697.html
> (ignore patches marked with [NOT FOR REVIEW NOW] tag)
>
> Patch 1 adds support for polling plug detection since custom PHY used here
> doesn't support HPD interrupt.
>
> Patch 2 enables overflow workaround for v1.32a. This HDMI controller exhibits
> same issues as HDMI controller used in iMX6 SoCs.
>
> Patch 3 adds CLK_SET_RATE_PARENT to hdmi clock.
>
> Patch 4 adds dt bindings documentation.
>
> Patch 5 adds actual H3 HDMI glue driver.
>
> Patch 6 and 7 add HDMI node to DT and enable it where needed.
>
> Allwinner used DW HDMI controller in a non standard way:
> - register offsets obfuscation layer, which can fortunately be turned off
> - register read lock, which has to be disabled by magic number
> - custom PHY, which have to be initialized before DW HDMI controller
> - non standard clocks
> - no HPD interrupt
>
> Because of that, I have two questions:
> - Since HPD have to be polled, is it enough just to enable poll mode? I'm
> mainly concerned about invalidating CEC address here.
> - PHY has to be initialized before DW HDMI controller to disable offset
> obfuscation and read lock among other things. This means that all clocks have
> to be enabled in glue driver. This poses a problem, since when using
> component model, dw-hdmi bridge uses drvdata for it's own private data and
> prevents glue layer to pass a pointer to unbind function, where clocks should
> be disabled. I noticed same issue in meson DW HDMI glue driver, where clocks
> are also not disabled when unbind callback is called. I noticed that when H3
> SoC is shutdown, HDMI output is still enabled and lastest image is shown on
> monitor until it is unplugged from power supply. Is there any simple solution
> to this?
>
> Chen-Yu,
> TL Lim was unable to obtain any answer from Allwinner about HDMI clocks. I think
> it is safe to assume that divider in HDMI clock doesn't have any effect.
>
> Branch based on linux-next from 1. September with integrated patches is
> available here:
> https://github.com/jernejsk/linux-1/tree/h3_hdmi_rfc


Out of curiosity I tried this one and got:



[ 0.071711] sun4i-usb-phy 1c19400.phy: Couldn't request ID GPIO
[ 0.074809] sun8i-h3-pinctrl 1c20800.pinctrl: initialized sunXi PIO driver
[ 0.076167] sun8i-h3-r-pinctrl 1f02c00.pinctrl: initialized sunXi PIO driver
[ 0.148009] ------------[ cut here ]------------
[ 0.148035] WARNING: CPU: 0 PID: 1 at
drivers/clk/sunxi-ng/ccu_common.c:41 ccu_nm_set_rate+0x1d0/0x274
[ 0.148046] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
4.13.0-rc6-next-20170825-aik-aik #24
[ 0.148051] Hardware name: Allwinner sun8i Family
[ 0.148082] [<c010de6c>] (unwind_backtrace) from [<c010b260>]
(show_stack+0x10/0x14)
[ 0.148101] [<c010b260>] (show_stack) from [<c077a464>]
(dump_stack+0x84/0x98)
[ 0.148117] [<c077a464>] (dump_stack) from [<c011abe0>] (__warn+0xe0/0xfc)
[ 0.148132] [<c011abe0>] (__warn) from [<c011acac>]
(warn_slowpath_null+0x20/0x28)
[ 0.148145] [<c011acac>] (warn_slowpath_null) from [<c03d1888>]
(ccu_nm_set_rate+0x1d0/0x274)
[ 0.148161] [<c03d1888>] (ccu_nm_set_rate) from [<c03c78b4>]
(clk_change_rate+0x19c/0x250)
[ 0.148175] [<c03c78b4>] (clk_change_rate) from [<c03c7b7c>]
(clk_core_set_rate_nolock+0x68/0xb0)
[ 0.148187] [<c03c7b7c>] (clk_core_set_rate_nolock) from [<c03c8134>]
(clk_set_rate+0x20/0x30)
[ 0.148202] [<c03c8134>] (clk_set_rate) from [<c03cc560>]
(of_clk_set_defaults+0x200/0x364)
[ 0.148219] [<c03cc560>] (of_clk_set_defaults) from [<c045427c>]
(platform_drv_probe+0x18/0xb0)
[ 0.148233] [<c045427c>] (platform_drv_probe) from [<c0452efc>]
(driver_probe_device+0x234/0x2e8)
[ 0.148246] [<c0452efc>] (driver_probe_device) from [<c0453068>]
(__driver_attach+0xb8/0xbc)
[ 0.148258] [<c0453068>] (__driver_attach) from [<c0451414[ 1.336154]
Unable to handle kernel NULL pointer dereference at virtual address 00000008

and a bit later:

[ 1.995572] Rebooting in 10 seconds..

Orange PI PC, script.bin.OPI-PC_1080p60_hdmi.

What do I miss? Thanks.



--
Alexey

2017-09-30 17:56:28

by Jernej Skrabec

[permalink] [raw]
Subject: Re: [RESEND RFC PATCH 0/7] sun8i H3 HDMI glue driver for DW HDMI

Hi,

Dne sobota, 30. september 2017 ob 13:58:03 CEST je Alexey Kardashevskiy
napisal(a):
> On 21/09/17 06:01, Jernej Skrabec wrote:
> > [added media mailing list due to CEC question]
> >
> > This patch series adds a HDMI glue driver for Allwinner H3 SoC. For now,
> > only video and CEC functionality is supported. Audio needs more tweaks.
> >
> > Series is based on the H3 DE2 patch series available on mailing list:
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2017-August/522697.h
> > tml (ignore patches marked with [NOT FOR REVIEW NOW] tag)
> >
> > Patch 1 adds support for polling plug detection since custom PHY used here
> > doesn't support HPD interrupt.
> >
> > Patch 2 enables overflow workaround for v1.32a. This HDMI controller
> > exhibits same issues as HDMI controller used in iMX6 SoCs.
> >
> > Patch 3 adds CLK_SET_RATE_PARENT to hdmi clock.
> >
> > Patch 4 adds dt bindings documentation.
> >
> > Patch 5 adds actual H3 HDMI glue driver.
> >
> > Patch 6 and 7 add HDMI node to DT and enable it where needed.
> >
> > Allwinner used DW HDMI controller in a non standard way:
> > - register offsets obfuscation layer, which can fortunately be turned off
> > - register read lock, which has to be disabled by magic number
> > - custom PHY, which have to be initialized before DW HDMI controller
> > - non standard clocks
> > - no HPD interrupt
> >
> > Because of that, I have two questions:
> > - Since HPD have to be polled, is it enough just to enable poll mode? I'm
> >
> > mainly concerned about invalidating CEC address here.
> >
> > - PHY has to be initialized before DW HDMI controller to disable offset
> >
> > obfuscation and read lock among other things. This means that all clocks
> > have to be enabled in glue driver. This poses a problem, since when
> > using component model, dw-hdmi bridge uses drvdata for it's own private
> > data and prevents glue layer to pass a pointer to unbind function,
> > where clocks should be disabled. I noticed same issue in meson DW HDMI
> > glue driver, where clocks are also not disabled when unbind callback is
> > called. I noticed that when H3 SoC is shutdown, HDMI output is still
> > enabled and lastest image is shown on monitor until it is unplugged
> > from power supply. Is there any simple solution to this?
> >
> > Chen-Yu,
> > TL Lim was unable to obtain any answer from Allwinner about HDMI clocks. I
> > think it is safe to assume that divider in HDMI clock doesn't have any
> > effect.
> >
> > Branch based on linux-next from 1. September with integrated patches is
> > available here:
> > https://github.com/jernejsk/linux-1/tree/h3_hdmi_rfc
>
> Out of curiosity I tried this one and got:
>
>
>
> [ 0.071711] sun4i-usb-phy 1c19400.phy: Couldn't request ID GPIO
> [ 0.074809] sun8i-h3-pinctrl 1c20800.pinctrl: initialized sunXi PIO
> driver [ 0.076167] sun8i-h3-r-pinctrl 1f02c00.pinctrl: initialized sunXi
> PIO driver [ 0.148009] ------------[ cut here ]------------
> [ 0.148035] WARNING: CPU: 0 PID: 1 at
> drivers/clk/sunxi-ng/ccu_common.c:41 ccu_nm_set_rate+0x1d0/0x274
> [ 0.148046] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
> 4.13.0-rc6-next-20170825-aik-aik #24
> [ 0.148051] Hardware name: Allwinner sun8i Family
> [ 0.148082] [<c010de6c>] (unwind_backtrace) from [<c010b260>]
> (show_stack+0x10/0x14)
> [ 0.148101] [<c010b260>] (show_stack) from [<c077a464>]
> (dump_stack+0x84/0x98)
> [ 0.148117] [<c077a464>] (dump_stack) from [<c011abe0>]
> (__warn+0xe0/0xfc) [ 0.148132] [<c011abe0>] (__warn) from [<c011acac>]
> (warn_slowpath_null+0x20/0x28)
> [ 0.148145] [<c011acac>] (warn_slowpath_null) from [<c03d1888>]
> (ccu_nm_set_rate+0x1d0/0x274)
> [ 0.148161] [<c03d1888>] (ccu_nm_set_rate) from [<c03c78b4>]
> (clk_change_rate+0x19c/0x250)
> [ 0.148175] [<c03c78b4>] (clk_change_rate) from [<c03c7b7c>]
> (clk_core_set_rate_nolock+0x68/0xb0)
> [ 0.148187] [<c03c7b7c>] (clk_core_set_rate_nolock) from [<c03c8134>]
> (clk_set_rate+0x20/0x30)
> [ 0.148202] [<c03c8134>] (clk_set_rate) from [<c03cc560>]
> (of_clk_set_defaults+0x200/0x364)
> [ 0.148219] [<c03cc560>] (of_clk_set_defaults) from [<c045427c>]
> (platform_drv_probe+0x18/0xb0)
> [ 0.148233] [<c045427c>] (platform_drv_probe) from [<c0452efc>]
> (driver_probe_device+0x234/0x2e8)
> [ 0.148246] [<c0452efc>] (driver_probe_device) from [<c0453068>]
> (__driver_attach+0xb8/0xbc)
> [ 0.148258] [<c0453068>] (__driver_attach) from [<c0451414[ 1.336154]
> Unable to handle kernel NULL pointer dereference at virtual address 00000008
>

Patch for that is already merged upstream and can be found here:
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/
drivers/clk/sunxi-ng?id=62d212bdb022deeb875f92f6e376c799e3f35eca

> and a bit later:
>
> [ 1.995572] Rebooting in 10 seconds..

I'm not sure about that one. Kernel config issue?

Regards,
Jernej

>
> Orange PI PC, script.bin.OPI-PC_1080p60_hdmi.
>
> What do I miss? Thanks.
>
>
>
> --
> Alexey


2017-10-01 01:46:49

by Alexey Kardashevskiy

[permalink] [raw]
Subject: Re: [RESEND RFC PATCH 0/7] sun8i H3 HDMI glue driver for DW HDMI

On 01/10/17 04:56, Jernej Škrabec wrote:
> Hi,
>
> Dne sobota, 30. september 2017 ob 13:58:03 CEST je Alexey Kardashevskiy
> napisal(a):
>> On 21/09/17 06:01, Jernej Skrabec wrote:
>>> [added media mailing list due to CEC question]
>>>
>>> This patch series adds a HDMI glue driver for Allwinner H3 SoC. For now,
>>> only video and CEC functionality is supported. Audio needs more tweaks.
>>>
>>> Series is based on the H3 DE2 patch series available on mailing list:
>>> http://lists.infradead.org/pipermail/linux-arm-kernel/2017-August/522697.h
>>> tml (ignore patches marked with [NOT FOR REVIEW NOW] tag)
>>>
>>> Patch 1 adds support for polling plug detection since custom PHY used here
>>> doesn't support HPD interrupt.
>>>
>>> Patch 2 enables overflow workaround for v1.32a. This HDMI controller
>>> exhibits same issues as HDMI controller used in iMX6 SoCs.
>>>
>>> Patch 3 adds CLK_SET_RATE_PARENT to hdmi clock.
>>>
>>> Patch 4 adds dt bindings documentation.
>>>
>>> Patch 5 adds actual H3 HDMI glue driver.
>>>
>>> Patch 6 and 7 add HDMI node to DT and enable it where needed.
>>>
>>> Allwinner used DW HDMI controller in a non standard way:
>>> - register offsets obfuscation layer, which can fortunately be turned off
>>> - register read lock, which has to be disabled by magic number
>>> - custom PHY, which have to be initialized before DW HDMI controller
>>> - non standard clocks
>>> - no HPD interrupt
>>>
>>> Because of that, I have two questions:
>>> - Since HPD have to be polled, is it enough just to enable poll mode? I'm
>>>
>>> mainly concerned about invalidating CEC address here.
>>>
>>> - PHY has to be initialized before DW HDMI controller to disable offset
>>>
>>> obfuscation and read lock among other things. This means that all clocks
>>> have to be enabled in glue driver. This poses a problem, since when
>>> using component model, dw-hdmi bridge uses drvdata for it's own private
>>> data and prevents glue layer to pass a pointer to unbind function,
>>> where clocks should be disabled. I noticed same issue in meson DW HDMI
>>> glue driver, where clocks are also not disabled when unbind callback is
>>> called. I noticed that when H3 SoC is shutdown, HDMI output is still
>>> enabled and lastest image is shown on monitor until it is unplugged
>>> from power supply. Is there any simple solution to this?
>>>
>>> Chen-Yu,
>>> TL Lim was unable to obtain any answer from Allwinner about HDMI clocks. I
>>> think it is safe to assume that divider in HDMI clock doesn't have any
>>> effect.
>>>
>>> Branch based on linux-next from 1. September with integrated patches is
>>> available here:
>>> https://github.com/jernejsk/linux-1/tree/h3_hdmi_rfc
>>
>> Out of curiosity I tried this one and got:
>>
>>
>>
>> [ 0.071711] sun4i-usb-phy 1c19400.phy: Couldn't request ID GPIO
>> [ 0.074809] sun8i-h3-pinctrl 1c20800.pinctrl: initialized sunXi PIO
>> driver [ 0.076167] sun8i-h3-r-pinctrl 1f02c00.pinctrl: initialized sunXi
>> PIO driver [ 0.148009] ------------[ cut here ]------------
>> [ 0.148035] WARNING: CPU: 0 PID: 1 at
>> drivers/clk/sunxi-ng/ccu_common.c:41 ccu_nm_set_rate+0x1d0/0x274
>> [ 0.148046] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
>> 4.13.0-rc6-next-20170825-aik-aik #24
>> [ 0.148051] Hardware name: Allwinner sun8i Family
>> [ 0.148082] [<c010de6c>] (unwind_backtrace) from [<c010b260>]
>> (show_stack+0x10/0x14)
>> [ 0.148101] [<c010b260>] (show_stack) from [<c077a464>]
>> (dump_stack+0x84/0x98)
>> [ 0.148117] [<c077a464>] (dump_stack) from [<c011abe0>]
>> (__warn+0xe0/0xfc) [ 0.148132] [<c011abe0>] (__warn) from [<c011acac>]
>> (warn_slowpath_null+0x20/0x28)
>> [ 0.148145] [<c011acac>] (warn_slowpath_null) from [<c03d1888>]
>> (ccu_nm_set_rate+0x1d0/0x274)
>> [ 0.148161] [<c03d1888>] (ccu_nm_set_rate) from [<c03c78b4>]
>> (clk_change_rate+0x19c/0x250)
>> [ 0.148175] [<c03c78b4>] (clk_change_rate) from [<c03c7b7c>]
>> (clk_core_set_rate_nolock+0x68/0xb0)
>> [ 0.148187] [<c03c7b7c>] (clk_core_set_rate_nolock) from [<c03c8134>]
>> (clk_set_rate+0x20/0x30)
>> [ 0.148202] [<c03c8134>] (clk_set_rate) from [<c03cc560>]
>> (of_clk_set_defaults+0x200/0x364)
>> [ 0.148219] [<c03cc560>] (of_clk_set_defaults) from [<c045427c>]
>> (platform_drv_probe+0x18/0xb0)
>> [ 0.148233] [<c045427c>] (platform_drv_probe) from [<c0452efc>]
>> (driver_probe_device+0x234/0x2e8)
>> [ 0.148246] [<c0452efc>] (driver_probe_device) from [<c0453068>]
>> (__driver_attach+0xb8/0xbc)
>> [ 0.148258] [<c0453068>] (__driver_attach) from [<c0451414[ 1.336154]
>> Unable to handle kernel NULL pointer dereference at virtual address 00000008
>>
>
> Patch for that is already merged upstream and can be found here:
> https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/
> drivers/clk/sunxi-ng?id=62d212bdb022deeb875f92f6e376c799e3f35eca

Lovely, it works, thanks!


>> and a bit later:
>>
>> [ 1.995572] Rebooting in 10 seconds..
>
> I'm not sure about that one. Kernel config issue?



Yup, I did not have CMA enabled.




--
Alexey

2017-11-02 07:21:01

by Stephen Boyd

[permalink] [raw]
Subject: Re: [RESEND RFC PATCH 3/7] clk: sunxi: Add CLK_SET_RATE_PARENT flag for H3 HDMI clock

On 09/20, Jernej Skrabec wrote:
> When setting the HDMI clock of H3, the PLL_VIDEO clock needs to be set.
>
> Add CLK_SET_RATE_PARENT flag for H3 HDMI clock.
>
> Signed-off-by: Jernej Skrabec <[email protected]>
> Signed-off-by: Icenowy Zheng <[email protected]>
> ---

Acked-by: Stephen Boyd <[email protected]>

--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

From 1579090183116901092@xxx Wed Sep 20 20:02:30 +0000 2017
X-GM-THRID: 1579088895389373217
X-Gmail-Labels: Inbox,Category Forums