[PATCH v8 09/24] drm/rockchip: dw_hdmi: Add support for niu clk

Sascha Hauer
2022-03-11T08:37:26Z

The rk3568 HDMI has an additional clock that needs to be enabled for the
HDMI controller to work. This clock is not needed for the HDMI
controller itself, but to make the SoC internal bus logic work. From the
reference manual:

> 2.8.6 NIU Clock gating reliance
>
> A part of niu clocks have a dependence on another niu clock in order to
> sharing the internal bus. When these clocks are in use, another niu
> clock must be opened, and cannot be gated. These clocks and the special
> clock on which they are relied are as following:
>
> Clocks which have dependency The clock which can not be gated
> -----------------------------------------------------------------
> ...
> pclk_vo_niu, hclk_vo_s_niu hclk_vo_niu
> ...

The clock framework does not support turning on a clock whenever another
clock is turned on, so this patch adds support for the dependent clock
to the HDMI driver. We call it "NIU", which is for "Native Interface
Unit"

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---

Notes:
Changes since v7:
- rename hclk to niu

drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index fe4f9556239ac..7adf9044cb73b 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -76,6 +76,7 @@ struct rockchip_hdmi {
const struct rockchip_hdmi_chip_data *chip_data;
struct clk *ref_clk;
struct clk *grf_clk;
+ struct clk *niu_clk;
struct dw_hdmi *hdmi;
struct regulator *avdd_0v9;
struct regulator *avdd_1v8;
@@ -229,6 +230,14 @@ static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
return PTR_ERR(hdmi->grf_clk);
}

+ hdmi->niu_clk = devm_clk_get_optional(hdmi->dev, "niu");
+ if (PTR_ERR(hdmi->niu_clk) == -EPROBE_DEFER) {
+ return -EPROBE_DEFER;
+ } else if (IS_ERR(hdmi->niu_clk)) {
+ DRM_DEV_ERROR(hdmi->dev, "failed to get niu clock\n");
+ return PTR_ERR(hdmi->niu_clk);
+ }
+
hdmi->avdd_0v9 = devm_regulator_get(hdmi->dev, "avdd-0v9");
if (IS_ERR(hdmi->avdd_0v9))
return PTR_ERR(hdmi->avdd_0v9);
@@ -596,6 +605,13 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
goto err_clk;
}

+ ret = clk_prepare_enable(hdmi->niu_clk);
+ if (ret) {
+ DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI hclk clock: %d\n",
+ ret);
+ goto err_clk;
+ }
+
if (hdmi->chip_data == &rk3568_chip_data) {
regmap_write(hdmi->regmap, RK3568_GRF_VO_CON1,
HIWORD_UPDATE(RK3568_HDMI_SDAIN_MSK |