[PATCH v4 14/39] drm/msm/dp: introduce max_streams for DP controller MST support

Yongxing Mou
2026-04-10T09:35:07Z

From: Abhinav Kumar <quic_abhinavk@quicinc.com>

Introduce the `mst_streams` field in each DP controller descriptor to
specify the number of supported MST streams. Most platforms support 2 or
4 MST streams, while platforms without MST support default to a single
stream (`DEFAULT_STREAM_COUNT = 1`).

Also accounts for platforms with asymmetric stream support, e.g., DP0
supporting 4 streams and DP1 supporting 2.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
---
drivers/gpu/drm/msm/dp/dp_ctrl.c | 20 +++++++++++++++++---
drivers/gpu/drm/msm/dp/dp_ctrl.h | 2 ++
drivers/gpu/drm/msm/dp/dp_display.c | 20 +++++++++++++++++++-
drivers/gpu/drm/msm/dp/dp_display.h | 1 +
4 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index fb6396727628..1e80d6fc7bda 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -128,6 +128,7 @@ struct msm_dp_ctrl_private {
struct clk_bulk_data *link_clks;

struct clk *pixel_clk[DP_STREAM_MAX];
+ unsigned int num_pixel_clks;

union phy_configure_opts phy_opts;

@@ -2707,7 +2708,7 @@ static const char * const pixel_clks[] = {
"stream_3_pixel",
};

-static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl *msm_dp_ctrl)
+static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl *msm_dp_ctrl, int max_stream)
{
struct msm_dp_ctrl_private *ctrl;
struct device *dev;
@@ -2740,7 +2741,8 @@ static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl *msm_dp_ctrl)
if (rc)
return rc;

- for (i = DP_STREAM_0; i < DP_STREAM_MAX; i++) {
+ ctrl->num_pixel_clks = 0;
+ for (i = DP_STREAM_0; i < max_stream; i++) {
ctrl->pixel_clk[i] = devm_clk_get(dev, pixel_clks[i]);

if (i == 0 && IS_ERR(ctrl->pixel_clk[i]))
@@ -2750,14 +2752,26 @@ static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl *msm_dp_ctrl)
DRM_DEBUG_DP("stream %d pixel clock not exist", i);
break;
}
+
+ ctrl->num_pixel_clks++;
}

return 0;
}

+int msm_dp_ctrl_get_stream_cnt(struct msm_dp_ctrl *msm_dp_ctrl)
+{
+ struct msm_dp_ctrl_private *ctrl;
+
+ ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
+
+ return ctrl->num_pixel_clks;
+}
+
struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link,
struct msm_dp_panel *panel, struct drm_dp_aux *aux,
struct phy *phy,
+ int max_stream,
void __iomem *ahb_base,
void __iomem *link_base)
{
@@ -2800,7 +2814,7 @@ struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link
ctrl->ahb_base = ahb_base;
ctrl->link_base = link_base;

- ret = msm_dp_ctrl_clk_init(&ctrl->msm_dp_ctrl);
+ ret = msm_dp_ctrl_clk_init(&ctrl->msm_dp_ctrl, max_stream);
if (ret) {
dev_err(dev, "failed to init clocks\n");
return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h
index b9f0705b03ba..6fed3ff3a72d 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.h
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h
@@ -29,6 +29,7 @@ struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev,
struct msm_dp_panel *panel,
struct drm_dp_aux *aux,
struct phy *phy,
+ int max_stream,
void __iomem *ahb_base,
void __iomem *link_base);

@@ -47,4 +48,5 @@ void msm_dp_ctrl_enable_irq(struct msm_dp_ctrl *msm_dp_ctrl);
void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl);

void msm_dp_ctrl_reinit_phy(struct msm_dp_ctrl *msm_dp_ctrl);
+int msm_dp_ctrl_get_stream_cnt(struct msm_dp_ctrl *dp_ctrl);
#endif /* _DP_CTRL_H_ */
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 736b621c0531..7984a0f9e938 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -87,12 +87,15 @@ struct msm_dp_display_private {

void __iomem *p0_base;
size_t p0_len;
+
+ int max_stream;
};

struct msm_dp_desc {
phys_addr_t io_start;
unsigned int id;
bool wide_bus_supported;
+ int mst_streams;
};

static const struct msm_dp_desc msm_dp_desc_glymur[] = {
@@ -567,13 +570,15 @@ static int msm_dp_init_sub_modules(struct msm_dp_display_private *dp)
}

dp->ctrl = msm_dp_ctrl_get(dev, dp->link, dp->panel, dp->aux,
- phy, dp->ahb_base, dp->link_base);
+ phy, dp->max_stream, dp->ahb_base, dp->link_base);
if (IS_ERR(dp->ctrl)) {
rc = PTR_ERR(dp->ctrl);
DRM_ERROR("failed to initialize ctrl, rc = %d\n", rc);
dp->ctrl = NULL;
goto error_link;
}
+ if (dp->max_stream != msm_dp_ctrl_get_stream_cnt(dp->ctrl))
+ dp->max_stream = 1;

dp->audio = msm_dp_audio_get(dp->msm_dp_display.pdev, dp->link_base);
if (IS_ERR(dp->audio)) {
@@ -1208,6 +1213,15 @@ static int msm_dp_display_get_io(struct msm_dp_display_private *display)
return 0;
}

+int msm_dp_get_mst_max_stream(struct msm_dp *msm_dp_display)
+{
+ struct msm_dp_display_private *dp;
+
+ dp = container_of(msm_dp_display, struct msm_dp_display_private, msm_dp_display);
+
+ return dp->max_stream;
+}
+
static int msm_dp_display_probe(struct platform_device *pdev)
{
int rc = 0;
@@ -1234,6 +1248,10 @@ static int msm_dp_display_probe(struct platform_device *pdev)
dp->msm_dp_display.is_edp =
(dp->msm_dp_display.connector_type == DRM_MODE_CONNECTOR_eDP);
dp->hpd_isr_status = 0;
+ dp->max_stream = 1;
+
+ if (desc->mst_streams > 1)
+ dp->max_stream = desc->mst_streams;

mutex_init(&dp->plugged_lock);

diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h
index a5c6ed5b18e4..b0cfdf215970 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -26,6 +26,7 @@ struct msm_dp {
bool psr_supported;
};

+int msm_dp_get_mst_max_stream(struct msm_dp *msm_dp_display);
int msm_dp_display_get_modes(struct msm_dp *msm_dp_display);
bool msm_dp_display_check_video_test(struct msm_dp *msm_dp_display);
int msm_dp_display_get_test_bpp(struct msm_dp *msm_dp_display);

--
2.43.0