mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Sascha Hauer <s.hauer@pengutronix.de>
To: "open list:BAREBOX" <barebox@lists.infradead.org>
Subject: [PATCH 06/12] video: rockchip: add support for RK3588 HDMI
Date: Mon, 28 Oct 2024 15:19:51 +0100	[thread overview]
Message-ID: <20241028-vop2-rk3588-v1-6-a54bf7c28adc@pengutronix.de> (raw)
In-Reply-To: <20241028-vop2-rk3588-v1-0-a54bf7c28adc@pengutronix.de>

This adds support for the RK3588 HDMI controller based on Linux commit:

| commit d687f549688832b6d91ec7244355b966a105f569
| Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
| Date:   Sat Jul 6 03:22:35 2024 +0300
|
|     drm/rockchip: Add basic RK3588 HDMI output support
|
|     The RK3588 SoC family integrates the newer Synopsys DesignWare HDMI 2.1
|     Quad-Pixel (QP) TX controller IP and a HDMI/eDP TX Combo PHY based on a
|     Samsung IP block.
|
|     Add just the basic support for now, i.e. RGB output up to 4K@60Hz,
|     without audio, CEC or any of the HDMI 2.1 specific features.
|
|     Co-developed-by: Algea Cao <algea.cao@rock-chips.com>
|     Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
|     Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/video/rockchip/Kconfig               |  11 ++
 drivers/video/rockchip/Makefile              |   1 +
 drivers/video/rockchip/dw_hdmi_qp-rockchip.c | 231 +++++++++++++++++++++++++++
 3 files changed, 243 insertions(+)

diff --git a/drivers/video/rockchip/Kconfig b/drivers/video/rockchip/Kconfig
index b91c6fc398..16e41d8db9 100644
--- a/drivers/video/rockchip/Kconfig
+++ b/drivers/video/rockchip/Kconfig
@@ -14,5 +14,16 @@ config DRIVER_VIDEO_ROCKCHIP_HDMI
         select OFTREE
         select DRIVER_VIDEO_EDID
         select DRIVER_VIDEO_DW_HDMI
+        help
+          Say y here if you want to use HDMI on RK356x based SoCs
+
+config DRIVER_VIDEO_ROCKCHIP_HDMI_QP
+        bool "Rockchip HDMI QP driver"
+        select VIDEO_VPL
+        select OFTREE
+        select DRIVER_VIDEO_EDID
+        select DRIVER_VIDEO_DW_HDMI
+        help
+          Say y here if you want to use HDMI on RK3588 based SoCs
 
 endif
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index 278ce1302d..86a7f39602 100644
--- a/drivers/video/rockchip/Makefile
+++ b/drivers/video/rockchip/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_DRIVER_VIDEO_ROCKCHIP_VOP2) += rockchip_drm_vop2.o rockchip_vop2_reg.o
 obj-$(CONFIG_DRIVER_VIDEO_ROCKCHIP_HDMI) += dw_hdmi-rockchip.o
+obj-$(CONFIG_DRIVER_VIDEO_ROCKCHIP_HDMI_QP) += dw_hdmi_qp-rockchip.o
diff --git a/drivers/video/rockchip/dw_hdmi_qp-rockchip.c b/drivers/video/rockchip/dw_hdmi_qp-rockchip.c
new file mode 100644
index 0000000000..1c337c30c1
--- /dev/null
+++ b/drivers/video/rockchip/dw_hdmi_qp-rockchip.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2024 Collabora Ltd.
+ *
+ * Author: Algea Cao <algea.cao@rock-chips.com>
+ * Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+ */
+#include <linux/clk.h>
+#include <driver.h>
+#include <mfd/syscon.h>
+#include <regulator.h>
+#include <linux/bits.h>
+#include <linux/regmap.h>
+#include <video/dw_hdmi.h>
+#include <linux/phy/phy.h>
+#include <linux/math.h>
+#include <video/drm/drm_connector.h>
+#include <video/drm/drm_modes.h>
+#include <fb.h>
+#include <linux/kernel.h>
+#include <video/dw_hdmi_qp.h>
+#include <linux/gpio/consumer.h>
+
+#include "rockchip_drm_drv.h"
+
+#define RK3588_GRF_SOC_CON2		0x0308
+#define RK3588_HDMI0_HPD_INT_MSK	BIT(13)
+#define RK3588_HDMI0_HPD_INT_CLR	BIT(12)
+#define RK3588_GRF_SOC_CON7		0x031c
+#define RK3588_SET_HPD_PATH_MASK	GENMASK(13, 12)
+#define RK3588_GRF_SOC_STATUS1		0x0384
+#define RK3588_HDMI0_LEVEL_INT		BIT(16)
+#define RK3588_GRF_VO1_CON3		0x000c
+#define RK3588_SCLIN_MASK		BIT(9)
+#define RK3588_SDAIN_MASK		BIT(10)
+#define RK3588_MODE_MASK		BIT(11)
+#define RK3588_I2S_SEL_MASK		BIT(13)
+#define RK3588_GRF_VO1_CON9		0x0024
+#define RK3588_HDMI0_GRANT_SEL		BIT(10)
+
+#define HIWORD_UPDATE(val, mask)	((val) | (mask) << 16)
+#define HOTPLUG_DEBOUNCE_MS		150
+
+struct rockchip_hdmi_qp {
+	struct device *dev;
+	struct regmap *regmap;
+	struct regmap *vo_regmap;
+	struct clk *ref_clk;
+	struct dw_hdmi_qp *hdmi;
+	struct phy *phy;
+	struct gpio_desc *enable_gpio;
+};
+
+static int dw_hdmi_qp_rk3588_mode_set(struct dw_hdmi_qp *dw_hdmi, void *data,
+				      const struct drm_display_mode *mode)
+{
+	struct rockchip_hdmi_qp *hdmi = data;
+	long rate;
+
+	/* Unconditionally switch to TMDS as FRL is not yet supported */
+	gpiod_set_value(hdmi->enable_gpio, 1);
+
+	rate = clk_round_rate(hdmi->ref_clk, mode->clock * 1000);
+
+	clk_set_rate(hdmi->ref_clk, rate);
+
+	/*
+	 * FIXME: Temporary workaround to pass pixel clock rate
+	 * to the PHY driver until phy_configure_opts_hdmi
+	 * becomes available in the PHY API. See also the related
+	 * comment in rk_hdptx_phy_power_on() from
+	 * drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+	 */
+	phy_set_bus_width(hdmi->phy, rate / 100);
+
+	return 0;
+}
+
+static int dw_hdmi_qp_rk3588_phy_init(struct dw_hdmi_qp *dw_hdmi, void *data)
+{
+	struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
+
+	return phy_power_on(hdmi->phy);
+}
+
+static void dw_hdmi_qp_rk3588_phy_disable(struct dw_hdmi_qp *dw_hdmi,
+					  void *data)
+{
+	struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
+
+	phy_power_off(hdmi->phy);
+}
+
+static enum drm_connector_status
+dw_hdmi_qp_rk3588_read_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
+{
+	struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
+	u32 val;
+
+	regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &val);
+
+	return val & RK3588_HDMI0_LEVEL_INT ?
+		connector_status_connected : connector_status_disconnected;
+}
+
+static void dw_hdmi_qp_rk3588_setup_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
+{
+	struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
+
+	regmap_write(hdmi->regmap,
+		     RK3588_GRF_SOC_CON2,
+		     HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR,
+				   RK3588_HDMI0_HPD_INT_CLR |
+				   RK3588_HDMI0_HPD_INT_MSK));
+}
+
+static const struct dw_hdmi_qp_phy_ops rk3588_hdmi_phy_ops = {
+	.mode_set	= dw_hdmi_qp_rk3588_mode_set,
+	.init		= dw_hdmi_qp_rk3588_phy_init,
+	.disable	= dw_hdmi_qp_rk3588_phy_disable,
+	.read_hpd	= dw_hdmi_qp_rk3588_read_hpd,
+	.setup_hpd	= dw_hdmi_qp_rk3588_setup_hpd,
+};
+
+static const struct of_device_id dw_hdmi_qp_rockchip_dt_ids[] = {
+	{ .compatible = "rockchip,rk3588-dw-hdmi-qp",
+	  .data = &rk3588_hdmi_phy_ops },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_hdmi_qp_rockchip_dt_ids);
+
+static int dw_hdmi_qp_rockchip_probe(struct device *dev)
+{
+	static const char * const clk_names[] = {
+		"pclk", "earc", "aud", "hdp", "hclk_vo1",
+		"ref" /* keep "ref" last */
+	};
+	struct dw_hdmi_qp_plat_data plat_data;
+	struct rockchip_hdmi_qp *hdmi;
+	struct clk *clk;
+	int ret, i;
+	u32 val;
+
+	if (!dev->of_node)
+		return -ENODEV;
+
+	hdmi = xzalloc(sizeof(*hdmi));
+
+	plat_data.phy_ops = device_get_match_data(dev);
+	if (!plat_data.phy_ops)
+		return dev_err_probe(dev, -EINVAL, "No match data\n");
+
+	plat_data.phy_data = hdmi;
+	hdmi->dev = dev;
+
+	hdmi->regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
+						       "rockchip,grf");
+	if (IS_ERR(hdmi->regmap)) {
+		dev_err(dev, "Unable to get rockchip,grf\n");
+		return PTR_ERR(hdmi->regmap);
+	}
+
+	hdmi->vo_regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
+							  "rockchip,vo-grf");
+	if (IS_ERR(hdmi->vo_regmap)) {
+		dev_err(dev, "Unable to get rockchip,vo-grf\n");
+		return PTR_ERR(hdmi->vo_regmap);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(clk_names); i++) {
+		clk = clk_get_enabled(hdmi->dev, clk_names[i]);
+
+		if (IS_ERR(clk)) {
+			ret = PTR_ERR(clk);
+			if (ret != -EPROBE_DEFER)
+				dev_err(dev, "Failed to get %s clock: %d\n",
+					clk_names[i], ret);
+			return ret;
+		}
+	}
+	hdmi->ref_clk = clk;
+
+	hdmi->enable_gpio = gpiod_get_optional(hdmi->dev, "enable",
+						    GPIOD_OUT_HIGH);
+	if (IS_ERR(hdmi->enable_gpio)) {
+		ret = PTR_ERR(hdmi->enable_gpio);
+		dev_err(dev, "Failed to request enable GPIO: %d\n", ret);
+		return ret;
+	}
+
+	hdmi->phy = of_phy_get(dev->of_node, NULL);
+	if (IS_ERR(hdmi->phy)) {
+		ret = PTR_ERR(hdmi->phy);
+		if (ret != -EPROBE_DEFER)
+			dev_err(dev, "failed to get phy: %d\n", ret);
+		return ret;
+	}
+
+	val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
+	      HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
+	      HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
+	      HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
+	regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON3, val);
+
+	val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK,
+			    RK3588_SET_HPD_PATH_MASK);
+	regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
+
+	val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL,
+			    RK3588_HDMI0_GRANT_SEL);
+	regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON9, val);
+
+	val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK, RK3588_HDMI0_HPD_INT_MSK);
+	regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
+
+	hdmi->hdmi = dw_hdmi_qp_bind(dev, &plat_data);
+	if (IS_ERR(hdmi->hdmi)) {
+		ret = PTR_ERR(hdmi->hdmi);
+		return ret;
+	}
+
+	return 0;
+}
+
+struct driver dw_hdmi_qp_rockchip_driver = {
+	.probe  = dw_hdmi_qp_rockchip_probe,
+	.name = "dwhdmiqp-rockchip",
+	.of_compatible = dw_hdmi_qp_rockchip_dt_ids,
+};
+device_platform_driver(dw_hdmi_qp_rockchip_driver);

