* [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:27 ` [PATCH v1 2/7] drm/bridge: analogix_dp: Return bitmask from analogix_dp_get_irq_type() Damon Ding
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ 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] 9+ 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: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, 0 replies; 9+ 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] 9+ 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:27 ` [PATCH v1 4/7] drm/bridge: analogix_dp: Extend clear_hotplug_interrupts to accept IRQ bitmask Damon Ding
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ 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] 9+ 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:27 ` [PATCH v1 5/7] drm/bridge: analogix_dp: Simplify analogix_dp_config_interrupt() Damon Ding
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ 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] 9+ 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; 9+ 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] 9+ 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: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, 0 replies; 9+ 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] 9+ 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; 9+ 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] 9+ 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
7 siblings, 0 replies; 9+ 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] 9+ messages in thread