Skip to content

Commit aff469d

Browse files
lumagYongxing Mou
authored andcommitted
FROMLIST: 1drm/bridge: display-connector: trigger initial HPD event for DP
If the DisplayPort drivers use display-connector for the HPD detection, the internal HPD state machine might be not active and thus the hardware might be not able to handle cable detection correctly. Instead it will depend on the externall HPD notifications to set the cable state, bypassing the internal HPD state machine (for example this is the case for the msm DP driver). However if the cable has been plugged before the HPD IRQ has been enabled, there will be no HPD event coming. The drivers might fail detection in such a case. Trigger the HPD notification after enabling the HPD IRQ, propagating the cable insertion state. Fixes: 2e2bf3a ("drm/bridge: display-connector: add DP support") Reported-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com> Link: https://lore.kernel.org/all/20260314-dp-connector-hpd-v1-2-786044cedc17@oss.qualcomm.com/
1 parent 9a754f9 commit aff469d

File tree

1 file changed

+19
-0
lines changed

1 file changed

+19
-0
lines changed

drivers/gpu/drm/bridge/display-connector.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/of.h>
1313
#include <linux/platform_device.h>
1414
#include <linux/regulator/consumer.h>
15+
#include <linux/workqueue.h>
1516

1617
#include <drm/drm_atomic_helper.h>
1718
#include <drm/drm_bridge.h>
@@ -25,6 +26,8 @@ struct display_connector {
2526

2627
struct regulator *supply;
2728
struct gpio_desc *ddc_en;
29+
30+
struct work_struct hpd_work;
2831
};
2932

3033
static inline struct display_connector *
@@ -92,15 +95,29 @@ static void display_connector_hpd_enable(struct drm_bridge *bridge)
9295
struct display_connector *conn = to_display_connector(bridge);
9396

9497
enable_irq(conn->hpd_irq);
98+
99+
if (conn->bridge.type == DRM_MODE_CONNECTOR_DisplayPort)
100+
schedule_work(&conn->hpd_work);
95101
}
96102

97103
static void display_connector_hpd_disable(struct drm_bridge *bridge)
98104
{
99105
struct display_connector *conn = to_display_connector(bridge);
100106

107+
if (conn->bridge.type == DRM_MODE_CONNECTOR_DisplayPort)
108+
cancel_work_sync(&conn->hpd_work);
109+
101110
disable_irq(conn->hpd_irq);
102111
}
103112

113+
static void display_connector_hpd_work(struct work_struct *work)
114+
{
115+
struct display_connector *conn = container_of(work, struct display_connector, hpd_work);
116+
struct drm_bridge *bridge = &conn->bridge;
117+
118+
drm_bridge_hpd_notify(bridge, display_connector_detect(bridge));
119+
}
120+
104121
static const struct drm_edid *display_connector_edid_read(struct drm_bridge *bridge,
105122
struct drm_connector *connector)
106123
{
@@ -395,6 +412,8 @@ static int display_connector_probe(struct platform_device *pdev)
395412
conn->bridge.ops |= DRM_BRIDGE_OP_DETECT;
396413
if (conn->hpd_irq >= 0)
397414
conn->bridge.ops |= DRM_BRIDGE_OP_HPD;
415+
if (conn->hpd_irq >= 0 && type == DRM_MODE_CONNECTOR_DisplayPort)
416+
INIT_WORK(&conn->hpd_work, display_connector_hpd_work);
398417

399418
dev_dbg(&pdev->dev,
400419
"Found %s display connector '%s' %s DDC bus and %s HPD GPIO (ops 0x%x)\n",

0 commit comments

Comments
 (0)