[PATCH v6 14/29] drm/msm/dp: replace power_on with active_stream_cnt
From: Yongxing Mou
Date: Mon Aug 31 2026 - 04:32:46 EST
From: Abhinav Kumar <quic_abhinavk@xxxxxxxxxxx>
The power_on boolean cannot represent DP MST, where multiple streams
share a single link and its associated resources.
Replace power_on with active_stream_cnt and use it to track the lifetime
of the shared link. Link initialization is performed when enabling the
first stream, while link teardown is deferred until the last stream is
disabled.
Signed-off-by: Abhinav Kumar <quic_abhinavk@xxxxxxxxxxx>
Signed-off-by: Yongxing Mou <yongxing.mou@xxxxxxxxxxxxxxxx>
---
drivers/gpu/drm/msm/dp/dp_audio.c | 2 +-
drivers/gpu/drm/msm/dp/dp_display.c | 38 ++++++++++++++++++-------------------
drivers/gpu/drm/msm/dp/dp_display.h | 2 +-
3 files changed, 20 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c
index df222943ae57..8118130a3220 100644
--- a/drivers/gpu/drm/msm/dp/dp_audio.c
+++ b/drivers/gpu/drm/msm/dp/dp_audio.c
@@ -284,7 +284,7 @@ int msm_dp_audio_prepare(struct drm_bridge *bridge,
* such cases check for connection status and bail out if not
* connected.
*/
- if (!msm_dp_display->power_on)
+ if (!msm_dp_display->active_stream_cnt)
goto end;
audio = msm_dp_audio_get_data(msm_dp_display);
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 6f79328c8b79..9c5563dcb856 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -645,16 +645,16 @@ static int msm_dp_display_prepare_link(struct msm_dp_display_private *dp)
if (dp->link->sink_count == 0)
return -ENOTCONN;
- if (!msm_dp_display->power_on) {
+ if (!msm_dp_display->active_stream_cnt) {
msm_dp_display_host_phy_init(dp);
force_link_train = true;
- }
- rc = msm_dp_ctrl_on_link(dp->ctrl, dp->panel);
- if (rc) {
- DRM_ERROR("Failed link training (rc=%d)\n", rc);
- // TODO: schedule drm_connector_set_link_status_property()
- return rc;
+ rc = msm_dp_ctrl_on_link(dp->ctrl, dp->panel);
+ if (rc) {
+ DRM_ERROR("Failed link training (rc=%d)\n", rc);
+ // TODO: schedule drm_connector_set_link_status_property()
+ return rc;
+ }
}
return msm_dp_ctrl_prepare_stream_on(dp->ctrl, dp->panel, force_link_train);
@@ -667,14 +667,10 @@ static int msm_dp_display_enable(struct msm_dp_display_private *dp,
struct msm_dp *msm_dp_display = &dp->msm_dp_display;
drm_dbg_dp(dp->drm_dev, "sink_count=%d\n", dp->link->sink_count);
- if (msm_dp_display->power_on) {
- drm_dbg_dp(dp->drm_dev, "Link already setup, return\n");
- return 0;
- }
rc = msm_dp_ctrl_on_stream(dp->ctrl, msm_dp_panel, msm_dp_display->mst_active);
- if (!rc)
- msm_dp_display->power_on = true;
+
+ msm_dp_display->active_stream_cnt++;
return rc;
}
@@ -723,13 +719,12 @@ static int msm_dp_display_disable(struct msm_dp_display_private *dp,
{
struct msm_dp *msm_dp_display = &dp->msm_dp_display;
- if (!msm_dp_display->power_on)
- return 0;
-
msm_dp_panel_disable_vsc_sdp(msm_dp_panel);
msm_dp_ctrl_off_pixel_clk(dp->ctrl, msm_dp_panel->stream_id);
+ msm_dp_display->active_stream_cnt--;
+
drm_dbg_dp(dp->drm_dev, "sink count: %d\n", dp->link->sink_count);
return 0;
}
@@ -851,10 +846,10 @@ void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp)
* if we are reading registers we need the link clocks to be on
* however till DP cable is connected this will not happen as we
* do not know the resolution to power up with. Hence check the
- * power_on status before dumping DP registers to avoid crash due
+ * active_stream_cnt status before dumping DP registers to avoid crash due
* to unclocked access
*/
- if (!dp->power_on)
+ if (!dp->active_stream_cnt)
return;
msm_disp_snapshot_add_block(disp_state, msm_dp_display->ahb_len,
@@ -1517,6 +1512,11 @@ static void msm_dp_display_unprepare(struct msm_dp_display_private *dp)
{
struct msm_dp *msm_dp_display = &dp->msm_dp_display;
+ if (msm_dp_display->active_stream_cnt) {
+ drm_dbg_dp(dp->drm_dev, "stream still active, return\n");
+ return;
+ }
+
/* dongle is still connected but sinks are disconnected */
if (dp->link->sink_count == 0)
msm_dp_link_psm_config(dp->link, &dp->panel->link_info, true);
@@ -1529,8 +1529,6 @@ static void msm_dp_display_unprepare(struct msm_dp_display_private *dp)
else
msm_dp_display_host_phy_exit(dp);
- msm_dp_display->power_on = false;
-
pm_runtime_put_sync(&msm_dp_display->pdev->dev);
drm_dbg_dp(dp->drm_dev, "type=%d Done\n", msm_dp_display->connector_type);
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h
index 317c19b809ec..7bd510cecb44 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -18,7 +18,7 @@ struct msm_dp {
struct drm_bridge *next_bridge;
struct drm_bridge *bridge;
bool audio_enabled;
- bool power_on;
+ u32 active_stream_cnt;
bool mst_active;
unsigned int connector_type;
bool is_edp;
--
2.43.0