-- 
2.39.5




  parent reply	other threads:[~2024-10-28 14:41 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-28 14:19 [PATCH 00/12] video: rockchip: add vop2 rk3588 support Sascha Hauer
2024-10-28 14:19 ` [PATCH 01/12] vop2: rk3588: make windows primary Sascha Hauer
2024-10-28 14:19 ` [PATCH 02/12] vop2: rk3588: pass clock to rk3588_calc_cru_cfg() Sascha Hauer
2024-10-28 14:19 ` [PATCH 03/12] clk: rockchip: rk3588: Update driver from Linux Sascha Hauer
2024-10-28 14:19 ` [PATCH 04/12] phy: add support for Rockchip Samsung HDMI/eDP Combo PHY driver Sascha Hauer
2024-10-28 14:19 ` [PATCH 05/12] video: add support for dw-hdmi-qp Sascha Hauer
2024-10-28 14:19 ` Sascha Hauer [this message]
2024-10-28 14:19 ` [PATCH 07/12] video: rockchip vop2: fix uninitialized variables Sascha Hauer
2024-10-28 14:19 ` [PATCH 08/12] phy: rockchip-inno-usb2: add support for rk3588 Sascha Hauer
2024-10-28 14:19 ` [PATCH 09/12] phy: phy-rockchip-samsung-hdptx: Add clock provider support Sascha Hauer
2024-10-28 14:19 ` [PATCH 10/12] drm/rockchip: vop2: Improve display modes handling on rk3588 Sascha Hauer
2024-10-28 14:19 ` [PATCH 11/12] ARM: dts: Rockchip rk3588: add HDMI node Sascha Hauer
2024-10-28 14:19 ` [PATCH 12/12] ARM: dts: rockchip rk3588: adjustments for vop Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241028-vop2-rk3588-v1-6-a54bf7c28adc@pengutronix.de \
    --to=s.hauer@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox