Re: [PATCH v4 37/39] drm/msm/dp: add HPD callback for dp MST

From: Dmitry Baryshkov

Date: Sat Apr 11 2026 - 18:01:20 EST


On Fri, Apr 10, 2026 at 05:34:12PM +0800, Yongxing Mou wrote:
> From: Abhinav Kumar <quic_abhinavk@xxxxxxxxxxx>
>
> Add HPD callback for the MST module which shall be invoked from the
> dp_display's HPD handler to perform MST specific operations in case
> of HPD. In MST case, route the HPD messages to MST module.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@xxxxxxxxxxx>
> Signed-off-by: Yongxing Mou <yongxing.mou@xxxxxxxxxxxxxxxx>
> ---
> drivers/gpu/drm/msm/dp/dp_display.c | 23 +++++++++++++++++++----
> drivers/gpu/drm/msm/dp/dp_mst_drm.c | 34 ++++++++++++++++++++++++++++++++++
> drivers/gpu/drm/msm/dp/dp_mst_drm.h | 1 +
> 3 files changed, 54 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
> index 919767945ba5..ca89e20b7563 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -454,6 +454,9 @@ static int msm_dp_hpd_plug_handle(struct msm_dp_display_private *dp)
> dp->msm_dp_display.connector_type,
> dp->link->sink_count);
>
> + if (dp->plugged)
> + return 0;
> +
> mutex_lock(&dp->plugged_lock);
>
> ret = pm_runtime_resume_and_get(&pdev->dev);
> @@ -556,12 +559,19 @@ static int msm_dp_irq_hpd_handle(struct msm_dp_display_private *dp)
> {
> u32 sink_request;
> int rc = 0;
> + struct msm_dp *msm_dp_display = &dp->msm_dp_display;
>
> /* irq_hpd can happen at either connected or disconnected state */
> drm_dbg_dp(dp->drm_dev, "Before, type=%d, sink_count=%d\n",
> dp->msm_dp_display.connector_type,
> dp->link->sink_count);
>
> + if (msm_dp_display->mst_active) {
> + if (msm_dp_aux_is_link_connected(dp->aux) != ISR_DISCONNECTED)

Will this work for USB-C?

> + msm_dp_mst_display_hpd_irq(&dp->msm_dp_display);
> + return 0;
> + }
> +
> /* check for any test request issued by sink */
> rc = msm_dp_link_process_request(dp->link);
> if (!rc) {
> @@ -1125,9 +1135,13 @@ static irqreturn_t msm_dp_display_irq_thread(int irq, void *dev_id)
> connector_status_connected);
>
> /* Send HPD as connected and distinguish it in the notifier */
> - if (hpd_isr_status & DP_DP_IRQ_HPD_INT_MASK)
> - drm_bridge_hpd_notify(dp->msm_dp_display.bridge,
> - connector_status_connected);
> + if (hpd_isr_status & DP_DP_IRQ_HPD_INT_MASK) {
> + if (dp->msm_dp_display.mst_active)
> + msm_dp_irq_hpd_handle(dp);

No, don't touch this code. HPD notifications might be coming from the
other entities. This IRQ thread can only send the HPD notification.
There rest should be handled in the notifier.

> + else
> + drm_bridge_hpd_notify(dp->msm_dp_display.bridge,
> + connector_status_connected);
> + }
>
> ret = IRQ_HANDLED;
>
> @@ -1793,7 +1807,8 @@ void msm_dp_bridge_hpd_notify(struct drm_bridge *bridge,
> msm_dp_hpd_plug_handle(dp);
> }
> } else {
> - msm_dp_hpd_unplug_handle(dp);
> + if (hpd_link_status == ISR_DISCONNECTED)

Why?

> + msm_dp_hpd_unplug_handle(dp);
> }
>
> pm_runtime_put_sync(&msm_dp_display->pdev->dev);
> diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c
> index bb3898b1f6b1..71d3f63973e6 100644
> --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.c
> +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c
> @@ -490,6 +490,40 @@ int msm_dp_mst_display_set_mgr_state(struct msm_dp *dp_display, bool state)
> return rc;
> }
>
> +/* DP MST HPD IRQ callback */

Useless comment.

> +void msm_dp_mst_display_hpd_irq(struct msm_dp *dp_display)
> +{
> + int rc;
> + struct msm_dp_mst *mst = dp_display->msm_dp_mst;
> + u8 ack[8] = {};
> + u8 esi[4];
> + unsigned int esi_res = DP_SINK_COUNT_ESI + 1;
> + bool handled;
> +
> + rc = drm_dp_dpcd_read_data(mst->dp_aux, DP_SINK_COUNT_ESI, esi, 4);
> + if (rc < 0) {
> + DRM_ERROR("DPCD sink status read failed, rlen=%d\n", rc);
> + return;
> + }
> +
> + drm_dbg_dp(dp_display->drm_dev, "MST irq: esi1[0x%x] esi2[0x%x] esi3[%x]\n",
> + esi[1], esi[2], esi[3]);
> +
> + rc = drm_dp_mst_hpd_irq_handle_event(&mst->mst_mgr, esi, ack, &handled);
> +
> + /* ack the request */
> + if (handled) {
> + rc = drm_dp_dpcd_write_byte(mst->dp_aux, esi_res, ack[1]);
> + if (rc < 0) {
> + DRM_ERROR("DPCD esi_res failed. rc=%d\n", rc);
> + return;
> + }
> +
> + drm_dp_mst_hpd_irq_send_new_request(&mst->mst_mgr);
> + }
> + drm_dbg_dp(dp_display->drm_dev, "MST display hpd_irq handled:%d rc:%d\n", handled, rc);
> +}
> +
> /* DP MST Connector OPs */
> static int
> msm_dp_mst_connector_detect(struct drm_connector *connector,
> diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.h b/drivers/gpu/drm/msm/dp/dp_mst_drm.h
> index 5d411529f681..08e145399cfc 100644
> --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.h
> +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.h
> @@ -9,5 +9,6 @@
>
> int msm_dp_mst_init(struct msm_dp *dp_display, u32 max_streams, struct drm_dp_aux *drm_aux);
> int msm_dp_mst_display_set_mgr_state(struct msm_dp *dp_display, bool state);
> +void msm_dp_mst_display_hpd_irq(struct msm_dp *dp_display);
>
> #endif /* _DP_MST_DRM_H_ */
>
> --
> 2.43.0
>

--
With best wishes
Dmitry