Re: [PATCH v4 13/39] drm/msm/dp: introduce stream_id for each DP panel

From: Dmitry Baryshkov

Date: Wed May 20 2026 - 05:40:11 EST


On Tue, May 19, 2026 at 04:26:21PM +0800, Yongxing Mou wrote:
>
>
> On 4/12/2026 1:55 AM, Dmitry Baryshkov wrote:
> > On Fri, Apr 10, 2026 at 05:33:48PM +0800, Yongxing Mou wrote:
> > > From: Abhinav Kumar <quic_abhinavk@xxxxxxxxxxx>
> > >
> > > With MST, each DP controller can handle multiple streams.
> > > There shall be one dp_panel for each stream but the dp_display
> > > object shall be shared among them. To represent this abstraction,
> > > create a stream_id for each DP panel which shall be set by the
> > > MST stream. For SST, default this to stream 0.
> > >
> > > Use the stream ID to control the pixel clock of that respective
> > > stream by extending the clock handles and state tracking of the
> > > DP pixel clock to an array of max supported streams. The maximum
> > > streams currently is 4.
> >
> > Please mention that panels are going to be dynamically assigned to
> > actual stream IDs.
> >
> Got it. will update next patch.
> > >
> > > Signed-off-by: Abhinav Kumar <quic_abhinavk@xxxxxxxxxxx>
> > > Signed-off-by: Yongxing Mou <yongxing.mou@xxxxxxxxxxxxxxxx>
> > > ---
> > > drivers/gpu/drm/msm/dp/dp_ctrl.c | 57 +++++++++++++++++++++++--------------
> > > drivers/gpu/drm/msm/dp/dp_ctrl.h | 2 +-
> > > drivers/gpu/drm/msm/dp/dp_display.c | 24 ++++++++++++++--
> > > drivers/gpu/drm/msm/dp/dp_display.h | 2 ++
> > > drivers/gpu/drm/msm/dp/dp_panel.h | 11 +++++++
> > > 5 files changed, 71 insertions(+), 25 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
> > > index 120ec00884e5..fb6396727628 100644
> > > --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
> > > +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
> > > @@ -127,7 +127,7 @@ struct msm_dp_ctrl_private {
> > > unsigned int num_link_clks;
> > > struct clk_bulk_data *link_clks;
> > > - struct clk *pixel_clk;
> > > + struct clk *pixel_clk[DP_STREAM_MAX];
> > > union phy_configure_opts phy_opts;
> > > @@ -139,7 +139,7 @@ struct msm_dp_ctrl_private {
> > > bool core_clks_on;
> > > bool link_clks_on;
> > > - bool stream_clks_on;
> > > + bool stream_clks_on[DP_STREAM_MAX];
> > > };
> > > static inline u32 msm_dp_read_ahb(const struct msm_dp_ctrl_private *ctrl, u32 offset)
> > > @@ -2176,39 +2176,40 @@ static bool msm_dp_ctrl_send_phy_test_pattern(struct msm_dp_ctrl_private *ctrl)
> > > return success;
> > > }
> > > -static int msm_dp_ctrl_on_pixel_clk(struct msm_dp_ctrl_private *ctrl, unsigned long pixel_rate)
> > > +static int msm_dp_ctrl_on_pixel_clk(struct msm_dp_ctrl_private *ctrl, unsigned long pixel_rate,
> > > + enum msm_dp_stream_id stream_id)
> > > {
> > > int ret;
> > > - ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000);
> > > + ret = clk_set_rate(ctrl->pixel_clk[stream_id], pixel_rate * 1000);
> > > if (ret) {
> > > DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret);
> > > return ret;
> > > }
> > > - if (ctrl->stream_clks_on) {
> > > + if (ctrl->stream_clks_on[stream_id]) {
> > > drm_dbg_dp(ctrl->drm_dev, "pixel clks already enabled\n");
> > > } else {
> > > - ret = clk_prepare_enable(ctrl->pixel_clk);
> > > + ret = clk_prepare_enable(ctrl->pixel_clk[stream_id]);
> > > if (ret) {
> > > DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret);
> > > return ret;
> > > }
> > > - ctrl->stream_clks_on = true;
> > > + ctrl->stream_clks_on[stream_id] = true;
> > > }
> > > return ret;
> > > }
> > > -void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl)
> > > +void msm_dp_ctrl_off_pixel_clk(struct msm_dp_ctrl *msm_dp_ctrl, enum msm_dp_stream_id stream_id)
> > > {
> > > struct msm_dp_ctrl_private *ctrl;
> > > ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
> > > - if (ctrl->stream_clks_on) {
> > > - clk_disable_unprepare(ctrl->pixel_clk);
> > > - ctrl->stream_clks_on = false;
> > > + if (ctrl->stream_clks_on[stream_id]) {
> > > + clk_disable_unprepare(ctrl->pixel_clk[stream_id]);
> > > + ctrl->stream_clks_on[stream_id] = false;
> > > }
> > > }
> > > @@ -2228,7 +2229,7 @@ static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl
> > > * running. Add the global reset just before disabling the
> > > * link clocks and core clocks.
> > > */
> > > - msm_dp_ctrl_off_pixel_clk(&ctrl->msm_dp_ctrl);
> > > + msm_dp_ctrl_off_pixel_clk(&ctrl->msm_dp_ctrl, ctrl->panel->stream_id);
> >
> > Why are we using ctrl->panel again here for the stream-related
> > functions? Didn't you got rid of its usage few patches ago?
> >
> For MST path, we pass panel to the func. For SST case, we still need to pass
> the sst panel to func, in here it is ctrl->panel.. in dp_display, it is
> dp_display->panel.

This doesn't sound correct. How do we differ between MST and SST in
dp_ctrl functions? I'd really store the panel only in
dp_display_private, passing it as required.

> > > msm_dp_ctrl_off_link(&ctrl->msm_dp_ctrl);
> > > ret = msm_dp_ctrl_on_link(&ctrl->msm_dp_ctrl);
> > > @@ -2238,7 +2239,7 @@ static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl
> > > }
> > > pixel_rate = ctrl->panel->msm_dp_mode.drm_mode.clock;
> > > - ret = msm_dp_ctrl_on_pixel_clk(ctrl, pixel_rate);
> > > + ret = msm_dp_ctrl_on_pixel_clk(ctrl, pixel_rate, ctrl->panel->stream_id);
> >
> > And here...
> >
> > > msm_dp_ctrl_send_phy_test_pattern(ctrl);
> > > @@ -1451,6 +1469,8 @@ void msm_dp_display_atomic_enable(struct msm_dp *msm_dp_display)
> > > dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
> > > + msm_dp_display_set_stream_info(msm_dp_display, dp->panel, 0);
> >
> > DP_STREAM_0
> >
> > > +
> > > rc = msm_dp_display_enable(dp);
> > > if (rc)
> > > DRM_ERROR("DP display enable failed, rc=%d\n", rc);
> >
>

--
With best wishes
Dmitry