Add the dp_mst_drm module and the core MST manager data structures.

Introduce the MST manager object, per-stream encoder state and the
initialization path for creating a DRM MST topology manager associated
with a DP controller.

Also add the registration hooks used to initialize the MST manager
during DP device setup.

Signed-off-by: Abhinav Kumar <[email protected]>
Signed-off-by: Yongxing Mou <[email protected]>
---
 drivers/gpu/drm/msm/Makefile            |  3 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 19 +++++++++-
 drivers/gpu/drm/msm/dp/dp_display.c     | 27 +++++++++++++
 drivers/gpu/drm/msm/dp/dp_display.h     |  5 +++
 drivers/gpu/drm/msm/dp/dp_mst_drm.c     | 67 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/msm/dp/dp_mst_drm.h     | 13 +++++++
 drivers/gpu/drm/msm/msm_drv.h           | 17 +++++++++
 7 files changed, 149 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 0b8f2cafed19..e16d3ebf651c 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -145,7 +145,8 @@ msm-display-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \
        dp/dp_link.o \
        dp/dp_panel.o \
        dp/dp_audio.o \
-       dp/dp_utils.o
+       dp/dp_utils.o \
+       dp/dp_mst_drm.o
 
 msm-display-$(CONFIG_DRM_MSM_HDMI_HDCP) += hdmi/hdmi_hdcp.o
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index da3556eb6ecc..7ee4e7e4d34a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -655,7 +655,7 @@ static int _dpu_kms_initialize_displayport(struct 
drm_device *dev,
        struct msm_display_info info;
        bool yuv_supported;
        int rc;
-       int i;
+       int i, stream_cnt;
 
        for (i = 0; i < ARRAY_SIZE(priv->kms->dp); i++) {
                if (!priv->kms->dp[i])
@@ -678,6 +678,16 @@ static int _dpu_kms_initialize_displayport(struct 
drm_device *dev,
                        DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc);
                        return rc;
                }
+
+               stream_cnt = msm_dp_get_mst_max_stream(priv->kms->dp[i]);
+
+               if (stream_cnt > 1) {
+                       rc = msm_dp_mst_register(priv->kms->dp[i]);
+                       if (rc) {
+                               DPU_ERROR("dp_mst_init failed for DP, rc = 
%d\n", rc);
+                               return rc;
+                       }
+               }
        }
 
        return 0;
@@ -905,6 +915,8 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms)
 static void dpu_kms_destroy(struct msm_kms *kms)
 {
        struct dpu_kms *dpu_kms;
+       struct msm_drm_private *priv;
+       int i;
 
        if (!kms) {
                DPU_ERROR("invalid kms\n");
@@ -912,6 +924,11 @@ static void dpu_kms_destroy(struct msm_kms *kms)
        }
 
        dpu_kms = to_dpu_kms(kms);
+       priv = dpu_kms->dev->dev_private;
+
+       for (i = 0; i < ARRAY_SIZE(priv->kms->dp); i++)
+               if (priv->kms->dp[i])
+                       msm_dp_mst_unregister(priv->kms->dp[i]);
 
        _dpu_kms_hw_destroy(dpu_kms);
 
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 1d1fb45024c6..e322176163e9 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -27,6 +27,7 @@
 #include "dp_drm.h"
 #include "dp_audio.h"
 #include "dp_debug.h"
+#include "dp_mst_drm.h"
 
 static bool psr_enabled = false;
 module_param(psr_enabled, bool, 0);
@@ -1277,6 +1278,32 @@ 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 msm_dp_ctrl_get_stream_cnt(dp->ctrl);
+}
+
+int msm_dp_mst_register(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 msm_dp_mst_mgr_init(msm_dp_display, 
msm_dp_ctrl_get_stream_cnt(dp->ctrl), dp->aux);
+}
+
+void msm_dp_mst_unregister(struct msm_dp *msm_dp_display)
+{
+       if (!msm_dp_display->msm_dp_mst)
+               return;
+
+       msm_dp_mst_mgr_destroy(msm_dp_display);
+}
+
 static int msm_dp_display_probe(struct platform_device *pdev)
 {
        int rc = 0;
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h 
b/drivers/gpu/drm/msm/dp/dp_display.h
index 4d4349068c2f..df5021ba7c15 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -24,6 +24,8 @@ struct msm_dp {
        unsigned int connector_type;
        bool is_edp;
 
+       void *msm_dp_mst;
+
        struct msm_dp_audio *msm_dp_audio;
        bool psr_supported;
 };
@@ -59,6 +61,9 @@ int msm_dp_display_set_mode_helper(struct msm_dp 
*msm_dp_display,
 int msm_dp_display_prepare_link(struct msm_dp *msm_dp_display);
 void msm_dp_display_unprepare(struct msm_dp *dp);
 
+int msm_dp_get_mst_max_stream(struct msm_dp *msm_dp_display);
+int msm_dp_mst_register(struct msm_dp *msm_dp_display);
+void msm_dp_mst_unregister(struct msm_dp *msm_dp_display);
 struct msm_dp_panel *msm_dp_display_get_panel(struct msm_dp *msm_dp_display,
                                              enum msm_dp_stream_id stream_id);
 #endif /* _DP_DISPLAY_H_ */
diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c 
b/drivers/gpu/drm/msm/dp/dp_mst_drm.c
new file mode 100644
index 000000000000..5d22aa34c521
--- /dev/null
+++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <drm/drm_edid.h>
+#include <drm/drm_fixed.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/display/drm_dp_mst_helper.h>
+
+#include "dp_mst_drm.h"
+#include "dp_panel.h"
+
+struct msm_dp_mst_encoder {
+       struct drm_encoder *enc;
+       int stream_id;
+       struct msm_dp_panel *dp_panel;
+};
+
+struct msm_dp_mst {
+       struct drm_dp_mst_topology_mgr mst_mgr;
+       struct msm_dp_mst_encoder mst_encoders[DP_STREAM_MAX];
+       struct msm_dp *msm_dp;
+       struct drm_dp_aux *dp_aux;
+       u32 max_streams;
+};
+
+int msm_dp_mst_mgr_init(struct msm_dp *dp_display, u32 max_streams, struct 
drm_dp_aux *drm_aux)
+{
+       struct drm_device *dev = dp_display->drm_dev;
+       struct msm_dp_mst *mst;
+       int ret;
+
+       mst = kzalloc_obj(*mst);
+       if (!mst)
+               return -ENOMEM;
+
+       mst->msm_dp = dp_display;
+       mst->max_streams = max_streams;
+       mst->dp_aux = drm_aux;
+
+       ret = drm_dp_mst_topology_mgr_init(&mst->mst_mgr, dev,
+                                          drm_aux,
+                                          16,
+                                          max_streams,
+                                          dp_display->connector->base.id);
+       if (ret) {
+               drm_err(dev, "[MST] topology manager init failed\n");
+               kfree(mst);
+               return ret;
+       }
+
+       dp_display->msm_dp_mst = mst;
+       return 0;
+}
+
+void msm_dp_mst_mgr_destroy(struct msm_dp *dp_display)
+{
+       struct msm_dp_mst *mst = dp_display->msm_dp_mst;
+
+       if (!mst)
+               return;
+
+       drm_dp_mst_topology_mgr_destroy(&mst->mst_mgr);
+       dp_display->msm_dp_mst = NULL;
+       kfree(mst);
+}
diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.h 
b/drivers/gpu/drm/msm/dp/dp_mst_drm.h
new file mode 100644
index 000000000000..7f35e7524cfd
--- /dev/null
+++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _DP_MST_DRM_H_
+#define _DP_MST_DRM_H_
+
+#include "dp_display.h"
+
+int msm_dp_mst_mgr_init(struct msm_dp *dp_display, u32 max_streams, struct 
drm_dp_aux *drm_aux);
+void msm_dp_mst_mgr_destroy(struct msm_dp *dp_display);
+
+#endif /* _DP_MST_DRM_H_ */
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index eb4bbae8557b..b14f097ae8cc 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -357,6 +357,9 @@ void msm_dp_snapshot(struct msm_disp_state *disp_state, 
struct msm_dp *dp_displa
 bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display,
                               const struct drm_display_mode *mode);
 bool msm_dp_wide_bus_available(const struct msm_dp *dp_display);
+int msm_dp_get_mst_max_stream(struct msm_dp *dp_display);
+int msm_dp_mst_register(struct msm_dp *dp_display);
+void msm_dp_mst_unregister(struct msm_dp *dp_display);
 
 #else
 static inline int __init msm_dp_register(void)
@@ -389,6 +392,20 @@ static inline bool msm_dp_wide_bus_available(const struct 
msm_dp *dp_display)
        return false;
 }
 
+static inline int msm_dp_get_mst_max_stream(struct msm_dp *dp_display)
+{
+       return -EINVAL;
+}
+
+static inline int msm_dp_mst_register(struct msm_dp *dp_display)
+{
+       return -EINVAL;
+}
+
+static inline void msm_dp_mst_unregister(struct msm_dp *dp_display)
+{
+}
+
 #endif
 
 #ifdef CONFIG_DRM_MSM_MDP4

-- 
2.43.0

Reply via email to