* [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP
@ 2026-07-30 3:27 Damon Ding
2026-07-30 3:27 ` [PATCH v1 1/7] drm/bridge: analogix_dp: Manage pm runtime and IRQ for native HPD pin detection Damon Ding
` (7 more replies)
0 siblings, 8 replies; 17+ messages in thread
From: Damon Ding @ 2026-07-30 3:27 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Heiko Stuebner, Andy Yan
Cc: Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Dmitry Baryshkov, Marek Szyprowski, Sebastian Reichel, dri-devel,
devicetree, linux-kernel, linux-rockchip, linux-arm-kernel,
Damon Ding
This series improves the HPD (Hotplug Detect) interrupt handling in
the Analogix DP driver to enable reliable native HPD pin detection on
Rockchip platforms, and introduces platform-specific HPD detection
schemes with fine-grained interrupt control.
On Rockchip platforms, the Analogix DP native HPD pin IRQ requires the
DP controller to remain powered, clocked and initialized to generate
plug/unplug interrupts. The previous driver enabled/disabled IRQ during
bridge enable/disable, which left no HPD detection when the display
pipeline was inactive. Additionally, the interrupt mute/unmute/clear
routines operated on all HPD interrupt bits unconditionally, lacking
the granularity needed for per-event control.
The series reorganizes IRQ and pm_runtime management into bind/unbind,
converts the interrupt type detection to a bitmask-based scheme for
fine-grained mute/unmute/clear operations, and configures Rockchip
platforms to use the HOTPLUG_CHG interrupt with a 2ms HPD deglitch
setting, which provides better stability than the PLUG + HPD_LOST
pair.
Tested on RK3576 with both native HPD pin and GPIO HPD configurations.
Native HPD pin mode:
&edp {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&edp_txm0_pins>;
};
GPIO HPD mode:
&edp {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&edp0_hpd>;
hpd-gpios = <&gpio4 RK_PC1 GPIO_ACTIVE_HIGH>;
};
&pinctrl {
edp {
edp0_hpd: edp0-hpd {
rockchip,pins = <4 RK_PC1 0 &pcfg_pull_none>;
};
};
};
Both configurations detect cable plug/unplug events correctly.
Patch 1: Move enable_irq()/disable_irq() to bind/unbind and hold a
pm_runtime reference for Rockchip native HPD pin mode.
Patch 2: Convert analogix_dp_get_irq_type() to return a u32 bitmask
instead of an enum, accumulating all pending interrupt flags.
Patch 3: Extend mute/unmute helpers to accept an irq_type bitmask for
per-event interrupt masking.
Patch 4: Extend clear_hotplug_interrupts() to accept an irq_type
bitmask for per-event pending interrupt clearing.
Patch 5: Simplify analogix_dp_config_interrupt() by removing redundant
local macros and leveraging the unmute helper.
Patch 6: Configure Rockchip platforms to use HOTPLUG_CHG interrupt with
2ms HPD deglitch; other platforms keep PLUG + HPD_LOST pair.
Patch 7: Skip native HPD interrupt register operations for GPIO HPD
mode, where hotplug is detected through an external GPIO.
Damon Ding (7):
drm/bridge: analogix_dp: Manage pm runtime and IRQ for native HPD pin
detection
drm/bridge: analogix_dp: Return bitmask from
analogix_dp_get_irq_type()
drm/bridge: analogix_dp: Extend mute/unmute HPD interrupts to accept
irq bitmask
drm/bridge: analogix_dp: Extend clear_hotplug_interrupts to accept IRQ
bitmask
drm/bridge: analogix_dp: Simplify analogix_dp_config_interrupt()
drm/bridge: analogix_dp: Use platform-specific HPD detection scheme
drm/bridge: analogix_dp: Skip native HPD interrupt ops for GPIO HPD
.../drm/bridge/analogix/analogix_dp_core.c | 46 ++++--
.../drm/bridge/analogix/analogix_dp_core.h | 10 +-
.../gpu/drm/bridge/analogix/analogix_dp_reg.c | 146 ++++++++++++------
3 files changed, 134 insertions(+), 68 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 1/7] drm/bridge: analogix_dp: Manage pm runtime and IRQ for native HPD pin detection
2026-07-30 3:27 [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP Damon Ding
@ 2026-07-30 3:27 ` Damon Ding
2026-07-30 3:39 ` sashiko-bot
2026-07-30 3:27 ` [PATCH v1 2/7] drm/bridge: analogix_dp: Return bitmask from analogix_dp_get_irq_type() Damon Ding
` (6 subsequent siblings)
7 siblings, 1 reply; 17+ messages in thread
From: Damon Ding @ 2026-07-30 3:27 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Heiko Stuebner, Andy Yan
Cc: Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Dmitry Baryshkov, Marek Szyprowski, Sebastian Reichel, dri-devel,
devicetree, linux-kernel, linux-rockchip, linux-arm-kernel,
Damon Ding
On Rockchip platforms, the Analogix DP native HPD pin IRQ functionality
requires the DP controller to be powered, clocked and initialized to
generate plug/unplug interrupts correctly.
To keep HPD detection active, move enable_irq()/disable_irq() from
bridge enabling/disabling handlers into analogix_dp_bind() and
analogix_dp_unbind(). Call pm_runtime_resume_and_get() before enabling
IRQ and pm_runtime_put_sync() after disabling IRQ for symmetric power
management.
Persistent power is only necessary for native HPD pin mode. It is not
required for force-HPD or GPIO HPD modes. Add helper to handle this
special case exclusively for Rockchip native HPD pin configurations.
Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
---
.../drm/bridge/analogix/analogix_dp_core.c | 22 ++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 8d3d4a6e6ca2..d414f4ff40c8 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -40,6 +40,12 @@
static const bool verify_fast_training;
+static bool analogix_dp_require_pm_for_hpd_irq(struct analogix_dp_device *dp)
+{
+ return analogix_dp_is_rockchip(dp->plat_data->dev_type) && !dp->hpd_gpiod &&
+ !dp->force_hpd;
+}
+
static void analogix_dp_init_dp(struct analogix_dp_device *dp)
{
analogix_dp_reset(dp);
@@ -1014,7 +1020,6 @@ static int analogix_dp_set_bridge(struct analogix_dp_device *dp)
goto out_dp_init;
}
- enable_irq(dp->irq);
return 0;
out_dp_init:
@@ -1156,8 +1161,6 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge)
if (dp->dpms_mode != DRM_MODE_DPMS_ON)
return;
- disable_irq(dp->irq);
-
analogix_dp_set_analog_power_down(dp, POWER_ALL, 1);
pm_runtime_put_sync(dp->dev);
@@ -1504,6 +1507,14 @@ int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev)
goto err_unregister_aux;
}
+ if (analogix_dp_require_pm_for_hpd_irq(dp)) {
+ ret = pm_runtime_resume_and_get(dp->dev);
+ if (ret)
+ goto err_unregister_aux;
+ }
+
+ enable_irq(dp->irq);
+
return 0;
err_unregister_aux:
@@ -1515,6 +1526,11 @@ EXPORT_SYMBOL_GPL(analogix_dp_bind);
void analogix_dp_unbind(struct analogix_dp_device *dp)
{
+ disable_irq(dp->irq);
+
+ if (analogix_dp_require_pm_for_hpd_irq(dp))
+ pm_runtime_put_sync(dp->dev);
+
drm_dp_aux_unregister(&dp->aux);
}
EXPORT_SYMBOL_GPL(analogix_dp_unbind);
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v1 2/7] drm/bridge: analogix_dp: Return bitmask from analogix_dp_get_irq_type()
2026-07-30 3:27 [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP Damon Ding
2026-07-30 3:27 ` [PATCH v1 1/7] drm/bridge: analogix_dp: Manage pm runtime and IRQ for native HPD pin detection Damon Ding
@ 2026-07-30 3:27 ` Damon Ding
2026-07-30 3:41 ` sashiko-bot
2026-07-30 3:27 ` [PATCH v1 3/7] drm/bridge: analogix_dp: Extend mute/unmute HPD interrupts to accept irq bitmask Damon Ding
` (5 subsequent siblings)
7 siblings, 1 reply; 17+ messages in thread
From: Damon Ding @ 2026-07-30 3:27 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Heiko Stuebner, Andy Yan
Cc: Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Dmitry Baryshkov, Marek Szyprowski, Sebastian Reichel, dri-devel,
devicetree, linux-kernel, linux-rockchip, linux-arm-kernel,
Damon Ding
Analogix DP controllers support two sets of interrupts for hotplug
detection: HOTPLUG_CHG, and the pair PLUG / HPD_LOST. The current
driver logic relies on PLUG/HPD_LOST and does not consume HOTPLUG_CHG,
nor does it check for INT_HPD for IRQ_HPD events.
The existing analogix_dp_get_irq_type() returns on the first matched
interrupt flag. This causes the hardirq handler to unconditionally mute
all HPD interrupts, including HOTPLUG_CHG and INT_HPD, creating a
limitation for future extensions.
To prepare fine-grained interrupt handling, convert the return type
from enum dp_irq_type to a u32 bitmask. Accumulate all pending
interrupt flags instead of returning early, and add detection for
DP_IRQ_TYPE_IRQ_HPD. Remove DP_IRQ_TYPE_UNKNOWN sentinel; use zero
to indicate no pending interrupts, which simplifies code and
facilitates future extension for additional interrupt types.
This prepares subsequent changes to pass specific irq flags into
mute/unmute helpers for selective interrupt control.
Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
---
.../gpu/drm/bridge/analogix/analogix_dp_core.c | 8 ++++----
.../gpu/drm/bridge/analogix/analogix_dp_core.h | 4 ++--
.../gpu/drm/bridge/analogix/analogix_dp_reg.c | 18 ++++++++++--------
3 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index d414f4ff40c8..c04af9fd4092 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -704,10 +704,10 @@ static irqreturn_t analogix_dp_hardirq(int irq, void *arg)
{
struct analogix_dp_device *dp = arg;
irqreturn_t ret = IRQ_NONE;
- enum dp_irq_type irq_type;
+ u32 irq_type;
irq_type = analogix_dp_get_irq_type(dp);
- if (irq_type != DP_IRQ_TYPE_UNKNOWN) {
+ if (irq_type) {
analogix_dp_mute_hpd_interrupt(dp);
ret = IRQ_WAKE_THREAD;
}
@@ -718,7 +718,7 @@ static irqreturn_t analogix_dp_hardirq(int irq, void *arg)
static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
{
struct analogix_dp_device *dp = arg;
- enum dp_irq_type irq_type;
+ u32 irq_type;
irq_type = analogix_dp_get_irq_type(dp);
if (irq_type & DP_IRQ_TYPE_HP_CABLE_IN ||
@@ -728,7 +728,7 @@ static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
drm_helper_hpd_irq_event(dp->drm_dev);
}
- if (irq_type != DP_IRQ_TYPE_UNKNOWN) {
+ if (irq_type) {
analogix_dp_clear_hotplug_interrupts(dp);
analogix_dp_unmute_hpd_interrupt(dp);
}
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
index c7997677a286..c2eba77f9a81 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
@@ -120,7 +120,7 @@ enum dp_irq_type {
DP_IRQ_TYPE_HP_CABLE_IN = BIT(0),
DP_IRQ_TYPE_HP_CABLE_OUT = BIT(1),
DP_IRQ_TYPE_HP_CHANGE = BIT(2),
- DP_IRQ_TYPE_UNKNOWN = BIT(3),
+ DP_IRQ_TYPE_IRQ_HPD = BIT(3),
};
struct video_info {
@@ -193,7 +193,7 @@ void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp,
int analogix_dp_init_analog_func(struct analogix_dp_device *dp);
void analogix_dp_init_hpd(struct analogix_dp_device *dp);
void analogix_dp_force_hpd(struct analogix_dp_device *dp);
-enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp);
+u32 analogix_dp_get_irq_type(struct analogix_dp_device *dp);
void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp);
void analogix_dp_reset_aux(struct analogix_dp_device *dp);
void analogix_dp_init_aux(struct analogix_dp_device *dp);
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index ea8401293a23..f4f859cb2936 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -413,8 +413,9 @@ void analogix_dp_force_hpd(struct analogix_dp_device *dp)
writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
}
-enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp)
+u32 analogix_dp_get_irq_type(struct analogix_dp_device *dp)
{
+ u32 irq_type = 0;
u32 reg;
if (dp->hpd_gpiod) {
@@ -426,17 +427,18 @@ enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp)
} else {
/* Parse hotplug interrupt status register */
reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4);
-
if (reg & PLUG)
- return DP_IRQ_TYPE_HP_CABLE_IN;
-
+ irq_type |= DP_IRQ_TYPE_HP_CABLE_IN;
if (reg & HPD_LOST)
- return DP_IRQ_TYPE_HP_CABLE_OUT;
-
+ irq_type |= DP_IRQ_TYPE_HP_CABLE_OUT;
if (reg & HOTPLUG_CHG)
- return DP_IRQ_TYPE_HP_CHANGE;
+ irq_type |= DP_IRQ_TYPE_HP_CHANGE;
+
+ reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA);
+ if (reg & INT_HPD)
+ irq_type |= DP_IRQ_TYPE_IRQ_HPD;
- return DP_IRQ_TYPE_UNKNOWN;
+ return irq_type;
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v1 3/7] drm/bridge: analogix_dp: Extend mute/unmute HPD interrupts to accept irq bitmask
2026-07-30 3:27 [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP Damon Ding
2026-07-30 3:27 ` [PATCH v1 1/7] drm/bridge: analogix_dp: Manage pm runtime and IRQ for native HPD pin detection Damon Ding
2026-07-30 3:27 ` [PATCH v1 2/7] drm/bridge: analogix_dp: Return bitmask from analogix_dp_get_irq_type() Damon Ding
@ 2026-07-30 3:27 ` Damon Ding
2026-07-30 3:41 ` sashiko-bot
2026-07-30 3:27 ` [PATCH v1 4/7] drm/bridge: analogix_dp: Extend clear_hotplug_interrupts to accept IRQ bitmask Damon Ding
` (4 subsequent siblings)
7 siblings, 1 reply; 17+ messages in thread
From: Damon Ding @ 2026-07-30 3:27 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Heiko Stuebner, Andy Yan
Cc: Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Dmitry Baryshkov, Marek Szyprowski, Sebastian Reichel, dri-devel,
devicetree, linux-kernel, linux-rockchip, linux-arm-kernel,
Damon Ding
Update the global HPD interrupt mute/unmute routines to accept an IRQ
bitmask parameter. Instead of masking and restoring all HPD interrupts
unconditionally, only operate on flags triggered by the current IRQ
event.
Pass the detected interrupt bitmask from hardirq and thread handler
into the updated per-event interrupt control helpers.
This implements fine-grained per-interrupt masking logic, eliminates
the limitations of global interrupt mute, and prepares subsequent
improvements for accurate HPD event handling.
Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
---
.../drm/bridge/analogix/analogix_dp_core.c | 4 +-
.../drm/bridge/analogix/analogix_dp_core.h | 4 +-
.../gpu/drm/bridge/analogix/analogix_dp_reg.c | 62 ++++++++++++++-----
3 files changed, 51 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index c04af9fd4092..1671f388ef30 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -708,7 +708,7 @@ static irqreturn_t analogix_dp_hardirq(int irq, void *arg)
irq_type = analogix_dp_get_irq_type(dp);
if (irq_type) {
- analogix_dp_mute_hpd_interrupt(dp);
+ analogix_dp_mute_hpd_interrupt(dp, irq_type);
ret = IRQ_WAKE_THREAD;
}
@@ -730,7 +730,7 @@ static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
if (irq_type) {
analogix_dp_clear_hotplug_interrupts(dp);
- analogix_dp_unmute_hpd_interrupt(dp);
+ analogix_dp_unmute_hpd_interrupt(dp, irq_type);
}
return IRQ_HANDLED;
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
index c2eba77f9a81..bc13ae45be69 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
@@ -183,8 +183,8 @@ void analogix_dp_init_interrupt(struct analogix_dp_device *dp);
void analogix_dp_reset(struct analogix_dp_device *dp);
void analogix_dp_swreset(struct analogix_dp_device *dp);
void analogix_dp_config_interrupt(struct analogix_dp_device *dp);
-void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp);
-void analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device *dp);
+void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp, u32 irq_type);
+void analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device *dp, u32 irq_type);
int analogix_dp_wait_pll_locked(struct analogix_dp_device *dp);
void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable);
void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp,
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index f4f859cb2936..42c1da160ad0 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -24,6 +24,9 @@
#define COMMON_INT_MASK_4 (HOTPLUG_CHG | HPD_LOST | PLUG)
#define INT_STA_MASK INT_HPD
+#define COMMON_INT_4_HPD_IRQ (DP_IRQ_TYPE_HP_CABLE_IN | DP_IRQ_TYPE_HP_CABLE_OUT | \
+ DP_IRQ_TYPE_HP_CHANGE)
+
void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable)
{
u32 reg;
@@ -192,30 +195,59 @@ void analogix_dp_config_interrupt(struct analogix_dp_device *dp)
writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
}
-void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp)
+void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp, u32 irq_type)
{
- u32 reg;
+ u32 reg, mask = 0;
- /* 0: mask, 1: unmask */
- reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
- reg &= ~COMMON_INT_MASK_4;
- writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
+ if (!irq_type)
+ return;
- reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
- reg &= ~INT_STA_MASK;
- writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
+ if (irq_type & COMMON_INT_4_HPD_IRQ) {
+ /* 0: mask, 1: unmask */
+ reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
+ if (irq_type & DP_IRQ_TYPE_HP_CABLE_IN)
+ mask |= PLUG;
+ if (irq_type & DP_IRQ_TYPE_HP_CABLE_OUT)
+ mask |= HPD_LOST;
+ if (irq_type & DP_IRQ_TYPE_HP_CHANGE)
+ mask |= HOTPLUG_CHG;
+ reg &= ~mask;
+ writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
+ }
+
+ if (irq_type & DP_IRQ_TYPE_IRQ_HPD) {
+ /* 0: mask, 1: unmask */
+ reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
+ reg &= ~INT_HPD;
+ writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
+ }
}
-void analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device *dp)
+void analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device *dp, u32 irq_type)
{
u32 reg;
- /* 0: mask, 1: unmask */
- reg = COMMON_INT_MASK_4;
- writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
+ if (!irq_type)
+ return;
- reg = INT_STA_MASK;
- writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
+ if (irq_type & COMMON_INT_4_HPD_IRQ) {
+ /* 0: mask, 1: unmask */
+ reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
+ if (irq_type & DP_IRQ_TYPE_HP_CABLE_IN)
+ reg |= PLUG;
+ if (irq_type & DP_IRQ_TYPE_HP_CABLE_OUT)
+ reg |= HPD_LOST;
+ if (irq_type & DP_IRQ_TYPE_HP_CHANGE)
+ reg |= HOTPLUG_CHG;
+ writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
+ }
+
+ if (irq_type & DP_IRQ_TYPE_IRQ_HPD) {
+ /* 0: mask, 1: unmask */
+ reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
+ reg |= INT_HPD;
+ writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
+ }
}
int analogix_dp_wait_pll_locked(struct analogix_dp_device *dp)
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v1 4/7] drm/bridge: analogix_dp: Extend clear_hotplug_interrupts to accept IRQ bitmask
2026-07-30 3:27 [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP Damon Ding
` (2 preceding siblings ...)
2026-07-30 3:27 ` [PATCH v1 3/7] drm/bridge: analogix_dp: Extend mute/unmute HPD interrupts to accept irq bitmask Damon Ding
@ 2026-07-30 3:27 ` Damon Ding
2026-07-30 3:38 ` sashiko-bot
2026-07-30 3:27 ` [PATCH v1 5/7] drm/bridge: analogix_dp: Simplify analogix_dp_config_interrupt() Damon Ding
` (3 subsequent siblings)
7 siblings, 1 reply; 17+ messages in thread
From: Damon Ding @ 2026-07-30 3:27 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Heiko Stuebner, Andy Yan
Cc: Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Dmitry Baryshkov, Marek Szyprowski, Sebastian Reichel, dri-devel,
devicetree, linux-kernel, linux-rockchip, linux-arm-kernel,
Damon Ding
Update analogix_dp_clear_hotplug_interrupts() to take an irq_type
bitmask argument. Instead of clearing all hotplug interrupt bits
unconditionally, only clear the interrupt flags corresponding to the
triggered events.
Pass the detected IRQ bitmask from the irq thread handler, and use the
full HPD_IRQ mask during HPD initialization.
This implements fine-grained pending interrupt clearing logic and
removes limitations brought by unconditional register writes,
supporting improved accuracy for HPD event handling.
Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
---
.../drm/bridge/analogix/analogix_dp_core.c | 2 +-
.../drm/bridge/analogix/analogix_dp_core.h | 2 +-
.../gpu/drm/bridge/analogix/analogix_dp_reg.c | 25 +++++++++++++------
3 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 1671f388ef30..5af4150f0e7e 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -729,7 +729,7 @@ static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
}
if (irq_type) {
- analogix_dp_clear_hotplug_interrupts(dp);
+ analogix_dp_clear_hotplug_interrupts(dp, irq_type);
analogix_dp_unmute_hpd_interrupt(dp, irq_type);
}
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
index bc13ae45be69..2066e575ce10 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
@@ -194,7 +194,7 @@ int analogix_dp_init_analog_func(struct analogix_dp_device *dp);
void analogix_dp_init_hpd(struct analogix_dp_device *dp);
void analogix_dp_force_hpd(struct analogix_dp_device *dp);
u32 analogix_dp_get_irq_type(struct analogix_dp_device *dp);
-void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp);
+void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp, u32 irq_type);
void analogix_dp_reset_aux(struct analogix_dp_device *dp);
void analogix_dp_init_aux(struct analogix_dp_device *dp);
int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp);
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index 42c1da160ad0..816be79a8da6 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -24,6 +24,8 @@
#define COMMON_INT_MASK_4 (HOTPLUG_CHG | HPD_LOST | PLUG)
#define INT_STA_MASK INT_HPD
+#define HPD_IRQ (DP_IRQ_TYPE_HP_CABLE_IN | DP_IRQ_TYPE_HP_CABLE_OUT | \
+ DP_IRQ_TYPE_HP_CHANGE | DP_IRQ_TYPE_IRQ_HPD)
#define COMMON_INT_4_HPD_IRQ (DP_IRQ_TYPE_HP_CABLE_IN | DP_IRQ_TYPE_HP_CABLE_OUT | \
DP_IRQ_TYPE_HP_CHANGE)
@@ -408,18 +410,25 @@ int analogix_dp_init_analog_func(struct analogix_dp_device *dp)
return 0;
}
-void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp)
+void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp, u32 irq_type)
{
- u32 reg;
+ u32 reg = 0;
- if (dp->hpd_gpiod)
+ if (dp->hpd_gpiod || !irq_type)
return;
- reg = HOTPLUG_CHG | HPD_LOST | PLUG;
- writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4);
+ if (irq_type & COMMON_INT_4_HPD_IRQ) {
+ if (irq_type & DP_IRQ_TYPE_HP_CABLE_IN)
+ reg |= PLUG;
+ if (irq_type & DP_IRQ_TYPE_HP_CABLE_OUT)
+ reg |= HPD_LOST;
+ if (irq_type & DP_IRQ_TYPE_HP_CHANGE)
+ reg |= HOTPLUG_CHG;
+ writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4);
+ }
- reg = INT_HPD;
- writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA);
+ if (irq_type & DP_IRQ_TYPE_IRQ_HPD)
+ writel(INT_HPD, dp->reg_base + ANALOGIX_DP_INT_STA);
}
void analogix_dp_init_hpd(struct analogix_dp_device *dp)
@@ -429,7 +438,7 @@ void analogix_dp_init_hpd(struct analogix_dp_device *dp)
if (dp->hpd_gpiod)
return;
- analogix_dp_clear_hotplug_interrupts(dp);
+ analogix_dp_clear_hotplug_interrupts(dp, HPD_IRQ);
reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
reg &= ~(F_HPD | HPD_CTRL);
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v1 5/7] drm/bridge: analogix_dp: Simplify analogix_dp_config_interrupt()
2026-07-30 3:27 [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP Damon Ding
` (3 preceding siblings ...)
2026-07-30 3:27 ` [PATCH v1 4/7] drm/bridge: analogix_dp: Extend clear_hotplug_interrupts to accept IRQ bitmask Damon Ding
@ 2026-07-30 3:27 ` Damon Ding
2026-07-30 3:27 ` [PATCH v1 6/7] drm/bridge: analogix_dp: Use platform-specific HPD detection scheme Damon Ding
` (2 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: Damon Ding @ 2026-07-30 3:27 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Heiko Stuebner, Andy Yan
Cc: Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Dmitry Baryshkov, Marek Szyprowski, Sebastian Reichel, dri-devel,
devicetree, linux-kernel, linux-rockchip, linux-arm-kernel,
Damon Ding
Remove local COMMON_INT_MASK and INT_STA_MASK macros. These constants
are only used once inside this function and bring no reuse benefit.
Replace open-coded register writes for COMMON_INT_MASK_1~3 with
direct writel(0) calls.
Leverage analogix_dp_unmute_hpd_interrupt() using the full HPD_IRQ
mask to initialize HPD interrupt state, removing duplicated register
handling.
Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
---
.../gpu/drm/bridge/analogix/analogix_dp_reg.c | 25 +++----------------
1 file changed, 4 insertions(+), 21 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index 816be79a8da6..42463e18f392 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -18,12 +18,6 @@
#include "analogix_dp_core.h"
#include "analogix_dp_reg.h"
-#define COMMON_INT_MASK_1 0
-#define COMMON_INT_MASK_2 0
-#define COMMON_INT_MASK_3 0
-#define COMMON_INT_MASK_4 (HOTPLUG_CHG | HPD_LOST | PLUG)
-#define INT_STA_MASK INT_HPD
-
#define HPD_IRQ (DP_IRQ_TYPE_HP_CABLE_IN | DP_IRQ_TYPE_HP_CABLE_OUT | \
DP_IRQ_TYPE_HP_CHANGE | DP_IRQ_TYPE_IRQ_HPD)
#define COMMON_INT_4_HPD_IRQ (DP_IRQ_TYPE_HP_CABLE_IN | DP_IRQ_TYPE_HP_CABLE_OUT | \
@@ -178,23 +172,12 @@ void analogix_dp_swreset(struct analogix_dp_device *dp)
void analogix_dp_config_interrupt(struct analogix_dp_device *dp)
{
- u32 reg;
-
/* 0: mask, 1: unmask */
- reg = COMMON_INT_MASK_1;
- writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_1);
-
- reg = COMMON_INT_MASK_2;
- writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2);
-
- reg = COMMON_INT_MASK_3;
- writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3);
-
- reg = COMMON_INT_MASK_4;
- writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
+ writel(0, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_1);
+ writel(0, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2);
+ writel(0, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3);
- reg = INT_STA_MASK;
- writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
+ analogix_dp_unmute_hpd_interrupt(dp, HPD_IRQ);
}
void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp, u32 irq_type)
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v1 6/7] drm/bridge: analogix_dp: Use platform-specific HPD detection scheme
2026-07-30 3:27 [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP Damon Ding
` (4 preceding siblings ...)
2026-07-30 3:27 ` [PATCH v1 5/7] drm/bridge: analogix_dp: Simplify analogix_dp_config_interrupt() Damon Ding
@ 2026-07-30 3:27 ` Damon Ding
2026-07-30 3:41 ` sashiko-bot
2026-07-30 3:27 ` [PATCH v1 7/7] drm/bridge: analogix_dp: Skip native HPD interrupt ops for GPIO HPD Damon Ding
2026-07-30 18:49 ` [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP Heiko Stübner
7 siblings, 1 reply; 17+ messages in thread
From: Damon Ding @ 2026-07-30 3:27 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Heiko Stuebner, Andy Yan
Cc: Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Dmitry Baryshkov, Marek Szyprowski, Sebastian Reichel, dri-devel,
devicetree, linux-kernel, linux-rockchip, linux-arm-kernel,
Damon Ding
Hotplug detection can be implemented either via HOTPLUG_CHG interrupt,
or the combination of PLUG and HPD_LOST interrupts.
For Rockchip platforms, configure HPD deglitch to 2ms and rely on
HOTPLUG_CHG interrupt for hotplug events, which is verified as the
optimal solution through engineering tests. Other platforms continue
using PLUG + HPD_LOST pair.
Adjust analogix_dp_config_interrupt() to apply platform-specific
interrupt masking and deglitch settings. Update threaded irq handler
to check corresponding interrupt flags according to platform type.
Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
---
.../gpu/drm/bridge/analogix/analogix_dp_core.c | 9 +++++++--
.../gpu/drm/bridge/analogix/analogix_dp_reg.c | 16 +++++++++++++++-
2 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 5af4150f0e7e..a292bc881b6b 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -719,10 +719,15 @@ static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
{
struct analogix_dp_device *dp = arg;
u32 irq_type;
+ bool hpd_detected;
irq_type = analogix_dp_get_irq_type(dp);
- if (irq_type & DP_IRQ_TYPE_HP_CABLE_IN ||
- irq_type & DP_IRQ_TYPE_HP_CABLE_OUT) {
+ if (!dp->hpd_gpiod && analogix_dp_is_rockchip(dp->plat_data->dev_type))
+ hpd_detected = irq_type & DP_IRQ_TYPE_HP_CHANGE;
+ else
+ hpd_detected = (irq_type & DP_IRQ_TYPE_HP_CABLE_IN) ||
+ (irq_type & DP_IRQ_TYPE_HP_CABLE_OUT);
+ if (hpd_detected) {
dev_dbg(dp->dev, "Detected cable status changed!\n");
if (dp->drm_dev)
drm_helper_hpd_irq_event(dp->drm_dev);
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index 42463e18f392..981ce3810e90 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -177,7 +177,21 @@ void analogix_dp_config_interrupt(struct analogix_dp_device *dp)
writel(0, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2);
writel(0, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3);
- analogix_dp_unmute_hpd_interrupt(dp, HPD_IRQ);
+ if (analogix_dp_is_rockchip(dp->plat_data->dev_type)) {
+ /*
+ * Either HOTPLUG_CHG interrupt or PLUG + HPD_LOST interrupt
+ * pair can be used to implement hotplug detection.
+ *
+ * On Rockchip platforms, configuring HPD deglitch to 2ms and
+ * using HOTPLUG_CHG interrupt for hotplug detection is proven
+ * as a better solution via engineering verification.
+ */
+ writel(0x80, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_L);
+ writel(0xbb, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_H);
+ analogix_dp_unmute_hpd_interrupt(dp, DP_IRQ_TYPE_HP_CHANGE);
+ } else {
+ analogix_dp_unmute_hpd_interrupt(dp, HPD_IRQ);
+ }
}
void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp, u32 irq_type)
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v1 7/7] drm/bridge: analogix_dp: Skip native HPD interrupt ops for GPIO HPD
2026-07-30 3:27 [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP Damon Ding
` (5 preceding siblings ...)
2026-07-30 3:27 ` [PATCH v1 6/7] drm/bridge: analogix_dp: Use platform-specific HPD detection scheme Damon Ding
@ 2026-07-30 3:27 ` Damon Ding
2026-07-30 18:49 ` [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP Heiko Stübner
7 siblings, 0 replies; 17+ messages in thread
From: Damon Ding @ 2026-07-30 3:27 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Heiko Stuebner, Andy Yan
Cc: Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Dmitry Baryshkov, Marek Szyprowski, Sebastian Reichel, dri-devel,
devicetree, linux-kernel, linux-rockchip, linux-arm-kernel,
Damon Ding
GPIO HPD does not rely on DP controller internal native HPD interrupts.
Skip native HPD register manipulations to avoid irrelevant operations.
Configure interrupt routine mutes native HPD interrupts when
dp->hpd_gpiod exists. Add identical condition guards in hardirq and
threaded irq handlers. Drop redundant dp->hpd_gpiod condition inside
analogix_dp_clear_hotplug_interrupts().
Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
---
.../drm/bridge/analogix/analogix_dp_core.c | 5 +--
.../gpu/drm/bridge/analogix/analogix_dp_reg.c | 32 +++++++++++--------
2 files changed, 21 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index a292bc881b6b..91fa7569950a 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -708,7 +708,8 @@ static irqreturn_t analogix_dp_hardirq(int irq, void *arg)
irq_type = analogix_dp_get_irq_type(dp);
if (irq_type) {
- analogix_dp_mute_hpd_interrupt(dp, irq_type);
+ if (!dp->hpd_gpiod)
+ analogix_dp_mute_hpd_interrupt(dp, irq_type);
ret = IRQ_WAKE_THREAD;
}
@@ -733,7 +734,7 @@ static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
drm_helper_hpd_irq_event(dp->drm_dev);
}
- if (irq_type) {
+ if (!dp->hpd_gpiod && irq_type) {
analogix_dp_clear_hotplug_interrupts(dp, irq_type);
analogix_dp_unmute_hpd_interrupt(dp, irq_type);
}
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
index 981ce3810e90..cf1f9216c742 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -177,20 +177,24 @@ void analogix_dp_config_interrupt(struct analogix_dp_device *dp)
writel(0, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2);
writel(0, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3);
- if (analogix_dp_is_rockchip(dp->plat_data->dev_type)) {
- /*
- * Either HOTPLUG_CHG interrupt or PLUG + HPD_LOST interrupt
- * pair can be used to implement hotplug detection.
- *
- * On Rockchip platforms, configuring HPD deglitch to 2ms and
- * using HOTPLUG_CHG interrupt for hotplug detection is proven
- * as a better solution via engineering verification.
- */
- writel(0x80, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_L);
- writel(0xbb, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_H);
- analogix_dp_unmute_hpd_interrupt(dp, DP_IRQ_TYPE_HP_CHANGE);
+ if (dp->hpd_gpiod) {
+ analogix_dp_mute_hpd_interrupt(dp, HPD_IRQ);
} else {
- analogix_dp_unmute_hpd_interrupt(dp, HPD_IRQ);
+ if (analogix_dp_is_rockchip(dp->plat_data->dev_type)) {
+ /*
+ * Either HOTPLUG_CHG interrupt or PLUG + HPD_LOST interrupt
+ * pair can be used to implement hotplug detection.
+ *
+ * On Rockchip platforms, configuring HPD deglitch to 2ms and
+ * using HOTPLUG_CHG interrupt for hotplug detection is proven
+ * as a better solution via engineering verification.
+ */
+ writel(0x80, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_L);
+ writel(0xbb, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_H);
+ analogix_dp_unmute_hpd_interrupt(dp, DP_IRQ_TYPE_HP_CHANGE);
+ } else {
+ analogix_dp_unmute_hpd_interrupt(dp, HPD_IRQ);
+ }
}
}
@@ -411,7 +415,7 @@ void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp, u32 irq
{
u32 reg = 0;
- if (dp->hpd_gpiod || !irq_type)
+ if (!irq_type)
return;
if (irq_type & COMMON_INT_4_HPD_IRQ) {
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v1 4/7] drm/bridge: analogix_dp: Extend clear_hotplug_interrupts to accept IRQ bitmask
2026-07-30 3:27 ` [PATCH v1 4/7] drm/bridge: analogix_dp: Extend clear_hotplug_interrupts to accept IRQ bitmask Damon Ding
@ 2026-07-30 3:38 ` sashiko-bot
0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-07-30 3:38 UTC (permalink / raw)
To: Damon Ding; +Cc: dri-devel, conor+dt, robh, devicetree
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [High] Data Race in Interrupt Mask Registers During RMW
Pre-existing issues:
- [High] Lost Hardware Hotplug Events Due to Late Status Clearing
--
--- Patch [4]: [PATCH v1 4/7] drm/bridge: analogix_dp: Extend clear_hotplug_interrupts to accept IRQ bitmask ---
commit f4ba8e259db1706905ae7d04afdea18e9d5a28d6
Author: Damon Ding <damon.ding@rock-chips.com>
drm/bridge: analogix_dp: Extend clear_hotplug_interrupts to accept IRQ bitmask
Update analogix_dp_clear_hotplug_interrupts() to take an irq_type
bitmask argument. Instead of clearing all hotplug interrupt bits
unconditionally, only clear the interrupt flags corresponding to the
triggered events.
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -733,7 +733,7 @@ static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
> }
>
> if (irq_type) {
> - analogix_dp_clear_hotplug_interrupts(dp);
> + analogix_dp_clear_hotplug_interrupts(dp, irq_type);
[Severity: High]
This is a pre-existing issue, but can this late clearing cause hardware
hotplug events to be silently lost?
Because the hardware interrupt status is cleared at the end of the threaded
handler, it executes after the time-consuming drm_helper_hpd_irq_event()
completes:
analogix_dp_irq_thread()
if (hpd_detected) {
...
drm_helper_hpd_irq_event(dp->drm_dev);
}
If a fast unplug/plug cable bounce occurs exactly while
drm_helper_hpd_irq_event() is executing, the hardware sets the status bit
again. Clearing the write-1-to-clear (W1C) register after this will clear
the new event without triggering a new interrupt.
Should the W1C status registers be cleared immediately after reading their
state, before executing the event handling logic?
> analogix_dp_unmute_hpd_interrupt(dp, irq_type);
[Severity: High]
Does this code need a spinlock to protect the interrupt mask registers?
Since the IRQ is requested without IRQF_ONESHOT, the hardirq handler can
preempt the threaded handler. If analogix_dp_unmute_hpd_interrupt() reads
ANALOGIX_DP_COMMON_INT_MASK_4 and gets preempted by a new hardirq that
masks a new event, the resuming threaded handler might overwrite the
register with its stale read value.
Could this cause a hotplug interrupt type to become permanently masked
if the hardirq overwrites the threaded handler's unmute operation?
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730032744.381566-1-damon.ding@rock-chips.com?part=4
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v1 1/7] drm/bridge: analogix_dp: Manage pm runtime and IRQ for native HPD pin detection
2026-07-30 3:27 ` [PATCH v1 1/7] drm/bridge: analogix_dp: Manage pm runtime and IRQ for native HPD pin detection Damon Ding
@ 2026-07-30 3:39 ` sashiko-bot
0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-07-30 3:39 UTC (permalink / raw)
To: Damon Ding; +Cc: devicetree, dri-devel, conor+dt, robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The HPD IRQ handler unconditionally accesses unclocked DP controller registers during runtime suspend on GPIO HPD and non-Rockchip configurations, causing a synchronous external abort (system crash).
--
--- Patch [1]: [PATCH v1 1/7] drm/bridge: analogix_dp: Manage pm runtime and IRQ for native HPD pin detection ---
commit 0b74430c48be5d81c8cb19f2cd5f520d6c7a696a
Author: Damon Ding <damon.ding@rock-chips.com>
drm/bridge: analogix_dp: Manage pm runtime and IRQ for native HPD pin detection
This commit moves enable_irq() and disable_irq() from bridge enable/disable
handlers to analogix_dp_bind() and analogix_dp_unbind() to keep HPD detection
active. It also acquires a runtime PM reference exclusively for Rockchip
native HPD pin configurations to ensure the controller remains powered.
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 30c0c0b41d5aa..1c98f92e001d8 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
[ ... ]
> @@ -1508,6 +1511,14 @@ int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev)
> goto err_unregister_aux;
> }
>
> + if (analogix_dp_require_pm_for_hpd_irq(dp)) {
> + ret = pm_runtime_resume_and_get(dp->dev);
> + if (ret)
> + goto err_unregister_aux;
> + }
> +
> + enable_irq(dp->irq);
> +
[Severity: High]
Since pm_runtime_resume_and_get() is only called for Rockchip native HPD,
other configurations (like GPIO HPD or Exynos) can enter runtime suspend
while the IRQ remains enabled here.
If the HPD interrupt fires (e.g. via an active GPIO pin) while the device is
in runtime suspend, will this cause a crash?
The hardirq handler executes and performs unconditional MMIO accesses to the
unclocked DP controller:
analogix_dp_hardirq()
analogix_dp_mute_hpd_interrupt()
readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
Accessing memory-mapped registers of a clock-gated peripheral typically
causes a synchronous external abort.
> return 0;
>
> err_unregister_aux:
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730032744.381566-1-damon.ding@rock-chips.com?part=1
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v1 2/7] drm/bridge: analogix_dp: Return bitmask from analogix_dp_get_irq_type()
2026-07-30 3:27 ` [PATCH v1 2/7] drm/bridge: analogix_dp: Return bitmask from analogix_dp_get_irq_type() Damon Ding
@ 2026-07-30 3:41 ` sashiko-bot
0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-07-30 3:41 UTC (permalink / raw)
To: Damon Ding; +Cc: dri-devel, robh, devicetree, conor+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Unconditional DP register access in hardirq/thread handlers causes bus faults when using GPIO HPD with PM runtime suspended.
--
--- Patch [2]: [PATCH v1 2/7] drm/bridge: analogix_dp: Return bitmask from analogix_dp_get_irq_type() ---
commit 23b7b1cae6716042fa037a50c31f18ad40263d93
Author: Damon Ding <damon.ding@rock-chips.com>
drm/bridge: analogix_dp: Return bitmask from analogix_dp_get_irq_type()
This commit converts analogix_dp_get_irq_type() to return a bitmask of pending
interrupt flags instead of just the first matched flag. It also updates the
handlers to check for a non-zero return value instead of DP_IRQ_TYPE_UNKNOWN.
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 1c98f92e001d8..ccb8a374b40b7 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -708,10 +708,10 @@ static irqreturn_t analogix_dp_hardirq(int irq, void *arg)
> {
[ ... ]
> irq_type = analogix_dp_get_irq_type(dp);
> - if (irq_type != DP_IRQ_TYPE_UNKNOWN) {
> + if (irq_type) {
> analogix_dp_mute_hpd_interrupt(dp);
[Severity: High]
Could this unconditional call to analogix_dp_mute_hpd_interrupt() cause a
regression (bus fault) when using GPIO HPD while the device is PM runtime
suspended?
Since an earlier patch in this series moved enable_irq() to
analogix_dp_bind() without keeping the device PM resumed for GPIO HPD
configurations, a GPIO interrupt can fire while the DP controller is suspended.
If that happens, analogix_dp_mute_hpd_interrupt() will directly read/write
MMIO registers (like ANALOGIX_DP_COMMON_INT_MASK_4) on an unclocked or
powered-off hardware block.
> ret = IRQ_WAKE_THREAD;
> }
[ ... ]
> @@ -722,7 +722,7 @@ static irqreturn_t analogix_dp_hardirq(int irq, void *arg)
> static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
> {
[ ... ]
> - if (irq_type != DP_IRQ_TYPE_UNKNOWN) {
> + if (irq_type) {
> analogix_dp_clear_hotplug_interrupts(dp);
> analogix_dp_unmute_hpd_interrupt(dp);
[Severity: High]
Similarly, could these function calls cause a regression for the same reason
if called during a GPIO HPD event while PM runtime suspended?
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730032744.381566-1-damon.ding@rock-chips.com?part=2
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v1 3/7] drm/bridge: analogix_dp: Extend mute/unmute HPD interrupts to accept irq bitmask
2026-07-30 3:27 ` [PATCH v1 3/7] drm/bridge: analogix_dp: Extend mute/unmute HPD interrupts to accept irq bitmask Damon Ding
@ 2026-07-30 3:41 ` sashiko-bot
0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-07-30 3:41 UTC (permalink / raw)
To: Damon Ding; +Cc: dri-devel, conor+dt, robh, devicetree
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Selective unmasking combined with unconditional status clearing permanently masks concurrently triggered hotplug interrupts, causing lost events.
- [High] Accessing DP controller mask registers in mute/unmute functions when using GPIO HPD causes a bus hang during runtime suspend.
--
--- Patch [3]: [PATCH v1 3/7] drm/bridge: analogix_dp: Extend mute/unmute HPD interrupts to accept irq bitmask ---
commit 09d81009e86378eb20f782e0e10f313daaa0f8d2
Author: Damon Ding <damon.ding@rock-chips.com>
drm/bridge: analogix_dp: Extend mute/unmute HPD interrupts to accept irq bitmask
This commit updates the global HPD interrupt mute/unmute routines to accept
an IRQ bitmask parameter. It passes the bitmask from the hardirq and thread
handlers to selectively mask/unmask flags triggered by the current IRQ event,
preparing for subsequent accurate HPD event handling.
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index ccb8a374b40b7..a3dc5eac91b8f 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
[ ... ]
> @@ -734,7 +734,7 @@ static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
>
> if (irq_type) {
> analogix_dp_clear_hotplug_interrupts(dp);
> - analogix_dp_unmute_hpd_interrupt(dp);
> + analogix_dp_unmute_hpd_interrupt(dp, irq_type);
[Severity: High]
Could this selective unmasking combined with the unconditional status clearing
permanently mask concurrently triggered hotplug interrupts?
Since analogix_dp_irq_thread() samples irq_type earlier via
analogix_dp_get_irq_type(), what happens if a new native hotplug interrupt
(like HOTPLUG_CHG) fires immediately after that read?
The hardirq would preempt the thread, read the updated status, and mask the
new interrupt. When the thread resumes, analogix_dp_clear_hotplug_interrupts()
unconditionally clears all hotplug status bits:
reg = HOTPLUG_CHG | HPD_LOST | PLUG;
writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4);
destroying the new interrupt's status. Then, this selective
analogix_dp_unmute_hpd_interrupt() call uses the stale irq_type snapshot that
lacks the new interrupt, leaving the newly triggered interrupt permanently
masked in ANALOGIX_DP_COMMON_INT_MASK_4 and lost until a driver reload.
> }
>
> return IRQ_HANDLED;
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
> index f4f859cb29366..42c1da160ad02 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
[ ... ]
> -void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp)
> +void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp, u32 irq_type)
> {
> - u32 reg;
> + u32 reg, mask = 0;
>
> - /* 0: mask, 1: unmask */
> - reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
> - reg &= ~COMMON_INT_MASK_4;
> - writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
> + if (!irq_type)
> + return;
>
> - reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
> - reg &= ~INT_STA_MASK;
> - writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
> + if (irq_type & COMMON_INT_4_HPD_IRQ) {
> + /* 0: mask, 1: unmask */
> + reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
[Severity: High]
Does this code perform an unprotected MMIO read on the DP controller when
using a GPIO for HPD?
If dp->hpd_gpiod is active, the DP controller might be in runtime suspend
(with power/clocks off) while the GPIO HPD IRQ remains enabled. A cable plug
would trigger the GPIO interrupt, and the call to
analogix_dp_mute_hpd_interrupt() in analogix_dp_hardirq() will attempt to
read the DP controller's mask registers here, potentially causing a bus hang.
> + if (irq_type & DP_IRQ_TYPE_HP_CABLE_IN)
> + mask |= PLUG;
> + if (irq_type & DP_IRQ_TYPE_HP_CABLE_OUT)
> + mask |= HPD_LOST;
> + if (irq_type & DP_IRQ_TYPE_HP_CHANGE)
> + mask |= HOTPLUG_CHG;
> + reg &= ~mask;
> + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
> + }
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730032744.381566-1-damon.ding@rock-chips.com?part=3
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v1 6/7] drm/bridge: analogix_dp: Use platform-specific HPD detection scheme
2026-07-30 3:27 ` [PATCH v1 6/7] drm/bridge: analogix_dp: Use platform-specific HPD detection scheme Damon Ding
@ 2026-07-30 3:41 ` sashiko-bot
0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-07-30 3:41 UTC (permalink / raw)
To: Damon Ding; +Cc: devicetree, robh, conor+dt, dri-devel
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] DisplayPort short HPD pulses are completely filtered out by the 2ms hardware deglitch filter, breaking link loss detection and PSR.
- [High] Hotplug interrupt unmasking logic unintentionally re-enables PLUG and HPD_LOST interrupts on Rockchip platforms, defeating the patch's purpose.
--
--- Patch [6]: [PATCH v1 6/7] drm/bridge: analogix_dp: Use platform-specific HPD detection scheme ---
commit af35433f355c1427bbfdea612a689613337f11ab
Author: Damon Ding <damon.ding@rock-chips.com>
Date: Thu Jul 30 03:27:43 2026 +0000
drm/bridge: analogix_dp: Use platform-specific HPD detection scheme
This commit configures the HPD deglitch filter to 2ms on Rockchip platforms
and updates the interrupt handling to rely exclusively on the HOTPLUG_CHG
interrupt instead of the PLUG and HPD_LOST combination. The threaded IRQ
handler is also adjusted to evaluate platform-specific interrupt flags.
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 9f6ecaa1aeb5e..b7aa10daae2f2 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -723,10 +723,15 @@ static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
> {
> struct analogix_dp_device *dp = arg;
> u32 irq_type;
> + bool hpd_detected;
>
> irq_type = analogix_dp_get_irq_type(dp);
> - if (irq_type & DP_IRQ_TYPE_HP_CABLE_IN ||
> - irq_type & DP_IRQ_TYPE_HP_CABLE_OUT) {
> + if (!dp->hpd_gpiod && analogix_dp_is_rockchip(dp->plat_data->dev_type))
> + hpd_detected = irq_type & DP_IRQ_TYPE_HP_CHANGE;
> + else
> + hpd_detected = (irq_type & DP_IRQ_TYPE_HP_CABLE_IN) ||
> + (irq_type & DP_IRQ_TYPE_HP_CABLE_OUT);
> + if (hpd_detected) {
[Severity: High]
Could this logic inadvertently re-enable the PLUG and HPD_LOST interrupts
that were intentionally masked during initialization?
When analogix_dp_get_irq_type() is called, it reads the raw interrupt
status register without checking against the active mask:
analogix_dp_get_irq_type() {
...
reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4);
if (reg & PLUG)
irq_type |= DP_IRQ_TYPE_HP_CABLE_IN;
if (reg & HPD_LOST)
irq_type |= DP_IRQ_TYPE_HP_CABLE_OUT;
...
}
If the hardware continues to set the PLUG and HPD_LOST status bits on cable
events even while they are masked, analogix_dp_get_irq_type() will still
return them in irq_type.
Later in analogix_dp_irq_thread(), this irq_type mask is passed to
analogix_dp_unmute_hpd_interrupt():
if (!dp->hpd_gpiod && irq_type) {
analogix_dp_clear_hotplug_interrupts(dp, irq_type);
analogix_dp_unmute_hpd_interrupt(dp, irq_type);
}
Would passing the unintentionally detected PLUG and HPD_LOST bits into
analogix_dp_unmute_hpd_interrupt() permanently unmask those interrupts,
defeating the platform-specific interrupt scheme on the very first event?
Additionally, because DP_IRQ_TYPE_IRQ_HPD is no longer included in the
hpd_detected calculation for Rockchip, will this prevent
drm_helper_hpd_irq_event() from being called to process link retraining
and Panel Self Refresh (PSR) events?
> dev_dbg(dp->dev, "Detected cable status changed!\n");
> if (dp->drm_dev)
> drm_helper_hpd_irq_event(dp->drm_dev);
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
> index 42463e18f392c..981ce3810e90d 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
[ ... ]
> @@ -177,7 +177,21 @@ void analogix_dp_config_interrupt(struct analogix_dp_device *dp)
> writel(0, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2);
> writel(0, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3);
>
> - analogix_dp_unmute_hpd_interrupt(dp, HPD_IRQ);
> + if (analogix_dp_is_rockchip(dp->plat_data->dev_type)) {
> + /*
> + * Either HOTPLUG_CHG interrupt or PLUG + HPD_LOST interrupt
> + * pair can be used to implement hotplug detection.
> + *
> + * On Rockchip platforms, configuring HPD deglitch to 2ms and
> + * using HOTPLUG_CHG interrupt for hotplug detection is proven
> + * as a better solution via engineering verification.
> + */
> + writel(0x80, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_L);
> + writel(0xbb, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_H);
[Severity: High]
Does configuring the deglitch filter to 2ms risk filtering out valid
DisplayPort short HPD pulses?
The DP specification defines short HPD pulses (which are used for sink
events like PSR and link retraining) as a low pulse lasting between 0.5ms
and 1.0ms.
Because the new 2ms filter configuration exceeds the maximum short pulse
duration of 1.0ms, will the hardware treat all valid DP short pulses as
noise and silently drop them before they can trigger an interrupt?
> + analogix_dp_unmute_hpd_interrupt(dp, DP_IRQ_TYPE_HP_CHANGE);
> + } else {
> + analogix_dp_unmute_hpd_interrupt(dp, HPD_IRQ);
> + }
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730032744.381566-1-damon.ding@rock-chips.com?part=6
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP
2026-07-30 3:27 [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP Damon Ding
` (6 preceding siblings ...)
2026-07-30 3:27 ` [PATCH v1 7/7] drm/bridge: analogix_dp: Skip native HPD interrupt ops for GPIO HPD Damon Ding
@ 2026-07-30 18:49 ` Heiko Stübner
2026-07-31 3:08 ` Damon Ding
7 siblings, 1 reply; 17+ messages in thread
From: Heiko Stübner @ 2026-07-30 18:49 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Andy Yan, Damon Ding
Cc: Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Dmitry Baryshkov, Marek Szyprowski, Sebastian Reichel, dri-devel,
devicetree, linux-kernel, linux-rockchip, linux-arm-kernel,
Damon Ding
Hi Damon,
Am Donnerstag, 30. Juli 2026, 05:27:37 Mitteleuropäische Sommerzeit schrieb Damon Ding:
> This series improves the HPD (Hotplug Detect) interrupt handling in
> the Analogix DP driver to enable reliable native HPD pin detection on
> Rockchip platforms, and introduces platform-specific HPD detection
> schemes with fine-grained interrupt control.
[...]
> Tested on RK3576 with both native HPD pin and GPIO HPD configurations.
>
> Native HPD pin mode:
>
> &edp {
> status = "okay";
> pinctrl-names = "default";
> pinctrl-0 = <&edp_txm0_pins>;
> };
>
> GPIO HPD mode:
>
> &edp {
> status = "okay";
> pinctrl-names = "default";
> pinctrl-0 = <&edp0_hpd>;
> hpd-gpios = <&gpio4 RK_PC1 GPIO_ACTIVE_HIGH>;
> };
>
> &pinctrl {
> edp {
> edp0_hpd: edp0-hpd {
> rockchip,pins = <4 RK_PC1 0 &pcfg_pull_none>;
> };
> };
> };
Yay and thanks a lot for working on that.
If I roll my display-port carrier board back to the analogix-dp being
the endpoint, this works exactly as expected :-) .
I can plug in the display at some point after the boot and have it
detected and setup correctly. Same with unplugging it while
the system is running. The connection status is correctly reported
in sysfs.
Though there is a caveat. When the eDP is not the last part, this does not
work anymore. The detect function always returns "connected" if there is
a next bridge available.
My board [0] has a physical DP connector on it, so models it as
dp-connector, but in that case the Analogix driver always reports being
connected.
Heiko
[0] https://lore.kernel.org/linux-rockchip/20251009225050.88192-3-heiko@sntech.de/
... same effect with hpd-gpios in either the edp node or dp-connector node
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP
2026-07-30 18:49 ` [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP Heiko Stübner
@ 2026-07-31 3:08 ` Damon Ding
2026-07-31 9:23 ` Heiko Stübner
0 siblings, 1 reply; 17+ messages in thread
From: Damon Ding @ 2026-07-31 3:08 UTC (permalink / raw)
To: Heiko Stübner, Andrzej Hajda, Neil Armstrong, Robert Foss,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Andy Yan
Cc: Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Dmitry Baryshkov, Marek Szyprowski, Sebastian Reichel, dri-devel,
devicetree, linux-kernel, linux-rockchip, linux-arm-kernel
[-- Attachment #1: Type: text/plain, Size: 2719 bytes --]
Hi Heiko,
On 7/31/2026 2:49 AM, Heiko Stübner wrote:
> Hi Damon,
>
> Am Donnerstag, 30. Juli 2026, 05:27:37 Mitteleuropäische Sommerzeit schrieb Damon Ding:
>> This series improves the HPD (Hotplug Detect) interrupt handling in
>> the Analogix DP driver to enable reliable native HPD pin detection on
>> Rockchip platforms, and introduces platform-specific HPD detection
>> schemes with fine-grained interrupt control.
>
> [...]
>
>> Tested on RK3576 with both native HPD pin and GPIO HPD configurations.
>>
>> Native HPD pin mode:
>>
>> &edp {
>> status = "okay";
>> pinctrl-names = "default";
>> pinctrl-0 = <&edp_txm0_pins>;
>> };
>>
>> GPIO HPD mode:
>>
>> &edp {
>> status = "okay";
>> pinctrl-names = "default";
>> pinctrl-0 = <&edp0_hpd>;
>> hpd-gpios = <&gpio4 RK_PC1 GPIO_ACTIVE_HIGH>;
>> };
>>
>> &pinctrl {
>> edp {
>> edp0_hpd: edp0-hpd {
>> rockchip,pins = <4 RK_PC1 0 &pcfg_pull_none>;
>> };
>> };
>> };
>
> Yay and thanks a lot for working on that.
>
> If I roll my display-port carrier board back to the analogix-dp being
> the endpoint, this works exactly as expected :-) .
>
> I can plug in the display at some point after the boot and have it
> detected and setup correctly. Same with unplugging it while
> the system is running. The connection status is correctly reported
> in sysfs.
>
>
> Though there is a caveat. When the eDP is not the last part, this does not
> work anymore. The detect function always returns "connected" if there is
> a next bridge available.
>
> My board [0] has a physical DP connector on it, so models it as
> dp-connector, but in that case the Analogix driver always reports being
> connected.
>
>
> [0] https://lore.kernel.org/linux-rockchip/20251009225050.88192-3-heiko@sntech.de/
> ... same effect with hpd-gpios in either the edp node or dp-connector node
>
>
My previous tests were carried out on the modified RK3576 IOTEST board
DTS based on RK3576 EVB1, which includes dp-connector by default. I also
did extra verification without dp-connector, and HPD detection works
correctly in both cases.
I've taken a look at the Tiger board DT configuration. The pinctrl
settings for the eDP HPD GPIO may need adjustment:
&pinctrl {
edp0 {
edp0_hpd_l: edp0-hpd-l-pin {
rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>;
};
};
};
It is recommended to configure GPIO4B5 as pull-down or pll-none. Pull-up
configuration may prevent GPIO interrupts from being triggered properly,
resulting in a permanent "connected" status.
Could you help try this modification and see if it resolves the issue?
Best regards,
Damon
[-- Attachment #2: 0001-TEST-arm64-dts-rockchip-Enable-eDP2DP-display-on-RK3.patch --]
[-- Type: text/plain, Size: 26452 bytes --]
From 1fb4d0c29681407367c8d93770c30c2213174473 Mon Sep 17 00:00:00 2001
From: Damon Ding <damon.ding@rock-chips.com>
Date: Tue, 28 Jul 2026 10:00:18 +0800
Subject: [PATCH] [TEST]arm64: dts: rockchip: Enable eDP2DP display on RK3576
IOTEST board
Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
---
.../boot/dts/rockchip/rk3576-iotest-v10.dts | 1126 +++++++++++++++++
1 file changed, 1126 insertions(+)
create mode 100755 arch/arm64/boot/dts/rockchip/rk3576-iotest-v10.dts
diff --git a/arch/arm64/boot/dts/rockchip/rk3576-iotest-v10.dts b/arch/arm64/boot/dts/rockchip/rk3576-iotest-v10.dts
new file mode 100755
index 000000000000..197087c831f6
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3576-iotest-v10.dts
@@ -0,0 +1,1126 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2024 Rockchip Electronics Co., Ltd.
+ *
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
+#include "rk3576.dtsi"
+
+/ {
+ model = "Rockchip RK3576 EVB V10 Board";
+ compatible = "rockchip,rk3576-evb1-v10", "rockchip,rk3576";
+
+ aliases {
+ ethernet0 = &gmac0;
+ ethernet1 = &gmac1;
+ };
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ power-supply = <&vcc3v3_lcd_n>;
+ pwms = <&gpio_pwm0 0 25000 0>;
+ };
+
+ chosen: chosen {
+ stdout-path = "serial0:1500000n8";
+ bootargs = "root=PARTUUID=614e0000-0000 rootwait";
+ };
+
+ adc_keys: adc-keys {
+ compatible = "adc-keys";
+ io-channels = <&saradc 1>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <1800000>;
+ poll-interval = <100>;
+
+ button-back {
+ label = "back";
+ linux,code = <KEY_BACK>;
+ press-threshold-microvolt = <1235000>;
+ };
+
+ button-menu {
+ label = "menu";
+ linux,code = <KEY_MENU>;
+ press-threshold-microvolt = <890000>;
+ };
+
+ button-vol-down {
+ label = "volume down";
+ linux,code = <KEY_VOLUMEDOWN>;
+ press-threshold-microvolt = <417000>;
+ };
+
+ button-vol-up {
+ label = "volume up";
+ linux,code = <KEY_VOLUMEUP>;
+ press-threshold-microvolt = <17000>;
+ };
+ };
+
+ dp-con {
+ compatible = "dp-connector";
+ label = "DP OUT";
+ type = "full-size";
+
+ port {
+ dp_con_in: endpoint {
+ remote-endpoint = <&edp_out_conn>;
+ };
+ };
+ };
+
+ hdmi-con {
+ compatible = "hdmi-connector";
+ type = "a";
+ };
+
+ leds: leds {
+ compatible = "gpio-leds";
+
+ work_led: led-0 {
+ gpios = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ gpio_pwm0: gpio-pwm0 {
+ compatible = "pwm-gpio";
+ gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>;
+ pinctrl-0 = <&gpio_pwm0_pin>;
+ pinctrl-names = "default";
+ #pwm-cells = <3>;
+ };
+
+ vbus5v0_typec: regulator-vbus5v0-typec {
+ compatible = "regulator-fixed";
+ regulator-name = "vbus5v0_typec";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&gpio0 RK_PD1 GPIO_ACTIVE_HIGH>;
+ vin-supply = <&vcc5v0_device>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_otg0_pwren>;
+ };
+
+ vcc12v_dcin: regulator-vcc12v-dcin {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc12v_dcin";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ };
+
+ vcc1v2_ufs_vccq_s0: regulator-vcc1v2-ufs-vccq-s0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc1v2_ufs_vccq_s0";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ vin-supply = <&vcc_sys>;
+ };
+
+ vcc1v8_ufs_vccq2_s0: regulator-vcc1v8-ufs-vccq2-s0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc1v8_ufs_vccq2_s0";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vcc_1v8_s3>;
+ };
+
+ vcc3v3_lcd_n: regulator-vcc3v3-lcd0-n {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_lcd0_n";
+ regulator-boot-on;
+ enable-active-high;
+ gpio = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>;
+ vin-supply = <&vcc_3v3_s0>;
+ };
+
+ vcc3v3_pcie1: regulator-vcc3v3-pcie1 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_pcie1";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ enable-active-high;
+ gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_HIGH>;
+ startup-delay-us = <5000>;
+ vin-supply = <&vcc12v_dcin>;
+ };
+
+ vcc3v3_rtc_s5: regulator-vcc3v3-rtc-s5 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_rtc_s5";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_sys>;
+ };
+
+ vcc5v0_device: regulator-vcc5v0-device {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_device";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc12v_dcin>;
+ };
+
+ vcc5v0_host: regulator-vcc5v0-host {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_host";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ gpio = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>;
+ vin-supply = <&vcc5v0_device>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_host_pwren>;
+ };
+
+ vcc_sys: regulator-vcc5v0-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc12v_dcin>;
+ };
+
+ vcc_1v1_nldo_s3: regulator-vcc-1v1-nldo-s3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_1v1_nldo_s3";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ vin-supply = <&vcc_sys>;
+ };
+
+ vcc_1v8_s0: regulator-vcc-1v8-s0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_1v8_s0";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vcc_1v8_s3>;
+ };
+
+ vcc_2v0_pldo_s3: regulator-vcc-2v0-pldo-s3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_2v0_pldo_s3";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ vin-supply = <&vcc_sys>;
+ };
+
+ vcc_3v3_s0: regulator-vcc-3v3-s0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_3v3_s0";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_3v3_s3>;
+ };
+
+ vcc3v3_sd: regulator-vcc-3v3-sd {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc_pwren>;
+ regulator-name = "vcc3v3_sd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_3v3_s0>;
+ };
+
+ vcc_ufs_s0: regulator-vcc-ufs-s0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_ufs_s0";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_sys>;
+ };
+
+ vcc_wifi_reg_on: regulator-wifi-reg-on {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpios = <&gpio1 RK_PC6 GPIO_ACTIVE_HIGH>;
+ pinctrl-0 = <&wifi_reg_on>;
+ pinctrl-names = "default";
+ regulator-name = "wifi_reg_on";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vcc_1v8_s3>;
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hp_det>;
+ simple-audio-card,name = "On-board Analog ES8388";
+ simple-audio-card,aux-devs = <&hp_power>, <&spk_power>;
+ simple-audio-card,bitclock-master = <&masterdai>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,frame-master = <&masterdai>;
+ simple-audio-card,hp-det-gpios = <&gpio0 RK_PD3 GPIO_ACTIVE_LOW>;
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,pin-switches = "Headphones", "Speaker", "Main Mic", "Headset Mic";
+ simple-audio-card,routing =
+ "Headphone Power INL", "LOUT1",
+ "Headphone Power INR", "ROUT1",
+ "Speaker Power INL", "LOUT2",
+ "Speaker Power INR", "ROUT2",
+ "Headphones", "Headphone Power OUTL",
+ "Headphones", "Headphone Power OUTR",
+ "Speaker", "Speaker Power OUTL",
+ "Speaker", "Speaker Power OUTR",
+ "LINPUT1", "Main Mic",
+ "LINPUT2", "Main Mic",
+ "RINPUT1", "Headset Mic",
+ "RINPUT2", "Headset Mic";
+ simple-audio-card,widgets =
+ "Microphone", "Main Mic",
+ "Microphone", "Headset Mic",
+ "Headphone", "Headphones",
+ "Speaker", "Speaker";
+
+ simple-audio-card,cpu {
+ sound-dai = <&sai1>;
+ };
+
+ masterdai: simple-audio-card,codec {
+ sound-dai = <&es8388>;
+ system-clock-frequency = <12288000>;
+ };
+ };
+
+ hp_power: headphone-amplifier {
+ compatible = "simple-audio-amplifier";
+ enable-gpios = <&gpio3 RK_PD6 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hp_ctl>;
+ sound-name-prefix = "Headphone Power";
+ };
+
+ spk_power: speaker-amplifier {
+ compatible = "simple-audio-amplifier";
+ enable-gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spk_ctl>;
+ sound-name-prefix = "Speaker Power";
+ VCC-supply = <&vcc5v0_device>;
+ };
+};
+
+&cpu_l0 {
+ cpu-supply = <&vdd_cpu_lit_s0>;
+};
+
+&cpu_b0 {
+ cpu-supply = <&vdd_cpu_big_s0>;
+};
+
+&combphy0_ps {
+ status = "okay";
+};
+
+&combphy1_psu {
+ status = "okay";
+};
+
+&edp {
+ status = "okay";
+ pinctrl-names = "default";
+ /*
+ * Please check the switch of GPIO4_C1, it may not be switched to
+ * eDP HPD function by default.
+ */
+ pinctrl-0 = <&edp_txm0_pins>;
+ // pinctrl-0 = <&edp0_hpd>;
+ // hpd-gpios = <&gpio4 RK_PC1 GPIO_ACTIVE_HIGH>;
+};
+
+// &pinctrl {
+// edp {
+// edp0_hpd: edp0-hpd {
+// rockchip,pins = <4 RK_PC1 0 &pcfg_pull_none>;
+// };
+// };
+// };
+
+&edp_in {
+ edp_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_edp>;
+ };
+};
+
+&edp_out {
+ edp_out_conn: endpoint {
+ remote-endpoint = <&dp_con_in>;
+ };
+};
+
+&gmac0 {
+ clock_in_out = "output";
+ phy-mode = "rgmii-rxid";
+ phy-handle = <&rgmii_phy0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <ð0m0_miim
+ ð0m0_tx_bus2
+ ð0m0_rx_bus2
+ ð0m0_rgmii_clk
+ ð0m0_rgmii_bus
+ ðm0_clk0_25m_out>;
+ tx_delay = <0x21>;
+ status = "okay";
+};
+
+&gmac1 {
+ clock_in_out = "output";
+ phy-handle = <&rgmii_phy1>;
+ phy-mode = "rgmii-rxid";
+ pinctrl-names = "default";
+ pinctrl-0 = <ð1m0_miim
+ ð1m0_tx_bus2
+ ð1m0_rx_bus2
+ ð1m0_rgmii_clk
+ ð1m0_rgmii_bus
+ ðm0_clk1_25m_out>;
+ tx_delay = <0x20>;
+ status = "okay";
+};
+
+&gpu {
+ mali-supply = <&vdd_gpu_s0>;
+ status = "okay";
+};
+
+&hdmi {
+ status = "disabled";
+};
+
+&hdmi_sound {
+ status = "disabled";
+};
+
+&hdptxphy {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+
+ rk806: pmic@23 {
+ compatible = "rockchip,rk806";
+ reg = <0x23>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
+ <&rk806_dvs2_null>, <&rk806_dvs3_null>;
+ system-power-controller;
+
+ vcc1-supply = <&vcc_sys>;
+ vcc2-supply = <&vcc_sys>;
+ vcc3-supply = <&vcc_sys>;
+ vcc4-supply = <&vcc_sys>;
+ vcc5-supply = <&vcc_sys>;
+ vcc6-supply = <&vcc_sys>;
+ vcc7-supply = <&vcc_sys>;
+ vcc8-supply = <&vcc_sys>;
+ vcc9-supply = <&vcc_sys>;
+ vcc10-supply = <&vcc_sys>;
+ vcc11-supply = <&vcc_2v0_pldo_s3>;
+ vcc12-supply = <&vcc_sys>;
+ vcc13-supply = <&vcc_1v1_nldo_s3>;
+ vcc14-supply = <&vcc_1v1_nldo_s3>;
+ vcca-supply = <&vcc_sys>;
+
+ rk806_dvs1_null: dvs1-null-pins {
+ pins = "gpio_pwrctrl1";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs2_null: dvs2-null-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs3_null: dvs3-null-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun0";
+ };
+
+ rk806_dvs1_slp: dvs1-slp-pins {
+ pins = "gpio_pwrctrl1";
+ function = "pin_fun1";
+ };
+
+ rk806_dvs1_pwrdn: dvs1-pwrdn-pins {
+ pins = "gpio_pwrctrl1";
+ function = "pin_fun2";
+ };
+
+ rk806_dvs1_rst: dvs1-rst-pins {
+ pins = "gpio_pwrctrl1";
+ function = "pin_fun3";
+ };
+
+ rk806_dvs2_slp: dvs2-slp-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun1";
+ };
+
+ rk806_dvs2_pwrdn: dvs2-pwrdn-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun2";
+ };
+
+ rk806_dvs2_rst: dvs2-rst-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun3";
+ };
+
+ rk806_dvs2_dvs: dvs2-dvs-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun4";
+ };
+
+ rk806_dvs2_gpio: dvs2-gpio-pins {
+ pins = "gpio_pwrctrl2";
+ function = "pin_fun5";
+ };
+
+ rk806_dvs3_slp: dvs3-slp-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun1";
+ };
+
+ rk806_dvs3_pwrdn: dvs3-pwrdn-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun2";
+ };
+
+ rk806_dvs3_rst: dvs3-rst-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun3";
+ };
+
+ rk806_dvs3_dvs: dvs3-dvs-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun4";
+ };
+
+ rk806_dvs3_gpio: dvs3-gpio-pins {
+ pins = "gpio_pwrctrl3";
+ function = "pin_fun5";
+ };
+
+ regulators {
+ vdd_cpu_big_s0: dcdc-reg1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_cpu_big_s0";
+ regulator-enable-ramp-delay = <400>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_npu_s0: dcdc-reg2 {
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_npu_s0";
+ regulator-enable-ramp-delay = <400>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_cpu_lit_s0: dcdc-reg3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_cpu_lit_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vcc_3v3_s3: dcdc-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc_3v3_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vdd_gpu_s0: dcdc-reg5 {
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <900000>;
+ regulator-ramp-delay = <12500>;
+ regulator-name = "vdd_gpu_s0";
+ regulator-enable-ramp-delay = <400>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <850000>;
+ };
+ };
+
+ vddq_ddr_s0: dcdc-reg6 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-name = "vddq_ddr_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_logic_s0: dcdc-reg7 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <800000>;
+ regulator-name = "vdd_logic_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8_s3: dcdc-reg8 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcc_1v8_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vdd2_ddr_s3: dcdc-reg9 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-name = "vdd2_ddr_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vdd_ddr_s0: dcdc-reg10 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-name = "vdd_ddr_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcca_1v8_s0: pldo-reg1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcca_1v8_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcca1v8_pldo2_s0: pldo-reg2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcca1v8_pldo2_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda_1v2_s0: pldo-reg3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-name = "vdda_1v2_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcca_3v3_s0: pldo-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcca_3v3_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd_s0: pldo-reg5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vccio_sd_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcca1v8_pldo6_s3: pldo-reg6 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcca1v8_pldo6_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vdd_0v75_s3: nldo-reg1 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <550000>;
+ regulator-max-microvolt = <750000>;
+ regulator-name = "vdd_0v75_s3";
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <750000>;
+ };
+ };
+
+ vdda_ddr_pll_s0: nldo-reg2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-name = "vdda_ddr_pll_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda0v75_hdmi_s0: nldo-reg3 {
+ regulator-boot-on;
+ regulator-min-microvolt = <837500>;
+ regulator-max-microvolt = <837500>;
+ regulator-name = "vdda0v75_hdmi_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda_0v85_s0: nldo-reg4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <850000>;
+ regulator-max-microvolt = <850000>;
+ regulator-name = "vdda_0v85_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda_0v75_s0: nldo-reg5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <750000>;
+ regulator-name = "vdda_0v75_s0";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&i2c2 {
+ status = "okay";
+
+ hym8563: rtc@51 {
+ compatible = "haoyu,hym8563";
+ reg = <0x51>;
+ clock-output-names = "hym8563";
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PA0 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&rtc_int>;
+ wakeup-source;
+ #clock-cells = <0>;
+ };
+};
+
+&i2c3 {
+ status = "okay";
+
+ es8388: audio-codec@10 {
+ compatible = "everest,es8388", "everest,es8328";
+ reg = <0x10>;
+ AVDD-supply = <&vcca_3v3_s0>;
+ DVDD-supply = <&vcc_1v8_s0>;
+ HPVDD-supply = <&vcca_3v3_s0>;
+ PVDD-supply = <&vcc_1v8_s0>;
+ assigned-clocks = <&cru CLK_SAI1_MCLKOUT_TO_IO>;
+ assigned-clock-rates = <12288000>;
+ clocks = <&cru CLK_SAI1_MCLKOUT_TO_IO>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sai1m0_mclk>;
+ #sound-dai-cells = <0>;
+ };
+};
+
+&mdio0 {
+ rgmii_phy0: ethernet-phy@1 {
+ compatible = "ethernet-phy-id001c.c916";
+ reg = <0x1>;
+ clocks = <&cru REFCLKO25M_GMAC0_OUT>;
+ assigned-clocks = <&cru REFCLKO25M_GMAC0_OUT>;
+ assigned-clock-rates = <25000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmii_phy0_rst>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <100000>;
+ reset-gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&mdio1 {
+ rgmii_phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-id001c.c916";
+ reg = <0x1>;
+ clocks = <&cru REFCLKO25M_GMAC1_OUT>;
+ assigned-clocks = <&cru REFCLKO25M_GMAC1_OUT>;
+ assigned-clock-rates = <25000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmii_phy1_rst>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <100000>;
+ reset-gpios = <&gpio3 RK_PA3 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&pcie0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie0_rst>;
+ reset-gpios = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc_3v3_s3>;
+ status = "okay";
+
+ pcie@0,0 {
+ reg = <0x0 0 0 0 0>;
+ bus-range = <0x0 0xf>;
+ device_type = "pci";
+ ranges;
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ wifi: wifi@0,0 {
+ compatible = "pci14e4,449d";
+ reg = <0x10000 0 0 0 0>;
+ clocks = <&hym8563>;
+ clock-names = "lpo";
+ };
+ };
+};
+
+&pcie1 {
+ reset-gpios = <&gpio4 RK_PC4 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie1>;
+
+ /*
+ * Disable usb_drd1_dwc3 if enabling pcie1 and set Dial_Switch_1
+ * to low state according to the schematic of page 17.
+ */
+ status = "disabled";
+};
+
+&pinctrl {
+ gpio_pwm0 {
+ gpio_pwm0_pin: gpio-pwm0-pin {
+ rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ audio {
+ hp_det: hp-det {
+ rockchip,pins = <0 RK_PD3 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
+ hp_ctl: hp-ctl {
+ rockchip,pins = <3 RK_PD6 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+
+ spk_ctl: spk-ctl {
+ rockchip,pins = <2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ bluetooth {
+ bt_reg_on: bt-reg-on {
+ rockchip,pins = <1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
+ bt_wake_host: bt-wake-host {
+ rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+
+ host_wake_bt: host-wake-bt {
+ rockchip,pins = <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ hdmi {
+ hdmi_tx_on_h: hdmi-tx-on-h {
+ rockchip,pins = <2 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ hym8563 {
+ rtc_int: rtc-int {
+ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ network {
+ rgmii_phy0_rst: rgmii-phy0-rst {
+ rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ rgmii_phy1_rst: rgmii-phy1-rst {
+ rockchip,pins = <3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pcie0 {
+ pcie0_rst: pcie0-rst {
+ rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ sdmmc {
+ sdmmc_pwren: sdmmc-pwren {
+ rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ usb {
+ usb_host_pwren: usb-host-pwren {
+ rockchip,pins = <0 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ usb_otg0_pwren: usb-otg0-pwren {
+ rockchip,pins = <0 RK_PD1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ usbc0_int: usbc0-int {
+ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ wifi {
+ wifi_reg_on: wifi-reg-on {
+ rockchip,pins = <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
+ wifi_wake_host: wifi-wake-host {
+ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+};
+
+&sai1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sai1m0_lrck
+ &sai1m0_sclk
+ &sai1m0_sdi0
+ &sai1m0_sdo0>;
+ status = "okay";
+};
+
+&sai6 {
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ full-pwr-cycle-in-suspend;
+ max-frequency = <200000000>;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+ no-sdio;
+ no-sd;
+ non-removable;
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ max-frequency = <200000000>;
+ no-sdio;
+ no-mmc;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc3v3_sd>;
+ vqmmc-supply = <&vccio_sd_s0>;
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcca_1v8_s0>;
+ status = "okay";
+};
+
+&u2phy0 {
+ status = "okay";
+};
+
+&u2phy0_otg {
+ phy-supply = <&vbus5v0_typec>;
+ status = "okay";
+};
+
+&u2phy1 {
+ status = "okay";
+};
+
+&u2phy1_otg {
+ phy-supply = <&vcc5v0_host>;
+ status = "okay";
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-0 = <&uart4m1_xfer &uart4m1_ctsn &uart4m1_rtsn>;
+ pinctrl-names = "default";
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm43438-bt";
+ clocks = <&hym8563>;
+ clock-names = "lpo";
+ device-wakeup-gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PB1 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&bt_reg_on &bt_wake_host &host_wake_bt>;
+ pinctrl-names = "default";
+ shutdown-gpios = <&gpio1 RK_PC7 GPIO_ACTIVE_HIGH>;
+ vbat-supply = <&vcc_3v3_s3>;
+ vddio-supply = <&vcc_1v8_s3>;
+ };
+};
+
+&ufshc {
+ status = "okay";
+};
+
+&usbdp_phy {
+ rockchip,dp-lane-mux = <2 3>;
+ status = "okay";
+};
+
+&usb_drd0_dwc3 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb_drd1_dwc3 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&vop {
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_edp: endpoint@ROCKCHIP_VOP2_EP_EDP0 {
+ reg = <ROCKCHIP_VOP2_EP_EDP0>;
+ remote-endpoint = <&edp_in_vp0>;
+ };
+};
--
2.34.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP
2026-07-31 3:08 ` Damon Ding
@ 2026-07-31 9:23 ` Heiko Stübner
[not found] ` <44ff5316-43cc-46be-b947-ea6e1f5da1bb@rock-chips.com>
0 siblings, 1 reply; 17+ messages in thread
From: Heiko Stübner @ 2026-07-31 9:23 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Andy Yan, Damon Ding
Cc: Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Dmitry Baryshkov, Marek Szyprowski, Sebastian Reichel, dri-devel,
devicetree, linux-kernel, linux-rockchip, linux-arm-kernel
Hi Damon,
Am Freitag, 31. Juli 2026, 05:08:45 Mitteleuropäische Sommerzeit schrieb Damon Ding:
> On 7/31/2026 2:49 AM, Heiko Stübner wrote:
> > Am Donnerstag, 30. Juli 2026, 05:27:37 Mitteleuropäische Sommerzeit schrieb Damon Ding:
> >> This series improves the HPD (Hotplug Detect) interrupt handling in
> >> the Analogix DP driver to enable reliable native HPD pin detection on
> >> Rockchip platforms, and introduces platform-specific HPD detection
> >> schemes with fine-grained interrupt control.
> >
> > [...]
> >
> >> Tested on RK3576 with both native HPD pin and GPIO HPD configurations.
> >>
> >> Native HPD pin mode:
> >>
> >> &edp {
> >> status = "okay";
> >> pinctrl-names = "default";
> >> pinctrl-0 = <&edp_txm0_pins>;
> >> };
> >>
> >> GPIO HPD mode:
> >>
> >> &edp {
> >> status = "okay";
> >> pinctrl-names = "default";
> >> pinctrl-0 = <&edp0_hpd>;
> >> hpd-gpios = <&gpio4 RK_PC1 GPIO_ACTIVE_HIGH>;
> >> };
> >>
> >> &pinctrl {
> >> edp {
> >> edp0_hpd: edp0-hpd {
> >> rockchip,pins = <4 RK_PC1 0 &pcfg_pull_none>;
> >> };
> >> };
> >> };
> >
> > Yay and thanks a lot for working on that.
> >
> > If I roll my display-port carrier board back to the analogix-dp being
> > the endpoint, this works exactly as expected :-) .
> >
> > I can plug in the display at some point after the boot and have it
> > detected and setup correctly. Same with unplugging it while
> > the system is running. The connection status is correctly reported
> > in sysfs.
> >
> >
> > Though there is a caveat. When the eDP is not the last part, this does not
> > work anymore. The detect function always returns "connected" if there is
> > a next bridge available.
> >
> > My board [0] has a physical DP connector on it, so models it as
> > dp-connector, but in that case the Analogix driver always reports being
> > connected.
> >
> >
> > [0] https://lore.kernel.org/linux-rockchip/20251009225050.88192-3-heiko@sntech.de/
> > ... same effect with hpd-gpios in either the edp node or dp-connector node
> >
> >
>
> My previous tests were carried out on the modified RK3576 IOTEST board
> DTS based on RK3576 EVB1, which includes dp-connector by default. I also
> did extra verification without dp-connector, and HPD detection works
> correctly in both cases.
>
> I've taken a look at the Tiger board DT configuration. The pinctrl
> settings for the eDP HPD GPIO may need adjustment:
>
> &pinctrl {
> edp0 {
> edp0_hpd_l: edp0-hpd-l-pin {
> rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>;
> };
> };
> };
>
> It is recommended to configure GPIO4B5 as pull-down or pll-none. Pull-up
> configuration may prevent GPIO interrupts from being triggered properly,
> resulting in a permanent "connected" status.
At least on that DP-carrier the pin direction is different.
I.e. it is active-low, meaning 0 for plugged in.
In the schematics I do see a hw pull up too - so pull-none in the pinconfig
would also be possible, but pull-down is definitly wrong on _this_ board.
So we're talking about the same code, I put the dts up on [0] .
I'm currently running with a printk diff [1] to showcase the issue.
So on boot, with the display unplugged I get:
[ 14.757911] ---> drm_bridge_connector_detect: detect
[ 14.757914] ---> analogix_dp_bridge_detect a
[ 14.757918] ---> drm_bridge_connector_detect: detect
[ 14.773779] ---> analogix_dp_bridge_detect a
[ 14.838658] rockchip-dp fdec0000.edp: failed to read dpcd caps: -110
[ 14.838662] [drm:analogix_dp_bridge_atomic_enable [analogix_dp]] *ERROR* dp commit error, ret = -110
[ 14.838670] rockchip-dp fdec0000.edp: failed to set bridge, retry: 0
[ 14.884791] rockchip-dp fdec0000.edp: failed to read dpcd caps: -110
[ 14.884793] [drm:analogix_dp_bridge_atomic_enable [analogix_dp]] *ERROR* dp commit error, ret = -110
[ 14.884796] rockchip-dp fdec0000.edp: failed to set bridge, retry: 1
[ 14.930925] rockchip-dp fdec0000.edp: failed to read dpcd caps: -110
[ 14.930927] [drm:analogix_dp_bridge_atomic_enable [analogix_dp]] *ERROR* dp commit error, ret = -110
[ 14.930930] rockchip-dp fdec0000.edp: failed to set bridge, retry: 2
[ 14.977032] rockchip-dp fdec0000.edp: failed to read dpcd caps: -110
[ 14.977034] [drm:analogix_dp_bridge_atomic_enable [analogix_dp]] *ERROR* dp commit error, ret = -110
[ 14.977037] rockchip-dp fdec0000.edp: failed to set bridge, retry: 3
[ 15.023150] rockchip-dp fdec0000.edp: failed to read dpcd caps: -110
[ 15.023152] [drm:analogix_dp_bridge_atomic_enable [analogix_dp]] *ERROR* dp commit error, ret = -110
[ 15.023155] rockchip-dp fdec0000.edp: failed to set bridge, retry: 4
[ 15.023168] rockchip-dp fdec0000.edp: too many times retry set bridge, give it up
[ 15.052485] Console: switching to colour frame buffer device 80x30
[ 15.210457] rockchip-drm display-subsystem: [drm] fb0: rockchipdrmfb frame buffer device
[ 15.223444] ---> drm_bridge_connector_detect: detect
[ 15.231974] ---> analogix_dp_bridge_detect a
[ 15.239587] ---> drm_bridge_connector_detect: detect
[ 15.245341] ---> analogix_dp_bridge_detect a
So analogix_dp_bridge_detect() is called and always returns connected.
Plugging in the the display, I get:
[ 290.592096] ---> display_connector_detect gpio value is 1 {display-connector returning connected}
[ 290.598648] ---> drm_bridge_connector_detect: detect
[ 290.604637] ---> analogix_dp_bridge_detect a
[ 290.609826] ---> drm_bridge_connector_detect: detect
[ 290.615784] ---> analogix_dp_bridge_detect a
Unplugging the display, I get:
[ 302.081444] ---> display_connector_detect gpio value is 0 {display-connector returning disconnected}
[ 302.087996] ---> drm_bridge_connector_detect: detect
[ 302.093945] ---> analogix_dp_bridge_detect a
[ 302.099131] ---> drm_bridge_connector_detect: detect
[ 302.105090] ---> analogix_dp_bridge_detect a
[ 302.144834] ---> drm_bridge_connector_detect: detect
[ 302.150784] ---> analogix_dp_bridge_detect a
[ 302.155933] ---> drm_bridge_connector_detect: detect
[ 302.161859] ---> analogix_dp_bridge_detect a
So it looks like on the gpio-side the detection is correct and/but
analogix_dp_bridge_detect() is always returning a connected state
("b" output is never reached).
I'm still working on understanding how the whole detection logic works
in drm ;-) .
Heiko
[0] https://github.com/mmind/linux-rockchip/blob/dev/v7.3/rk3588-tiger-dp-carrier-v5/arch/arm64/boot/dts/rockchip/rk3588-tiger-displayport-carrier.dts
[1]
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 7a89548a7a885..0accdf62637ae 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -915,8 +915,10 @@ analogix_dp_bridge_detect(struct drm_bridge *bridge, struct drm_connector *conne
struct analogix_dp_device *dp = to_dp(bridge);
enum drm_connector_status status = connector_status_disconnected;
+printk("---> %s a\n", __func__);
if (dp->plat_data->next_bridge)
return connector_status_connected;
+printk("---> %s b\n", __func__);
if (!analogix_dp_detect_hpd(dp))
status = connector_status_connected;
diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c
index 16c0631adeb18..b0c07694b82e3 100644
--- a/drivers/gpu/drm/bridge/display-connector.c
+++ b/drivers/gpu/drm/bridge/display-connector.c
@@ -45,6 +45,7 @@ static enum drm_connector_status display_connector_detect(struct drm_bridge *bri
struct display_connector *conn = to_display_connector(bridge);
if (conn->hpd_gpio) {
+printk("---> %s gpio value is %d\n", __func__, gpiod_get_value_cansleep(conn->hpd_gpio));
if (gpiod_get_value_cansleep(conn->hpd_gpio))
return connector_status_connected;
else
@@ -84,6 +85,7 @@ static enum drm_connector_status display_connector_detect(struct drm_bridge *bri
static enum drm_connector_status
display_connector_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector)
{
+printk("---> %s\n", __func__);
return display_connector_detect(bridge);
}
diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c
index 649969fca1413..8816d837c9a77 100644
--- a/drivers/gpu/drm/display/drm_bridge_connector.c
+++ b/drivers/gpu/drm/display/drm_bridge_connector.c
@@ -218,6 +218,7 @@ drm_bridge_connector_detect(struct drm_connector *connector, bool force)
enum drm_connector_status status;
if (detect) {
+printk("---> %s: detect\n", __func__);
status = detect->funcs->detect(detect, connector);
if (hdmi)
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP
[not found] ` <44ff5316-43cc-46be-b947-ea6e1f5da1bb@rock-chips.com>
@ 2026-07-31 10:30 ` Heiko Stübner
0 siblings, 0 replies; 17+ messages in thread
From: Heiko Stübner @ 2026-07-31 10:30 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Andy Yan, Damon Ding
Cc: Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Dmitry Baryshkov, Marek Szyprowski, Sebastian Reichel, dri-devel,
devicetree, linux-kernel, linux-rockchip, linux-arm-kernel
Hi Damon,
Am Freitag, 31. Juli 2026, 11:55:42 Mitteleuropäische Sommerzeit schrieb Damon Ding:
> On 7/31/2026 5:23 PM, Heiko Stübner wrote:
> > Am Freitag, 31. Juli 2026, 05:08:45 Mitteleuropäische Sommerzeit schrieb Damon Ding:
> >> On 7/31/2026 2:49 AM, Heiko Stübner wrote:
> >>> Am Donnerstag, 30. Juli 2026, 05:27:37 Mitteleuropäische Sommerzeit schrieb Damon Ding:
> >>>> This series improves the HPD (Hotplug Detect) interrupt handling in
> >>>> the Analogix DP driver to enable reliable native HPD pin detection on
> >>>> Rockchip platforms, and introduces platform-specific HPD detection
> >>>> schemes with fine-grained interrupt control.
> >>>
> >>> [...]
> >>>
> >>>> Tested on RK3576 with both native HPD pin and GPIO HPD configurations.
> >>>>
> >>>> Native HPD pin mode:
> >>>>
> >>>> &edp {
> >>>> status = "okay";
> >>>> pinctrl-names = "default";
> >>>> pinctrl-0 = <&edp_txm0_pins>;
> >>>> };
> >>>>
> >>>> GPIO HPD mode:
> >>>>
> >>>> &edp {
> >>>> status = "okay";
> >>>> pinctrl-names = "default";
> >>>> pinctrl-0 = <&edp0_hpd>;
> >>>> hpd-gpios = <&gpio4 RK_PC1 GPIO_ACTIVE_HIGH>;
> >>>> };
> >>>>
> >>>> &pinctrl {
> >>>> edp {
> >>>> edp0_hpd: edp0-hpd {
> >>>> rockchip,pins = <4 RK_PC1 0 &pcfg_pull_none>;
> >>>> };
> >>>> };
> >>>> };
> >>>
> >>> Yay and thanks a lot for working on that.
> >>>
> >>> If I roll my display-port carrier board back to the analogix-dp being
> >>> the endpoint, this works exactly as expected :-) .
> >>>
> >>> I can plug in the display at some point after the boot and have it
> >>> detected and setup correctly. Same with unplugging it while
> >>> the system is running. The connection status is correctly reported
> >>> in sysfs.
> >>>
> >>>
> >>> Though there is a caveat. When the eDP is not the last part, this does not
> >>> work anymore. The detect function always returns "connected" if there is
> >>> a next bridge available.
> >>>
> >>> My board [0] has a physical DP connector on it, so models it as
> >>> dp-connector, but in that case the Analogix driver always reports being
> >>> connected.
> >>>
> >>>
> >>> [0] https://lore.kernel.org/linux-rockchip/20251009225050.88192-3-heiko@sntech.de/
> >>> ... same effect with hpd-gpios in either the edp node or dp-connector node
> >>>
> >>>
> >>
> >> My previous tests were carried out on the modified RK3576 IOTEST board
> >> DTS based on RK3576 EVB1, which includes dp-connector by default. I also
> >> did extra verification without dp-connector, and HPD detection works
> >> correctly in both cases.
> >>
> >> I've taken a look at the Tiger board DT configuration. The pinctrl
> >> settings for the eDP HPD GPIO may need adjustment:
> >>
> >> &pinctrl {
> >> edp0 {
> >> edp0_hpd_l: edp0-hpd-l-pin {
> >> rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>;
> >> };
> >> };
> >> };
> >>
> >> It is recommended to configure GPIO4B5 as pull-down or pll-none. Pull-up
> >> configuration may prevent GPIO interrupts from being triggered properly,
> >> resulting in a permanent "connected" status.
> >
> > At least on that DP-carrier the pin direction is different.
> > I.e. it is active-low, meaning 0 for plugged in.
> >
> > In the schematics I do see a hw pull up too - so pull-none in the pinconfig
> > would also be possible, but pull-down is definitly wrong on _this_ board.
> >
> > So we're talking about the same code, I put the dts up on [0] .
> >
> > I'm currently running with a printk diff [1] to showcase the issue.
> >
> > So on boot, with the display unplugged I get:
> > [ 14.757911] ---> drm_bridge_connector_detect: detect
> > [ 14.757914] ---> analogix_dp_bridge_detect a
> > [ 14.757918] ---> drm_bridge_connector_detect: detect
> > [ 14.773779] ---> analogix_dp_bridge_detect a
> > [ 14.838658] rockchip-dp fdec0000.edp: failed to read dpcd caps: -110
> > [ 14.838662] [drm:analogix_dp_bridge_atomic_enable [analogix_dp]] *ERROR* dp commit error, ret = -110
> > [ 14.838670] rockchip-dp fdec0000.edp: failed to set bridge, retry: 0
> > [ 14.884791] rockchip-dp fdec0000.edp: failed to read dpcd caps: -110
> > [ 14.884793] [drm:analogix_dp_bridge_atomic_enable [analogix_dp]] *ERROR* dp commit error, ret = -110
> > [ 14.884796] rockchip-dp fdec0000.edp: failed to set bridge, retry: 1
> > [ 14.930925] rockchip-dp fdec0000.edp: failed to read dpcd caps: -110
> > [ 14.930927] [drm:analogix_dp_bridge_atomic_enable [analogix_dp]] *ERROR* dp commit error, ret = -110
> > [ 14.930930] rockchip-dp fdec0000.edp: failed to set bridge, retry: 2
> > [ 14.977032] rockchip-dp fdec0000.edp: failed to read dpcd caps: -110
> > [ 14.977034] [drm:analogix_dp_bridge_atomic_enable [analogix_dp]] *ERROR* dp commit error, ret = -110
> > [ 14.977037] rockchip-dp fdec0000.edp: failed to set bridge, retry: 3
> > [ 15.023150] rockchip-dp fdec0000.edp: failed to read dpcd caps: -110
> > [ 15.023152] [drm:analogix_dp_bridge_atomic_enable [analogix_dp]] *ERROR* dp commit error, ret = -110
> > [ 15.023155] rockchip-dp fdec0000.edp: failed to set bridge, retry: 4
> > [ 15.023168] rockchip-dp fdec0000.edp: too many times retry set bridge, give it up
> > [ 15.052485] Console: switching to colour frame buffer device 80x30
> > [ 15.210457] rockchip-drm display-subsystem: [drm] fb0: rockchipdrmfb frame buffer device
> > [ 15.223444] ---> drm_bridge_connector_detect: detect
> > [ 15.231974] ---> analogix_dp_bridge_detect a
> > [ 15.239587] ---> drm_bridge_connector_detect: detect
> > [ 15.245341] ---> analogix_dp_bridge_detect a
> >
> > So analogix_dp_bridge_detect() is called and always returns connected.
> >
> > Plugging in the the display, I get:
> > [ 290.592096] ---> display_connector_detect gpio value is 1 {display-connector returning connected}
> > [ 290.598648] ---> drm_bridge_connector_detect: detect
> > [ 290.604637] ---> analogix_dp_bridge_detect a
> > [ 290.609826] ---> drm_bridge_connector_detect: detect
> > [ 290.615784] ---> analogix_dp_bridge_detect a
> >
> > Unplugging the display, I get:
> > [ 302.081444] ---> display_connector_detect gpio value is 0 {display-connector returning disconnected}
> > [ 302.087996] ---> drm_bridge_connector_detect: detect
> > [ 302.093945] ---> analogix_dp_bridge_detect a
> > [ 302.099131] ---> drm_bridge_connector_detect: detect
> > [ 302.105090] ---> analogix_dp_bridge_detect a
> > [ 302.144834] ---> drm_bridge_connector_detect: detect
> > [ 302.150784] ---> analogix_dp_bridge_detect a
> > [ 302.155933] ---> drm_bridge_connector_detect: detect
> > [ 302.161859] ---> analogix_dp_bridge_detect a
> >
> >
> > So it looks like on the gpio-side the detection is correct and/but
> > analogix_dp_bridge_detect() is always returning a connected state
> > ("b" output is never reached).
> >
> > I'm still working on understanding how the whole detection logic works
> > in drm ;-) .
> >
> >
>
> I think I've spotted the environmental difference between our setups.
> Your DTS places the hpd-gpios property under the dp-connector node,
> which is a scenario I haven't covered yet. I will reproduce and test
> this case locally.
>
> As a quick experiment, could you try removing hpd-gpios from
> dp-connector and move it under the edp node instead? As expected, GPIO
> HPD should work properly with that configuration.
I've updated the branch in [0] with that hpd move to the edp node, but
the result is similar:
With the panel _disconnected_ on boot I see
[ 12.887555] ---> drm_bridge_connector_detect: detect
[ 12.893104] ---> analogix_dp_bridge_detect a
[ 12.897881] ---> drm_bridge_connector_detect: detect
[ 12.903424] ---> analogix_dp_bridge_detect a
[ 14.124848] [drm:analogix_dp_bridge_atomic_enable [analogix_dp]] *ERROR* failed to get hpd single ret = -110
[ 14.124891] rockchip-dp fdec0000.edp: failed to set bridge, retry: 0
[ 14.236031] [drm:analogix_dp_bridge_atomic_enable [analogix_dp]] *ERROR* failed to get hpd single ret = -110
[ 14.236074] rockchip-dp fdec0000.edp: failed to set bridge, retry: 1
[ 14.346940] [drm:analogix_dp_bridge_atomic_enable [analogix_dp]] *ERROR* failed to get hpd single ret = -110
[ 14.346990] rockchip-dp fdec0000.edp: failed to set bridge, retry: 2
[ 14.458590] [drm:analogix_dp_bridge_atomic_enable [analogix_dp]] *ERROR* failed to get hpd single ret = -110
[ 14.458638] rockchip-dp fdec0000.edp: failed to set bridge, retry: 3
[ 14.570262] [drm:analogix_dp_bridge_atomic_enable [analogix_dp]] *ERROR* failed to get hpd single ret = -110
[ 14.570312] rockchip-dp fdec0000.edp: failed to set bridge, retry: 4
[ 14.570328] rockchip-dp fdec0000.edp: too many times retry set bridge, give it up
[ 14.751371] ---> drm_bridge_connector_detect: detect
[ 14.757207] ---> analogix_dp_bridge_detect a
So with the diff from earlier, analogix_dp_bridge_detect() still runs,
finds its next bridge and returns "connected".
I.e. the
> > if (dp->plat_data->next_bridge)
> > return connector_status_connected;
part.
Heiko
> > [0] https://github.com/mmind/linux-rockchip/blob/dev/v7.3/rk3588-tiger-dp-carrier-v5/arch/arm64/boot/dts/rockchip/rk3588-tiger-displayport-carrier.dts
> > [1]
> > diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> > index 7a89548a7a885..0accdf62637ae 100644
> > --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> > +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> > @@ -915,8 +915,10 @@ analogix_dp_bridge_detect(struct drm_bridge *bridge, struct drm_connector *conne
> > struct analogix_dp_device *dp = to_dp(bridge);
> > enum drm_connector_status status = connector_status_disconnected;
> >
> > +printk("---> %s a\n", __func__);
> > if (dp->plat_data->next_bridge)
> > return connector_status_connected;
> > +printk("---> %s b\n", __func__);
> >
> > if (!analogix_dp_detect_hpd(dp))
> > status = connector_status_connected;
> > diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c
> > index 16c0631adeb18..b0c07694b82e3 100644
> > --- a/drivers/gpu/drm/bridge/display-connector.c
> > +++ b/drivers/gpu/drm/bridge/display-connector.c
> > @@ -45,6 +45,7 @@ static enum drm_connector_status display_connector_detect(struct drm_bridge *bri
> > struct display_connector *conn = to_display_connector(bridge);
> >
> > if (conn->hpd_gpio) {
> > +printk("---> %s gpio value is %d\n", __func__, gpiod_get_value_cansleep(conn->hpd_gpio));
> > if (gpiod_get_value_cansleep(conn->hpd_gpio))
> > return connector_status_connected;
> > else
> > @@ -84,6 +85,7 @@ static enum drm_connector_status display_connector_detect(struct drm_bridge *bri
> > static enum drm_connector_status
> > display_connector_bridge_detect(struct drm_bridge *bridge, struct drm_connector *connector)
> > {
> > +printk("---> %s\n", __func__);
> > return display_connector_detect(bridge);
> > }
> >
> > diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c
> > index 649969fca1413..8816d837c9a77 100644
> > --- a/drivers/gpu/drm/display/drm_bridge_connector.c
> > +++ b/drivers/gpu/drm/display/drm_bridge_connector.c
> > @@ -218,6 +218,7 @@ drm_bridge_connector_detect(struct drm_connector *connector, bool force)
> > enum drm_connector_status status;
> >
> > if (detect) {
> > +printk("---> %s: detect\n", __func__);
> > status = detect->funcs->detect(detect, connector);
> >
> > if (hdmi)
> >
> >
> >
> >
> >
>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2026-07-31 10:30 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-30 3:27 [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP Damon Ding
2026-07-30 3:27 ` [PATCH v1 1/7] drm/bridge: analogix_dp: Manage pm runtime and IRQ for native HPD pin detection Damon Ding
2026-07-30 3:39 ` sashiko-bot
2026-07-30 3:27 ` [PATCH v1 2/7] drm/bridge: analogix_dp: Return bitmask from analogix_dp_get_irq_type() Damon Ding
2026-07-30 3:41 ` sashiko-bot
2026-07-30 3:27 ` [PATCH v1 3/7] drm/bridge: analogix_dp: Extend mute/unmute HPD interrupts to accept irq bitmask Damon Ding
2026-07-30 3:41 ` sashiko-bot
2026-07-30 3:27 ` [PATCH v1 4/7] drm/bridge: analogix_dp: Extend clear_hotplug_interrupts to accept IRQ bitmask Damon Ding
2026-07-30 3:38 ` sashiko-bot
2026-07-30 3:27 ` [PATCH v1 5/7] drm/bridge: analogix_dp: Simplify analogix_dp_config_interrupt() Damon Ding
2026-07-30 3:27 ` [PATCH v1 6/7] drm/bridge: analogix_dp: Use platform-specific HPD detection scheme Damon Ding
2026-07-30 3:41 ` sashiko-bot
2026-07-30 3:27 ` [PATCH v1 7/7] drm/bridge: analogix_dp: Skip native HPD interrupt ops for GPIO HPD Damon Ding
2026-07-30 18:49 ` [PATCH v1 0/7] Add HPD support for Rockchip Analogix DP Heiko Stübner
2026-07-31 3:08 ` Damon Ding
2026-07-31 9:23 ` Heiko Stübner
[not found] ` <44ff5316-43cc-46be-b947-ea6e1f5da1bb@rock-chips.com>
2026-07-31 10:30 ` Heiko Stübner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox