Re: [PATCH v4 27/39] drm/msm/dp: replace power_on with active_stream_cnt for dp_display

From: Yongxing Mou

Date: Mon Jun 15 2026 - 04:50:34 EST




On 4/12/2026 8:11 AM, Dmitry Baryshkov wrote:
On Fri, Apr 10, 2026 at 05:34:02PM +0800, Yongxing Mou wrote:
From: Abhinav Kumar <quic_abhinavk@xxxxxxxxxxx>

For DP MST, the link clock and power domain resources stay on until
both streams have been disabled OR we receive hotplug. Introduce an
active_stream_cnt to track the number of active streams and necessary
state handling. Replace the power_on variable with active_stream_cnt
as power_on boolean works only for a single stream.

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, 22 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c
index 41018e82efa1..035e230201fd 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) {
rc = -EINVAL;
goto end;
}
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 33d8539afee7..e6ecbb3a688e 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -657,15 +657,15 @@ int msm_dp_display_prepare(struct msm_dp *msm_dp_display)
if (dp->link->sink_count == 0)
return rc;
- if (!msm_dp_display->power_on) {
+ if (!msm_dp_display->active_stream_cnt) {

Okay, I'm now being lost between the names. When is prepare being
called? Is it still part of the atomic_enable()? Or atomic_pre_enable()?

I’ve renamed the function to msm_dp_display_prepare_link, which looks better. We’re still in atomic_enable().
msm_dp_display_host_phy_init(dp);
force_link_train = true;
- }
- rc = msm_dp_ctrl_on_link(dp->ctrl, msm_dp_display->mst_active);
- if (rc)
- DRM_ERROR("Failed link training (rc=%d)\n", rc);
- // TODO: schedule drm_connector_set_link_status_property()
+ rc = msm_dp_ctrl_on_link(dp->ctrl, msm_dp_display->mst_active);
+ if (rc)
+ DRM_ERROR("Failed link training (rc=%d)\n", rc);
+ // TODO: schedule drm_connector_set_link_status_property()
+ }

Again, this more than the scope of the commit message.

Got it..I will update the commit message to explain why this change is needed. Under MST, preparing the link only needs to be done once by the first stream.
return msm_dp_ctrl_prepare_stream_on(dp->ctrl, force_link_train);
}
@@ -674,18 +674,12 @@ static int msm_dp_display_enable(struct msm_dp_display_private *dp,
struct msm_dp_panel *msm_dp_panel)
{
int rc = 0;
- 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);
- if (!rc)
- msm_dp_display->power_on = true;
+ dp->msm_dp_display.active_stream_cnt++;
return rc;
}
@@ -731,16 +725,14 @@ static void msm_dp_display_audio_notify_disable(struct msm_dp_display_private *d
static int msm_dp_display_disable(struct msm_dp_display_private *dp,
struct msm_dp_panel *msm_dp_panel)
{
- struct msm_dp *msm_dp_display = &dp->msm_dp_display;
-
- if (!msm_dp_display->power_on)
+ if (!dp->msm_dp_display.active_stream_cnt)
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->power_on = false;
+ dp->msm_dp_display.active_stream_cnt--;
drm_dbg_dp(dp->drm_dev, "sink count: %d\n", dp->link->sink_count);
return 0;
@@ -876,7 +868,7 @@ void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp)
* power_on 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,
@@ -1559,6 +1551,11 @@ void msm_dp_display_disable_helper(struct msm_dp *msm_dp_display,
dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
+ if (!msm_dp_display->active_stream_cnt) {
+ drm_dbg_dp(dp->drm_dev, "no active streams\n");
+ return;
+ }
+
msm_dp_ctrl_push_idle(dp->ctrl, msm_dp_panel);
msm_dp_ctrl_mst_stream_channel_slot_setup(dp->ctrl);
msm_dp_ctrl_mst_send_act(dp->ctrl);
@@ -1579,6 +1576,11 @@ void msm_dp_display_unprepare(struct msm_dp *msm_dp_display)
dp = container_of(msm_dp_display, struct msm_dp_display_private, 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);
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h
index 0ede5505be58..2548f67cd441 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