From 14cf391f07d6b75476e207b4baf1b7314ecfe700 Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Mon, 15 Jul 2024 09:36:03 +0800 Subject: [PATCH] drm/rockchip: cdn-dp: support get hpd by gpio DPTX may use tcphy0 or tcphy1. If hardware design support both tcphy0 and tcphy1, then each phy port need a hpd line. For example, tcphy0 port use GPIO1B5 and tcphy1 port use GPIO1B6, it should config dts as follow: &cdn_dp { ... pinctrl-names = "default"; pinctrl-0 = <&cnd_dp_hpd>; hpd-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>, <&gpio1 RK_PB6 GPIO_ACTIVE_HIGH>; phys = <&tcphy0_dp>, <&tcphy1_dp>; ... }; &pinctrl { ... dp { cdn_dp_hpd: cdn-dp-hpd { rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>, <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; }; }; ... }; If only 1 phy port can be used for DPTX, For example, using tcphy0 and GPIO1B5 as hpd pin. It should config dts as follow: &cdn_dp { ... pinctrl-names = "default"; pinctrl-0 = <&cnd_dp_hpd>; hpd-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>; phys = <&tcphy0_dp>; ... }; &pinctrl { ... dp { cdn_dp_hpd: cdn-dp-hpd { rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>; }; }; ... }; Change-Id: Id1acc428431bb13d7074e9daaab2fcca2ac2782e Signed-off-by: Zhang Yubing --- drivers/gpu/drm/rockchip/cdn-dp-core.c | 63 ++++++++++++++++++++++++++ drivers/gpu/drm/rockchip/cdn-dp-core.h | 3 ++ 2 files changed, 66 insertions(+) diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index 63fe2d612941..ca3227125421 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -6,7 +6,9 @@ #include #include +#include #include +#include #include #include #include @@ -150,6 +152,9 @@ static void cdn_dp_clk_disable(struct cdn_dp_device *dp) static int cdn_dp_get_port_lanes(struct cdn_dp_port *port) { + if (port->hpd_gpio && !gpiod_get_value_cansleep(port->hpd_gpio)) + return 0; + return phy_get_bus_width(port->phy); } @@ -776,6 +781,15 @@ static const struct drm_encoder_helper_funcs cdn_dp_encoder_helper_funcs = { static int cdn_dp_encoder_late_register(struct drm_encoder *encoder) { struct cdn_dp_device *dp = encoder_to_dp(encoder); + int i; + + for (i = 0; i < dp->ports; i++) { + if (!dp->port[i]) + continue; + + if (dp->port[i]->hpd_gpio) + enable_irq(dp->port[i]->hpd_irq); + } dp->registered = true; schedule_delayed_work(&dp->event_work, 0); @@ -786,6 +800,15 @@ static int cdn_dp_encoder_late_register(struct drm_encoder *encoder) static void cdn_dp_encoder_early_unregister(struct drm_encoder *encoder) { struct cdn_dp_device *dp = encoder_to_dp(encoder); + int i; + + for (i = 0; i < dp->ports; i++) { + if (!dp->port[i]) + continue; + + if (dp->port[i]->hpd_gpio) + disable_irq(dp->port[i]->hpd_irq); + } dp->registered = false; barrier(); @@ -1033,6 +1056,16 @@ out: return ret; } +static irqreturn_t cdn_dp_hpd_irq_handler(int irq, void *arg) +{ + struct cdn_dp_port *port = arg; + struct cdn_dp_device *dp = port->dp; + + schedule_delayed_work(&dp->event_work, 0); + + return IRQ_HANDLED; +} + static void cdn_dp_pd_event_work(struct work_struct *work) { struct cdn_dp_device *dp = container_of(to_delayed_work(work), struct cdn_dp_device, @@ -1309,6 +1342,36 @@ static int cdn_dp_probe(struct platform_device *pdev) return -EINVAL; } + for (i = 0; i < dp->ports; i++) { + if (!dp->port[i]) + continue; + + port = dp->port[i]; + port->hpd_gpio = devm_gpiod_get_index_optional(dev, "hpd", i, GPIOD_IN); + if (IS_ERR(port->hpd_gpio)) { + DRM_DEV_ERROR(dev, "failed to get port%d hpd gpio\n", i); + return PTR_ERR(port->hpd_gpio); + } + + if (port->hpd_gpio) { + port->hpd_irq = gpiod_to_irq(port->hpd_gpio); + + if (port->hpd_irq < 0) { + DRM_DEV_ERROR(dev, "failed to get port%d hpd irq\n", i); + return port->hpd_irq; + } + + ret = devm_request_irq(dev, port->hpd_irq, cdn_dp_hpd_irq_handler, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING | + IRQF_NO_AUTOEN, "cdn-dp-hpd", port); + if (ret) { + DRM_DEV_ERROR(dev, "failed to request HPD interrupt\n"); + return ret; + } + } + } + mutex_init(&dp->lock); dev_set_drvdata(dev, dp); diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h b/drivers/gpu/drm/rockchip/cdn-dp-core.h index 2d7f2c1fbc51..0efcce4b8125 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.h +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h @@ -58,6 +58,9 @@ struct cdn_dp_port { u8 lanes; bool phy_enabled; u8 id; + + struct gpio_desc *hpd_gpio; + int hpd_irq; }; struct cdn_dp_device {