All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/17] video: dw_hdmi: Support Vendor PHY
@ 2023-12-11  8:59 Jagan Teki
  2023-12-11  8:59 ` [PATCH 01/17] video: rockchip: hdmi: Detect hpd after controller init Jagan Teki
                   ` (17 more replies)
  0 siblings, 18 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

Unlike RK3399, Sunxi/Meson DW HDMI the new Rockchip SoC Rk3328 would
support external vendor PHY with DW HDMI chip.

Support this vendor PHY by adding new platform PHY ops via DW HDMI
driver and call the respective generic phy from platform driver code.

This series tested in RK3328 with 1080p (1920x1080) resolution.

Patch 0001/0005: Support Vendor PHY
Patch 0006/0008: VOP extension for win, dsp offsets
Patch 0009/0010: RK3328 VOP, HDMI clocks
Patch 0011:	 Rockchip Inno HDMI PHY
Patch 0012:	 RK3328 HDMI driver
Patch 0013:	 RK3328 VOP driver
Patch 0014/0017: Enable HDMI Out for RK3328

Importent:
One pontential issues is that Linux HDMI out on RK3328 has effected by
this patchset as I wouldn't find any relation or clue.

[    0.752016] Loading compiled-in X.509 certificates
[    0.787796] inno_hdmi_phy_rk3328_clk_recalc_rate: parent 24000000
[    0.788391] inno-hdmi-phy ff430000.phy: inno_hdmi_phy_rk3328_clk_recalc_rate rate 148500000 vco 148500000
[    0.798353] rockchip-drm display-subsystem: bound ff370000.vop (ops vop_component_ops)
[    0.799403] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-0v9 not found, using dummy regulator
[    0.800288] rk_iommu ff373f00.iommu: Enable stall request timed out, status: 0x00004b
[    0.801131] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-1v8 not found, using dummy regulator
[    0.802056] rk_iommu ff373f00.iommu: Disable paging request timed out, status: 0x00004b
[    0.803233] dwhdmi-rockchip ff3c0000.hdmi: Detected HDMI TX controller v2.11a with HDCP (inno_dw_hdmi_phy2)
[    0.805355] dwhdmi-rockchip ff3c0000.hdmi: registered DesignWare HDMI I2C bus driver
[    0.808769] rockchip-drm display-subsystem: bound ff3c0000.hdmi (ops dw_hdmi_rockchip_ops)
[    0.810869] [drm] Initialized rockchip 1.0.0 20140818 for display-subsystem on minor 0

The only way I can use Linux HDMI by disabling IOMMU or support
disable-iommu link for RK3328 via DT [1].

[1] https://www.spinics.net/lists/devicetree/msg605124.html

Any inputs?
Jagan.

Jagan Teki (17):
  video: rockchip: hdmi: Detect hpd after controller init
  video: dw_hdmi: Add Vendor PHY handling
  video: dw_hdmi: Extend the HPD detection
  video: dw_hdmi: Add read_hpd hook
  video: dw_hdmi: Add setup_hpd hook
  video: rockchip: vop: Simplify rkvop_enable
  video: rockchip: vop: Add win offset support
  video: rockchip: vop: Add dsp offset support
  clk: rockchip: rk3328: Add VOP clk support
  clk: rk3328: Add get hdmiphy clock
  phy: rockchip: Add Rockchip INNO HDMI PHY driver
  video: rockchip: Add rk3328 hdmi support
  video: rockchip: Add rk3328 vop support
  ARM: dts: rk3328: Enable VOP for bootph-all
  rockchip: Enable preconsole for rk3328
  configs: evb-rk3328: Enable vidconsole for rk3328
  configs: Enable HDMI Out for ROC-RK3328-CC

 arch/arm/dts/rk3328-u-boot.dtsi               |   4 +
 .../include/asm/arch-rockchip/cru_rk3328.h    |  34 +
 arch/arm/mach-rockchip/Kconfig                |   1 +
 common/Kconfig                                |   2 +-
 configs/roc-cc-rk3328_defconfig               |   5 +
 drivers/clk/rockchip/clk_rk3328.c             | 100 +-
 drivers/phy/rockchip/Kconfig                  |   7 +
 drivers/phy/rockchip/Makefile                 |   1 +
 drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 885 ++++++++++++++++++
 drivers/video/dw_hdmi.c                       |  48 +-
 drivers/video/meson/meson_dw_hdmi.c           |  11 +-
 drivers/video/rockchip/Makefile               |   2 +
 drivers/video/rockchip/rk3328_hdmi.c          | 131 +++
 drivers/video/rockchip/rk3328_vop.c           |  66 ++
 drivers/video/rockchip/rk3399_hdmi.c          |   8 +-
 drivers/video/rockchip/rk_hdmi.c              |  12 +-
 drivers/video/rockchip/rk_hdmi.h              |   3 +
 drivers/video/rockchip/rk_vop.c               |  44 +-
 drivers/video/rockchip/rk_vop.h               |   4 +
 drivers/video/sunxi/sunxi_dw_hdmi.c           |  19 +-
 include/configs/evb_rk3328.h                  |   5 +
 include/configs/rk3328_common.h               |   1 +
 include/dw_hdmi.h                             |  17 +-
 23 files changed, 1371 insertions(+), 39 deletions(-)
 create mode 100644 drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
 create mode 100644 drivers/video/rockchip/rk3328_hdmi.c
 create mode 100644 drivers/video/rockchip/rk3328_vop.c

-- 
2.25.1


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

* [PATCH 01/17] video: rockchip: hdmi: Detect hpd after controller init
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-11  8:59 ` [PATCH 02/17] video: dw_hdmi: Add Vendor PHY handling Jagan Teki
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

From: Jagan Teki <jagan@edgeble.ai>

HDP is a hardware connector event, so detect the same once the
controller and attached PHY initialization are done.

Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
 drivers/video/rockchip/rk_hdmi.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c
index 8dcd4d5964..b75a174489 100644
--- a/drivers/video/rockchip/rk_hdmi.c
+++ b/drivers/video/rockchip/rk_hdmi.c
@@ -112,14 +112,14 @@ int rk_hdmi_probe(struct udevice *dev)
 	struct dw_hdmi *hdmi = &priv->hdmi;
 	int ret;
 
+	dw_hdmi_init(hdmi);
+	dw_hdmi_phy_init(hdmi);
+
 	ret = dw_hdmi_phy_wait_for_hpd(hdmi);
 	if (ret < 0) {
 		debug("hdmi can not get hpd signal\n");
 		return -1;
 	}
 
-	dw_hdmi_init(hdmi);
-	dw_hdmi_phy_init(hdmi);
-
 	return 0;
 }
-- 
2.25.1


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

* [PATCH 02/17] video: dw_hdmi: Add Vendor PHY handling
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
  2023-12-11  8:59 ` [PATCH 01/17] video: rockchip: hdmi: Detect hpd after controller init Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-11  9:08   ` Neil Armstrong
  2023-12-13 19:50   ` Simon Glass
  2023-12-11  8:59 ` [PATCH 03/17] video: dw_hdmi: Extend the HPD detection Jagan Teki
                   ` (15 subsequent siblings)
  17 siblings, 2 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

From: Jagan Teki <jagan@edgeble.ai>

DW HDMI support Vendor PHY like Rockchip RK3328 Inno HDMI PHY.

Extend the vendor phy handling by adding platform phy hooks.

Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
 drivers/video/dw_hdmi.c              | 29 +++++++++++++++++++++++++++-
 drivers/video/meson/meson_dw_hdmi.c  | 11 ++++++++++-
 drivers/video/rockchip/rk3399_hdmi.c |  8 +++++++-
 drivers/video/rockchip/rk_hdmi.c     |  2 +-
 drivers/video/sunxi/sunxi_dw_hdmi.c  | 11 ++++++++++-
 include/dw_hdmi.h                    | 14 +++++++++++++-
 6 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/drivers/video/dw_hdmi.c b/drivers/video/dw_hdmi.c
index c4fbb18294..ea12a09407 100644
--- a/drivers/video/dw_hdmi.c
+++ b/drivers/video/dw_hdmi.c
@@ -988,7 +988,7 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
 
 	hdmi_av_composer(hdmi, edid);
 
-	ret = hdmi->phy_set(hdmi, edid->pixelclock.typ);
+	ret = hdmi->ops->phy_set(hdmi, edid->pixelclock.typ);
 	if (ret)
 		return ret;
 
@@ -1009,10 +1009,37 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
 	return 0;
 }
 
+static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
+	.phy_set = dw_hdmi_phy_cfg,
+};
+
+static void dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
+{
+	if (!hdmi->data)
+		return;
+
+	/* hook Synopsys PHYs ops */
+	if (!hdmi->data->phy_force_vendor) {
+		hdmi->ops = &dw_hdmi_synopsys_phy_ops;
+		return;
+	}
+
+	/* Vendor HDMI PHYs must assign phy_ops in plat_data */
+	if (!hdmi->data->phy_ops) {
+		printf("Unsupported Vendor HDMI phy_ops\n");
+		return;
+	}
+
+	/* hook Vendor HDMI PHYs ops */
+	hdmi->ops = hdmi->data->phy_ops;
+}
+
 void dw_hdmi_init(struct dw_hdmi *hdmi)
 {
 	uint ih_mute;
 
+	dw_hdmi_detect_phy(hdmi);
+
 	/*
 	 * boot up defaults are:
 	 * hdmi_ih_mute   = 0x03 (disabled)
diff --git a/drivers/video/meson/meson_dw_hdmi.c b/drivers/video/meson/meson_dw_hdmi.c
index 5db01904b5..63ca3ac52e 100644
--- a/drivers/video/meson/meson_dw_hdmi.c
+++ b/drivers/video/meson/meson_dw_hdmi.c
@@ -375,6 +375,15 @@ static int meson_dw_hdmi_wait_hpd(struct dw_hdmi *hdmi)
 	return -ETIMEDOUT;
 }
 
+static const struct dw_hdmi_phy_ops dw_hdmi_meson_phy_ops = {
+	.phy_set = meson_dw_hdmi_phy_cfg,
+};
+
+static const struct dw_hdmi_plat_data dw_hdmi_meson_plat_data = {
+	.phy_force_vendor = true,
+	.phy_ops = &dw_hdmi_meson_phy_ops,
+};
+
 static int meson_dw_hdmi_probe(struct udevice *dev)
 {
 	struct meson_dw_hdmi *priv = dev_get_priv(dev);
@@ -397,7 +406,7 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
 
 	priv->hdmi.hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
 	priv->hdmi.hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
-	priv->hdmi.phy_set = meson_dw_hdmi_phy_init;
+	priv->hdmi.data = &dw_hdmi_meson_plat_data;
 	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
 		priv->hdmi.reg_io_width = 1;
 	else {
diff --git a/drivers/video/rockchip/rk3399_hdmi.c b/drivers/video/rockchip/rk3399_hdmi.c
index 3041360c6e..b32139a8a6 100644
--- a/drivers/video/rockchip/rk3399_hdmi.c
+++ b/drivers/video/rockchip/rk3399_hdmi.c
@@ -64,8 +64,14 @@ static const struct dm_display_ops rk3399_hdmi_ops = {
 	.enable = rk3399_hdmi_enable,
 };
 
+static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
+};
+
 static const struct udevice_id rk3399_hdmi_ids[] = {
-	{ .compatible = "rockchip,rk3399-dw-hdmi" },
+	{
+		.compatible = "rockchip,rk3399-dw-hdmi",
+		.data = (ulong)&rk3399_hdmi_drv_data
+	},
 	{ }
 };
 
diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c
index b75a174489..e34f532cd6 100644
--- a/drivers/video/rockchip/rk_hdmi.c
+++ b/drivers/video/rockchip/rk_hdmi.c
@@ -83,6 +83,7 @@ int rk_hdmi_of_to_plat(struct udevice *dev)
 	struct rk_hdmi_priv *priv = dev_get_priv(dev);
 	struct dw_hdmi *hdmi = &priv->hdmi;
 
+	hdmi->data = (const struct dw_hdmi_plat_data *)dev_get_driver_data(dev);
 	hdmi->ioaddr = (ulong)dev_read_addr(dev);
 	hdmi->mpll_cfg = rockchip_mpll_cfg;
 	hdmi->phy_cfg = rockchip_phy_config;
@@ -90,7 +91,6 @@ int rk_hdmi_of_to_plat(struct udevice *dev)
 	/* hdmi->i2c_clk_{high,low} are set up by the SoC driver */
 
 	hdmi->reg_io_width = 4;
-	hdmi->phy_set = dw_hdmi_phy_cfg;
 
 	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
 
diff --git a/drivers/video/sunxi/sunxi_dw_hdmi.c b/drivers/video/sunxi/sunxi_dw_hdmi.c
index 0324a050d0..4b67a1614e 100644
--- a/drivers/video/sunxi/sunxi_dw_hdmi.c
+++ b/drivers/video/sunxi/sunxi_dw_hdmi.c
@@ -369,6 +369,15 @@ static int sunxi_dw_hdmi_probe(struct udevice *dev)
 	return 0;
 }
 
+static const struct dw_hdmi_phy_ops dw_hdmi_sunxi_phy_ops = {
+	.phy_set = sunxi_dw_hdmi_phy_cfg,
+};
+
+static const struct dw_hdmi_plat_data dw_hdmi_sunxi_plat_data = {
+	.phy_force_vendor = true,
+	.phy_ops = &dw_hdmi_sunxi_phy_ops,
+};
+
 static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
 {
 	struct sunxi_dw_hdmi_priv *priv = dev_get_priv(dev);
@@ -379,7 +388,7 @@ static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
 	hdmi->i2c_clk_high = 0xd8;
 	hdmi->i2c_clk_low = 0xfe;
 	hdmi->reg_io_width = 1;
-	hdmi->phy_set = sunxi_dw_hdmi_phy_cfg;
+	hdmi->data = &dw_hdmi_sunxi_plat_data;
 
 	ret = reset_get_bulk(dev, &priv->resets);
 	if (ret)
diff --git a/include/dw_hdmi.h b/include/dw_hdmi.h
index 8acae3839f..4ad8b39f84 100644
--- a/include/dw_hdmi.h
+++ b/include/dw_hdmi.h
@@ -534,6 +534,17 @@ struct hdmi_data_info {
 	struct hdmi_vmode video_mode;
 };
 
+struct dw_hdmi;
+
+struct dw_hdmi_phy_ops {
+	int (*phy_set)(struct dw_hdmi *hdmi, uint mpixelclock);
+};
+
+struct dw_hdmi_plat_data {
+	bool phy_force_vendor;
+	const struct dw_hdmi_phy_ops *phy_ops;
+};
+
 struct dw_hdmi {
 	ulong ioaddr;
 	const struct hdmi_mpll_config *mpll_cfg;
@@ -543,8 +554,9 @@ struct dw_hdmi {
 	u8 reg_io_width;
 	struct hdmi_data_info hdmi_data;
 	struct udevice *ddc_bus;
+	const struct dw_hdmi_phy_ops *ops;
+	const struct dw_hdmi_plat_data *data;
 
-	int (*phy_set)(struct dw_hdmi *hdmi, uint mpixelclock);
 	void (*write_reg)(struct dw_hdmi *hdmi, u8 val, int offset);
 	u8 (*read_reg)(struct dw_hdmi *hdmi, int offset);
 };
-- 
2.25.1


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

* [PATCH 03/17] video: dw_hdmi: Extend the HPD detection
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
  2023-12-11  8:59 ` [PATCH 01/17] video: rockchip: hdmi: Detect hpd after controller init Jagan Teki
  2023-12-11  8:59 ` [PATCH 02/17] video: dw_hdmi: Add Vendor PHY handling Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-11  8:59 ` [PATCH 04/17] video: dw_hdmi: Add read_hpd hook Jagan Teki
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

From: Jagan Teki <jagan@edgeble.ai>

HPD detection on some DW HDMIdesigned SoC's would need to read and
setup the HPD status explicitly.

So, extend the HPD detection code by adding the dw_hdmi_detect_hpd
function and move the default detection code caller there.

The new read and setup hdp will integrate the same function in
later patches.

Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
 drivers/video/dw_hdmi.c             | 13 +++++++++++++
 drivers/video/rockchip/rk_hdmi.c    |  8 +++-----
 drivers/video/sunxi/sunxi_dw_hdmi.c |  8 +++-----
 include/dw_hdmi.h                   |  1 +
 4 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/video/dw_hdmi.c b/drivers/video/dw_hdmi.c
index ea12a09407..0a597206f0 100644
--- a/drivers/video/dw_hdmi.c
+++ b/drivers/video/dw_hdmi.c
@@ -936,6 +936,19 @@ int dw_hdmi_phy_wait_for_hpd(struct dw_hdmi *hdmi)
 	return -1;
 }
 
+int dw_hdmi_detect_hpd(struct dw_hdmi *hdmi)
+{
+	int ret;
+
+	ret = dw_hdmi_phy_wait_for_hpd(hdmi);
+	if (ret < 0) {
+		debug("hdmi can not get hpd signal\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
 void dw_hdmi_phy_init(struct dw_hdmi *hdmi)
 {
 	/* enable phy i2cm done irq */
diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c
index e34f532cd6..8a65f2440e 100644
--- a/drivers/video/rockchip/rk_hdmi.c
+++ b/drivers/video/rockchip/rk_hdmi.c
@@ -115,11 +115,9 @@ int rk_hdmi_probe(struct udevice *dev)
 	dw_hdmi_init(hdmi);
 	dw_hdmi_phy_init(hdmi);
 
-	ret = dw_hdmi_phy_wait_for_hpd(hdmi);
-	if (ret < 0) {
-		debug("hdmi can not get hpd signal\n");
-		return -1;
-	}
+	ret = dw_hdmi_detect_hpd(hdmi);
+	if (ret < 0)
+		return ret;
 
 	return 0;
 }
diff --git a/drivers/video/sunxi/sunxi_dw_hdmi.c b/drivers/video/sunxi/sunxi_dw_hdmi.c
index 4b67a1614e..513276d812 100644
--- a/drivers/video/sunxi/sunxi_dw_hdmi.c
+++ b/drivers/video/sunxi/sunxi_dw_hdmi.c
@@ -358,11 +358,9 @@ static int sunxi_dw_hdmi_probe(struct udevice *dev)
 
 	sunxi_dw_hdmi_phy_init(&priv->hdmi);
 
-	ret = dw_hdmi_phy_wait_for_hpd(&priv->hdmi);
-	if (ret < 0) {
-		debug("hdmi can not get hpd signal\n");
-		return -1;
-	}
+	ret = dw_hdmi_detect_hpd(&priv->hdmi);
+	if (ret < 0)
+		return ret;
 
 	dw_hdmi_init(&priv->hdmi);
 
diff --git a/include/dw_hdmi.h b/include/dw_hdmi.h
index 4ad8b39f84..756560e092 100644
--- a/include/dw_hdmi.h
+++ b/include/dw_hdmi.h
@@ -568,5 +568,6 @@ void dw_hdmi_phy_init(struct dw_hdmi *hdmi);
 int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid);
 int dw_hdmi_read_edid(struct dw_hdmi *hdmi, u8 *buf, int buf_size);
 void dw_hdmi_init(struct dw_hdmi *hdmi);
+int dw_hdmi_detect_hpd(struct dw_hdmi *hdmi);
 
 #endif
-- 
2.25.1


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

* [PATCH 04/17] video: dw_hdmi: Add read_hpd hook
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
                   ` (2 preceding siblings ...)
  2023-12-11  8:59 ` [PATCH 03/17] video: dw_hdmi: Extend the HPD detection Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-11  8:59 ` [PATCH 05/17] video: dw_hdmi: Add setup_hpd hook Jagan Teki
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

From: Jagan Teki <jagan@edgeble.ai>

Add support for DW HDMI Read HPD status.

Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
 drivers/video/dw_hdmi.c | 3 +++
 include/dw_hdmi.h       | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/video/dw_hdmi.c b/drivers/video/dw_hdmi.c
index 0a597206f0..172e6b45a6 100644
--- a/drivers/video/dw_hdmi.c
+++ b/drivers/video/dw_hdmi.c
@@ -946,6 +946,9 @@ int dw_hdmi_detect_hpd(struct dw_hdmi *hdmi)
 		return -ENODEV;
 	}
 
+	if (hdmi->ops->read_hpd)
+		hdmi->ops->read_hpd(hdmi, true);
+
 	return 0;
 }
 
diff --git a/include/dw_hdmi.h b/include/dw_hdmi.h
index 756560e092..d6de472cee 100644
--- a/include/dw_hdmi.h
+++ b/include/dw_hdmi.h
@@ -538,6 +538,7 @@ struct dw_hdmi;
 
 struct dw_hdmi_phy_ops {
 	int (*phy_set)(struct dw_hdmi *hdmi, uint mpixelclock);
+	void (*read_hpd)(struct dw_hdmi *hdmi, bool hdp_status);
 };
 
 struct dw_hdmi_plat_data {
-- 
2.25.1


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

* [PATCH 05/17] video: dw_hdmi: Add setup_hpd hook
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
                   ` (3 preceding siblings ...)
  2023-12-11  8:59 ` [PATCH 04/17] video: dw_hdmi: Add read_hpd hook Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-11  8:59 ` [PATCH 06/17] video: rockchip: vop: Simplify rkvop_enable Jagan Teki
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

From: Jagan Teki <jagan@edgeble.ai>

Add support for DW HDMI Setup HPD status.

Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
 drivers/video/dw_hdmi.c | 3 +++
 include/dw_hdmi.h       | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/video/dw_hdmi.c b/drivers/video/dw_hdmi.c
index 172e6b45a6..3e0e20e59b 100644
--- a/drivers/video/dw_hdmi.c
+++ b/drivers/video/dw_hdmi.c
@@ -1080,4 +1080,7 @@ void dw_hdmi_init(struct dw_hdmi *hdmi)
 
 	/* enable i2c client nack % arbitration error irq */
 	hdmi_write(hdmi, ~0x44, HDMI_I2CM_CTLINT);
+
+	if (hdmi->ops->setup_hpd)
+		hdmi->ops->setup_hpd(hdmi);
 }
diff --git a/include/dw_hdmi.h b/include/dw_hdmi.h
index d6de472cee..9a44b9e90c 100644
--- a/include/dw_hdmi.h
+++ b/include/dw_hdmi.h
@@ -539,6 +539,7 @@ struct dw_hdmi;
 struct dw_hdmi_phy_ops {
 	int (*phy_set)(struct dw_hdmi *hdmi, uint mpixelclock);
 	void (*read_hpd)(struct dw_hdmi *hdmi, bool hdp_status);
+	void (*setup_hpd)(struct dw_hdmi *hdmi);
 };
 
 struct dw_hdmi_plat_data {
-- 
2.25.1


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

* [PATCH 06/17] video: rockchip: vop: Simplify rkvop_enable
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
                   ` (4 preceding siblings ...)
  2023-12-11  8:59 ` [PATCH 05/17] video: dw_hdmi: Add setup_hpd hook Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-11  8:59 ` [PATCH 07/17] video: rockchip: vop: Add win offset support Jagan Teki
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

From: Jagan Teki <jagan@edgeble.ai>

Get the regs from priv pointer instead of passing it an argument.

This would simplify the code and better readability.

Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
 drivers/video/rockchip/rk_vop.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c
index c514e2a0e4..158ba7cbf6 100644
--- a/drivers/video/rockchip/rk_vop.c
+++ b/drivers/video/rockchip/rk_vop.c
@@ -39,11 +39,13 @@ enum vop_pol {
 	DCLK_INVERT    = 3
 };
 
-static void rkvop_enable(struct udevice *dev, struct rk3288_vop *regs, ulong fbbase,
+static void rkvop_enable(struct udevice *dev, ulong fbbase,
 			 int fb_bits_per_pixel,
 			 const struct display_timing *edid,
 			 struct reset_ctl *dclk_rst)
 {
+	struct rk_vop_priv *priv = dev_get_priv(dev);
+	struct rk3288_vop *regs = priv->regs;
 	u32 lb_mode;
 	u32 rgb_mode;
 	u32 hactive = edid->hactive.typ;
@@ -243,9 +245,7 @@ static void rkvop_mode_set(struct udevice *dev,
 static int rk_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
 {
 	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
-	struct rk_vop_priv *priv = dev_get_priv(dev);
 	int vop_id, remote_vop_id;
-	struct rk3288_vop *regs = priv->regs;
 	struct display_timing timing;
 	struct udevice *disp;
 	int ret;
@@ -380,7 +380,7 @@ static int rk_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
 		return ret;
 	}
 
-	rkvop_enable(dev, regs, fbbase, 1 << l2bpp, &timing, &dclk_rst);
+	rkvop_enable(dev, fbbase, 1 << l2bpp, &timing, &dclk_rst);
 
 	ret = display_enable(disp, 1 << l2bpp, &timing);
 	if (ret)
-- 
2.25.1


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

* [PATCH 07/17] video: rockchip: vop: Add win offset support
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
                   ` (5 preceding siblings ...)
  2023-12-11  8:59 ` [PATCH 06/17] video: rockchip: vop: Simplify rkvop_enable Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-11  8:59 ` [PATCH 08/17] video: rockchip: vop: Add dsp " Jagan Teki
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

From: Jagan Teki <jagan@edgeble.ai>

Unlike RK3399, RK3288 the Newer Rockchip SoC's like RK3328 have
different offsets for win registers.

Group the win register set via win_regs pointers so that win_offset
would point the win_regs to access for any changes in the offset value.

Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
 drivers/video/rockchip/rk_vop.c | 22 +++++++++++++---------
 drivers/video/rockchip/rk_vop.h |  2 ++
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c
index 158ba7cbf6..b719a4e4ea 100644
--- a/drivers/video/rockchip/rk_vop.c
+++ b/drivers/video/rockchip/rk_vop.c
@@ -46,6 +46,7 @@ static void rkvop_enable(struct udevice *dev, ulong fbbase,
 {
 	struct rk_vop_priv *priv = dev_get_priv(dev);
 	struct rk3288_vop *regs = priv->regs;
+	struct rk3288_vop *win_regs = priv->regs + priv->win_offset;
 	u32 lb_mode;
 	u32 rgb_mode;
 	u32 hactive = edid->hactive.typ;
@@ -53,32 +54,32 @@ static void rkvop_enable(struct udevice *dev, ulong fbbase,
 	int ret;
 
 	writel(V_ACT_WIDTH(hactive - 1) | V_ACT_HEIGHT(vactive - 1),
-	       &regs->win0_act_info);
+	       &win_regs->win0_act_info);
 
 	writel(V_DSP_XST(edid->hsync_len.typ + edid->hback_porch.typ) |
 	       V_DSP_YST(edid->vsync_len.typ + edid->vback_porch.typ),
-	       &regs->win0_dsp_st);
+	       &win_regs->win0_dsp_st);
 
 	writel(V_DSP_WIDTH(hactive - 1) |
 		V_DSP_HEIGHT(vactive - 1),
-		&regs->win0_dsp_info);
+		&win_regs->win0_dsp_info);
 
-	clrsetbits_le32(&regs->win0_color_key, M_WIN0_KEY_EN | M_WIN0_KEY_COLOR,
+	clrsetbits_le32(&win_regs->win0_color_key, M_WIN0_KEY_EN | M_WIN0_KEY_COLOR,
 			V_WIN0_KEY_EN(0) | V_WIN0_KEY_COLOR(0));
 
 	switch (fb_bits_per_pixel) {
 	case 16:
 		rgb_mode = RGB565;
-		writel(V_RGB565_VIRWIDTH(hactive), &regs->win0_vir);
+		writel(V_RGB565_VIRWIDTH(hactive), &win_regs->win0_vir);
 		break;
 	case 24:
 		rgb_mode = RGB888;
-		writel(V_RGB888_VIRWIDTH(hactive), &regs->win0_vir);
+		writel(V_RGB888_VIRWIDTH(hactive), &win_regs->win0_vir);
 		break;
 	case 32:
 	default:
 		rgb_mode = ARGB8888;
-		writel(V_ARGB888_VIRWIDTH(hactive), &regs->win0_vir);
+		writel(V_ARGB888_VIRWIDTH(hactive), &win_regs->win0_vir);
 		break;
 	}
 
@@ -91,12 +92,12 @@ static void rkvop_enable(struct udevice *dev, ulong fbbase,
 	else
 		lb_mode = LB_RGB_1280X8;
 
-	clrsetbits_le32(&regs->win0_ctrl0,
+	clrsetbits_le32(&win_regs->win0_ctrl0,
 			M_WIN0_LB_MODE | M_WIN0_DATA_FMT | M_WIN0_EN,
 			V_WIN0_LB_MODE(lb_mode) | V_WIN0_DATA_FMT(rgb_mode) |
 			V_WIN0_EN(1));
 
-	writel(fbbase, &regs->win0_yrgb_mst);
+	writel(fbbase, &win_regs->win0_yrgb_mst);
 	writel(0x01, &regs->reg_cfg_done); /* enable reg config */
 
 	ret = reset_assert(dclk_rst);
@@ -415,6 +416,8 @@ int rk_vop_probe(struct udevice *dev)
 {
 	struct video_uc_plat *plat = dev_get_uclass_plat(dev);
 	struct rk_vop_priv *priv = dev_get_priv(dev);
+	struct rkvop_driverdata *ops =
+		(struct rkvop_driverdata *)dev_get_driver_data(dev);
 	int ret = 0;
 	ofnode port, node;
 	struct reset_ctl ahb_rst;
@@ -448,6 +451,7 @@ int rk_vop_probe(struct udevice *dev)
 #endif
 
 	priv->regs = dev_read_addr_ptr(dev);
+	priv->win_offset = ops->win_offset;
 
 	/*
 	 * Try all the ports until we find one that works. In practice this
diff --git a/drivers/video/rockchip/rk_vop.h b/drivers/video/rockchip/rk_vop.h
index 0528fb23f5..909f5602e5 100644
--- a/drivers/video/rockchip/rk_vop.h
+++ b/drivers/video/rockchip/rk_vop.h
@@ -11,6 +11,7 @@
 struct rk_vop_priv {
 	void *grf;
 	void *regs;
+	int win_offset;
 };
 
 enum vop_features {
@@ -18,6 +19,7 @@ enum vop_features {
 };
 
 struct rkvop_driverdata {
+	int win_offset;
 	/* configuration */
 	u32 features;
 	/* block-specific setters/getters */
-- 
2.25.1


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

* [PATCH 08/17] video: rockchip: vop: Add dsp offset support
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
                   ` (6 preceding siblings ...)
  2023-12-11  8:59 ` [PATCH 07/17] video: rockchip: vop: Add win offset support Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-11  8:59 ` [PATCH 09/17] clk: rockchip: rk3328: Add VOP clk support Jagan Teki
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

From: Jagan Teki <jagan@edgeble.ai>

Unlike RK3399, RK3288 the Newer Rockchip SoC's like RK3328 have
different offsets for dsp registers.

Group the dsp register set via dsp_regs pointers so that dsp_offset
would point the dsp_regs to access for any changes in the offset value.

Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
 drivers/video/rockchip/rk_vop.c | 14 ++++++++------
 drivers/video/rockchip/rk_vop.h |  2 ++
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c
index b719a4e4ea..acc02e5d7c 100644
--- a/drivers/video/rockchip/rk_vop.c
+++ b/drivers/video/rockchip/rk_vop.c
@@ -165,6 +165,7 @@ static void rkvop_mode_set(struct udevice *dev,
 {
 	struct rk_vop_priv *priv = dev_get_priv(dev);
 	struct rk3288_vop *regs = priv->regs;
+	struct rk3288_vop *dsp_regs = priv->regs + priv->dsp_offset;
 	struct rkvop_driverdata *data =
 		(struct rkvop_driverdata *)dev_get_driver_data(dev);
 
@@ -198,27 +199,27 @@ static void rkvop_mode_set(struct udevice *dev,
 
 	writel(V_HSYNC(hsync_len) |
 	       V_HORPRD(hsync_len + hback_porch + hactive + hfront_porch),
-			&regs->dsp_htotal_hs_end);
+			&dsp_regs->dsp_htotal_hs_end);
 
 	writel(V_HEAP(hsync_len + hback_porch + hactive) |
 	       V_HASP(hsync_len + hback_porch),
-	       &regs->dsp_hact_st_end);
+	       &dsp_regs->dsp_hact_st_end);
 
 	writel(V_VSYNC(vsync_len) |
 	       V_VERPRD(vsync_len + vback_porch + vactive + vfront_porch),
-	       &regs->dsp_vtotal_vs_end);
+	       &dsp_regs->dsp_vtotal_vs_end);
 
 	writel(V_VAEP(vsync_len + vback_porch + vactive)|
 	       V_VASP(vsync_len + vback_porch),
-	       &regs->dsp_vact_st_end);
+	       &dsp_regs->dsp_vact_st_end);
 
 	writel(V_HEAP(hsync_len + hback_porch + hactive) |
 	       V_HASP(hsync_len + hback_porch),
-	       &regs->post_dsp_hact_info);
+	       &dsp_regs->post_dsp_hact_info);
 
 	writel(V_VAEP(vsync_len + vback_porch + vactive)|
 	       V_VASP(vsync_len + vback_porch),
-	       &regs->post_dsp_vact_info);
+	       &dsp_regs->post_dsp_vact_info);
 
 	writel(0x01, &regs->reg_cfg_done); /* enable reg config */
 }
@@ -452,6 +453,7 @@ int rk_vop_probe(struct udevice *dev)
 
 	priv->regs = dev_read_addr_ptr(dev);
 	priv->win_offset = ops->win_offset;
+	priv->dsp_offset = ops->dsp_offset;
 
 	/*
 	 * Try all the ports until we find one that works. In practice this
diff --git a/drivers/video/rockchip/rk_vop.h b/drivers/video/rockchip/rk_vop.h
index 909f5602e5..eba68d87c4 100644
--- a/drivers/video/rockchip/rk_vop.h
+++ b/drivers/video/rockchip/rk_vop.h
@@ -12,6 +12,7 @@ struct rk_vop_priv {
 	void *grf;
 	void *regs;
 	int win_offset;
+	int dsp_offset;
 };
 
 enum vop_features {
@@ -20,6 +21,7 @@ enum vop_features {
 
 struct rkvop_driverdata {
 	int win_offset;
+	int dsp_offset;
 	/* configuration */
 	u32 features;
 	/* block-specific setters/getters */
-- 
2.25.1


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

* [PATCH 09/17] clk: rockchip: rk3328: Add VOP clk support
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
                   ` (7 preceding siblings ...)
  2023-12-11  8:59 ` [PATCH 08/17] video: rockchip: vop: Add dsp " Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-11  8:59 ` [PATCH 10/17] clk: rk3328: Add get hdmiphy clock Jagan Teki
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

From: Jagan Teki <jagan@edgeble.ai>

VOP get and set clock would needed for VOP drivers.

Add support for it.

Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
 .../include/asm/arch-rockchip/cru_rk3328.h    | 34 ++++++++
 drivers/clk/rockchip/clk_rk3328.c             | 83 ++++++++++++++++++-
 2 files changed, 115 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3328.h b/arch/arm/include/asm/arch-rockchip/cru_rk3328.h
index 226744d67d..4ad1d33e05 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3328.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3328.h
@@ -62,6 +62,40 @@ check_member(rk3328_cru, sdmmc_ext_con[1], 0x39c);
 enum apll_frequencies {
 	APLL_816_MHZ,
 	APLL_600_MHZ,
+
+	/* CRU_CLK_SEL37_CON */
+	ACLK_VIO_PLL_SEL_CPLL		= 0,
+	ACLK_VIO_PLL_SEL_GPLL		= 1,
+	ACLK_VIO_PLL_SEL_HDMIPHY	= 2,
+	ACLK_VIO_PLL_SEL_USB480M	= 3,
+	ACLK_VIO_PLL_SEL_SHIFT		= 6,
+	ACLK_VIO_PLL_SEL_MASK		= 3 << ACLK_VIO_PLL_SEL_SHIFT,
+	ACLK_VIO_DIV_CON_SHIFT		= 0,
+	ACLK_VIO_DIV_CON_MASK		= 0x1f << ACLK_VIO_DIV_CON_SHIFT,
+	HCLK_VIO_DIV_CON_SHIFT		= 8,
+	HCLK_VIO_DIV_CON_MASK		= 0x1f << HCLK_VIO_DIV_CON_SHIFT,
+
+	/* CRU_CLK_SEL39_CON */
+	ACLK_VOP_PLL_SEL_CPLL		= 0,
+	ACLK_VOP_PLL_SEL_GPLL		= 1,
+	ACLK_VOP_PLL_SEL_HDMIPHY	= 2,
+	ACLK_VOP_PLL_SEL_USB480M	= 3,
+	ACLK_VOP_PLL_SEL_SHIFT		= 6,
+	ACLK_VOP_PLL_SEL_MASK		= 3 << ACLK_VOP_PLL_SEL_SHIFT,
+	ACLK_VOP_DIV_CON_SHIFT		= 0,
+	ACLK_VOP_DIV_CON_MASK		= 0x1f << ACLK_VOP_DIV_CON_SHIFT,
+
+	/* CRU_CLK_SEL40_CON */
+	DCLK_LCDC_PLL_SEL_GPLL		= 0,
+	DCLK_LCDC_PLL_SEL_CPLL		= 1,
+	DCLK_LCDC_PLL_SEL_SHIFT		= 0,
+	DCLK_LCDC_PLL_SEL_MASK		= 1 << DCLK_LCDC_PLL_SEL_SHIFT,
+	DCLK_LCDC_SEL_HDMIPHY		= 0,
+	DCLK_LCDC_SEL_PLL		= 1,
+	DCLK_LCDC_SEL_SHIFT		= 1,
+	DCLK_LCDC_SEL_MASK		= 1 << DCLK_LCDC_SEL_SHIFT,
+	DCLK_LCDC_DIV_CON_SHIFT		= 8,
+	DCLK_LCDC_DIV_CON_MASK		= 0xFf << DCLK_LCDC_DIV_CON_SHIFT,
 };
 
 void rk3328_configure_cpu(struct rk3328_cru *cru,
diff --git a/drivers/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c
index ef97381f0e..7fcf84f08e 100644
--- a/drivers/clk/rockchip/clk_rk3328.c
+++ b/drivers/clk/rockchip/clk_rk3328.c
@@ -581,6 +581,81 @@ static ulong rk3328_spi_set_clk(struct rk3328_cru *cru, uint hz)
 	return rk3328_spi_get_clk(cru);
 }
 
+#ifndef CONFIG_SPL_BUILD
+static ulong rk3328_vop_get_clk(struct rk3328_clk_priv *priv, ulong clk_id)
+{
+	struct rk3328_cru *cru = priv->cru;
+	u32 div, con, parent;
+
+	switch (clk_id) {
+	case ACLK_VOP_PRE:
+		con = readl(&cru->clksel_con[39]);
+		div = (con & ACLK_VOP_DIV_CON_MASK) >> ACLK_VOP_DIV_CON_SHIFT;
+		parent = GPLL_HZ;
+		break;
+	case ACLK_VIO_PRE:
+		con = readl(&cru->clksel_con[37]);
+		div = (con & ACLK_VIO_DIV_CON_MASK) >> ACLK_VIO_DIV_CON_SHIFT;
+		parent = GPLL_HZ;
+		break;
+	default:
+		debug("%s: Unsupported vop get clk#%ld\n", __func__, clk_id);
+		return -ENOENT;
+	}
+
+	return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3328_vop_set_clk(struct rk3328_clk_priv *priv,
+				ulong clk_id, uint hz)
+{
+	struct rk3328_cru *cru = priv->cru;
+	int src_clk_div;
+	u32 con, parent;
+
+	src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz);
+	assert(src_clk_div - 1 < 31);
+
+	switch (clk_id) {
+	case ACLK_VOP_PRE:
+		rk_clrsetreg(&cru->clksel_con[39],
+			     ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK,
+			     ACLK_VOP_PLL_SEL_CPLL << ACLK_VOP_PLL_SEL_SHIFT |
+			     (src_clk_div - 1) << ACLK_VOP_DIV_CON_SHIFT);
+		break;
+	case ACLK_VIO_PRE:
+		rk_clrsetreg(&cru->clksel_con[37],
+			     ACLK_VIO_PLL_SEL_MASK | ACLK_VIO_DIV_CON_MASK,
+			     ACLK_VIO_PLL_SEL_CPLL << ACLK_VIO_PLL_SEL_SHIFT |
+			     (src_clk_div - 1) << ACLK_VIO_DIV_CON_SHIFT);
+		break;
+	case DCLK_LCDC:
+		con = readl(&cru->clksel_con[40]);
+		con = (con & DCLK_LCDC_SEL_MASK) >> DCLK_LCDC_SEL_SHIFT;
+		if (con) {
+			parent = readl(&cru->clksel_con[40]);
+			parent = (parent & DCLK_LCDC_PLL_SEL_MASK) >>
+				 DCLK_LCDC_PLL_SEL_SHIFT;
+			if (parent)
+				src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz);
+			else
+				src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz);
+
+			rk_clrsetreg(&cru->clksel_con[40],
+				     DCLK_LCDC_DIV_CON_MASK,
+				     (src_clk_div - 1) <<
+				     DCLK_LCDC_DIV_CON_SHIFT);
+		}
+		break;
+	default:
+		printf("%s: Unable to set vop clk#%ld\n", __func__, clk_id);
+		return -EINVAL;
+	}
+
+	return rk3328_vop_get_clk(priv, clk_id);
+}
+#endif
+
 static ulong rk3328_clk_get_rate(struct clk *clk)
 {
 	struct rk3328_clk_priv *priv = dev_get_priv(clk->dev);
@@ -649,7 +724,13 @@ static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate)
 	case SCLK_SPI:
 		ret = rk3328_spi_set_clk(priv->cru, rate);
 		break;
+#ifndef CONFIG_SPL_BUILD
 	case DCLK_LCDC:
+	case ACLK_VOP_PRE:
+	case ACLK_VIO_PRE:
+		rate = rk3328_vop_set_clk(priv, clk->id, rate);
+		break;
+#endif
 	case SCLK_PDM:
 	case SCLK_RTC32K:
 	case SCLK_UART0:
@@ -664,11 +745,9 @@ static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate)
 	case ACLK_PERI_PRE:
 	case HCLK_PERI:
 	case PCLK_PERI:
-	case ACLK_VIO_PRE:
 	case HCLK_VIO_PRE:
 	case ACLK_RGA_PRE:
 	case SCLK_RGA:
-	case ACLK_VOP_PRE:
 	case ACLK_RKVDEC_PRE:
 	case ACLK_RKVENC:
 	case ACLK_VPU_PRE:
-- 
2.25.1


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

* [PATCH 10/17] clk: rk3328: Add get hdmiphy clock
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
                   ` (8 preceding siblings ...)
  2023-12-11  8:59 ` [PATCH 09/17] clk: rockchip: rk3328: Add VOP clk support Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-11  8:59 ` [PATCH 11/17] phy: rockchip: Add Rockchip INNO HDMI PHY driver Jagan Teki
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

From: Jagan Teki <jagan@edgeble.ai>

Add support to get the hdmiphy clock for RK3328 PCLK_HDMIPHY.

Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
 drivers/clk/rockchip/clk_rk3328.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c
index 7fcf84f08e..5a4a555d36 100644
--- a/drivers/clk/rockchip/clk_rk3328.c
+++ b/drivers/clk/rockchip/clk_rk3328.c
@@ -179,6 +179,10 @@ enum {
 	CLK_I2C3_DIV_CON_SHIFT		= 8,
 	CLK_I2C2_PLL_SEL_SHIFT		= 7,
 	CLK_I2C2_DIV_CON_SHIFT		= 0,
+
+	/* CLKSEL_CON40 */
+	CLK_HDMIPHY_DIV_CON_SHIFT	= 3,
+	CLK_HDMIPHY_DIV_CON_MASK	= 0x7 << CLK_HDMIPHY_DIV_CON_SHIFT,
 };
 
 #define VCO_MAX_KHZ	(3200 * (MHz / KHz))
@@ -656,6 +660,16 @@ static ulong rk3328_vop_set_clk(struct rk3328_clk_priv *priv,
 }
 #endif
 
+static ulong rk3328_hdmiphy_get_clk(struct rk3328_cru *cru)
+{
+	u32 div, con;
+
+	con = readl(&cru->clksel_con[40]);
+	div = (con & CLK_HDMIPHY_DIV_CON_MASK) >> CLK_HDMIPHY_DIV_CON_SHIFT;
+
+	return DIV_TO_RATE(GPLL_HZ, div);
+}
+
 static ulong rk3328_clk_get_rate(struct clk *clk)
 {
 	struct rk3328_clk_priv *priv = dev_get_priv(clk->dev);
@@ -685,6 +699,9 @@ static ulong rk3328_clk_get_rate(struct clk *clk)
 	case SCLK_SPI:
 		rate = rk3328_spi_get_clk(priv->cru);
 		break;
+	case PCLK_HDMIPHY:
+		rate = rk3328_hdmiphy_get_clk(priv->cru);
+		break;
 	default:
 		return -ENOENT;
 	}
-- 
2.25.1


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

* [PATCH 11/17] phy: rockchip: Add Rockchip INNO HDMI PHY driver
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
                   ` (9 preceding siblings ...)
  2023-12-11  8:59 ` [PATCH 10/17] clk: rk3328: Add get hdmiphy clock Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-11  8:59 ` [PATCH 12/17] video: rockchip: Add rk3328 hdmi support Jagan Teki
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

From: Jagan Teki <jagan@edgeble.ai>

Add Rockchip INNO HDMI PHY driver for RK3328.

Reference from linux-next phy-rockchip-inno-hdmi driver.

Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
 drivers/phy/rockchip/Kconfig                  |   7 +
 drivers/phy/rockchip/Makefile                 |   1 +
 drivers/phy/rockchip/phy-rockchip-inno-hdmi.c | 885 ++++++++++++++++++
 3 files changed, 893 insertions(+)
 create mode 100644 drivers/phy/rockchip/phy-rockchip-inno-hdmi.c

diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
index 0247d93ab4..80128335d5 100644
--- a/drivers/phy/rockchip/Kconfig
+++ b/drivers/phy/rockchip/Kconfig
@@ -12,6 +12,13 @@ config PHY_ROCKCHIP_INNO_DSIDPHY
 	help
 	  Support for Rockchip MIPI DPHY with Innosilicon IP block.
 
+config PHY_ROCKCHIP_INNO_HDMI
+	bool "Rockchip INNO HDMI PHY Driver"
+	depends on ARCH_ROCKCHIP
+	select PHY
+	help
+	  Enable this to support the Rockchip Innosilicon HDMI PHY.
+
 config PHY_ROCKCHIP_INNO_USB2
 	bool "Rockchip INNO USB2PHY Driver"
 	depends on ARCH_ROCKCHIP
diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile
index 7fdbd10797..0420017425 100644
--- a/drivers/phy/rockchip/Makefile
+++ b/drivers/phy/rockchip/Makefile
@@ -3,6 +3,7 @@
 # Copyright (C) 2020 Amarula Solutions(India)
 #
 
+obj-$(CONFIG_PHY_ROCKCHIP_INNO_HDMI)	+= phy-rockchip-inno-hdmi.o
 obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2)	+= phy-rockchip-inno-usb2.o
 obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY) += phy-rockchip-naneng-combphy.o
 obj-$(CONFIG_PHY_ROCKCHIP_PCIE)		+= phy-rockchip-pcie.o
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
new file mode 100644
index 0000000000..3bb1a254ff
--- /dev/null
+++ b/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
@@ -0,0 +1,885 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Rockchip Innosilicon HDMI PHY
+ *
+ * Copyright (c) 2023 Edgeble AI Technologies Pvt. Ltd.
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ */
+
+#include <clk-uclass.h>
+#include <dm.h>
+#include <div64.h>
+#include <dm/device_compat.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <generic-phy.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+
+#define UPDATE(x, h, l)		(((x) << (l)) & GENMASK((h), (l)))
+
+/* REG: 0x01 */
+#define RK3328_BYPASS_RXSENSE_EN			BIT(2)
+#define RK3328_BYPASS_POWERON_EN			BIT(1)
+#define RK3328_BYPASS_PLLPD_EN				BIT(0)
+/* REG: 0x02 */
+#define RK3328_INT_POL_HIGH				BIT(7)
+#define RK3328_BYPASS_PDATA_EN				BIT(4)
+#define RK3328_PDATA_EN					BIT(0)
+/* REG:0x05 */
+#define RK3328_INT_TMDS_CLK(x)				UPDATE(x, 7, 4)
+#define RK3328_INT_TMDS_D2(x)				UPDATE(x, 3, 0)
+/* REG:0x07 */
+#define RK3328_INT_TMDS_D1(x)				UPDATE(x, 7, 4)
+#define RK3328_INT_TMDS_D0(x)				UPDATE(x, 3, 0)
+/* for all RK3328_INT_TMDS_*, ESD_DET as defined in 0xc8-0xcb */
+#define RK3328_INT_AGND_LOW_PULSE_LOCKED		BIT(3)
+#define RK3328_INT_RXSENSE_LOW_PULSE_LOCKED		BIT(2)
+#define RK3328_INT_VSS_AGND_ESD_DET			BIT(1)
+#define RK3328_INT_AGND_VSS_ESD_DET			BIT(0)
+/* REG: 0xa0 */
+#define RK3328_PCLK_VCO_DIV_5_MASK			BIT(1)
+#define RK3328_PCLK_VCO_DIV_5(x)			UPDATE(x, 1, 1)
+#define RK3328_PRE_PLL_POWER_DOWN			BIT(0)
+/* REG: 0xa1 */
+#define RK3328_PRE_PLL_PRE_DIV_MASK			GENMASK(5, 0)
+#define RK3328_PRE_PLL_PRE_DIV(x)			UPDATE(x, 5, 0)
+/* REG: 0xa2 */
+/* unset means center spread */
+#define RK3328_SPREAD_SPECTRUM_MOD_DOWN			BIT(7)
+#define RK3328_SPREAD_SPECTRUM_MOD_DISABLE		BIT(6)
+#define RK3328_PRE_PLL_FRAC_DIV_DISABLE			UPDATE(3, 5, 4)
+#define RK3328_PRE_PLL_FB_DIV_11_8_MASK			GENMASK(3, 0)
+#define RK3328_PRE_PLL_FB_DIV_11_8(x)			UPDATE((x) >> 8, 3, 0)
+/* REG: 0xa3 */
+#define RK3328_PRE_PLL_FB_DIV_7_0(x)			UPDATE(x, 7, 0)
+/* REG: 0xa4*/
+#define RK3328_PRE_PLL_TMDSCLK_DIV_C_MASK		GENMASK(1, 0)
+#define RK3328_PRE_PLL_TMDSCLK_DIV_C(x)			UPDATE(x, 1, 0)
+#define RK3328_PRE_PLL_TMDSCLK_DIV_B_MASK		GENMASK(3, 2)
+#define RK3328_PRE_PLL_TMDSCLK_DIV_B(x)			UPDATE(x, 3, 2)
+#define RK3328_PRE_PLL_TMDSCLK_DIV_A_MASK		GENMASK(5, 4)
+#define RK3328_PRE_PLL_TMDSCLK_DIV_A(x)			UPDATE(x, 5, 4)
+/* REG: 0xa5 */
+#define RK3328_PRE_PLL_PCLK_DIV_B_SHIFT			5
+#define RK3328_PRE_PLL_PCLK_DIV_B_MASK			GENMASK(6, 5)
+#define RK3328_PRE_PLL_PCLK_DIV_B(x)			UPDATE(x, 6, 5)
+#define RK3328_PRE_PLL_PCLK_DIV_A_MASK			GENMASK(4, 0)
+#define RK3328_PRE_PLL_PCLK_DIV_A(x)			UPDATE(x, 4, 0)
+/* REG: 0xa6 */
+#define RK3328_PRE_PLL_PCLK_DIV_C_SHIFT			5
+#define RK3328_PRE_PLL_PCLK_DIV_C_MASK			GENMASK(6, 5)
+#define RK3328_PRE_PLL_PCLK_DIV_C(x)			UPDATE(x, 6, 5)
+#define RK3328_PRE_PLL_PCLK_DIV_D_MASK			GENMASK(4, 0)
+#define RK3328_PRE_PLL_PCLK_DIV_D(x)			UPDATE(x, 4, 0)
+/* REG: 0xa9 */
+#define RK3328_PRE_PLL_LOCK_STATUS			BIT(0)
+/* REG: 0xaa */
+#define RK3328_POST_PLL_POST_DIV_ENABLE			GENMASK(3, 2)
+#define RK3328_POST_PLL_REFCLK_SEL_TMDS			BIT(1)
+#define RK3328_POST_PLL_POWER_DOWN			BIT(0)
+/* REG:0xab */
+#define RK3328_POST_PLL_FB_DIV_8(x)			UPDATE((x) >> 8, 7, 7)
+#define RK3328_POST_PLL_PRE_DIV(x)			UPDATE(x, 4, 0)
+/* REG: 0xac */
+#define RK3328_POST_PLL_FB_DIV_7_0(x)			UPDATE(x, 7, 0)
+/* REG: 0xad */
+#define RK3328_POST_PLL_POST_DIV_MASK			GENMASK(1, 0)
+#define RK3328_POST_PLL_POST_DIV_2			0x0
+#define RK3328_POST_PLL_POST_DIV_4			0x1
+#define RK3328_POST_PLL_POST_DIV_8			0x3
+/* REG: 0xaf */
+#define RK3328_POST_PLL_LOCK_STATUS			BIT(0)
+/* REG: 0xb0 */
+#define RK3328_BANDGAP_ENABLE				BIT(2)
+/* REG: 0xb2 */
+#define RK3328_TMDS_CLK_DRIVER_EN			BIT(3)
+#define RK3328_TMDS_D2_DRIVER_EN			BIT(2)
+#define RK3328_TMDS_D1_DRIVER_EN			BIT(1)
+#define RK3328_TMDS_D0_DRIVER_EN			BIT(0)
+#define RK3328_TMDS_DRIVER_ENABLE		(RK3328_TMDS_CLK_DRIVER_EN | \
+						RK3328_TMDS_D2_DRIVER_EN | \
+						RK3328_TMDS_D1_DRIVER_EN | \
+						RK3328_TMDS_D0_DRIVER_EN)
+/* REG:0xc5 */
+#define RK3328_BYPASS_TERM_RESISTOR_CALIB		BIT(7)
+#define RK3328_TERM_RESISTOR_CALIB_SPEED_14_8(x)	UPDATE((x) >> 8, 6, 0)
+/* REG:0xc6 */
+#define RK3328_TERM_RESISTOR_CALIB_SPEED_7_0(x)		UPDATE(x, 7, 0)
+/* REG:0xc7 */
+#define RK3328_TERM_RESISTOR_50				UPDATE(0, 2, 1)
+#define RK3328_TERM_RESISTOR_62_5			UPDATE(1, 2, 1)
+#define RK3328_TERM_RESISTOR_75				UPDATE(2, 2, 1)
+#define RK3328_TERM_RESISTOR_100			UPDATE(3, 2, 1)
+/* REG 0xc8 - 0xcb */
+#define RK3328_ESD_DETECT_MASK				GENMASK(7, 6)
+#define RK3328_ESD_DETECT_340MV				(0x0 << 6)
+#define RK3328_ESD_DETECT_280MV				(0x1 << 6)
+#define RK3328_ESD_DETECT_260MV				(0x2 << 6)
+#define RK3328_ESD_DETECT_240MV				(0x3 << 6)
+/* resistors can be used in parallel */
+#define RK3328_TMDS_TERM_RESIST_MASK			GENMASK(5, 0)
+#define RK3328_TMDS_TERM_RESIST_75			BIT(5)
+#define RK3328_TMDS_TERM_RESIST_150			BIT(4)
+#define RK3328_TMDS_TERM_RESIST_300			BIT(3)
+#define RK3328_TMDS_TERM_RESIST_600			BIT(2)
+#define RK3328_TMDS_TERM_RESIST_1000			BIT(1)
+#define RK3328_TMDS_TERM_RESIST_2000			BIT(0)
+/* REG: 0xd1 */
+#define RK3328_PRE_PLL_FRAC_DIV_23_16(x)		UPDATE((x) >> 16, 7, 0)
+/* REG: 0xd2 */
+#define RK3328_PRE_PLL_FRAC_DIV_15_8(x)			UPDATE((x) >> 8, 7, 0)
+/* REG: 0xd3 */
+#define RK3328_PRE_PLL_FRAC_DIV_7_0(x)			UPDATE(x, 7, 0)
+
+struct phy_config {
+	unsigned long	tmdsclock;
+	u8		regs[14];
+};
+
+struct pre_pll_config {
+	unsigned long pixclock;
+	unsigned long tmdsclock;
+	u8 prediv;
+	u16 fbdiv;
+	u8 tmds_div_a;
+	u8 tmds_div_b;
+	u8 tmds_div_c;
+	u8 pclk_div_a;
+	u8 pclk_div_b;
+	u8 pclk_div_c;
+	u8 pclk_div_d;
+	u8 vco_div_5_en;
+	u32 fracdiv;
+};
+
+struct post_pll_config {
+	unsigned long tmdsclock;
+	u8 prediv;
+	u16 fbdiv;
+	u8 postdiv;
+	u8 version;
+};
+
+struct inno_hdmi_phy_plat_ops {
+	void (*init)(struct phy *phy);
+	int (*power_on)(struct phy *phy, const struct post_pll_config *cfg,
+			const struct phy_config *phy_cfg);
+	void (*power_off)(struct phy *phy);
+	void (*clk_enable)(struct phy *phy);
+	void (*clk_disable)(struct phy *phy);
+	unsigned long (*clk_recalc_rate)(struct phy *phy,
+					 unsigned long parent_rate);
+	long (*clk_round_rate)(struct phy *phy, unsigned long rate);
+	int (*clk_set_rate)(struct phy *phy, unsigned long rate,
+			    unsigned long parent_rate);
+};
+
+enum inno_hdmi_phy_type {
+	INNO_HDMI_PHY_RK3328,
+};
+
+struct inno_hdmi_phy_data {
+	enum inno_hdmi_phy_type	phy_type;
+	const struct inno_hdmi_phy_plat_ops *plat_ops;
+	const struct phy_config	*phy_cfg_table;
+};
+
+struct inno_hdmi_phy {
+	struct udevice *dev;
+	ofnode node;
+	void *regs;
+
+	struct clk refoclk;
+	struct clk sysclk;
+	unsigned long tmdsclock;
+	unsigned long pixclock;
+	u32 bus_width;
+	struct phy_config *phy_cfg;
+	const struct inno_hdmi_phy_data *data;
+};
+
+static const struct pre_pll_config pre_pll_cfg_table[] = {
+	{ 25175000,  25175000,  3,  125, 3, 1, 1,  1, 3, 3,  4, 0, 0xe00000},
+	{ 25175000,  31468750,  1,   41, 0, 3, 3,  1, 3, 3,  4, 0, 0xf5554f},
+	{ 27000000,  27000000,  1,   36, 0, 3, 3,  1, 2, 3,  4, 0,      0x0},
+	{ 27000000,  33750000,  1,   45, 0, 3, 3,  1, 3, 3,  4, 0,      0x0},
+	{ 31500000,  31500000,  1,   42, 0, 3, 3,  1, 2, 3,  4, 0,      0x0},
+	{ 31500000,  39375000,  1,  105, 1, 3, 3, 10, 0, 3,  4, 0,      0x0},
+	{ 33750000,  33750000,  1,   45, 0, 3, 3,  1, 2, 3,  4, 0,      0x0},
+	{ 33750000,  42187500,  1,  169, 2, 3, 3, 15, 0, 3,  4, 0,      0x0},
+	{ 35500000,  35500000,  1,   71, 2, 2, 2,  6, 0, 3,  4, 0,      0x0},
+	{ 35500000,  44375000,  1,   74, 3, 1, 1, 25, 0, 1,  1, 0,      0x0},
+	{ 36000000,  36000000,  1,   36, 2, 1, 1,  1, 1, 3,  4, 0,      0x0},
+	{ 36000000,  45000000,  1,   45, 2, 1, 1, 15, 0, 1,  1, 0,      0x0},
+	{ 40000000,  40000000,  1,   40, 2, 1, 1,  1, 1, 3,  4, 0,      0x0},
+	{ 40000000,  50000000,  1,   50, 2, 1, 1, 15, 0, 1,  1, 0,      0x0},
+	{ 49500000,  49500000,  1,   66, 0, 3, 3,  1, 2, 3,  4, 0,      0x0},
+	{ 49500000,  61875000,  1,  165, 1, 3, 3, 10, 0, 3,  4, 0,      0x0},
+	{ 50000000,  50000000,  1,   50, 2, 1, 1,  1, 1, 3,  4, 0,      0x0},
+	{ 50000000,  62500000,  1,  125, 2, 2, 2, 15, 0, 2,  2, 0,      0x0},
+	{ 54000000,  54000000,  1,   36, 0, 2, 2,  1, 0, 3,  4, 0,      0x0},
+	{ 54000000,  67500000,  1,   45, 0, 2, 2,  1, 3, 2,  2, 0,      0x0},
+	{ 56250000,  56250000,  1,   75, 0, 3, 3,  1, 2, 3,  4, 0,      0x0},
+	{ 56250000,  70312500,  1,  117, 3, 1, 1, 25, 0, 1,  1, 0,      0x0},
+	{ 59341000,  59341000,  1,  118, 2, 2, 2,  6, 0, 3,  4, 0, 0xae978d},
+	{ 59341000,  74176250,  2,  148, 2, 1, 1, 15, 0, 1,  1, 0, 0x5a3d70},
+	{ 59400000,  59400000,  1,   99, 3, 1, 1,  1, 3, 3,  4, 0,      0x0},
+	{ 59400000,  74250000,  1,   99, 0, 3, 3,  1, 3, 3,  4, 0,      0x0},
+	{ 65000000,  65000000,  1,   65, 2, 1, 1,  1, 1, 3,  4, 0,      0x0},
+	{ 65000000,  81250000,  3,  325, 0, 3, 3,  1, 3, 3,  4, 0,      0x0},
+	{ 68250000,  68250000,  1,   91, 0, 3, 3,  1, 2, 3,  4, 0,      0x0},
+	{ 68250000,  85312500,  1,  142, 3, 1, 1, 25, 0, 1,  1, 0,      0x0},
+	{ 71000000,  71000000,  1,   71, 2, 1, 1,  1, 1, 3,  4, 0,      0x0},
+	{ 71000000,  88750000,  3,  355, 0, 3, 3,  1, 3, 3,  4, 0,      0x0},
+	{ 72000000,  72000000,  1,   36, 2, 0, 0,  1, 1, 2,  2, 0,      0x0},
+	{ 72000000,  90000000,  1,   60, 0, 2, 2,  1, 3, 2,  2, 0,      0x0},
+	{ 73250000,  73250000,  3,  293, 0, 3, 3,  1, 2, 3,  4, 0,      0x0},
+	{ 73250000,  91562500,  1,   61, 0, 2, 2,  1, 3, 2,  2, 0,      0x0},
+	{ 74176000,  74176000,  1,   37, 2, 0, 0,  1, 1, 2,  2, 0, 0x16872b},
+	{ 74176000,  92720000,  2,  185, 2, 1, 1, 15, 0, 1,  1, 0, 0x70a3d7},
+	{ 74250000,  74250000,  1,   99, 0, 3, 3,  1, 2, 3,  4, 0,      0x0},
+	{ 74250000,  92812500,  4,  495, 0, 3, 3,  1, 3, 3,  4, 0,      0x0},
+	{ 75000000,  75000000,  1,   50, 0, 2, 2,  1, 0, 3,  4, 0,      0x0},
+	{ 75000000,  93750000,  1,  125, 0, 3, 3,  1, 3, 3,  4, 0,      0x0},
+	{ 78750000,  78750000,  1,  105, 0, 3, 3,  1, 2, 3,  4, 0,      0x0},
+	{ 78750000,  98437500,  1,  164, 3, 1, 1, 25, 0, 1,  1, 0,      0x0},
+	{ 79500000,  79500000,  1,   53, 0, 2, 2,  1, 0, 3,  4, 0,      0x0},
+	{ 79500000,  99375000,  1,  199, 2, 2, 2, 15, 0, 2,  2, 0,      0x0},
+	{ 83500000,  83500000,  2,  167, 2, 1, 1,  1, 1, 3,  4, 0,      0x0},
+	{ 83500000, 104375000,  1,  104, 2, 1, 1, 15, 0, 1,  1, 0, 0x600000},
+	{ 85500000,  85500000,  1,   57, 0, 2, 2,  1, 0, 3,  4, 0,      0x0},
+	{ 85500000, 106875000,  1,  178, 3, 1, 1, 25, 0, 1,  1, 0,      0x0},
+	{ 85750000,  85750000,  3,  343, 0, 3, 3,  1, 2, 3,  4, 0,      0x0},
+	{ 85750000, 107187500,  1,  143, 0, 3, 3,  1, 3, 3,  4, 0,      0x0},
+	{ 88750000,  88750000,  3,  355, 0, 3, 3,  1, 2, 3,  4, 0,      0x0},
+	{ 88750000, 110937500,  1,  110, 2, 1, 1, 15, 0, 1,  1, 0, 0xf00000},
+	{ 94500000,  94500000,  1,   63, 0, 2, 2,  1, 0, 3,  4, 0,      0x0},
+	{ 94500000, 118125000,  1,  197, 3, 1, 1, 25, 0, 1,  1, 0,      0x0},
+	{101000000, 101000000,  1,  101, 2, 1, 1,  1, 1, 3,  4, 0,      0x0},
+	{101000000, 126250000,  1,   42, 0, 1, 1,  1, 3, 1,  1, 0,      0x0},
+	{102250000, 102250000,  4,  409, 2, 1, 1,  1, 1, 3,  4, 0,      0x0},
+	{102250000, 127812500,  1,  128, 2, 1, 1, 15, 0, 1,  1, 0,      0x0},
+	{106500000, 106500000,  1,   71, 0, 2, 2,  1, 0, 3,  4, 0,      0x0},
+	{106500000, 133125000,  1,  133, 2, 1, 1, 15, 0, 1,  1, 0,      0x0},
+	{108000000, 108000000,  1,   36, 0, 1, 1,  1, 0, 2,  2, 0,      0x0},
+	{108000000, 135000000,  1,   45, 0, 1, 1,  1, 3, 1,  1, 0,      0x0},
+	{115500000, 115500000,  1,   77, 0, 2, 2,  1, 0, 3,  4, 0,      0x0},
+	{115500000, 144375000,  1,   48, 0, 1, 1,  1, 3, 1,  1, 0,      0x0},
+	{117500000, 117500000,  2,  235, 2, 1, 1,  1, 1, 3,  4, 0,      0x0},
+	{117500000, 146875000,  1,   49, 0, 1, 1,  1, 3, 1,  1, 0,      0x0},
+	{119000000, 119000000,  1,  119, 2, 1, 1,  1, 1, 3,  4, 0,      0x0},
+	{119000000, 148750000,  3,  148, 0, 1, 1,  1, 3, 1,  1, 0, 0xc00000},
+	{121750000, 121750000,  4,  487, 2, 1, 1,  1, 1, 3,  4, 0,      0x0},
+	{121750000, 152187500,  1,  203, 0, 3, 3,  1, 3, 3,  4, 0,      0x0},
+	{122500000, 122500000,  2,  245, 2, 1, 1,  1, 1, 3,  4, 0,      0x0},
+	{122500000, 153125000,  1,   51, 0, 1, 1,  1, 3, 1,  1, 0,      0x0},
+	{135000000, 135000000,  1,   45, 0, 1, 1,  1, 0, 2,  2, 0,      0x0},
+	{135000000, 168750000,  1,  169, 2, 1, 1, 15, 0, 1,  1, 0,      0x0},
+	{136750000, 136750000,  1,   68, 2, 0, 0,  1, 1, 2,  2, 0, 0x600000},
+	{136750000, 170937500,  1,  113, 0, 2, 2,  1, 3, 2,  2, 0, 0xf5554f},
+	{140250000, 140250000,  2,  187, 0, 2, 2,  1, 0, 3,  4, 0,      0x0},
+	{140250000, 175312500,  1,  117, 0, 2, 2,  1, 3, 2,  2, 0,      0x0},
+	{146250000, 146250000,  2,  195, 0, 2, 2,  1, 0, 3,  4, 0,      0x0},
+	{146250000, 182812500,  1,   61, 0, 1, 1,  1, 3, 1,  1, 0,      0x0},
+	{148250000, 148250000,  3,  222, 2, 0, 0,  1, 1, 2,  2, 0, 0x600000},
+	{148250000, 185312500,  1,  123, 0, 2, 2,  1, 3, 2,  2, 0, 0x8aaab0},
+	{148352000, 148352000,  2,  148, 2, 0, 0,  1, 1, 2,  2, 0, 0x5a1cac},
+	{148352000, 185440000,  3,  185, 0, 1, 1,  1, 3, 1,  1, 0, 0x70a3d7},
+	{148500000, 148500000,  1,   99, 0, 2, 2,  1, 0, 3,  4, 0,      0x0},
+	{148500000, 185625000,  4,  495, 0, 2, 2,  1, 3, 2,  2, 0,      0x0},
+	{154000000, 154000000,  1,   77, 2, 0, 0,  1, 1, 2,  2, 0,      0x0},
+	{154000000, 192500000,  1,   64, 0, 1, 1,  1, 3, 1,  1, 0,      0x0},
+	{156000000, 156000000,  1,   52, 0, 1, 1,  1, 0, 2,  2, 0,      0x0},
+	{156000000, 195000000,  1,   65, 0, 1, 1,  1, 3, 1,  1, 0,      0x0},
+	{156750000, 156750000,  2,  209, 0, 2, 2,  1, 0, 3,  4, 0,      0x0},
+	{156750000, 195937500,  1,  196, 2, 1, 1, 15, 0, 1,  1, 0,      0x0},
+	{157000000, 157000000,  2,  157, 2, 0, 0,  1, 1, 2,  2, 0,      0x0},
+	{157000000, 196250000,  1,  131, 0, 2, 2,  1, 3, 2,  2, 0,      0x0},
+	{157500000, 157500000,  1,  105, 0, 2, 2,  1, 0, 3,  4, 0,      0x0},
+	{157500000, 196875000,  1,  197, 2, 1, 1, 15, 0, 1,  1, 0,      0x0},
+	{162000000, 162000000,  1,   54, 0, 1, 1,  1, 0, 2,  2, 0,      0x0},
+	{162000000, 202500000,  2,  135, 0, 1, 1,  1, 3, 1,  1, 0,      0x0},
+	{175500000, 175500000,  1,  117, 0, 2, 2,  1, 0, 3,  4, 0,      0x0},
+	{175500000, 219375000,  1,   73, 0, 1, 1,  1, 3, 1,  1, 0,      0x0},
+	{179500000, 179500000,  3,  359, 0, 2, 2,  1, 0, 3,  4, 0,      0x0},
+	{179500000, 224375000,  1,   75, 0, 1, 1,  1, 3, 1,  1, 0,      0x0},
+	{182750000, 182750000,  1,   91, 2, 0, 0,  1, 1, 2,  2, 0, 0x600000},
+	{182750000, 228437500,  1,  152, 0, 2, 2,  1, 3, 2,  2, 0, 0x4aaab0},
+	{182750000, 228437500,  1,  152, 0, 2, 2,  1, 3, 2,  2, 0, 0x4aaab0},
+	{187000000, 187000000,  2,  187, 2, 0, 0,  1, 1, 2,  2, 0,      0x0},
+	{187000000, 233750000,  1,   39, 0, 0, 0,  1, 3, 0,  0, 1,      0x0},
+	{187250000, 187250000,  3,  280, 2, 0, 0,  1, 1, 2,  2, 0, 0xe00000},
+	{187250000, 234062500,  1,  156, 0, 2, 2,  1, 3, 2,  2, 0,  0xaaab0},
+	{189000000, 189000000,  1,   63, 0, 1, 1,  1, 0, 2,  2, 0,      0x0},
+	{189000000, 236250000,  1,   79, 0, 1, 1,  1, 3, 1,  1, 0,      0x0},
+	{193250000, 193250000,  3,  289, 2, 0, 0,  1, 1, 2,  2, 0, 0xe00000},
+	{193250000, 241562500,  1,  161, 0, 2, 2,  1, 3, 2,  2, 0,  0xaaab0},
+	{202500000, 202500000,  2,  135, 0, 1, 1,  1, 0, 2,  2, 0,      0x0},
+	{202500000, 253125000,  1,  169, 0, 2, 2,  1, 3, 2,  2, 0,      0x0},
+	{204750000, 204750000,  4,  273, 0, 1, 1,  1, 0, 2,  2, 0,      0x0},
+	{204750000, 255937500,  1,  171, 0, 2, 2,  1, 3, 2,  2, 0,      0x0},
+	{208000000, 208000000,  1,  104, 2, 0, 0,  1, 1, 2,  2, 0,      0x0},
+	{208000000, 260000000,  1,  173, 0, 2, 2,  1, 3, 2,  2, 0,      0x0},
+	{214750000, 214750000,  1,  107, 2, 0, 0,  1, 1, 2,  2, 0, 0x600000},
+	{214750000, 268437500,  1,  178, 0, 2, 2,  1, 3, 2,  2, 0, 0xf5554f},
+	{218250000, 218250000,  4,  291, 0, 1, 1,  1, 0, 2,  2, 0,      0x0},
+	{218250000, 272812500,  1,   91, 0, 1, 1,  1, 3, 1,  1, 0,      0x0},
+	{229500000, 229500000,  2,  153, 0, 1, 1,  1, 0, 2,  2, 0,      0x0},
+	{229500000, 286875000,  1,  191, 0, 2, 2,  1, 3, 2,  2, 0,      0x0},
+	{234000000, 234000000,  1,   39, 0, 0, 0,  1, 0, 1,  1, 0,      0x0},
+	{234000000, 292500000,  1,  195, 0, 2, 2,  1, 3, 2,  2, 0,      0x0},
+	{241500000, 241500000,  2,  161, 0, 1, 1,  1, 0, 2,  2, 0,      0x0},
+	{241500000, 301875000,  1,  201, 0, 2, 2,  1, 3, 2,  2, 0,      0x0},
+	{245250000, 245250000,  4,  327, 0, 1, 1,  1, 0, 2,  2, 0,      0x0},
+	{245250000, 306562500,  1,   51, 0, 0, 0,  1, 3, 0,  0, 1,      0x0},
+	{245500000, 245500000,  4,  491, 2, 0, 0,  1, 1, 2,  2, 0,      0x0},
+	{245500000, 306875000,  1,   51, 0, 0, 0,  1, 3, 0,  0, 1,      0x0},
+	{261000000, 261000000,  1,   87, 0, 1, 1,  1, 0, 2,  2, 0,      0x0},
+	{261000000, 326250000,  1,  109, 0, 1, 1,  1, 3, 1,  1, 0,      0x0},
+	{268250000, 268250000,  9,  402, 0, 0, 0,  1, 0, 1,  1, 0, 0x600000},
+	{268250000, 335312500,  1,  111, 0, 1, 1,  1, 3, 1,  1, 0, 0xc5554f},
+	{268500000, 268500000,  2,  179, 0, 1, 1,  1, 0, 2,  2, 0,      0x0},
+	{268500000, 335625000,  1,   56, 0, 0, 0,  1, 3, 0,  0, 1,      0x0},
+	{281250000, 281250000,  4,  375, 0, 1, 1,  1, 0, 2,  2, 0,      0x0},
+	{281250000, 351562500,  1,  117, 0, 3, 1,  1, 3, 1,  1, 0,      0x0},
+	{288000000, 288000000,  1,   48, 0, 0, 0,  1, 0, 1,  1, 0,      0x0},
+	{288000000, 360000000,  1,   60, 0, 2, 0,  1, 3, 0,  0, 1,      0x0},
+	{296703000, 296703000,  1,   49, 0, 0, 0,  1, 0, 1,  1, 0, 0x7353f7},
+	{296703000, 370878750,  1,  123, 0, 3, 1,  1, 3, 1,  1, 0, 0xa051eb},
+	{297000000, 297000000,  1,   99, 0, 1, 1,  1, 0, 2,  2, 0,      0x0},
+	{297000000, 371250000,  4,  495, 0, 3, 1,  1, 3, 1,  1, 0,      0x0},
+	{312250000, 312250000,  9,  468, 0, 0, 0,  1, 0, 1,  1, 0, 0x600000},
+	{312250000, 390312500,  1,  130, 0, 3, 1,  1, 3, 1,  1, 0, 0x1aaab0},
+	{317000000, 317000000,  3,  317, 0, 1, 1,  1, 0, 2,  2, 0,      0x0},
+	{317000000, 396250000,  1,   66, 0, 2, 0,  1, 3, 0,  0, 1,      0x0},
+	{319750000, 319750000,  3,  159, 0, 0, 0,  1, 0, 1,  1, 0, 0xe00000},
+	{319750000, 399687500,  3,  199, 0, 2, 0,  1, 3, 0,  0, 1, 0xd80000},
+	{333250000, 333250000,  9,  499, 0, 0, 0,  1, 0, 1,  1, 0, 0xe00000},
+	{333250000, 416562500,  1,  138, 0, 3, 1,  1, 3, 1,  1, 0, 0xdaaab0},
+	{348500000, 348500000,  9,  522, 0, 2, 0,  1, 0, 1,  1, 0, 0xc00000},
+	{348500000, 435625000,  1,  145, 0, 3, 1,  1, 3, 1,  1, 0, 0x35554f},
+	{356500000, 356500000,  9,  534, 0, 2, 0,  1, 0, 1,  1, 0, 0xc00000},
+	{356500000, 445625000,  1,  148, 0, 3, 1,  1, 3, 1,  1, 0, 0x8aaab0},
+	{380500000, 380500000,  9,  570, 0, 2, 0,  1, 0, 1,  1, 0, 0xc00000},
+	{380500000, 475625000,  1,  158, 0, 3, 1,  1, 3, 1,  1, 0, 0x8aaab0},
+	{443250000, 443250000,  1,   73, 0, 2, 0,  1, 0, 1,  1, 0, 0xe00000},
+	{443250000, 554062500,  1,   92, 0, 2, 0,  1, 3, 0,  0, 1, 0x580000},
+	{505250000, 505250000,  9,  757, 0, 2, 0,  1, 0, 1,  1, 0, 0xe00000},
+	{552750000, 552750000,  3,  276, 0, 2, 0,  1, 0, 1,  1, 0, 0x600000},
+	{593407000, 296703500,  3,  296, 0, 1, 1,  1, 0, 1,  1, 0, 0xb41893},
+	{593407000, 370879375,  4,  494, 0, 3, 1,  1, 3, 0,  0, 1, 0x817e4a},
+	{593407000, 593407000,  3,  296, 0, 2, 0,  1, 0, 1,  1, 0, 0xb41893},
+	{594000000, 297000000,  1,   99, 0, 1, 1,  1, 0, 1,  1, 0,      0x0},
+	{594000000, 371250000,  4,  495, 0, 3, 1,  1, 3, 0,  0, 1,      0x0},
+	{594000000, 594000000,  1,   99, 0, 2, 0,  1, 0, 1,  1, 0,      0x0},
+	{ /* sentinel */ }
+};
+
+static const struct post_pll_config post_pll_cfg_table[] = {
+	{33750000,  1, 40, 8, 1},
+	{33750000,  1, 80, 8, 2},
+	{74250000,  1, 40, 8, 1},
+	{74250000, 18, 80, 8, 2},
+	{148500000, 2, 40, 4, 3},
+	{297000000, 4, 40, 2, 3},
+	{594000000, 8, 40, 1, 3},
+	{ /* sentinel */ }
+};
+
+/* phy tuning values for an undocumented set of registers */
+static const struct phy_config rk3328_phy_cfg[] = {
+	{	165000000, {
+			0x07, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x08, 0x08, 0x08,
+			0x00, 0xac, 0xcc, 0xcc, 0xcc,
+		},
+	}, {
+		340000000, {
+			0x0b, 0x0d, 0x0d, 0x0d, 0x07, 0x15, 0x08, 0x08, 0x08,
+			0x3f, 0xac, 0xcc, 0xcd, 0xdd,
+		},
+	}, {
+		594000000, {
+			0x10, 0x1a, 0x1a, 0x1a, 0x07, 0x15, 0x08, 0x08, 0x08,
+			0x00, 0xac, 0xcc, 0xcc, 0xcc,
+		},
+	}, { /* sentinel */ },
+};
+
+static inline void inno_write(struct inno_hdmi_phy *inno, u32 reg, u8 val)
+{
+	writel(val, inno->regs + (reg * 4));
+}
+
+static inline u8 inno_read(struct inno_hdmi_phy *inno, u32 reg)
+{
+	u32 val;
+
+	val = readl(inno->regs + (reg * 4));
+
+	return val;
+}
+
+static inline void inno_update_bits(struct inno_hdmi_phy *inno, u8 reg,
+				    u8 mask, u8 val)
+{
+	u32 tmp, orig;
+
+	orig = inno_read(inno, reg);
+	tmp = orig & ~mask;
+	tmp |= val & mask;
+	inno_write(inno, reg, tmp);
+}
+
+#define inno_poll(reg, val, cond, sleep_us, timeout_us) \
+	readl_poll_sleep_timeout((reg) * 4, val, cond, sleep_us, timeout_us)
+
+static unsigned long inno_hdmi_phy_get_tmdsclk(struct inno_hdmi_phy *inno,
+					       unsigned long rate)
+{
+	int bus_width = inno->bus_width;
+
+	switch (bus_width) {
+	case 4:
+	case 5:
+	case 6:
+	case 10:
+	case 12:
+	case 16:
+		return (u64)rate * bus_width / 8;
+	default:
+		return rate;
+	}
+}
+
+static
+unsigned long inno_hdmi_phy_rk3328_clk_recalc_rate(struct phy *phy,
+						   unsigned long parent_rate)
+{
+	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+	unsigned long frac;
+	u8 nd, no_a, no_b, no_d;
+	u64 vco;
+	u16 nf;
+
+	nd = inno_read(inno, 0xa1) & RK3328_PRE_PLL_PRE_DIV_MASK;
+	nf = ((inno_read(inno, 0xa2) & RK3328_PRE_PLL_FB_DIV_11_8_MASK) << 8);
+	nf |= inno_read(inno, 0xa3);
+	vco = parent_rate * nf;
+
+	if (!(inno_read(inno, 0xa2) & RK3328_PRE_PLL_FRAC_DIV_DISABLE)) {
+		frac = inno_read(inno, 0xd3) |
+		       (inno_read(inno, 0xd2) << 8) |
+		       (inno_read(inno, 0xd1) << 16);
+		vco += DIV_ROUND_CLOSEST(parent_rate * frac, (1 << 24));
+	}
+
+	if (inno_read(inno, 0xa0) & RK3328_PCLK_VCO_DIV_5_MASK) {
+		do_div(vco, nd * 5);
+	} else {
+		no_a = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_A_MASK;
+		no_b = inno_read(inno, 0xa5) & RK3328_PRE_PLL_PCLK_DIV_B_MASK;
+		no_b >>= RK3328_PRE_PLL_PCLK_DIV_B_SHIFT;
+		no_b += 2;
+		no_d = inno_read(inno, 0xa6) & RK3328_PRE_PLL_PCLK_DIV_D_MASK;
+
+		do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2));
+	}
+
+	inno->pixclock = DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000;
+
+	dev_info(phy->dev, "rate %lu vco %llu\n", inno->pixclock, vco);
+
+	return inno->pixclock;
+}
+
+static long inno_hdmi_phy_rk3328_clk_round_rate(struct phy *phy,
+						unsigned long rate)
+{
+	const struct pre_pll_config *cfg = pre_pll_cfg_table;
+
+	rate = (rate / 1000) * 1000;
+
+	for (; cfg->pixclock != 0; cfg++)
+		if (cfg->pixclock == rate)
+			break;
+
+	if (cfg->pixclock == 0)
+		return -EINVAL;
+
+	return cfg->pixclock;
+}
+
+static const
+struct pre_pll_config *inno_hdmi_phy_get_pre_pll_cfg(struct inno_hdmi_phy *inno,
+						     unsigned long rate)
+{
+	const struct pre_pll_config *cfg = pre_pll_cfg_table;
+	unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
+
+	for (; cfg->pixclock != 0; cfg++)
+		if (cfg->pixclock == rate && cfg->tmdsclock == tmdsclock)
+			break;
+
+	if (cfg->pixclock == 0)
+		return ERR_PTR(-EINVAL);
+
+	return cfg;
+}
+
+static int
+inno_hdmi_phy_rk3328_clk_set_rate(struct phy *phy,
+				  unsigned long rate,
+				  unsigned long parent_rate)
+{
+	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+	unsigned long tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
+	const struct pre_pll_config *cfg;
+	u32 val;
+	int ret;
+
+	dev_info(phy->dev, "rate %lu tmdsclk %lu\n", rate, tmdsclock);
+
+	if (inno->pixclock == rate && inno->tmdsclock == tmdsclock)
+		return 0;
+
+	cfg = inno_hdmi_phy_get_pre_pll_cfg(inno, rate);
+	if (IS_ERR(cfg))
+		return PTR_ERR(cfg);
+
+	inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN,
+			 RK3328_PRE_PLL_POWER_DOWN);
+
+	/* Configure pre-pll */
+	inno_update_bits(inno, 0xa0, RK3328_PCLK_VCO_DIV_5_MASK,
+			 RK3328_PCLK_VCO_DIV_5(cfg->vco_div_5_en));
+	inno_write(inno, 0xa1, RK3328_PRE_PLL_PRE_DIV(cfg->prediv));
+
+	val = RK3328_SPREAD_SPECTRUM_MOD_DISABLE;
+	if (!cfg->fracdiv)
+		val |= RK3328_PRE_PLL_FRAC_DIV_DISABLE;
+	inno_write(inno, 0xa2, RK3328_PRE_PLL_FB_DIV_11_8(cfg->fbdiv) | val);
+	inno_write(inno, 0xa3, RK3328_PRE_PLL_FB_DIV_7_0(cfg->fbdiv));
+	inno_write(inno, 0xa5, RK3328_PRE_PLL_PCLK_DIV_A(cfg->pclk_div_a) |
+		   RK3328_PRE_PLL_PCLK_DIV_B(cfg->pclk_div_b));
+	inno_write(inno, 0xa6, RK3328_PRE_PLL_PCLK_DIV_C(cfg->pclk_div_c) |
+		   RK3328_PRE_PLL_PCLK_DIV_D(cfg->pclk_div_d));
+	inno_write(inno, 0xa4, RK3328_PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c) |
+		   RK3328_PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) |
+		   RK3328_PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b));
+	inno_write(inno, 0xd3, RK3328_PRE_PLL_FRAC_DIV_7_0(cfg->fracdiv));
+	inno_write(inno, 0xd2, RK3328_PRE_PLL_FRAC_DIV_15_8(cfg->fracdiv));
+	inno_write(inno, 0xd1, RK3328_PRE_PLL_FRAC_DIV_23_16(cfg->fracdiv));
+
+	inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN, 0);
+
+	/* Wait for Pre-PLL lock */
+	ret = inno_poll(0xa9, val, val & RK3328_PRE_PLL_LOCK_STATUS,
+			1000, 10000);
+	if (ret) {
+		dev_err(phy->dev, "Pre-PLL locking failed\n");
+		return ret;
+	}
+
+	inno->pixclock = rate;
+	inno->tmdsclock = tmdsclock;
+
+	return 0;
+}
+
+static void inno_hdmi_phy_rk3328_clk_enable(struct phy *phy)
+{
+	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+
+	inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN, 0);
+}
+
+static void inno_hdmi_phy_rk3328_clk_disable(struct phy *phy)
+{
+	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+
+	inno_update_bits(inno, 0xa0, RK3328_PRE_PLL_POWER_DOWN,
+			 RK3328_PRE_PLL_POWER_DOWN);
+}
+
+static int
+inno_hdmi_phy_rk3328_power_on(struct phy *phy,
+			      const struct post_pll_config *cfg,
+			      const struct phy_config *phy_cfg)
+{
+	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+	int ret;
+	u32 v;
+
+	inno_update_bits(inno, 0x02, RK3328_PDATA_EN, 0);
+	inno_update_bits(inno, 0xaa, RK3328_POST_PLL_POWER_DOWN,
+			 RK3328_POST_PLL_POWER_DOWN);
+
+	inno_write(inno, 0xac, RK3328_POST_PLL_FB_DIV_7_0(cfg->fbdiv));
+	if (cfg->postdiv == 1) {
+		inno_write(inno, 0xab, RK3328_POST_PLL_FB_DIV_8(cfg->fbdiv) |
+			   RK3328_POST_PLL_PRE_DIV(cfg->prediv));
+		inno_write(inno, 0xaa, RK3328_POST_PLL_REFCLK_SEL_TMDS |
+			   RK3328_POST_PLL_POWER_DOWN);
+	} else {
+		v = (cfg->postdiv / 2) - 1;
+		v &= RK3328_POST_PLL_POST_DIV_MASK;
+		inno_write(inno, 0xad, v);
+		inno_write(inno, 0xab, RK3328_POST_PLL_FB_DIV_8(cfg->fbdiv) |
+			   RK3328_POST_PLL_PRE_DIV(cfg->prediv));
+		inno_write(inno, 0xaa, RK3328_POST_PLL_POST_DIV_ENABLE |
+			   RK3328_POST_PLL_REFCLK_SEL_TMDS |
+			   RK3328_POST_PLL_POWER_DOWN);
+	}
+
+	for (v = 0; v < 14; v++)
+		inno_write(inno, 0xb5 + v, phy_cfg->regs[v]);
+
+	/* set ESD detection threshold for TMDS CLK, D2, D1 and D0 */
+	for (v = 0; v < 4; v++)
+		inno_update_bits(inno, 0xc8 + v, RK3328_ESD_DETECT_MASK,
+				 RK3328_ESD_DETECT_340MV);
+
+	if (phy_cfg->tmdsclock > 340000000) {
+		/* Set termination resistor to 100ohm */
+		v = clk_get_rate(&inno->sysclk) / 100000;
+		inno_write(inno, 0xc5, RK3328_TERM_RESISTOR_CALIB_SPEED_14_8(v)
+			   | RK3328_BYPASS_TERM_RESISTOR_CALIB);
+		inno_write(inno, 0xc6, RK3328_TERM_RESISTOR_CALIB_SPEED_7_0(v));
+		inno_write(inno, 0xc7, RK3328_TERM_RESISTOR_100);
+		inno_update_bits(inno, 0xc5,
+				 RK3328_BYPASS_TERM_RESISTOR_CALIB, 0);
+	} else {
+		inno_write(inno, 0xc5, RK3328_BYPASS_TERM_RESISTOR_CALIB);
+
+		/* clk termination resistor is 50ohm (parallel resistors) */
+		if (phy_cfg->tmdsclock > 165000000)
+			inno_update_bits(inno, 0xc8,
+					 RK3328_TMDS_TERM_RESIST_MASK,
+					 RK3328_TMDS_TERM_RESIST_75 |
+					 RK3328_TMDS_TERM_RESIST_150);
+
+		/* data termination resistor for D2, D1 and D0 is 150ohm */
+		for (v = 0; v < 3; v++)
+			inno_update_bits(inno, 0xc9 + v,
+					 RK3328_TMDS_TERM_RESIST_MASK,
+					 RK3328_TMDS_TERM_RESIST_150);
+	}
+
+	inno_update_bits(inno, 0xaa, RK3328_POST_PLL_POWER_DOWN, 0);
+	inno_update_bits(inno, 0xb0, RK3328_BANDGAP_ENABLE,
+			 RK3328_BANDGAP_ENABLE);
+	inno_update_bits(inno, 0xb2, RK3328_TMDS_DRIVER_ENABLE,
+			 RK3328_TMDS_DRIVER_ENABLE);
+
+	/* Wait for post PLL lock */
+	ret = inno_poll(0xaf, v, v & RK3328_POST_PLL_LOCK_STATUS,
+			1000, 10000);
+	if (ret) {
+		dev_err(phy->dev, "Post-PLL locking failed\n");
+		return ret;
+	}
+
+	if (phy_cfg->tmdsclock > 340000000)
+		mdelay(100);
+
+	inno_update_bits(inno, 0x02, RK3328_PDATA_EN, RK3328_PDATA_EN);
+
+	/* Enable PHY IRQ */
+	inno_write(inno, 0x05, RK3328_INT_TMDS_CLK(RK3328_INT_VSS_AGND_ESD_DET)
+		   | RK3328_INT_TMDS_D2(RK3328_INT_VSS_AGND_ESD_DET));
+	inno_write(inno, 0x07, RK3328_INT_TMDS_D1(RK3328_INT_VSS_AGND_ESD_DET)
+		   | RK3328_INT_TMDS_D0(RK3328_INT_VSS_AGND_ESD_DET));
+
+	return 0;
+}
+
+static void inno_hdmi_phy_rk3328_power_off(struct phy *phy)
+{
+	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+
+	inno_update_bits(inno, 0xb2, RK3328_TMDS_DRIVER_ENABLE, 0);
+	inno_update_bits(inno, 0xb0, RK3328_BANDGAP_ENABLE, 0);
+	inno_update_bits(inno, 0xaa, RK3328_POST_PLL_POWER_DOWN,
+			 RK3328_POST_PLL_POWER_DOWN);
+
+	/* Disable PHY IRQ */
+	inno_write(inno, 0x05, 0);
+	inno_write(inno, 0x07, 0);
+}
+
+static void inno_hdmi_phy_rk3328_init(struct phy *phy)
+{
+	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+	const struct inno_hdmi_phy_plat_ops *plat_ops = inno->data->plat_ops;
+
+	/*
+	 * Use phy internal register control
+	 * rxsense/poweron/pllpd/pdataen signal.
+	 */
+	inno_write(inno, 0x01, RK3328_BYPASS_RXSENSE_EN |
+		   RK3328_BYPASS_POWERON_EN |
+		   RK3328_BYPASS_PLLPD_EN);
+	inno_write(inno, 0x02, RK3328_INT_POL_HIGH | RK3328_BYPASS_PDATA_EN |
+		   RK3328_PDATA_EN);
+
+	/* Disable phy irq */
+	inno_write(inno, 0x05, 0);
+	inno_write(inno, 0x07, 0);
+
+	if (plat_ops->clk_recalc_rate)
+		plat_ops->clk_recalc_rate(phy, clk_get_rate(&inno->refoclk));
+
+	if (plat_ops->clk_round_rate)
+		plat_ops->clk_round_rate(phy, inno->pixclock);
+}
+
+static const struct inno_hdmi_phy_plat_ops rk3328_hdmi_phy_plat_ops = {
+	.init = inno_hdmi_phy_rk3328_init,
+	.power_on = inno_hdmi_phy_rk3328_power_on,
+	.power_off = inno_hdmi_phy_rk3328_power_off,
+	.clk_enable = inno_hdmi_phy_rk3328_clk_enable,
+	.clk_disable = inno_hdmi_phy_rk3328_clk_disable,
+	.clk_recalc_rate = inno_hdmi_phy_rk3328_clk_recalc_rate,
+	.clk_round_rate = inno_hdmi_phy_rk3328_clk_round_rate,
+	.clk_set_rate = inno_hdmi_phy_rk3328_clk_set_rate,
+};
+
+static int inno_hdmi_phy_power_on(struct phy *phy)
+{
+	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+	const struct post_pll_config *cfg = post_pll_cfg_table;
+	const struct phy_config *phy_cfg = inno->data->phy_cfg_table;
+	u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, inno->pixclock);
+	const struct inno_hdmi_phy_plat_ops *plat_ops = inno->data->plat_ops;
+	int ret;
+
+	if (!tmdsclock) {
+		dev_err(phy->dev, "TMDS clock is zero!\n");
+		return -EINVAL;
+	}
+
+	if (!plat_ops->power_on)
+		return -EINVAL;
+
+	dev_info(phy->dev, "TMDS clock = %d\n", tmdsclock);
+
+	for (; cfg->tmdsclock != ~0UL; cfg++)
+		if (tmdsclock <= cfg->tmdsclock)
+			break;
+
+	for (; phy_cfg->tmdsclock != ~0UL; phy_cfg++)
+		if (tmdsclock <= phy_cfg->tmdsclock)
+			break;
+
+	if (cfg->tmdsclock == 0 || phy_cfg->tmdsclock == 0)
+		return -EINVAL;
+
+	if (plat_ops->clk_set_rate) {
+		ret = plat_ops->clk_set_rate(phy, inno->pixclock, 24000000);
+		if (ret)
+			return ret;
+	}
+
+	if (plat_ops->clk_enable)
+		plat_ops->clk_enable(phy);
+
+	if (plat_ops->power_on) {
+		ret = plat_ops->power_on(phy, cfg, phy_cfg);
+		if (ret) {
+			if (plat_ops->clk_disable)
+				plat_ops->clk_disable(phy);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int inno_hdmi_phy_power_off(struct phy *phy)
+{
+	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+	const struct inno_hdmi_phy_plat_ops *plat_ops = inno->data->plat_ops;
+
+	if (!plat_ops->power_off)
+		return -EINVAL;
+
+	plat_ops->power_off(phy);
+
+	if (plat_ops->clk_disable)
+		plat_ops->clk_disable(phy);
+
+	inno->tmdsclock = 0;
+
+	return 0;
+}
+
+static int inno_hdmi_phy_init(struct phy *phy)
+{
+	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+
+	if (inno->data->plat_ops->init)
+		inno->data->plat_ops->init(phy);
+
+	return 0;
+}
+
+static struct phy_ops inno_hdmi_phy_ops = {
+	.init = inno_hdmi_phy_init,
+	.power_on = inno_hdmi_phy_power_on,
+	.power_off = inno_hdmi_phy_power_off,
+};
+
+static int inno_hdmi_phy_probe(struct udevice *dev)
+{
+	struct inno_hdmi_phy *inno = dev_get_priv(dev);
+	int ret;
+
+	inno->regs = dev_read_addr_ptr(dev);
+	if (!inno->regs)
+		return -ENOMEM;
+
+	inno->data = (const struct inno_hdmi_phy_data *)dev_get_driver_data(dev);
+	if (!inno->data)
+		return -EINVAL;
+
+	inno->bus_width = 8;
+
+	ret = clk_get_by_name(dev, "refoclk", &inno->refoclk);
+	if (ret) {
+		dev_err(dev, "failed to get the refoclk (ret=%d)\n", ret);
+		return ret;
+	}
+
+	ret = clk_get_by_name(dev, "sysclk", &inno->sysclk);
+	if (ret) {
+		dev_err(dev, "failed to get the sysclk (ret=%d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct inno_hdmi_phy_data rk3328_inno_hdmi_phy_drv_data = {
+	.phy_type = INNO_HDMI_PHY_RK3328,
+	.plat_ops = &rk3328_hdmi_phy_plat_ops,
+	.phy_cfg_table = rk3328_phy_cfg,
+};
+
+static const struct udevice_id inno_hdmi_phy_ids[] = {
+	{
+		.compatible = "rockchip,rk3328-hdmi-phy",
+		.data = (ulong)&rk3328_inno_hdmi_phy_drv_data,
+	},
+	{ /* sentile */ }
+};
+
+U_BOOT_DRIVER(inno_hdmi_phy) = {
+	.name = "inno_hdmi_phy",
+	.id = UCLASS_PHY,
+	.of_match = inno_hdmi_phy_ids,
+	.ops = &inno_hdmi_phy_ops,
+	.probe = inno_hdmi_phy_probe,
+	.priv_auto = sizeof(struct inno_hdmi_phy),
+};
-- 
2.25.1


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

* [PATCH 12/17] video: rockchip: Add rk3328 hdmi support
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
                   ` (10 preceding siblings ...)
  2023-12-11  8:59 ` [PATCH 11/17] phy: rockchip: Add Rockchip INNO HDMI PHY driver Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-11  8:59 ` [PATCH 13/17] video: rockchip: Add rk3328 vop support Jagan Teki
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

From: Jagan Teki <jagan@edgeble.ai>

Add Rockchip RK3328 HDMI Out driver.

Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
 drivers/video/rockchip/Makefile      |   1 +
 drivers/video/rockchip/rk3328_hdmi.c | 131 +++++++++++++++++++++++++++
 drivers/video/rockchip/rk_hdmi.h     |   3 +
 3 files changed, 135 insertions(+)
 create mode 100644 drivers/video/rockchip/rk3328_hdmi.c

diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index 8128289cc8..4991303c73 100644
--- a/drivers/video/rockchip/Makefile
+++ b/drivers/video/rockchip/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399_vop.o
 obj-$(CONFIG_DISPLAY_ROCKCHIP_EDP) += rk_edp.o
 obj-$(CONFIG_DISPLAY_ROCKCHIP_LVDS) += rk_lvds.o
 obj-hdmi-$(CONFIG_ROCKCHIP_RK3288) += rk3288_hdmi.o
+obj-hdmi-$(CONFIG_ROCKCHIP_RK3328) += rk3328_hdmi.o
 obj-hdmi-$(CONFIG_ROCKCHIP_RK3399) += rk3399_hdmi.o
 obj-$(CONFIG_DISPLAY_ROCKCHIP_HDMI) += rk_hdmi.o $(obj-hdmi-y)
 obj-mipi-$(CONFIG_ROCKCHIP_RK3288) += rk3288_mipi.o
diff --git a/drivers/video/rockchip/rk3328_hdmi.c b/drivers/video/rockchip/rk3328_hdmi.c
new file mode 100644
index 0000000000..23624699ba
--- /dev/null
+++ b/drivers/video/rockchip/rk3328_hdmi.c
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 Edgeble AI Technologies Pvt. Ltd.
+ */
+
+#include <clk.h>
+#include <display.h>
+#include <dm.h>
+#include <dw_hdmi.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/grf_rk3328.h>
+#include "rk_hdmi.h"
+
+#define RK3328_IO_3V_DOMAIN              (7 << (9 + 16))
+#define RK3328_IO_5V_DOMAIN              ((7 << 9) | (3 << (9 + 16)))
+#define RK3328_IO_DDC_IN_MSK             ((3 << 10) | (3 << (10 + 16)))
+#define RK3328_IO_CTRL_BY_HDMI           ((1 << 13) | (1 << (13 + 16)))
+
+static int rk3328_hdmi_enable(struct udevice *dev, int panel_bpp,
+			      const struct display_timing *edid)
+{
+	struct rk_hdmi_priv *priv = dev_get_priv(dev);
+
+	return dw_hdmi_enable(&priv->hdmi, edid);
+}
+
+static int rk3328_dw_hdmi_phy_cfg(struct dw_hdmi *hdmi, uint pixclock)
+{
+	struct rk_hdmi_priv *priv = container_of(hdmi, struct rk_hdmi_priv, hdmi);
+	int ret;
+
+	ret = generic_phy_init(&priv->phy);
+	if (ret) {
+		printf("failed to init phy (ret=%d)\n", ret);
+		return ret;
+	}
+
+	ret = generic_phy_power_on(&priv->phy);
+	if (ret) {
+		printf("failed to power on phy (ret=%d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void rk3328_dw_hdmi_setup_hpd(struct dw_hdmi *hdmi)
+{
+	struct rk_hdmi_priv *priv = container_of(hdmi, struct rk_hdmi_priv, hdmi);
+	struct rk3328_grf_regs *grf = priv->grf;
+
+	writel(RK3328_IO_DDC_IN_MSK, &grf->soc_con[2]);
+	writel(RK3328_IO_CTRL_BY_HDMI, &grf->soc_con[3]);
+}
+
+static void rk3328_dw_hdmi_read_hpd(struct dw_hdmi *hdmi, bool hpd_status)
+{
+	struct rk_hdmi_priv *priv = container_of(hdmi, struct rk_hdmi_priv, hdmi);
+	struct rk3328_grf_regs *grf = priv->grf;
+
+	if (hpd_status)
+		writel(RK3328_IO_5V_DOMAIN, &grf->soc_con[4]);
+	else
+		writel(RK3328_IO_3V_DOMAIN, &grf->soc_con[4]);
+}
+
+static const struct dw_hdmi_phy_ops dw_hdmi_rk3328_phy_ops = {
+	.phy_set = rk3328_dw_hdmi_phy_cfg,
+	.setup_hpd = rk3328_dw_hdmi_setup_hpd,
+	.read_hpd = rk3328_dw_hdmi_read_hpd,
+};
+
+static const struct dw_hdmi_plat_data dw_hdmi_rk3328_plat_data = {
+	.phy_force_vendor = true,
+	.phy_ops = &dw_hdmi_rk3328_phy_ops,
+};
+
+static int rk3328_hdmi_of_to_plat(struct udevice *dev)
+{
+	struct rk_hdmi_priv *priv = dev_get_priv(dev);
+	struct dw_hdmi *hdmi = &priv->hdmi;
+
+	hdmi->i2c_clk_high = 0x71;
+	hdmi->i2c_clk_low = 0x76;
+
+	rk_hdmi_of_to_plat(dev);
+
+	hdmi->data = &dw_hdmi_rk3328_plat_data;
+
+	return 0;
+}
+
+static int rk3328_hdmi_probe(struct udevice *dev)
+{
+	struct rk_hdmi_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = generic_phy_get_by_name(dev, "hdmi", &priv->phy);
+	if (ret) {
+		printf("failed to get hdmi phy\n");
+		return ret;
+	};
+
+	ret = rk_hdmi_probe(dev);
+	if (ret) {
+		printf("failed to probe rk hdmi\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct dm_display_ops rk3328_hdmi_ops = {
+	.read_edid = rk_hdmi_read_edid,
+	.enable = rk3328_hdmi_enable,
+};
+
+static const struct udevice_id rk3328_hdmi_ids[] = {
+	{ .compatible = "rockchip,rk3328-dw-hdmi" },
+	{ }
+};
+
+U_BOOT_DRIVER(rk3328_hdmi_rockchip) = {
+	.name = "rk3328_hdmi_rockchip",
+	.id = UCLASS_DISPLAY,
+	.of_match = rk3328_hdmi_ids,
+	.ops = &rk3328_hdmi_ops,
+	.of_to_plat = rk3328_hdmi_of_to_plat,
+	.probe = rk3328_hdmi_probe,
+	.priv_auto	= sizeof(struct rk_hdmi_priv),
+};
diff --git a/drivers/video/rockchip/rk_hdmi.h b/drivers/video/rockchip/rk_hdmi.h
index 200dbaea74..dcfba3d3d7 100644
--- a/drivers/video/rockchip/rk_hdmi.h
+++ b/drivers/video/rockchip/rk_hdmi.h
@@ -6,6 +6,8 @@
 #ifndef __RK_HDMI_H__
 #define __RK_HDMI_H__
 
+#include <generic-phy.h>
+
 struct rkhdmi_driverdata {
 	/* configuration */
 	u8 i2c_clk_high;
@@ -19,6 +21,7 @@ struct rkhdmi_driverdata {
 
 struct rk_hdmi_priv {
 	struct dw_hdmi hdmi;
+	struct phy phy;
 	void *grf;
 };
 
-- 
2.25.1


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

* [PATCH 13/17] video: rockchip: Add rk3328 vop support
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
                   ` (11 preceding siblings ...)
  2023-12-11  8:59 ` [PATCH 12/17] video: rockchip: Add rk3328 hdmi support Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-16 22:45   ` Johan Jonker
  2023-12-11  8:59 ` [PATCH 14/17] ARM: dts: rk3328: Enable VOP for bootph-all Jagan Teki
                   ` (4 subsequent siblings)
  17 siblings, 1 reply; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

From: Jagan Teki <jagan@edgeble.ai>

Add support for Rockchip RK3328 VOP.

Signed-off-by: Jagan Teki <jagan@edgeble.ai>
---
 drivers/video/rockchip/Makefile     |  1 +
 drivers/video/rockchip/rk3328_vop.c | 66 +++++++++++++++++++++++++++++
 2 files changed, 67 insertions(+)
 create mode 100644 drivers/video/rockchip/rk3328_vop.c

diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index 4991303c73..f55beceebf 100644
--- a/drivers/video/rockchip/Makefile
+++ b/drivers/video/rockchip/Makefile
@@ -6,6 +6,7 @@
 ifdef CONFIG_VIDEO_ROCKCHIP
 obj-y += rk_vop.o
 obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288_vop.o
+obj-$(CONFIG_ROCKCHIP_RK3328) += rk3328_vop.o
 obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399_vop.o
 obj-$(CONFIG_DISPLAY_ROCKCHIP_EDP) += rk_edp.o
 obj-$(CONFIG_DISPLAY_ROCKCHIP_LVDS) += rk_lvds.o
diff --git a/drivers/video/rockchip/rk3328_vop.c b/drivers/video/rockchip/rk3328_vop.c
new file mode 100644
index 0000000000..2512314e64
--- /dev/null
+++ b/drivers/video/rockchip/rk3328_vop.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 Edgeble AI Technologies Pvt. Ltd.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <video.h>
+#include <asm/io.h>
+#include "rk_vop.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void rk3328_set_pin_polarity(struct udevice *dev,
+				    enum vop_modes mode, u32 polarity)
+{
+	struct rk_vop_priv *priv = dev_get_priv(dev);
+	struct rk3288_vop *regs = priv->regs;
+
+	switch (mode) {
+	case VOP_MODE_HDMI:
+		clrsetbits_le32(&regs->dsp_ctrl1,
+				M_RK3399_DSP_HDMI_POL,
+				V_RK3399_DSP_HDMI_POL(polarity));
+		break;
+	default:
+		debug("%s: unsupported output mode %x\n", __func__, mode);
+	}
+}
+
+static int rk3328_vop_probe(struct udevice *dev)
+{
+	/* Before relocation we don't need to do anything */
+	if (!(gd->flags & GD_FLG_RELOC))
+		return 0;
+
+	return rk_vop_probe(dev);
+}
+
+struct rkvop_driverdata rk3328_driverdata = {
+	.dsp_offset = 0x490,
+	.win_offset = 0xd0,
+	.features = VOP_FEATURE_OUTPUT_10BIT,
+	.set_pin_polarity = rk3328_set_pin_polarity,
+};
+
+static const struct udevice_id rk3328_vop_ids[] = {
+	{
+		.compatible = "rockchip,rk3328-vop",
+		.data = (ulong)&rk3328_driverdata
+	},
+	{ /* sentile */ }
+};
+
+static const struct video_ops rk3328_vop_ops = {
+};
+
+U_BOOT_DRIVER(rk3328_vop) = {
+	.name	= "rk3328_vop",
+	.id	= UCLASS_VIDEO,
+	.of_match = rk3328_vop_ids,
+	.ops	= &rk3328_vop_ops,
+	.bind	= rk_vop_bind,
+	.probe	= rk3328_vop_probe,
+	.priv_auto	= sizeof(struct rk_vop_priv),
+};
-- 
2.25.1


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

* [PATCH 14/17] ARM: dts: rk3328: Enable VOP for bootph-all
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
                   ` (12 preceding siblings ...)
  2023-12-11  8:59 ` [PATCH 13/17] video: rockchip: Add rk3328 vop support Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-11  8:59 ` [PATCH 15/17] rockchip: Enable preconsole for rk3328 Jagan Teki
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

Model: Firefly roc-rk3328-cc
DRAM: 1 GiB (effective 1022 MiB)
Video device 'vop@ff370000' cannot allocate frame buffer memory -ensure the device is set up before relocation
Error binding driver 'rockchip_rk3328_vop': -28
Some drivers failed to bind
initcall sequence 000000003ffcd5e8 failed at call 000000000021a5c4 (err=-28)
 ### ERROR ### Please RESET the board ###

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 arch/arm/dts/rk3328-u-boot.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/dts/rk3328-u-boot.dtsi b/arch/arm/dts/rk3328-u-boot.dtsi
index a9f2536de2..5258fec566 100644
--- a/arch/arm/dts/rk3328-u-boot.dtsi
+++ b/arch/arm/dts/rk3328-u-boot.dtsi
@@ -68,3 +68,7 @@
 &spi0 {
 	bootph-all;
 };
+
+&vop {
+	bootph-all;
+};
-- 
2.25.1


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

* [PATCH 15/17] rockchip: Enable preconsole for rk3328
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
                   ` (13 preceding siblings ...)
  2023-12-11  8:59 ` [PATCH 14/17] ARM: dts: rk3328: Enable VOP for bootph-all Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-11  8:59 ` [PATCH 16/17] configs: evb-rk3328: Enable vidconsole " Jagan Teki
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

Enable and set the start address of pre-console buffer for RK3328.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 arch/arm/mach-rockchip/Kconfig | 1 +
 common/Kconfig                 | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index b577a911e7..60f403fe74 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -179,6 +179,7 @@ config ROCKCHIP_RK3328
 	select SUPPORT_TPL
 	select TPL
 	select TPL_NEEDS_SEPARATE_STACK if TPL
+	imply PRE_CONSOLE_BUFFER
 	imply ROCKCHIP_COMMON_BOARD
 	imply ROCKCHIP_SDRAM_COMMON
 	imply SPL_ROCKCHIP_COMMON_BOARD
diff --git a/common/Kconfig b/common/Kconfig
index 0f54819519..093ebfbd1e 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -208,7 +208,7 @@ config PRE_CON_BUF_ADDR
 	default 0x2f000000 if ARCH_SUNXI && MACH_SUN9I
 	default 0x4f000000 if ARCH_SUNXI && !MACH_SUN9I
 	default 0x0f000000 if ROCKCHIP_RK3288
-	default 0x0f200000 if ROCKCHIP_RK3399
+	default 0x0f200000 if ROCKCHIP_RK3399 || ROCKCHIP_RK3328
 	help
 	  This sets the start address of the pre-console buffer. This must
 	  be in available memory and is accessed before relocation and
-- 
2.25.1


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

* [PATCH 16/17] configs: evb-rk3328: Enable vidconsole for rk3328
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
                   ` (14 preceding siblings ...)
  2023-12-11  8:59 ` [PATCH 15/17] rockchip: Enable preconsole for rk3328 Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-11  8:59 ` [PATCH 17/17] configs: Enable HDMI Out for ROC-RK3328-CC Jagan Teki
  2023-12-15  6:36   ` Jagan Teki
  17 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

Enable video console for Rockchip RK3328.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 include/configs/evb_rk3328.h    | 5 +++++
 include/configs/rk3328_common.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/include/configs/evb_rk3328.h b/include/configs/evb_rk3328.h
index d10e5b1d2e..c985080f7b 100644
--- a/include/configs/evb_rk3328.h
+++ b/include/configs/evb_rk3328.h
@@ -6,6 +6,11 @@
 #ifndef __EVB_RK3328_H
 #define __EVB_RK3328_H
 
+#define ROCKCHIP_DEVICE_SETTINGS \
+		"stdin=serial,usbkbd\0" \
+		"stdout=serial,vidconsole\0" \
+		"stderr=serial,vidconsole\0"
+
 #include <configs/rk3328_common.h>
 
 #endif
diff --git a/include/configs/rk3328_common.h b/include/configs/rk3328_common.h
index e920ec7e5d..2c40674b22 100644
--- a/include/configs/rk3328_common.h
+++ b/include/configs/rk3328_common.h
@@ -26,6 +26,7 @@
 	ENV_MEM_LAYOUT_SETTINGS \
 	"fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \
 	"partitions=" PARTS_DEFAULT \
+	ROCKCHIP_DEVICE_SETTINGS \
 	"boot_targets=" BOOT_TARGETS "\0"
 
 #endif
-- 
2.25.1


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

* [PATCH 17/17] configs: Enable HDMI Out for ROC-RK3328-CC
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
                   ` (15 preceding siblings ...)
  2023-12-11  8:59 ` [PATCH 16/17] configs: evb-rk3328: Enable vidconsole " Jagan Teki
@ 2023-12-11  8:59 ` Jagan Teki
  2023-12-15  6:36   ` Jagan Teki
  17 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-11  8:59 UTC (permalink / raw)
  To: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

U-Boot 2024.01-rc4-00053-gb9f7cafdd9-dirty (Dec 11 2023 - 13:18:15 +0530)

Model: Firefly roc-rk3328-cc
DRAM:  1 GiB (effective 1022 MiB)
PMIC:  RK8050 (on=0x40, off=0x00)
Core:  236 devices, 26 uclasses, devicetree: separate
MMC:   mmc@ff500000: 1, mmc@ff520000: 0
Loading Environment from MMC... *** Warning - bad CRC, using default environment

tmdsclock = 148500000; chipversion = 1
In:    serial
Out:   vidconsole
Err:   vidconsole
Model: Firefly roc-rk3328-cc
Net:   eth0: ethernet@ff540000
Hit any key to stop autoboot:  0
=> dm tree
 Class     Index  Probed  Driver                Name
-----------------------------------------------------------
 root          0  [ + ]   root_driver           root_driver
 firmware      0  [   ]   psci                  |-- psci
 clk           0  [ + ]   fixed_clock           |-- xin24m
 syscon        0  [ + ]   rockchip_rk3328_grf   |-- syscon@ff100000
 serial        0  [ + ]   ns16550_serial        |-- serial@ff130000
 i2c           0  [ + ]   rockchip_rk3066_i2c   |-- i2c@ff160000
 pmic          0  [ + ]   rockchip_rk805        |   `-- pmic@18
 sysreset      0  [   ]   rk8xx_sysreset        |       |-- rk8xx_sysreset
 regulator     0  [ + ]   rk8xx_buck            |       |-- DCDC_REG1
 regulator     1  [ + ]   rk8xx_buck            |       |-- DCDC_REG2
 regulator     2  [ + ]   rk8xx_buck            |       |-- DCDC_REG3
 regulator     3  [ + ]   rk8xx_buck            |       |-- DCDC_REG4
 regulator     4  [ + ]   rk8xx_ldo             |       |-- LDO_REG1
 regulator     5  [ + ]   rk8xx_ldo             |       |-- LDO_REG2
 regulator     6  [ + ]   rk8xx_ldo             |       `-- LDO_REG3
 video         0  [ + ]   rk3328_vop            |-- vop@ff370000
 vidconsole    0  [ + ]   vidconsole0           |   `-- vop@ff370000.vidconsole0
 display       0  [ + ]   rk3328_hdmi_rockchip  |-- hdmi@ff3c0000
 phy           0  [ + ]   inno_hdmi_phy         |-- phy@ff430000
 clk           1  [ + ]   rockchip_rk3328_cru   |-- clock-controller@ff440000
 sysreset      1  [   ]   rockchip_sysreset     |   |-- sysreset
 reset         0  [ + ]   rockchip_reset        |   `-- reset

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 configs/roc-cc-rk3328_defconfig | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/configs/roc-cc-rk3328_defconfig b/configs/roc-cc-rk3328_defconfig
index 4ac3c9403b..4eef9016dc 100644
--- a/configs/roc-cc-rk3328_defconfig
+++ b/configs/roc-cc-rk3328_defconfig
@@ -79,6 +79,7 @@ CONFIG_PHY_REALTEK=y
 CONFIG_PHY_GIGE=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PHY_ROCKCHIP_INNO_HDMI=y
 CONFIG_PHY_ROCKCHIP_INNO_USB2=y
 CONFIG_PINCTRL=y
 CONFIG_SPL_PINCTRL=y
@@ -114,6 +115,10 @@ CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GENERIC=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_VIDEO=y
+CONFIG_DISPLAY=y
+CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_DISPLAY_ROCKCHIP_HDMI=y
 CONFIG_SPL_TINY_MEMSET=y
 CONFIG_TPL_TINY_MEMSET=y
 CONFIG_ERRNO_STR=y
-- 
2.25.1


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

* Re: [PATCH 02/17] video: dw_hdmi: Add Vendor PHY handling
  2023-12-11  8:59 ` [PATCH 02/17] video: dw_hdmi: Add Vendor PHY handling Jagan Teki
@ 2023-12-11  9:08   ` Neil Armstrong
  2023-12-12  9:25     ` Jagan Teki
  2023-12-13 19:50   ` Simon Glass
  1 sibling, 1 reply; 32+ messages in thread
From: Neil Armstrong @ 2023-12-11  9:08 UTC (permalink / raw)
  To: Jagan Teki, Anatolij Gustschin, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

On 11/12/2023 09:59, Jagan Teki wrote:
> From: Jagan Teki <jagan@edgeble.ai>
> 
> DW HDMI support Vendor PHY like Rockchip RK3328 Inno HDMI PHY.
> 
> Extend the vendor phy handling by adding platform phy hooks.
> 
> Signed-off-by: Jagan Teki <jagan@edgeble.ai>
> ---
>   drivers/video/dw_hdmi.c              | 29 +++++++++++++++++++++++++++-
>   drivers/video/meson/meson_dw_hdmi.c  | 11 ++++++++++-
>   drivers/video/rockchip/rk3399_hdmi.c |  8 +++++++-
>   drivers/video/rockchip/rk_hdmi.c     |  2 +-
>   drivers/video/sunxi/sunxi_dw_hdmi.c  | 11 ++++++++++-
>   include/dw_hdmi.h                    | 14 +++++++++++++-
>   6 files changed, 69 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/video/dw_hdmi.c b/drivers/video/dw_hdmi.c
> index c4fbb18294..ea12a09407 100644
> --- a/drivers/video/dw_hdmi.c
> +++ b/drivers/video/dw_hdmi.c
> @@ -988,7 +988,7 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
>   
>   	hdmi_av_composer(hdmi, edid);
>   
> -	ret = hdmi->phy_set(hdmi, edid->pixelclock.typ);
> +	ret = hdmi->ops->phy_set(hdmi, edid->pixelclock.typ);
>   	if (ret)
>   		return ret;
>   
> @@ -1009,10 +1009,37 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
>   	return 0;
>   }
>   
> +static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
> +	.phy_set = dw_hdmi_phy_cfg,
> +};
> +
> +static void dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
> +{
> +	if (!hdmi->data)
> +		return;
> +
> +	/* hook Synopsys PHYs ops */
> +	if (!hdmi->data->phy_force_vendor) {
> +		hdmi->ops = &dw_hdmi_synopsys_phy_ops;
> +		return;
> +	}
> +
> +	/* Vendor HDMI PHYs must assign phy_ops in plat_data */
> +	if (!hdmi->data->phy_ops) {
> +		printf("Unsupported Vendor HDMI phy_ops\n");
> +		return;
> +	}
> +
> +	/* hook Vendor HDMI PHYs ops */
> +	hdmi->ops = hdmi->data->phy_ops;
> +}
> +
>   void dw_hdmi_init(struct dw_hdmi *hdmi)
>   {
>   	uint ih_mute;
>   
> +	dw_hdmi_detect_phy(hdmi);
> +
>   	/*
>   	 * boot up defaults are:
>   	 * hdmi_ih_mute   = 0x03 (disabled)
> diff --git a/drivers/video/meson/meson_dw_hdmi.c b/drivers/video/meson/meson_dw_hdmi.c
> index 5db01904b5..63ca3ac52e 100644
> --- a/drivers/video/meson/meson_dw_hdmi.c
> +++ b/drivers/video/meson/meson_dw_hdmi.c
> @@ -375,6 +375,15 @@ static int meson_dw_hdmi_wait_hpd(struct dw_hdmi *hdmi)
>   	return -ETIMEDOUT;
>   }
>   
> +static const struct dw_hdmi_phy_ops dw_hdmi_meson_phy_ops = {
> +	.phy_set = meson_dw_hdmi_phy_cfg,

Pretty sure this should be meson_dw_hdmi_phy_init

> +};
> +
> +static const struct dw_hdmi_plat_data dw_hdmi_meson_plat_data = {
> +	.phy_force_vendor = true,
> +	.phy_ops = &dw_hdmi_meson_phy_ops,
> +};
> +
>   static int meson_dw_hdmi_probe(struct udevice *dev)
>   {
>   	struct meson_dw_hdmi *priv = dev_get_priv(dev);
> @@ -397,7 +406,7 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
>   
>   	priv->hdmi.hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
>   	priv->hdmi.hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
> -	priv->hdmi.phy_set = meson_dw_hdmi_phy_init;
> +	priv->hdmi.data = &dw_hdmi_meson_plat_data;
>   	if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
>   		priv->hdmi.reg_io_width = 1;
>   	else {
> diff --git a/drivers/video/rockchip/rk3399_hdmi.c b/drivers/video/rockchip/rk3399_hdmi.c
> index 3041360c6e..b32139a8a6 100644
> --- a/drivers/video/rockchip/rk3399_hdmi.c
> +++ b/drivers/video/rockchip/rk3399_hdmi.c
> @@ -64,8 +64,14 @@ static const struct dm_display_ops rk3399_hdmi_ops = {
>   	.enable = rk3399_hdmi_enable,
>   };
>   
> +static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
> +};
> +
>   static const struct udevice_id rk3399_hdmi_ids[] = {
> -	{ .compatible = "rockchip,rk3399-dw-hdmi" },
> +	{
> +		.compatible = "rockchip,rk3399-dw-hdmi",
> +		.data = (ulong)&rk3399_hdmi_drv_data
> +	},
>   	{ }
>   };
>   
> diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c
> index b75a174489..e34f532cd6 100644
> --- a/drivers/video/rockchip/rk_hdmi.c
> +++ b/drivers/video/rockchip/rk_hdmi.c
> @@ -83,6 +83,7 @@ int rk_hdmi_of_to_plat(struct udevice *dev)
>   	struct rk_hdmi_priv *priv = dev_get_priv(dev);
>   	struct dw_hdmi *hdmi = &priv->hdmi;
>   
> +	hdmi->data = (const struct dw_hdmi_plat_data *)dev_get_driver_data(dev);
>   	hdmi->ioaddr = (ulong)dev_read_addr(dev);
>   	hdmi->mpll_cfg = rockchip_mpll_cfg;
>   	hdmi->phy_cfg = rockchip_phy_config;
> @@ -90,7 +91,6 @@ int rk_hdmi_of_to_plat(struct udevice *dev)
>   	/* hdmi->i2c_clk_{high,low} are set up by the SoC driver */
>   
>   	hdmi->reg_io_width = 4;
> -	hdmi->phy_set = dw_hdmi_phy_cfg;
>   
>   	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
>   
> diff --git a/drivers/video/sunxi/sunxi_dw_hdmi.c b/drivers/video/sunxi/sunxi_dw_hdmi.c
> index 0324a050d0..4b67a1614e 100644
> --- a/drivers/video/sunxi/sunxi_dw_hdmi.c
> +++ b/drivers/video/sunxi/sunxi_dw_hdmi.c
> @@ -369,6 +369,15 @@ static int sunxi_dw_hdmi_probe(struct udevice *dev)
>   	return 0;
>   }
>   
> +static const struct dw_hdmi_phy_ops dw_hdmi_sunxi_phy_ops = {
> +	.phy_set = sunxi_dw_hdmi_phy_cfg,
> +};
> +
> +static const struct dw_hdmi_plat_data dw_hdmi_sunxi_plat_data = {
> +	.phy_force_vendor = true,
> +	.phy_ops = &dw_hdmi_sunxi_phy_ops,
> +};
> +
>   static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
>   {
>   	struct sunxi_dw_hdmi_priv *priv = dev_get_priv(dev);
> @@ -379,7 +388,7 @@ static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
>   	hdmi->i2c_clk_high = 0xd8;
>   	hdmi->i2c_clk_low = 0xfe;
>   	hdmi->reg_io_width = 1;
> -	hdmi->phy_set = sunxi_dw_hdmi_phy_cfg;
> +	hdmi->data = &dw_hdmi_sunxi_plat_data;
>   
>   	ret = reset_get_bulk(dev, &priv->resets);
>   	if (ret)
> diff --git a/include/dw_hdmi.h b/include/dw_hdmi.h
> index 8acae3839f..4ad8b39f84 100644
> --- a/include/dw_hdmi.h
> +++ b/include/dw_hdmi.h
> @@ -534,6 +534,17 @@ struct hdmi_data_info {
>   	struct hdmi_vmode video_mode;
>   };
>   
> +struct dw_hdmi;
> +
> +struct dw_hdmi_phy_ops {
> +	int (*phy_set)(struct dw_hdmi *hdmi, uint mpixelclock);
> +};
> +
> +struct dw_hdmi_plat_data {
> +	bool phy_force_vendor;
> +	const struct dw_hdmi_phy_ops *phy_ops;
> +};

Why do you need a separate phy_ops and this phy_force_vendor ?

Simply use the provided phy_ops is pointer != NULL

I think simply use a single struct passed as pdata to have:

if (!hdmi->data)
	hdmi->ops = &dw_hdmi_synopsys_phy_ops;
else
	/* hook Vendor HDMI PHYs ops */
	hdmi->ops = hdmi->data;

Neil

> +
>   struct dw_hdmi {
>   	ulong ioaddr;
>   	const struct hdmi_mpll_config *mpll_cfg;
> @@ -543,8 +554,9 @@ struct dw_hdmi {
>   	u8 reg_io_width;
>   	struct hdmi_data_info hdmi_data;
>   	struct udevice *ddc_bus;
> +	const struct dw_hdmi_phy_ops *ops;
> +	const struct dw_hdmi_plat_data *data;
>   
> -	int (*phy_set)(struct dw_hdmi *hdmi, uint mpixelclock);
>   	void (*write_reg)(struct dw_hdmi *hdmi, u8 val, int offset);
>   	u8 (*read_reg)(struct dw_hdmi *hdmi, int offset);
>   };


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

* Re: [PATCH 02/17] video: dw_hdmi: Add Vendor PHY handling
  2023-12-11  9:08   ` Neil Armstrong
@ 2023-12-12  9:25     ` Jagan Teki
  0 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-12  9:25 UTC (permalink / raw)
  To: neil.armstrong
  Cc: Anatolij Gustschin, Andre Przywara, Kever Yang, Simon Glass,
	Heiko Stuebner, u-boot, Da Xue, Jagan Teki

On Mon, Dec 11, 2023 at 2:38 PM Neil Armstrong
<neil.armstrong@linaro.org> wrote:
>
> On 11/12/2023 09:59, Jagan Teki wrote:
> > From: Jagan Teki <jagan@edgeble.ai>
> >
> > DW HDMI support Vendor PHY like Rockchip RK3328 Inno HDMI PHY.
> >
> > Extend the vendor phy handling by adding platform phy hooks.
> >
> > Signed-off-by: Jagan Teki <jagan@edgeble.ai>
> > ---
> >   drivers/video/dw_hdmi.c              | 29 +++++++++++++++++++++++++++-
> >   drivers/video/meson/meson_dw_hdmi.c  | 11 ++++++++++-
> >   drivers/video/rockchip/rk3399_hdmi.c |  8 +++++++-
> >   drivers/video/rockchip/rk_hdmi.c     |  2 +-
> >   drivers/video/sunxi/sunxi_dw_hdmi.c  | 11 ++++++++++-
> >   include/dw_hdmi.h                    | 14 +++++++++++++-
> >   6 files changed, 69 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/video/dw_hdmi.c b/drivers/video/dw_hdmi.c
> > index c4fbb18294..ea12a09407 100644
> > --- a/drivers/video/dw_hdmi.c
> > +++ b/drivers/video/dw_hdmi.c
> > @@ -988,7 +988,7 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
> >
> >       hdmi_av_composer(hdmi, edid);
> >
> > -     ret = hdmi->phy_set(hdmi, edid->pixelclock.typ);
> > +     ret = hdmi->ops->phy_set(hdmi, edid->pixelclock.typ);
> >       if (ret)
> >               return ret;
> >
> > @@ -1009,10 +1009,37 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
> >       return 0;
> >   }
> >
> > +static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
> > +     .phy_set = dw_hdmi_phy_cfg,
> > +};
> > +
> > +static void dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
> > +{
> > +     if (!hdmi->data)
> > +             return;
> > +
> > +     /* hook Synopsys PHYs ops */
> > +     if (!hdmi->data->phy_force_vendor) {
> > +             hdmi->ops = &dw_hdmi_synopsys_phy_ops;
> > +             return;
> > +     }
> > +
> > +     /* Vendor HDMI PHYs must assign phy_ops in plat_data */
> > +     if (!hdmi->data->phy_ops) {
> > +             printf("Unsupported Vendor HDMI phy_ops\n");
> > +             return;
> > +     }
> > +
> > +     /* hook Vendor HDMI PHYs ops */
> > +     hdmi->ops = hdmi->data->phy_ops;
> > +}
> > +
> >   void dw_hdmi_init(struct dw_hdmi *hdmi)
> >   {
> >       uint ih_mute;
> >
> > +     dw_hdmi_detect_phy(hdmi);
> > +
> >       /*
> >        * boot up defaults are:
> >        * hdmi_ih_mute   = 0x03 (disabled)
> > diff --git a/drivers/video/meson/meson_dw_hdmi.c b/drivers/video/meson/meson_dw_hdmi.c
> > index 5db01904b5..63ca3ac52e 100644
> > --- a/drivers/video/meson/meson_dw_hdmi.c
> > +++ b/drivers/video/meson/meson_dw_hdmi.c
> > @@ -375,6 +375,15 @@ static int meson_dw_hdmi_wait_hpd(struct dw_hdmi *hdmi)
> >       return -ETIMEDOUT;
> >   }
> >
> > +static const struct dw_hdmi_phy_ops dw_hdmi_meson_phy_ops = {
> > +     .phy_set = meson_dw_hdmi_phy_cfg,
>
> Pretty sure this should be meson_dw_hdmi_phy_init

Correct, I will update this.

>
> > +};
> > +
> > +static const struct dw_hdmi_plat_data dw_hdmi_meson_plat_data = {
> > +     .phy_force_vendor = true,
> > +     .phy_ops = &dw_hdmi_meson_phy_ops,
> > +};
> > +
> >   static int meson_dw_hdmi_probe(struct udevice *dev)
> >   {
> >       struct meson_dw_hdmi *priv = dev_get_priv(dev);
> > @@ -397,7 +406,7 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
> >
> >       priv->hdmi.hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
> >       priv->hdmi.hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
> > -     priv->hdmi.phy_set = meson_dw_hdmi_phy_init;
> > +     priv->hdmi.data = &dw_hdmi_meson_plat_data;
> >       if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
> >               priv->hdmi.reg_io_width = 1;
> >       else {
> > diff --git a/drivers/video/rockchip/rk3399_hdmi.c b/drivers/video/rockchip/rk3399_hdmi.c
> > index 3041360c6e..b32139a8a6 100644
> > --- a/drivers/video/rockchip/rk3399_hdmi.c
> > +++ b/drivers/video/rockchip/rk3399_hdmi.c
> > @@ -64,8 +64,14 @@ static const struct dm_display_ops rk3399_hdmi_ops = {
> >       .enable = rk3399_hdmi_enable,
> >   };
> >
> > +static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
> > +};
> > +
> >   static const struct udevice_id rk3399_hdmi_ids[] = {
> > -     { .compatible = "rockchip,rk3399-dw-hdmi" },
> > +     {
> > +             .compatible = "rockchip,rk3399-dw-hdmi",
> > +             .data = (ulong)&rk3399_hdmi_drv_data
> > +     },
> >       { }
> >   };
> >
> > diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c
> > index b75a174489..e34f532cd6 100644
> > --- a/drivers/video/rockchip/rk_hdmi.c
> > +++ b/drivers/video/rockchip/rk_hdmi.c
> > @@ -83,6 +83,7 @@ int rk_hdmi_of_to_plat(struct udevice *dev)
> >       struct rk_hdmi_priv *priv = dev_get_priv(dev);
> >       struct dw_hdmi *hdmi = &priv->hdmi;
> >
> > +     hdmi->data = (const struct dw_hdmi_plat_data *)dev_get_driver_data(dev);
> >       hdmi->ioaddr = (ulong)dev_read_addr(dev);
> >       hdmi->mpll_cfg = rockchip_mpll_cfg;
> >       hdmi->phy_cfg = rockchip_phy_config;
> > @@ -90,7 +91,6 @@ int rk_hdmi_of_to_plat(struct udevice *dev)
> >       /* hdmi->i2c_clk_{high,low} are set up by the SoC driver */
> >
> >       hdmi->reg_io_width = 4;
> > -     hdmi->phy_set = dw_hdmi_phy_cfg;
> >
> >       priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
> >
> > diff --git a/drivers/video/sunxi/sunxi_dw_hdmi.c b/drivers/video/sunxi/sunxi_dw_hdmi.c
> > index 0324a050d0..4b67a1614e 100644
> > --- a/drivers/video/sunxi/sunxi_dw_hdmi.c
> > +++ b/drivers/video/sunxi/sunxi_dw_hdmi.c
> > @@ -369,6 +369,15 @@ static int sunxi_dw_hdmi_probe(struct udevice *dev)
> >       return 0;
> >   }
> >
> > +static const struct dw_hdmi_phy_ops dw_hdmi_sunxi_phy_ops = {
> > +     .phy_set = sunxi_dw_hdmi_phy_cfg,
> > +};
> > +
> > +static const struct dw_hdmi_plat_data dw_hdmi_sunxi_plat_data = {
> > +     .phy_force_vendor = true,
> > +     .phy_ops = &dw_hdmi_sunxi_phy_ops,
> > +};
> > +
> >   static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
> >   {
> >       struct sunxi_dw_hdmi_priv *priv = dev_get_priv(dev);
> > @@ -379,7 +388,7 @@ static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
> >       hdmi->i2c_clk_high = 0xd8;
> >       hdmi->i2c_clk_low = 0xfe;
> >       hdmi->reg_io_width = 1;
> > -     hdmi->phy_set = sunxi_dw_hdmi_phy_cfg;
> > +     hdmi->data = &dw_hdmi_sunxi_plat_data;
> >
> >       ret = reset_get_bulk(dev, &priv->resets);
> >       if (ret)
> > diff --git a/include/dw_hdmi.h b/include/dw_hdmi.h
> > index 8acae3839f..4ad8b39f84 100644
> > --- a/include/dw_hdmi.h
> > +++ b/include/dw_hdmi.h
> > @@ -534,6 +534,17 @@ struct hdmi_data_info {
> >       struct hdmi_vmode video_mode;
> >   };
> >
> > +struct dw_hdmi;
> > +
> > +struct dw_hdmi_phy_ops {
> > +     int (*phy_set)(struct dw_hdmi *hdmi, uint mpixelclock);
> > +};
> > +
> > +struct dw_hdmi_plat_data {
> > +     bool phy_force_vendor;
> > +     const struct dw_hdmi_phy_ops *phy_ops;
> > +};
>
> Why do you need a separate phy_ops and this phy_force_vendor ?
>
> Simply use the provided phy_ops is pointer != NULL
>
> I think simply use a single struct passed as pdata to have:
>
> if (!hdmi->data)
>         hdmi->ops = &dw_hdmi_synopsys_phy_ops;
> else
>         /* hook Vendor HDMI PHYs ops */
>         hdmi->ops = hdmi->data;

This logic seems not proper according to DW HDMI vendor phy support.

phy_set -> dw_hdmi_phy_cfg in dw_hdmi.c is what synopsys default phy
ops set. and reset defined in their hdmi drivers are vendor-related.
So only rk3399 has default synopsys phy_set but meson, sunxi and this
rk3328 has vendor phy ops. We need to define plat_data with phy_ops
and phy_force_vendor flag to support this setup.

Thanks,
Jagan.

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

* Re: [PATCH 02/17] video: dw_hdmi: Add Vendor PHY handling
  2023-12-11  8:59 ` [PATCH 02/17] video: dw_hdmi: Add Vendor PHY handling Jagan Teki
  2023-12-11  9:08   ` Neil Armstrong
@ 2023-12-13 19:50   ` Simon Glass
  2023-12-14  4:44     ` Jagan Teki
  1 sibling, 1 reply; 32+ messages in thread
From: Simon Glass @ 2023-12-13 19:50 UTC (permalink / raw)
  To: Jagan Teki
  Cc: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Heiko Stuebner, u-boot, Da Xue, Jagan Teki

Hi Jagan,

On Mon, 11 Dec 2023 at 02:00, Jagan Teki <jagan@amarulasolutions.com> wrote:
>
> From: Jagan Teki <jagan@edgeble.ai>
>
> DW HDMI support Vendor PHY like Rockchip RK3328 Inno HDMI PHY.
>
> Extend the vendor phy handling by adding platform phy hooks.
>
> Signed-off-by: Jagan Teki <jagan@edgeble.ai>
> ---
>  drivers/video/dw_hdmi.c              | 29 +++++++++++++++++++++++++++-
>  drivers/video/meson/meson_dw_hdmi.c  | 11 ++++++++++-
>  drivers/video/rockchip/rk3399_hdmi.c |  8 +++++++-
>  drivers/video/rockchip/rk_hdmi.c     |  2 +-
>  drivers/video/sunxi/sunxi_dw_hdmi.c  | 11 ++++++++++-
>  include/dw_hdmi.h                    | 14 +++++++++++++-
>  6 files changed, 69 insertions(+), 6 deletions(-)
>

Isn't there a PHY framework we should use in U-Boot?

Regards,
Sim on

> diff --git a/drivers/video/dw_hdmi.c b/drivers/video/dw_hdmi.c
> index c4fbb18294..ea12a09407 100644
> --- a/drivers/video/dw_hdmi.c
> +++ b/drivers/video/dw_hdmi.c
> @@ -988,7 +988,7 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
>
>         hdmi_av_composer(hdmi, edid);
>
> -       ret = hdmi->phy_set(hdmi, edid->pixelclock.typ);
> +       ret = hdmi->ops->phy_set(hdmi, edid->pixelclock.typ);
>         if (ret)
>                 return ret;
>
> @@ -1009,10 +1009,37 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
>         return 0;
>  }
>
> +static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
> +       .phy_set = dw_hdmi_phy_cfg,
> +};
> +
> +static void dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
> +{
> +       if (!hdmi->data)
> +               return;
> +
> +       /* hook Synopsys PHYs ops */
> +       if (!hdmi->data->phy_force_vendor) {
> +               hdmi->ops = &dw_hdmi_synopsys_phy_ops;
> +               return;
> +       }
> +
> +       /* Vendor HDMI PHYs must assign phy_ops in plat_data */
> +       if (!hdmi->data->phy_ops) {
> +               printf("Unsupported Vendor HDMI phy_ops\n");
> +               return;
> +       }
> +
> +       /* hook Vendor HDMI PHYs ops */
> +       hdmi->ops = hdmi->data->phy_ops;
> +}
> +
>  void dw_hdmi_init(struct dw_hdmi *hdmi)
>  {
>         uint ih_mute;
>
> +       dw_hdmi_detect_phy(hdmi);
> +
>         /*
>          * boot up defaults are:
>          * hdmi_ih_mute   = 0x03 (disabled)
> diff --git a/drivers/video/meson/meson_dw_hdmi.c b/drivers/video/meson/meson_dw_hdmi.c
> index 5db01904b5..63ca3ac52e 100644
> --- a/drivers/video/meson/meson_dw_hdmi.c
> +++ b/drivers/video/meson/meson_dw_hdmi.c
> @@ -375,6 +375,15 @@ static int meson_dw_hdmi_wait_hpd(struct dw_hdmi *hdmi)
>         return -ETIMEDOUT;
>  }
>
> +static const struct dw_hdmi_phy_ops dw_hdmi_meson_phy_ops = {
> +       .phy_set = meson_dw_hdmi_phy_cfg,
> +};
> +
> +static const struct dw_hdmi_plat_data dw_hdmi_meson_plat_data = {
> +       .phy_force_vendor = true,
> +       .phy_ops = &dw_hdmi_meson_phy_ops,
> +};
> +
>  static int meson_dw_hdmi_probe(struct udevice *dev)
>  {
>         struct meson_dw_hdmi *priv = dev_get_priv(dev);
> @@ -397,7 +406,7 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
>
>         priv->hdmi.hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
>         priv->hdmi.hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
> -       priv->hdmi.phy_set = meson_dw_hdmi_phy_init;
> +       priv->hdmi.data = &dw_hdmi_meson_plat_data;
>         if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
>                 priv->hdmi.reg_io_width = 1;
>         else {
> diff --git a/drivers/video/rockchip/rk3399_hdmi.c b/drivers/video/rockchip/rk3399_hdmi.c
> index 3041360c6e..b32139a8a6 100644
> --- a/drivers/video/rockchip/rk3399_hdmi.c
> +++ b/drivers/video/rockchip/rk3399_hdmi.c
> @@ -64,8 +64,14 @@ static const struct dm_display_ops rk3399_hdmi_ops = {
>         .enable = rk3399_hdmi_enable,
>  };
>
> +static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
> +};
> +
>  static const struct udevice_id rk3399_hdmi_ids[] = {
> -       { .compatible = "rockchip,rk3399-dw-hdmi" },
> +       {
> +               .compatible = "rockchip,rk3399-dw-hdmi",
> +               .data = (ulong)&rk3399_hdmi_drv_data
> +       },
>         { }
>  };
>
> diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c
> index b75a174489..e34f532cd6 100644
> --- a/drivers/video/rockchip/rk_hdmi.c
> +++ b/drivers/video/rockchip/rk_hdmi.c
> @@ -83,6 +83,7 @@ int rk_hdmi_of_to_plat(struct udevice *dev)
>         struct rk_hdmi_priv *priv = dev_get_priv(dev);
>         struct dw_hdmi *hdmi = &priv->hdmi;
>
> +       hdmi->data = (const struct dw_hdmi_plat_data *)dev_get_driver_data(dev);
>         hdmi->ioaddr = (ulong)dev_read_addr(dev);
>         hdmi->mpll_cfg = rockchip_mpll_cfg;
>         hdmi->phy_cfg = rockchip_phy_config;
> @@ -90,7 +91,6 @@ int rk_hdmi_of_to_plat(struct udevice *dev)
>         /* hdmi->i2c_clk_{high,low} are set up by the SoC driver */
>
>         hdmi->reg_io_width = 4;
> -       hdmi->phy_set = dw_hdmi_phy_cfg;
>
>         priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
>
> diff --git a/drivers/video/sunxi/sunxi_dw_hdmi.c b/drivers/video/sunxi/sunxi_dw_hdmi.c
> index 0324a050d0..4b67a1614e 100644
> --- a/drivers/video/sunxi/sunxi_dw_hdmi.c
> +++ b/drivers/video/sunxi/sunxi_dw_hdmi.c
> @@ -369,6 +369,15 @@ static int sunxi_dw_hdmi_probe(struct udevice *dev)
>         return 0;
>  }
>
> +static const struct dw_hdmi_phy_ops dw_hdmi_sunxi_phy_ops = {
> +       .phy_set = sunxi_dw_hdmi_phy_cfg,
> +};
> +
> +static const struct dw_hdmi_plat_data dw_hdmi_sunxi_plat_data = {
> +       .phy_force_vendor = true,
> +       .phy_ops = &dw_hdmi_sunxi_phy_ops,
> +};
> +
>  static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
>  {
>         struct sunxi_dw_hdmi_priv *priv = dev_get_priv(dev);
> @@ -379,7 +388,7 @@ static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
>         hdmi->i2c_clk_high = 0xd8;
>         hdmi->i2c_clk_low = 0xfe;
>         hdmi->reg_io_width = 1;
> -       hdmi->phy_set = sunxi_dw_hdmi_phy_cfg;
> +       hdmi->data = &dw_hdmi_sunxi_plat_data;
>
>         ret = reset_get_bulk(dev, &priv->resets);
>         if (ret)
> diff --git a/include/dw_hdmi.h b/include/dw_hdmi.h
> index 8acae3839f..4ad8b39f84 100644
> --- a/include/dw_hdmi.h
> +++ b/include/dw_hdmi.h
> @@ -534,6 +534,17 @@ struct hdmi_data_info {
>         struct hdmi_vmode video_mode;
>  };
>
> +struct dw_hdmi;
> +
> +struct dw_hdmi_phy_ops {
> +       int (*phy_set)(struct dw_hdmi *hdmi, uint mpixelclock);
> +};
> +
> +struct dw_hdmi_plat_data {
> +       bool phy_force_vendor;
> +       const struct dw_hdmi_phy_ops *phy_ops;
> +};
> +
>  struct dw_hdmi {
>         ulong ioaddr;
>         const struct hdmi_mpll_config *mpll_cfg;
> @@ -543,8 +554,9 @@ struct dw_hdmi {
>         u8 reg_io_width;
>         struct hdmi_data_info hdmi_data;
>         struct udevice *ddc_bus;
> +       const struct dw_hdmi_phy_ops *ops;

??

We should use phy.h I believe. Having said that, it sorely needs a
proper conversion to driver model.

> +       const struct dw_hdmi_plat_data *data;
>
> -       int (*phy_set)(struct dw_hdmi *hdmi, uint mpixelclock);
>         void (*write_reg)(struct dw_hdmi *hdmi, u8 val, int offset);
>         u8 (*read_reg)(struct dw_hdmi *hdmi, int offset);
>  };
> --
> 2.25.1
>

Regards,
Simon

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

* Re: [PATCH 02/17] video: dw_hdmi: Add Vendor PHY handling
  2023-12-13 19:50   ` Simon Glass
@ 2023-12-14  4:44     ` Jagan Teki
  0 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-14  4:44 UTC (permalink / raw)
  To: Simon Glass
  Cc: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Heiko Stuebner, u-boot, Da Xue, Jagan Teki

Hi Simon,

On Thu, Dec 14, 2023 at 1:21 AM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Jagan,
>
> On Mon, 11 Dec 2023 at 02:00, Jagan Teki <jagan@amarulasolutions.com> wrote:
> >
> > From: Jagan Teki <jagan@edgeble.ai>
> >
> > DW HDMI support Vendor PHY like Rockchip RK3328 Inno HDMI PHY.
> >
> > Extend the vendor phy handling by adding platform phy hooks.
> >
> > Signed-off-by: Jagan Teki <jagan@edgeble.ai>
> > ---
> >  drivers/video/dw_hdmi.c              | 29 +++++++++++++++++++++++++++-
> >  drivers/video/meson/meson_dw_hdmi.c  | 11 ++++++++++-
> >  drivers/video/rockchip/rk3399_hdmi.c |  8 +++++++-
> >  drivers/video/rockchip/rk_hdmi.c     |  2 +-
> >  drivers/video/sunxi/sunxi_dw_hdmi.c  | 11 ++++++++++-
> >  include/dw_hdmi.h                    | 14 +++++++++++++-
> >  6 files changed, 69 insertions(+), 6 deletions(-)
> >
>
> Isn't there a PHY framework we should use in U-Boot?

Yes, the driver is using generic PHY.

>
> Regards,
> Sim on
>
> > diff --git a/drivers/video/dw_hdmi.c b/drivers/video/dw_hdmi.c
> > index c4fbb18294..ea12a09407 100644
> > --- a/drivers/video/dw_hdmi.c
> > +++ b/drivers/video/dw_hdmi.c
> > @@ -988,7 +988,7 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
> >
> >         hdmi_av_composer(hdmi, edid);
> >
> > -       ret = hdmi->phy_set(hdmi, edid->pixelclock.typ);
> > +       ret = hdmi->ops->phy_set(hdmi, edid->pixelclock.typ);
> >         if (ret)
> >                 return ret;
> >
> > @@ -1009,10 +1009,37 @@ int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
> >         return 0;
> >  }
> >
> > +static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = {
> > +       .phy_set = dw_hdmi_phy_cfg,
> > +};
> > +
> > +static void dw_hdmi_detect_phy(struct dw_hdmi *hdmi)
> > +{
> > +       if (!hdmi->data)
> > +               return;
> > +
> > +       /* hook Synopsys PHYs ops */
> > +       if (!hdmi->data->phy_force_vendor) {
> > +               hdmi->ops = &dw_hdmi_synopsys_phy_ops;
> > +               return;
> > +       }
> > +
> > +       /* Vendor HDMI PHYs must assign phy_ops in plat_data */
> > +       if (!hdmi->data->phy_ops) {
> > +               printf("Unsupported Vendor HDMI phy_ops\n");
> > +               return;
> > +       }
> > +
> > +       /* hook Vendor HDMI PHYs ops */
> > +       hdmi->ops = hdmi->data->phy_ops;
> > +}
> > +
> >  void dw_hdmi_init(struct dw_hdmi *hdmi)
> >  {
> >         uint ih_mute;
> >
> > +       dw_hdmi_detect_phy(hdmi);
> > +
> >         /*
> >          * boot up defaults are:
> >          * hdmi_ih_mute   = 0x03 (disabled)
> > diff --git a/drivers/video/meson/meson_dw_hdmi.c b/drivers/video/meson/meson_dw_hdmi.c
> > index 5db01904b5..63ca3ac52e 100644
> > --- a/drivers/video/meson/meson_dw_hdmi.c
> > +++ b/drivers/video/meson/meson_dw_hdmi.c
> > @@ -375,6 +375,15 @@ static int meson_dw_hdmi_wait_hpd(struct dw_hdmi *hdmi)
> >         return -ETIMEDOUT;
> >  }
> >
> > +static const struct dw_hdmi_phy_ops dw_hdmi_meson_phy_ops = {
> > +       .phy_set = meson_dw_hdmi_phy_cfg,
> > +};
> > +
> > +static const struct dw_hdmi_plat_data dw_hdmi_meson_plat_data = {
> > +       .phy_force_vendor = true,
> > +       .phy_ops = &dw_hdmi_meson_phy_ops,
> > +};
> > +
> >  static int meson_dw_hdmi_probe(struct udevice *dev)
> >  {
> >         struct meson_dw_hdmi *priv = dev_get_priv(dev);
> > @@ -397,7 +406,7 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
> >
> >         priv->hdmi.hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
> >         priv->hdmi.hdmi_data.enc_in_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
> > -       priv->hdmi.phy_set = meson_dw_hdmi_phy_init;
> > +       priv->hdmi.data = &dw_hdmi_meson_plat_data;
> >         if (meson_hdmi_is_compatible(priv, HDMI_COMPATIBLE_G12A))
> >                 priv->hdmi.reg_io_width = 1;
> >         else {
> > diff --git a/drivers/video/rockchip/rk3399_hdmi.c b/drivers/video/rockchip/rk3399_hdmi.c
> > index 3041360c6e..b32139a8a6 100644
> > --- a/drivers/video/rockchip/rk3399_hdmi.c
> > +++ b/drivers/video/rockchip/rk3399_hdmi.c
> > @@ -64,8 +64,14 @@ static const struct dm_display_ops rk3399_hdmi_ops = {
> >         .enable = rk3399_hdmi_enable,
> >  };
> >
> > +static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
> > +};
> > +
> >  static const struct udevice_id rk3399_hdmi_ids[] = {
> > -       { .compatible = "rockchip,rk3399-dw-hdmi" },
> > +       {
> > +               .compatible = "rockchip,rk3399-dw-hdmi",
> > +               .data = (ulong)&rk3399_hdmi_drv_data
> > +       },
> >         { }
> >  };
> >
> > diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c
> > index b75a174489..e34f532cd6 100644
> > --- a/drivers/video/rockchip/rk_hdmi.c
> > +++ b/drivers/video/rockchip/rk_hdmi.c
> > @@ -83,6 +83,7 @@ int rk_hdmi_of_to_plat(struct udevice *dev)
> >         struct rk_hdmi_priv *priv = dev_get_priv(dev);
> >         struct dw_hdmi *hdmi = &priv->hdmi;
> >
> > +       hdmi->data = (const struct dw_hdmi_plat_data *)dev_get_driver_data(dev);
> >         hdmi->ioaddr = (ulong)dev_read_addr(dev);
> >         hdmi->mpll_cfg = rockchip_mpll_cfg;
> >         hdmi->phy_cfg = rockchip_phy_config;
> > @@ -90,7 +91,6 @@ int rk_hdmi_of_to_plat(struct udevice *dev)
> >         /* hdmi->i2c_clk_{high,low} are set up by the SoC driver */
> >
> >         hdmi->reg_io_width = 4;
> > -       hdmi->phy_set = dw_hdmi_phy_cfg;
> >
> >         priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
> >
> > diff --git a/drivers/video/sunxi/sunxi_dw_hdmi.c b/drivers/video/sunxi/sunxi_dw_hdmi.c
> > index 0324a050d0..4b67a1614e 100644
> > --- a/drivers/video/sunxi/sunxi_dw_hdmi.c
> > +++ b/drivers/video/sunxi/sunxi_dw_hdmi.c
> > @@ -369,6 +369,15 @@ static int sunxi_dw_hdmi_probe(struct udevice *dev)
> >         return 0;
> >  }
> >
> > +static const struct dw_hdmi_phy_ops dw_hdmi_sunxi_phy_ops = {
> > +       .phy_set = sunxi_dw_hdmi_phy_cfg,
> > +};
> > +
> > +static const struct dw_hdmi_plat_data dw_hdmi_sunxi_plat_data = {
> > +       .phy_force_vendor = true,
> > +       .phy_ops = &dw_hdmi_sunxi_phy_ops,
> > +};
> > +
> >  static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
> >  {
> >         struct sunxi_dw_hdmi_priv *priv = dev_get_priv(dev);
> > @@ -379,7 +388,7 @@ static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
> >         hdmi->i2c_clk_high = 0xd8;
> >         hdmi->i2c_clk_low = 0xfe;
> >         hdmi->reg_io_width = 1;
> > -       hdmi->phy_set = sunxi_dw_hdmi_phy_cfg;
> > +       hdmi->data = &dw_hdmi_sunxi_plat_data;
> >
> >         ret = reset_get_bulk(dev, &priv->resets);
> >         if (ret)
> > diff --git a/include/dw_hdmi.h b/include/dw_hdmi.h
> > index 8acae3839f..4ad8b39f84 100644
> > --- a/include/dw_hdmi.h
> > +++ b/include/dw_hdmi.h
> > @@ -534,6 +534,17 @@ struct hdmi_data_info {
> >         struct hdmi_vmode video_mode;
> >  };
> >
> > +struct dw_hdmi;
> > +
> > +struct dw_hdmi_phy_ops {
> > +       int (*phy_set)(struct dw_hdmi *hdmi, uint mpixelclock);
> > +};
> > +
> > +struct dw_hdmi_plat_data {
> > +       bool phy_force_vendor;
> > +       const struct dw_hdmi_phy_ops *phy_ops;
> > +};
> > +
> >  struct dw_hdmi {
> >         ulong ioaddr;
> >         const struct hdmi_mpll_config *mpll_cfg;
> > @@ -543,8 +554,9 @@ struct dw_hdmi {
> >         u8 reg_io_width;
> >         struct hdmi_data_info hdmi_data;
> >         struct udevice *ddc_bus;
> > +       const struct dw_hdmi_phy_ops *ops;
>
> ??
>
> We should use phy.h I believe. Having said that, it sorely needs a
> proper conversion to driver model.

As I said, the driver uses generic phy with phy_ops. The above ops are
dw hdmi platform phy ops that driver uses internally for rk3328. DW
HDMI is also available for rk3228, so internal platform phy ops can
vary. The generic phy ops in the driver will call platform phy ops via
driver data.

Jagan.

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

* Re: [PATCH 00/17] video: dw_hdmi: Support Vendor PHY
  2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
@ 2023-12-15  6:36   ` Jagan Teki
  2023-12-11  8:59 ` [PATCH 02/17] video: dw_hdmi: Add Vendor PHY handling Jagan Teki
                     ` (16 subsequent siblings)
  17 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-15  6:36 UTC (permalink / raw)
  To: Heiko Stuebner, Kever Yang, Anatolij Gustschin
  Cc: u-boot, Da Xue, Neil Armstrong, Andre Przywara, Simon Glass,
	open list:ARM/Rockchip SoC...

Hi Heiko/Kerver/Anatoloj,

On Mon, Dec 11, 2023 at 2:30 PM Jagan Teki <jagan@amarulasolutions.com> wrote:
>
> Unlike RK3399, Sunxi/Meson DW HDMI the new Rockchip SoC Rk3328 would
> support external vendor PHY with DW HDMI chip.
>
> Support this vendor PHY by adding new platform PHY ops via DW HDMI
> driver and call the respective generic phy from platform driver code.
>
> This series tested in RK3328 with 1080p (1920x1080) resolution.
>
> Patch 0001/0005: Support Vendor PHY
> Patch 0006/0008: VOP extension for win, dsp offsets
> Patch 0009/0010: RK3328 VOP, HDMI clocks
> Patch 0011:      Rockchip Inno HDMI PHY
> Patch 0012:      RK3328 HDMI driver
> Patch 0013:      RK3328 VOP driver
> Patch 0014/0017: Enable HDMI Out for RK3328
>
> Importent:
> One pontential issues is that Linux HDMI out on RK3328 has effected by
> this patchset as I wouldn't find any relation or clue.
>
> [    0.752016] Loading compiled-in X.509 certificates
> [    0.787796] inno_hdmi_phy_rk3328_clk_recalc_rate: parent 24000000
> [    0.788391] inno-hdmi-phy ff430000.phy: inno_hdmi_phy_rk3328_clk_recalc_rate rate 148500000 vco 148500000
> [    0.798353] rockchip-drm display-subsystem: bound ff370000.vop (ops vop_component_ops)
> [    0.799403] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-0v9 not found, using dummy regulator
> [    0.800288] rk_iommu ff373f00.iommu: Enable stall request timed out, status: 0x00004b
> [    0.801131] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-1v8 not found, using dummy regulator
> [    0.802056] rk_iommu ff373f00.iommu: Disable paging request timed out, status: 0x00004b
> [    0.803233] dwhdmi-rockchip ff3c0000.hdmi: Detected HDMI TX controller v2.11a with HDCP (inno_dw_hdmi_phy2)
> [    0.805355] dwhdmi-rockchip ff3c0000.hdmi: registered DesignWare HDMI I2C bus driver
> [    0.808769] rockchip-drm display-subsystem: bound ff3c0000.hdmi (ops dw_hdmi_rockchip_ops)
> [    0.810869] [drm] Initialized rockchip 1.0.0 20140818 for display-subsystem on minor 0
>
> The only way I can use Linux HDMI by disabling IOMMU or support
> disable-iommu link for RK3328 via DT [1].
>
> [1] https://www.spinics.net/lists/devicetree/msg605124.html

Is anyone aware of this issue? I did post the patches for Linux IOMMU
but seems not a proper solution. Any suggestions?

Thanks,
Jagan.

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

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

* Re: [PATCH 00/17] video: dw_hdmi: Support Vendor PHY
@ 2023-12-15  6:36   ` Jagan Teki
  0 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-15  6:36 UTC (permalink / raw)
  To: Heiko Stuebner, Kever Yang, Anatolij Gustschin
  Cc: u-boot, Da Xue, Neil Armstrong, Andre Przywara, Simon Glass,
	open list:ARM/Rockchip SoC...

Hi Heiko/Kerver/Anatoloj,

On Mon, Dec 11, 2023 at 2:30 PM Jagan Teki <jagan@amarulasolutions.com> wrote:
>
> Unlike RK3399, Sunxi/Meson DW HDMI the new Rockchip SoC Rk3328 would
> support external vendor PHY with DW HDMI chip.
>
> Support this vendor PHY by adding new platform PHY ops via DW HDMI
> driver and call the respective generic phy from platform driver code.
>
> This series tested in RK3328 with 1080p (1920x1080) resolution.
>
> Patch 0001/0005: Support Vendor PHY
> Patch 0006/0008: VOP extension for win, dsp offsets
> Patch 0009/0010: RK3328 VOP, HDMI clocks
> Patch 0011:      Rockchip Inno HDMI PHY
> Patch 0012:      RK3328 HDMI driver
> Patch 0013:      RK3328 VOP driver
> Patch 0014/0017: Enable HDMI Out for RK3328
>
> Importent:
> One pontential issues is that Linux HDMI out on RK3328 has effected by
> this patchset as I wouldn't find any relation or clue.
>
> [    0.752016] Loading compiled-in X.509 certificates
> [    0.787796] inno_hdmi_phy_rk3328_clk_recalc_rate: parent 24000000
> [    0.788391] inno-hdmi-phy ff430000.phy: inno_hdmi_phy_rk3328_clk_recalc_rate rate 148500000 vco 148500000
> [    0.798353] rockchip-drm display-subsystem: bound ff370000.vop (ops vop_component_ops)
> [    0.799403] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-0v9 not found, using dummy regulator
> [    0.800288] rk_iommu ff373f00.iommu: Enable stall request timed out, status: 0x00004b
> [    0.801131] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-1v8 not found, using dummy regulator
> [    0.802056] rk_iommu ff373f00.iommu: Disable paging request timed out, status: 0x00004b
> [    0.803233] dwhdmi-rockchip ff3c0000.hdmi: Detected HDMI TX controller v2.11a with HDCP (inno_dw_hdmi_phy2)
> [    0.805355] dwhdmi-rockchip ff3c0000.hdmi: registered DesignWare HDMI I2C bus driver
> [    0.808769] rockchip-drm display-subsystem: bound ff3c0000.hdmi (ops dw_hdmi_rockchip_ops)
> [    0.810869] [drm] Initialized rockchip 1.0.0 20140818 for display-subsystem on minor 0
>
> The only way I can use Linux HDMI by disabling IOMMU or support
> disable-iommu link for RK3328 via DT [1].
>
> [1] https://www.spinics.net/lists/devicetree/msg605124.html

Is anyone aware of this issue? I did post the patches for Linux IOMMU
but seems not a proper solution. Any suggestions?

Thanks,
Jagan.

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

* Re: [PATCH 00/17] video: dw_hdmi: Support Vendor PHY
  2023-12-15  6:36   ` Jagan Teki
@ 2023-12-15  7:13     ` Kever Yang
  -1 siblings, 0 replies; 32+ messages in thread
From: Kever Yang @ 2023-12-15  7:13 UTC (permalink / raw)
  To: Jagan Teki, Heiko Stuebner, Anatolij Gustschin
  Cc: u-boot, Da Xue, Neil Armstrong, Andre Przywara, Simon Glass,
	open list:ARM/Rockchip SoC..., 薛小明,
	操瑞杰, 闫孝军

Hi Jagan,

On 2023/12/15 14:36, Jagan Teki wrote:
> Hi Heiko/Kerver/Anatoloj,
>
> On Mon, Dec 11, 2023 at 2:30 PM Jagan Teki <jagan@amarulasolutions.com> wrote:
>> Unlike RK3399, Sunxi/Meson DW HDMI the new Rockchip SoC Rk3328 would
>> support external vendor PHY with DW HDMI chip.
>>
>> Support this vendor PHY by adding new platform PHY ops via DW HDMI
>> driver and call the respective generic phy from platform driver code.
>>
>> This series tested in RK3328 with 1080p (1920x1080) resolution.
>>
>> Patch 0001/0005: Support Vendor PHY
>> Patch 0006/0008: VOP extension for win, dsp offsets
>> Patch 0009/0010: RK3328 VOP, HDMI clocks
>> Patch 0011:      Rockchip Inno HDMI PHY
>> Patch 0012:      RK3328 HDMI driver
>> Patch 0013:      RK3328 VOP driver
>> Patch 0014/0017: Enable HDMI Out for RK3328
>>
>> Importent:
>> One pontential issues is that Linux HDMI out on RK3328 has effected by
>> this patchset as I wouldn't find any relation or clue.
>>
>> [    0.752016] Loading compiled-in X.509 certificates
>> [    0.787796] inno_hdmi_phy_rk3328_clk_recalc_rate: parent 24000000
>> [    0.788391] inno-hdmi-phy ff430000.phy: inno_hdmi_phy_rk3328_clk_recalc_rate rate 148500000 vco 148500000
>> [    0.798353] rockchip-drm display-subsystem: bound ff370000.vop (ops vop_component_ops)
>> [    0.799403] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-0v9 not found, using dummy regulator
>> [    0.800288] rk_iommu ff373f00.iommu: Enable stall request timed out, status: 0x00004b
>> [    0.801131] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-1v8 not found, using dummy regulator
>> [    0.802056] rk_iommu ff373f00.iommu: Disable paging request timed out, status: 0x00004b
>> [    0.803233] dwhdmi-rockchip ff3c0000.hdmi: Detected HDMI TX controller v2.11a with HDCP (inno_dw_hdmi_phy2)
>> [    0.805355] dwhdmi-rockchip ff3c0000.hdmi: registered DesignWare HDMI I2C bus driver
>> [    0.808769] rockchip-drm display-subsystem: bound ff3c0000.hdmi (ops dw_hdmi_rockchip_ops)
>> [    0.810869] [drm] Initialized rockchip 1.0.0 20140818 for display-subsystem on minor 0
>>
>> The only way I can use Linux HDMI by disabling IOMMU or support
>> disable-iommu link for RK3328 via DT [1].
>>
>> [1] https://www.spinics.net/lists/devicetree/msg605124.html
> Is anyone aware of this issue? I did post the patches for Linux IOMMU
> but seems not a proper solution. Any suggestions?

I'm not expert in HDMI/VOP, so I can't provide a suitable solution in 
the kernel,

but here is the reason why we need patch to workaround the issue in the 
kernel:

- The VOP driver working in U-Boot is non-IOMMU mode, and the VOP access 
DDR by physical address;

- The VOP driver working in kernel with IOMMU enabled(by default), the 
VOP access DDR with virtual address(by IOMMU);

- The VOP is keep working in kernel before kernel VOP driver is enabled, 
and the IOMMU driver will be enabled by

    the Linux PM framework, since the IOMMU is not correctly configured 
at this point, the VOP will access unknown

     space(the original physical address in U-Boot) convert by IOMMU;

So we need to disable the IOMMU temporary in kernel startup before VOP 
driver is enabled.


Thanks,

- Kever

>
> Thanks,
> Jagan.

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

* Re: [PATCH 00/17] video: dw_hdmi: Support Vendor PHY
@ 2023-12-15  7:13     ` Kever Yang
  0 siblings, 0 replies; 32+ messages in thread
From: Kever Yang @ 2023-12-15  7:13 UTC (permalink / raw)
  To: Jagan Teki, Heiko Stuebner, Anatolij Gustschin
  Cc: u-boot, Da Xue, Neil Armstrong, Andre Przywara, Simon Glass,
	open list:ARM/Rockchip SoC..., 薛小明,
	操瑞杰, 闫孝军

Hi Jagan,

On 2023/12/15 14:36, Jagan Teki wrote:
> Hi Heiko/Kerver/Anatoloj,
>
> On Mon, Dec 11, 2023 at 2:30 PM Jagan Teki <jagan@amarulasolutions.com> wrote:
>> Unlike RK3399, Sunxi/Meson DW HDMI the new Rockchip SoC Rk3328 would
>> support external vendor PHY with DW HDMI chip.
>>
>> Support this vendor PHY by adding new platform PHY ops via DW HDMI
>> driver and call the respective generic phy from platform driver code.
>>
>> This series tested in RK3328 with 1080p (1920x1080) resolution.
>>
>> Patch 0001/0005: Support Vendor PHY
>> Patch 0006/0008: VOP extension for win, dsp offsets
>> Patch 0009/0010: RK3328 VOP, HDMI clocks
>> Patch 0011:      Rockchip Inno HDMI PHY
>> Patch 0012:      RK3328 HDMI driver
>> Patch 0013:      RK3328 VOP driver
>> Patch 0014/0017: Enable HDMI Out for RK3328
>>
>> Importent:
>> One pontential issues is that Linux HDMI out on RK3328 has effected by
>> this patchset as I wouldn't find any relation or clue.
>>
>> [    0.752016] Loading compiled-in X.509 certificates
>> [    0.787796] inno_hdmi_phy_rk3328_clk_recalc_rate: parent 24000000
>> [    0.788391] inno-hdmi-phy ff430000.phy: inno_hdmi_phy_rk3328_clk_recalc_rate rate 148500000 vco 148500000
>> [    0.798353] rockchip-drm display-subsystem: bound ff370000.vop (ops vop_component_ops)
>> [    0.799403] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-0v9 not found, using dummy regulator
>> [    0.800288] rk_iommu ff373f00.iommu: Enable stall request timed out, status: 0x00004b
>> [    0.801131] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-1v8 not found, using dummy regulator
>> [    0.802056] rk_iommu ff373f00.iommu: Disable paging request timed out, status: 0x00004b
>> [    0.803233] dwhdmi-rockchip ff3c0000.hdmi: Detected HDMI TX controller v2.11a with HDCP (inno_dw_hdmi_phy2)
>> [    0.805355] dwhdmi-rockchip ff3c0000.hdmi: registered DesignWare HDMI I2C bus driver
>> [    0.808769] rockchip-drm display-subsystem: bound ff3c0000.hdmi (ops dw_hdmi_rockchip_ops)
>> [    0.810869] [drm] Initialized rockchip 1.0.0 20140818 for display-subsystem on minor 0
>>
>> The only way I can use Linux HDMI by disabling IOMMU or support
>> disable-iommu link for RK3328 via DT [1].
>>
>> [1] https://www.spinics.net/lists/devicetree/msg605124.html
> Is anyone aware of this issue? I did post the patches for Linux IOMMU
> but seems not a proper solution. Any suggestions?

I'm not expert in HDMI/VOP, so I can't provide a suitable solution in 
the kernel,

but here is the reason why we need patch to workaround the issue in the 
kernel:

- The VOP driver working in U-Boot is non-IOMMU mode, and the VOP access 
DDR by physical address;

- The VOP driver working in kernel with IOMMU enabled(by default), the 
VOP access DDR with virtual address(by IOMMU);

- The VOP is keep working in kernel before kernel VOP driver is enabled, 
and the IOMMU driver will be enabled by

    the Linux PM framework, since the IOMMU is not correctly configured 
at this point, the VOP will access unknown

     space(the original physical address in U-Boot) convert by IOMMU;

So we need to disable the IOMMU temporary in kernel startup before VOP 
driver is enabled.


Thanks,

- Kever

>
> Thanks,
> Jagan.

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

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

* Re: [PATCH 13/17] video: rockchip: Add rk3328 vop support
  2023-12-11  8:59 ` [PATCH 13/17] video: rockchip: Add rk3328 vop support Jagan Teki
@ 2023-12-16 22:45   ` Johan Jonker
  2023-12-18 12:40     ` Jagan Teki
  0 siblings, 1 reply; 32+ messages in thread
From: Johan Jonker @ 2023-12-16 22:45 UTC (permalink / raw)
  To: Jagan Teki, Anatolij Gustschin, Neil Armstrong, Andre Przywara,
	Kever Yang, Simon Glass, Heiko Stuebner
  Cc: u-boot, Da Xue, Jagan Teki

Hi Jagan,

In  your patch U-boot users must add a new file for each new Rockchip SoC.

With the VOP2 introduction the VOP1 structures and functions are frozen/stabilized.

My proposal would be to use a file simular to Linux rockchip_vop_reg.c and port it to U-boot as is done in the manufacturer tree.

Together with a simple basic rockchip_vop.c to start with.

Not sure if we need a kind of DRM frame work.

Question: What do the U-boot maintainers think of this DRM implementation in use by Rockchip. Is that a route that useful for mainline?

Let me know your ideas.

Johan


On 12/11/23 09:59, Jagan Teki wrote:
> From: Jagan Teki <jagan@edgeble.ai>
>
> Add support for Rockchip RK3328 VOP.
>
> Signed-off-by: Jagan Teki <jagan@edgeble.ai>
> ---
>  drivers/video/rockchip/Makefile     |  1 +
>  drivers/video/rockchip/rk3328_vop.c | 66 +++++++++++++++++++++++++++++
>  2 files changed, 67 insertions(+)
>  create mode 100644 drivers/video/rockchip/rk3328_vop.c
>
> diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
> index 4991303c73..f55beceebf 100644
> --- a/drivers/video/rockchip/Makefile
> +++ b/drivers/video/rockchip/Makefile
> @@ -6,6 +6,7 @@
>  ifdef CONFIG_VIDEO_ROCKCHIP
>  obj-y += rk_vop.o
>  obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288_vop.o
> +obj-$(CONFIG_ROCKCHIP_RK3328) += rk3328_vop.o
>  obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399_vop.o
>  obj-$(CONFIG_DISPLAY_ROCKCHIP_EDP) += rk_edp.o
>  obj-$(CONFIG_DISPLAY_ROCKCHIP_LVDS) += rk_lvds.o
> diff --git a/drivers/video/rockchip/rk3328_vop.c b/drivers/video/rockchip/rk3328_vop.c
> new file mode 100644
> index 0000000000..2512314e64
> --- /dev/null
> +++ b/drivers/video/rockchip/rk3328_vop.c
> @@ -0,0 +1,66 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2023 Edgeble AI Technologies Pvt. Ltd.
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <video.h>
> +#include <asm/io.h>
> +#include "rk_vop.h"
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static void rk3328_set_pin_polarity(struct udevice *dev,
> +				    enum vop_modes mode, u32 polarity)
> +{
> +	struct rk_vop_priv *priv = dev_get_priv(dev);
> +	struct rk3288_vop *regs = priv->regs;
> +
> +	switch (mode) {
> +	case VOP_MODE_HDMI:
> +		clrsetbits_le32(&regs->dsp_ctrl1,
> +				M_RK3399_DSP_HDMI_POL,
> +				V_RK3399_DSP_HDMI_POL(polarity));
> +		break;
> +	default:
> +		debug("%s: unsupported output mode %x\n", __func__, mode);
> +	}
> +}
> +
> +static int rk3328_vop_probe(struct udevice *dev)
> +{
> +	/* Before relocation we don't need to do anything */
> +	if (!(gd->flags & GD_FLG_RELOC))
> +		return 0;
> +
> +	return rk_vop_probe(dev);
> +}
> +
> +struct rkvop_driverdata rk3328_driverdata = {
> +	.dsp_offset = 0x490,
> +	.win_offset = 0xd0,
> +	.features = VOP_FEATURE_OUTPUT_10BIT,
> +	.set_pin_polarity = rk3328_set_pin_polarity,
> +};
> +
> +static const struct udevice_id rk3328_vop_ids[] = {
> +	{
> +		.compatible = "rockchip,rk3328-vop",
> +		.data = (ulong)&rk3328_driverdata
> +	},
> +	{ /* sentile */ }
> +};
> +
> +static const struct video_ops rk3328_vop_ops = {
> +};
> +
> +U_BOOT_DRIVER(rk3328_vop) = {
> +	.name	= "rk3328_vop",
> +	.id	= UCLASS_VIDEO,
> +	.of_match = rk3328_vop_ids,
> +	.ops	= &rk3328_vop_ops,
> +	.bind	= rk_vop_bind,
> +	.probe	= rk3328_vop_probe,
> +	.priv_auto	= sizeof(struct rk_vop_priv),
> +};

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

* Re: [PATCH 13/17] video: rockchip: Add rk3328 vop support
  2023-12-16 22:45   ` Johan Jonker
@ 2023-12-18 12:40     ` Jagan Teki
  0 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-18 12:40 UTC (permalink / raw)
  To: Johan Jonker
  Cc: Anatolij Gustschin, Neil Armstrong, Andre Przywara, Kever Yang,
	Simon Glass, Heiko Stuebner, u-boot, Da Xue, Jagan Teki

Please don't top-post.

On Sun, Dec 17, 2023 at 4:15 AM Johan Jonker <jbx6244@yandex.com> wrote:
>
> Hi Jagan,
>
> In  your patch U-boot users must add a new file for each new Rockchip SoC.
>
> With the VOP2 introduction the VOP1 structures and functions are frozen/stabilized.
>
> My proposal would be to use a file simular to Linux rockchip_vop_reg.c and port it to U-boot as is done in the manufacturer tree.
>
> Together with a simple basic rockchip_vop.c to start with.
>
> Not sure if we need a kind of DRM frame work.
>
> Question: What do the U-boot maintainers think of this DRM implementation in use by Rockchip. Is that a route that useful for mainline?
>
> Let me know your ideas.

Yes, I got your point-based rockchip-bsp tree of DRM. Technically it
wouldn't required as we have created this structure before and more
likely the new RK SoCs like RK3568, RK3588 are working on this tree as
well. Why do we need DRM framework as long as this seems suitable?

Jagan.

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

* Re: [PATCH 00/17] video: dw_hdmi: Support Vendor PHY
  2023-12-15  7:13     ` Kever Yang
@ 2023-12-18 13:53       ` Robin Murphy
  -1 siblings, 0 replies; 32+ messages in thread
From: Robin Murphy @ 2023-12-18 13:53 UTC (permalink / raw)
  To: Kever Yang, Jagan Teki, Heiko Stuebner, Anatolij Gustschin
  Cc: u-boot, Da Xue, Neil Armstrong, Andre Przywara, Simon Glass,
	open list:ARM/Rockchip SoC..., 薛小明,
	操瑞杰, 闫孝军

On 2023-12-15 7:13 am, Kever Yang wrote:
> Hi Jagan,
> 
> On 2023/12/15 14:36, Jagan Teki wrote:
>> Hi Heiko/Kerver/Anatoloj,
>>
>> On Mon, Dec 11, 2023 at 2:30 PM Jagan Teki 
>> <jagan@amarulasolutions.com> wrote:
>>> Unlike RK3399, Sunxi/Meson DW HDMI the new Rockchip SoC Rk3328 would
>>> support external vendor PHY with DW HDMI chip.
>>>
>>> Support this vendor PHY by adding new platform PHY ops via DW HDMI
>>> driver and call the respective generic phy from platform driver code.
>>>
>>> This series tested in RK3328 with 1080p (1920x1080) resolution.
>>>
>>> Patch 0001/0005: Support Vendor PHY
>>> Patch 0006/0008: VOP extension for win, dsp offsets
>>> Patch 0009/0010: RK3328 VOP, HDMI clocks
>>> Patch 0011:      Rockchip Inno HDMI PHY
>>> Patch 0012:      RK3328 HDMI driver
>>> Patch 0013:      RK3328 VOP driver
>>> Patch 0014/0017: Enable HDMI Out for RK3328
>>>
>>> Importent:
>>> One pontential issues is that Linux HDMI out on RK3328 has effected by
>>> this patchset as I wouldn't find any relation or clue.
>>>
>>> [    0.752016] Loading compiled-in X.509 certificates
>>> [    0.787796] inno_hdmi_phy_rk3328_clk_recalc_rate: parent 24000000
>>> [    0.788391] inno-hdmi-phy ff430000.phy: 
>>> inno_hdmi_phy_rk3328_clk_recalc_rate rate 148500000 vco 148500000
>>> [    0.798353] rockchip-drm display-subsystem: bound ff370000.vop 
>>> (ops vop_component_ops)
>>> [    0.799403] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-0v9 not 
>>> found, using dummy regulator
>>> [    0.800288] rk_iommu ff373f00.iommu: Enable stall request timed 
>>> out, status: 0x00004b
>>> [    0.801131] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-1v8 not 
>>> found, using dummy regulator
>>> [    0.802056] rk_iommu ff373f00.iommu: Disable paging request timed 
>>> out, status: 0x00004b
>>> [    0.803233] dwhdmi-rockchip ff3c0000.hdmi: Detected HDMI TX 
>>> controller v2.11a with HDCP (inno_dw_hdmi_phy2)
>>> [    0.805355] dwhdmi-rockchip ff3c0000.hdmi: registered DesignWare 
>>> HDMI I2C bus driver
>>> [    0.808769] rockchip-drm display-subsystem: bound ff3c0000.hdmi 
>>> (ops dw_hdmi_rockchip_ops)
>>> [    0.810869] [drm] Initialized rockchip 1.0.0 20140818 for 
>>> display-subsystem on minor 0
>>>
>>> The only way I can use Linux HDMI by disabling IOMMU or support
>>> disable-iommu link for RK3328 via DT [1].
>>>
>>> [1] https://www.spinics.net/lists/devicetree/msg605124.html
>> Is anyone aware of this issue? I did post the patches for Linux IOMMU
>> but seems not a proper solution. Any suggestions?
> 
> I'm not expert in HDMI/VOP, so I can't provide a suitable solution in 
> the kernel,
> 
> but here is the reason why we need patch to workaround the issue in the 
> kernel:
> 
> - The VOP driver working in U-Boot is non-IOMMU mode, and the VOP access 
> DDR by physical address;
> 
> - The VOP driver working in kernel with IOMMU enabled(by default), the 
> VOP access DDR with virtual address(by IOMMU);
> 
> - The VOP is keep working in kernel before kernel VOP driver is enabled, 
> and the IOMMU driver will be enabled by
> 
>     the Linux PM framework, since the IOMMU is not correctly configured 
> at this point, the VOP will access unknown
> 
>      space(the original physical address in U-Boot) convert by IOMMU;
> 
> So we need to disable the IOMMU temporary in kernel startup before VOP 
> driver is enabled.

If U-Boot isn't handing off an active framebuffer, then it should be 
U-Boot's responsibility to stop the VOP before it exits; if on the other 
hand it is, then it can now use the "iommu-addresses" DT property (see 
the reserved-memory schema) on the framebuffer region, and we should 
just need a bit of work in the IOMMU driver to ensure that is respected 
during the period between the IOMMU initialising and the Linux VOP 
driver subsequently taking over (i.e. so it won't get stuck on an 
unexpected page fault as seems to be happening above). The IOMMU aspect 
of that ought to be fairly straightforward; the trickier part might be 
the runtime PM aspect to ensure the IOMMU doesn't let itself go idle and 
actually turn anything off during that period. I also still think that 
doing the full rk_iommu_disable() upon runtime suspend is wrong, but 
that's more of a thing which confounds the underlying issue here, rather 
than being the problem in itself.

Thanks,
Robin.

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

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

* Re: [PATCH 00/17] video: dw_hdmi: Support Vendor PHY
@ 2023-12-18 13:53       ` Robin Murphy
  0 siblings, 0 replies; 32+ messages in thread
From: Robin Murphy @ 2023-12-18 13:53 UTC (permalink / raw)
  To: Kever Yang, Jagan Teki, Heiko Stuebner, Anatolij Gustschin
  Cc: u-boot, Da Xue, Neil Armstrong, Andre Przywara, Simon Glass,
	open list:ARM/Rockchip SoC..., 薛小明,
	操瑞杰, 闫孝军

On 2023-12-15 7:13 am, Kever Yang wrote:
> Hi Jagan,
> 
> On 2023/12/15 14:36, Jagan Teki wrote:
>> Hi Heiko/Kerver/Anatoloj,
>>
>> On Mon, Dec 11, 2023 at 2:30 PM Jagan Teki 
>> <jagan@amarulasolutions.com> wrote:
>>> Unlike RK3399, Sunxi/Meson DW HDMI the new Rockchip SoC Rk3328 would
>>> support external vendor PHY with DW HDMI chip.
>>>
>>> Support this vendor PHY by adding new platform PHY ops via DW HDMI
>>> driver and call the respective generic phy from platform driver code.
>>>
>>> This series tested in RK3328 with 1080p (1920x1080) resolution.
>>>
>>> Patch 0001/0005: Support Vendor PHY
>>> Patch 0006/0008: VOP extension for win, dsp offsets
>>> Patch 0009/0010: RK3328 VOP, HDMI clocks
>>> Patch 0011:      Rockchip Inno HDMI PHY
>>> Patch 0012:      RK3328 HDMI driver
>>> Patch 0013:      RK3328 VOP driver
>>> Patch 0014/0017: Enable HDMI Out for RK3328
>>>
>>> Importent:
>>> One pontential issues is that Linux HDMI out on RK3328 has effected by
>>> this patchset as I wouldn't find any relation or clue.
>>>
>>> [    0.752016] Loading compiled-in X.509 certificates
>>> [    0.787796] inno_hdmi_phy_rk3328_clk_recalc_rate: parent 24000000
>>> [    0.788391] inno-hdmi-phy ff430000.phy: 
>>> inno_hdmi_phy_rk3328_clk_recalc_rate rate 148500000 vco 148500000
>>> [    0.798353] rockchip-drm display-subsystem: bound ff370000.vop 
>>> (ops vop_component_ops)
>>> [    0.799403] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-0v9 not 
>>> found, using dummy regulator
>>> [    0.800288] rk_iommu ff373f00.iommu: Enable stall request timed 
>>> out, status: 0x00004b
>>> [    0.801131] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-1v8 not 
>>> found, using dummy regulator
>>> [    0.802056] rk_iommu ff373f00.iommu: Disable paging request timed 
>>> out, status: 0x00004b
>>> [    0.803233] dwhdmi-rockchip ff3c0000.hdmi: Detected HDMI TX 
>>> controller v2.11a with HDCP (inno_dw_hdmi_phy2)
>>> [    0.805355] dwhdmi-rockchip ff3c0000.hdmi: registered DesignWare 
>>> HDMI I2C bus driver
>>> [    0.808769] rockchip-drm display-subsystem: bound ff3c0000.hdmi 
>>> (ops dw_hdmi_rockchip_ops)
>>> [    0.810869] [drm] Initialized rockchip 1.0.0 20140818 for 
>>> display-subsystem on minor 0
>>>
>>> The only way I can use Linux HDMI by disabling IOMMU or support
>>> disable-iommu link for RK3328 via DT [1].
>>>
>>> [1] https://www.spinics.net/lists/devicetree/msg605124.html
>> Is anyone aware of this issue? I did post the patches for Linux IOMMU
>> but seems not a proper solution. Any suggestions?
> 
> I'm not expert in HDMI/VOP, so I can't provide a suitable solution in 
> the kernel,
> 
> but here is the reason why we need patch to workaround the issue in the 
> kernel:
> 
> - The VOP driver working in U-Boot is non-IOMMU mode, and the VOP access 
> DDR by physical address;
> 
> - The VOP driver working in kernel with IOMMU enabled(by default), the 
> VOP access DDR with virtual address(by IOMMU);
> 
> - The VOP is keep working in kernel before kernel VOP driver is enabled, 
> and the IOMMU driver will be enabled by
> 
>     the Linux PM framework, since the IOMMU is not correctly configured 
> at this point, the VOP will access unknown
> 
>      space(the original physical address in U-Boot) convert by IOMMU;
> 
> So we need to disable the IOMMU temporary in kernel startup before VOP 
> driver is enabled.

If U-Boot isn't handing off an active framebuffer, then it should be 
U-Boot's responsibility to stop the VOP before it exits; if on the other 
hand it is, then it can now use the "iommu-addresses" DT property (see 
the reserved-memory schema) on the framebuffer region, and we should 
just need a bit of work in the IOMMU driver to ensure that is respected 
during the period between the IOMMU initialising and the Linux VOP 
driver subsequently taking over (i.e. so it won't get stuck on an 
unexpected page fault as seems to be happening above). The IOMMU aspect 
of that ought to be fairly straightforward; the trickier part might be 
the runtime PM aspect to ensure the IOMMU doesn't let itself go idle and 
actually turn anything off during that period. I also still think that 
doing the full rk_iommu_disable() upon runtime suspend is wrong, but 
that's more of a thing which confounds the underlying issue here, rather 
than being the problem in itself.

Thanks,
Robin.

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

* Re: [PATCH 00/17] video: dw_hdmi: Support Vendor PHY
  2023-12-18 13:53       ` Robin Murphy
@ 2023-12-18 18:53         ` Jagan Teki
  -1 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-18 18:53 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Kever Yang, Heiko Stuebner, Anatolij Gustschin, u-boot, Da Xue,
	Neil Armstrong, Andre Przywara, Simon Glass,
	open list:ARM/Rockchip SoC..., 薛小明,
	操瑞杰, 闫孝军

On Mon, Dec 18, 2023 at 7:23 PM Robin Murphy <robin.murphy@arm.com> wrote:
>
> On 2023-12-15 7:13 am, Kever Yang wrote:
> > Hi Jagan,
> >
> > On 2023/12/15 14:36, Jagan Teki wrote:
> >> Hi Heiko/Kerver/Anatoloj,
> >>
> >> On Mon, Dec 11, 2023 at 2:30 PM Jagan Teki
> >> <jagan@amarulasolutions.com> wrote:
> >>> Unlike RK3399, Sunxi/Meson DW HDMI the new Rockchip SoC Rk3328 would
> >>> support external vendor PHY with DW HDMI chip.
> >>>
> >>> Support this vendor PHY by adding new platform PHY ops via DW HDMI
> >>> driver and call the respective generic phy from platform driver code.
> >>>
> >>> This series tested in RK3328 with 1080p (1920x1080) resolution.
> >>>
> >>> Patch 0001/0005: Support Vendor PHY
> >>> Patch 0006/0008: VOP extension for win, dsp offsets
> >>> Patch 0009/0010: RK3328 VOP, HDMI clocks
> >>> Patch 0011:      Rockchip Inno HDMI PHY
> >>> Patch 0012:      RK3328 HDMI driver
> >>> Patch 0013:      RK3328 VOP driver
> >>> Patch 0014/0017: Enable HDMI Out for RK3328
> >>>
> >>> Importent:
> >>> One pontential issues is that Linux HDMI out on RK3328 has effected by
> >>> this patchset as I wouldn't find any relation or clue.
> >>>
> >>> [    0.752016] Loading compiled-in X.509 certificates
> >>> [    0.787796] inno_hdmi_phy_rk3328_clk_recalc_rate: parent 24000000
> >>> [    0.788391] inno-hdmi-phy ff430000.phy:
> >>> inno_hdmi_phy_rk3328_clk_recalc_rate rate 148500000 vco 148500000
> >>> [    0.798353] rockchip-drm display-subsystem: bound ff370000.vop
> >>> (ops vop_component_ops)
> >>> [    0.799403] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-0v9 not
> >>> found, using dummy regulator
> >>> [    0.800288] rk_iommu ff373f00.iommu: Enable stall request timed
> >>> out, status: 0x00004b
> >>> [    0.801131] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-1v8 not
> >>> found, using dummy regulator
> >>> [    0.802056] rk_iommu ff373f00.iommu: Disable paging request timed
> >>> out, status: 0x00004b
> >>> [    0.803233] dwhdmi-rockchip ff3c0000.hdmi: Detected HDMI TX
> >>> controller v2.11a with HDCP (inno_dw_hdmi_phy2)
> >>> [    0.805355] dwhdmi-rockchip ff3c0000.hdmi: registered DesignWare
> >>> HDMI I2C bus driver
> >>> [    0.808769] rockchip-drm display-subsystem: bound ff3c0000.hdmi
> >>> (ops dw_hdmi_rockchip_ops)
> >>> [    0.810869] [drm] Initialized rockchip 1.0.0 20140818 for
> >>> display-subsystem on minor 0
> >>>
> >>> The only way I can use Linux HDMI by disabling IOMMU or support
> >>> disable-iommu link for RK3328 via DT [1].
> >>>
> >>> [1] https://www.spinics.net/lists/devicetree/msg605124.html
> >> Is anyone aware of this issue? I did post the patches for Linux IOMMU
> >> but seems not a proper solution. Any suggestions?
> >
> > I'm not expert in HDMI/VOP, so I can't provide a suitable solution in
> > the kernel,
> >
> > but here is the reason why we need patch to workaround the issue in the
> > kernel:
> >
> > - The VOP driver working in U-Boot is non-IOMMU mode, and the VOP access
> > DDR by physical address;
> >
> > - The VOP driver working in kernel with IOMMU enabled(by default), the
> > VOP access DDR with virtual address(by IOMMU);
> >
> > - The VOP is keep working in kernel before kernel VOP driver is enabled,
> > and the IOMMU driver will be enabled by
> >
> >     the Linux PM framework, since the IOMMU is not correctly configured
> > at this point, the VOP will access unknown
> >
> >      space(the original physical address in U-Boot) convert by IOMMU;
> >
> > So we need to disable the IOMMU temporary in kernel startup before VOP
> > driver is enabled.
>
> If U-Boot isn't handing off an active framebuffer, then it should be
> U-Boot's responsibility to stop the VOP before it exits; if on the other
> hand it is, then it can now use the "iommu-addresses" DT property (see
> the reserved-memory schema) on the framebuffer region, and we should
> just need a bit of work in the IOMMU driver to ensure that is respected
> during the period between the IOMMU initialising and the Linux VOP
> driver subsequently taking over (i.e. so it won't get stuck on an
> unexpected page fault as seems to be happening above). The IOMMU aspect
> of that ought to be fairly straightforward; the trickier part might be
> the runtime PM aspect to ensure the IOMMU doesn't let itself go idle and
> actually turn anything off during that period. I also still think that
> doing the full rk_iommu_disable() upon runtime suspend is wrong, but
> that's more of a thing which confounds the underlying issue here, rather
> than being the problem in itself.

Thanks for your comments. Okay, keeping the Linux IOMMU issue aside I
think whatever change that u-boot makes on VOP has to clear it before
handoff to Linux - so clearing the VOP registers during handoff seems
working. I only wonder why it happens only on RK3328 (RK3399 and
RK3288 seem fine).

I will post the next version with VOP clear during handoff.

Thanks,
Jagan.

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

* Re: [PATCH 00/17] video: dw_hdmi: Support Vendor PHY
@ 2023-12-18 18:53         ` Jagan Teki
  0 siblings, 0 replies; 32+ messages in thread
From: Jagan Teki @ 2023-12-18 18:53 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Kever Yang, Heiko Stuebner, Anatolij Gustschin, u-boot, Da Xue,
	Neil Armstrong, Andre Przywara, Simon Glass,
	open list:ARM/Rockchip SoC..., 薛小明,
	操瑞杰, 闫孝军

On Mon, Dec 18, 2023 at 7:23 PM Robin Murphy <robin.murphy@arm.com> wrote:
>
> On 2023-12-15 7:13 am, Kever Yang wrote:
> > Hi Jagan,
> >
> > On 2023/12/15 14:36, Jagan Teki wrote:
> >> Hi Heiko/Kerver/Anatoloj,
> >>
> >> On Mon, Dec 11, 2023 at 2:30 PM Jagan Teki
> >> <jagan@amarulasolutions.com> wrote:
> >>> Unlike RK3399, Sunxi/Meson DW HDMI the new Rockchip SoC Rk3328 would
> >>> support external vendor PHY with DW HDMI chip.
> >>>
> >>> Support this vendor PHY by adding new platform PHY ops via DW HDMI
> >>> driver and call the respective generic phy from platform driver code.
> >>>
> >>> This series tested in RK3328 with 1080p (1920x1080) resolution.
> >>>
> >>> Patch 0001/0005: Support Vendor PHY
> >>> Patch 0006/0008: VOP extension for win, dsp offsets
> >>> Patch 0009/0010: RK3328 VOP, HDMI clocks
> >>> Patch 0011:      Rockchip Inno HDMI PHY
> >>> Patch 0012:      RK3328 HDMI driver
> >>> Patch 0013:      RK3328 VOP driver
> >>> Patch 0014/0017: Enable HDMI Out for RK3328
> >>>
> >>> Importent:
> >>> One pontential issues is that Linux HDMI out on RK3328 has effected by
> >>> this patchset as I wouldn't find any relation or clue.
> >>>
> >>> [    0.752016] Loading compiled-in X.509 certificates
> >>> [    0.787796] inno_hdmi_phy_rk3328_clk_recalc_rate: parent 24000000
> >>> [    0.788391] inno-hdmi-phy ff430000.phy:
> >>> inno_hdmi_phy_rk3328_clk_recalc_rate rate 148500000 vco 148500000
> >>> [    0.798353] rockchip-drm display-subsystem: bound ff370000.vop
> >>> (ops vop_component_ops)
> >>> [    0.799403] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-0v9 not
> >>> found, using dummy regulator
> >>> [    0.800288] rk_iommu ff373f00.iommu: Enable stall request timed
> >>> out, status: 0x00004b
> >>> [    0.801131] dwhdmi-rockchip ff3c0000.hdmi: supply avdd-1v8 not
> >>> found, using dummy regulator
> >>> [    0.802056] rk_iommu ff373f00.iommu: Disable paging request timed
> >>> out, status: 0x00004b
> >>> [    0.803233] dwhdmi-rockchip ff3c0000.hdmi: Detected HDMI TX
> >>> controller v2.11a with HDCP (inno_dw_hdmi_phy2)
> >>> [    0.805355] dwhdmi-rockchip ff3c0000.hdmi: registered DesignWare
> >>> HDMI I2C bus driver
> >>> [    0.808769] rockchip-drm display-subsystem: bound ff3c0000.hdmi
> >>> (ops dw_hdmi_rockchip_ops)
> >>> [    0.810869] [drm] Initialized rockchip 1.0.0 20140818 for
> >>> display-subsystem on minor 0
> >>>
> >>> The only way I can use Linux HDMI by disabling IOMMU or support
> >>> disable-iommu link for RK3328 via DT [1].
> >>>
> >>> [1] https://www.spinics.net/lists/devicetree/msg605124.html
> >> Is anyone aware of this issue? I did post the patches for Linux IOMMU
> >> but seems not a proper solution. Any suggestions?
> >
> > I'm not expert in HDMI/VOP, so I can't provide a suitable solution in
> > the kernel,
> >
> > but here is the reason why we need patch to workaround the issue in the
> > kernel:
> >
> > - The VOP driver working in U-Boot is non-IOMMU mode, and the VOP access
> > DDR by physical address;
> >
> > - The VOP driver working in kernel with IOMMU enabled(by default), the
> > VOP access DDR with virtual address(by IOMMU);
> >
> > - The VOP is keep working in kernel before kernel VOP driver is enabled,
> > and the IOMMU driver will be enabled by
> >
> >     the Linux PM framework, since the IOMMU is not correctly configured
> > at this point, the VOP will access unknown
> >
> >      space(the original physical address in U-Boot) convert by IOMMU;
> >
> > So we need to disable the IOMMU temporary in kernel startup before VOP
> > driver is enabled.
>
> If U-Boot isn't handing off an active framebuffer, then it should be
> U-Boot's responsibility to stop the VOP before it exits; if on the other
> hand it is, then it can now use the "iommu-addresses" DT property (see
> the reserved-memory schema) on the framebuffer region, and we should
> just need a bit of work in the IOMMU driver to ensure that is respected
> during the period between the IOMMU initialising and the Linux VOP
> driver subsequently taking over (i.e. so it won't get stuck on an
> unexpected page fault as seems to be happening above). The IOMMU aspect
> of that ought to be fairly straightforward; the trickier part might be
> the runtime PM aspect to ensure the IOMMU doesn't let itself go idle and
> actually turn anything off during that period. I also still think that
> doing the full rk_iommu_disable() upon runtime suspend is wrong, but
> that's more of a thing which confounds the underlying issue here, rather
> than being the problem in itself.

Thanks for your comments. Okay, keeping the Linux IOMMU issue aside I
think whatever change that u-boot makes on VOP has to clear it before
handoff to Linux - so clearing the VOP registers during handoff seems
working. I only wonder why it happens only on RK3328 (RK3399 and
RK3288 seem fine).

I will post the next version with VOP clear during handoff.

Thanks,
Jagan.

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

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

end of thread, other threads:[~2023-12-18 18:54 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-11  8:59 [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
2023-12-11  8:59 ` [PATCH 01/17] video: rockchip: hdmi: Detect hpd after controller init Jagan Teki
2023-12-11  8:59 ` [PATCH 02/17] video: dw_hdmi: Add Vendor PHY handling Jagan Teki
2023-12-11  9:08   ` Neil Armstrong
2023-12-12  9:25     ` Jagan Teki
2023-12-13 19:50   ` Simon Glass
2023-12-14  4:44     ` Jagan Teki
2023-12-11  8:59 ` [PATCH 03/17] video: dw_hdmi: Extend the HPD detection Jagan Teki
2023-12-11  8:59 ` [PATCH 04/17] video: dw_hdmi: Add read_hpd hook Jagan Teki
2023-12-11  8:59 ` [PATCH 05/17] video: dw_hdmi: Add setup_hpd hook Jagan Teki
2023-12-11  8:59 ` [PATCH 06/17] video: rockchip: vop: Simplify rkvop_enable Jagan Teki
2023-12-11  8:59 ` [PATCH 07/17] video: rockchip: vop: Add win offset support Jagan Teki
2023-12-11  8:59 ` [PATCH 08/17] video: rockchip: vop: Add dsp " Jagan Teki
2023-12-11  8:59 ` [PATCH 09/17] clk: rockchip: rk3328: Add VOP clk support Jagan Teki
2023-12-11  8:59 ` [PATCH 10/17] clk: rk3328: Add get hdmiphy clock Jagan Teki
2023-12-11  8:59 ` [PATCH 11/17] phy: rockchip: Add Rockchip INNO HDMI PHY driver Jagan Teki
2023-12-11  8:59 ` [PATCH 12/17] video: rockchip: Add rk3328 hdmi support Jagan Teki
2023-12-11  8:59 ` [PATCH 13/17] video: rockchip: Add rk3328 vop support Jagan Teki
2023-12-16 22:45   ` Johan Jonker
2023-12-18 12:40     ` Jagan Teki
2023-12-11  8:59 ` [PATCH 14/17] ARM: dts: rk3328: Enable VOP for bootph-all Jagan Teki
2023-12-11  8:59 ` [PATCH 15/17] rockchip: Enable preconsole for rk3328 Jagan Teki
2023-12-11  8:59 ` [PATCH 16/17] configs: evb-rk3328: Enable vidconsole " Jagan Teki
2023-12-11  8:59 ` [PATCH 17/17] configs: Enable HDMI Out for ROC-RK3328-CC Jagan Teki
2023-12-15  6:36 ` [PATCH 00/17] video: dw_hdmi: Support Vendor PHY Jagan Teki
2023-12-15  6:36   ` Jagan Teki
2023-12-15  7:13   ` Kever Yang
2023-12-15  7:13     ` Kever Yang
2023-12-18 13:53     ` Robin Murphy
2023-12-18 13:53       ` Robin Murphy
2023-12-18 18:53       ` Jagan Teki
2023-12-18 18:53         ` Jagan Teki

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.