From: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
To: Rob Clark <robin.clark@oss.qualcomm.com>,
Dmitry Baryshkov <lumag@kernel.org>,
Abhinav Kumar <abhinav.kumar@linux.dev>,
Sean Paul <sean@poorly.run>,
Marijn Suijten <marijn.suijten@somainline.org>,
David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>,
Jessica Zhang <jesszhan0024@gmail.com>
Cc: linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org,
freedreno@lists.freedesktop.org, linux-kernel@vger.kernel.org,
Yongxing Mou <yongxing.mou@oss.qualcomm.com>,
Abhinav Kumar <quic_abhinavk@quicinc.com>
Subject: [PATCH v8 12/29] drm/msm/dp: introduce dp_mst_drm module
Date: Tue, 10 Nov 2026 12:54:33 +0800 [thread overview]
Message-ID: <20261110-msm-dp-mst-v8-12-d040fb33db5f@oss.qualcomm.com> (raw)
In-Reply-To: <20261110-msm-dp-mst-v8-0-d040fb33db5f@oss.qualcomm.com>
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 <quic_abhinavk@quicinc.com>
Signed-off-by: Yongxing Mou <yongxing.mou@oss.qualcomm.com>
---
drivers/gpu/drm/msm/Makefile | 3 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 22 ++++++++++-
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, 152 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 1e246616f83f3..48640d9bf7cb5 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -147,7 +147,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 da3556eb6ecc2..3c3203ca32c76 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");
@@ -913,6 +925,14 @@ static void dpu_kms_destroy(struct msm_kms *kms)
dpu_kms = to_dpu_kms(kms);
+ if (dpu_kms->dev) {
+ 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);
msm_kms_destroy(&dpu_kms->base);
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index fa027659a079f..9449ef692189c 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -28,6 +28,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);
@@ -1286,6 +1287,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 96be45c3dc923..7b6d76f33ac61 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 0000000000000..5d22aa34c521c
--- /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 0000000000000..7f35e7524cfdd
--- /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 2840e8a5052d7..31ab50f620bcd 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
next prev parent reply other threads:[~2026-11-10 4:55 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 4:54 [PATCH v8 00/29] drm/msm/dp: Add MST support for MSM chipsets Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 01/29] drm/msm/dp: skip sink requests while the mainlink clocks are off Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 02/29] drm/msm/dp: add support to send ACT packets for MST Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 03/29] drm/msm/dp: add support to enable MST in mainlink control Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 04/29] drm/msm/dp: no need to update tu calculation for mst Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 05/29] drm/msm/dp: always program MST_FIFO_CONSTANT_FILL for MST use cases Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 06/29] drm/msm/dp: add support for sending VCPF packets in DP controller Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 07/29] drm/msm/dp: add support for MST channel slot allocation Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 08/29] drm/msm/dp: replace power_on with active_stream_mask Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 09/29] drm/msm/dp: factor out _helper variants of bridge ops accepting a panel Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 10/29] drm/msm/dp: add link_ready to manage link-level operations Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 11/29] drm/msm/dp: add msm_dp_display_get_panel() to initialize DP panel Yongxing Mou
2026-11-10 4:54 ` Yongxing Mou [this message]
2026-11-10 4:54 ` [PATCH v8 13/29] drm/msm/dp: add MST connector creation and topology callbacks Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 14/29] drm/msm/dpu: pass msm_display_info to dpu_encoder_get_intf() Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 15/29] drm/msm/dpu: use stream_id to select MST interfaces Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 16/29] drm/msm/dpu: add per-stream MST encoders Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 17/29] drm/msm/dp: move link capabilities to dp_link Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 18/29] drm/msm/dp: add atomic stream handling for MST Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 19/29] drm/bridge_connector: suppress hotplug for IRQ_HPD without status changes Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 20/29] drm/bridge_connector: avoid detect-based HPD notifications for DisplayPort Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 21/29] drm/msm/dp: add HPD callback for dp MST Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 22/29] drm/msm/dp: wire MST helpers into atomic check and commit paths Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 23/29] drm/msm/dp: mark the SST bridge disconnected when mst is active Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 24/29] drm/msm/dp: enable MST on capable sinks Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 25/29] drm/msm/dp: mark the SST bridge disconnected when an MST-capable sink is present Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 26/29] drm/msm/dp: wake threaded handler for HPD IRQs Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 27/29] drm/msm/dp: ignore IRQ HPD latched together with an unplug Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 28/29] drm/msm/dp: select MST stream bpp during atomic check Yongxing Mou
2026-11-10 4:54 ` [PATCH v8 29/29] soc: qcom: pmic-glink-altmode: skip retimer reset on DP IRQ Yongxing Mou
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261110-msm-dp-mst-v8-12-d040fb33db5f@oss.qualcomm.com \
--to=yongxing.mou@oss.qualcomm.com \
--cc=abhinav.kumar@linux.dev \
--cc=airlied@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=freedreno@lists.freedesktop.org \
--cc=jesszhan0024@gmail.com \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lumag@kernel.org \
--cc=marijn.suijten@somainline.org \
--cc=quic_abhinavk@quicinc.com \
--cc=robin.clark@oss.qualcomm.com \
--cc=sean@poorly.run \
--cc=simona@ffwll.ch \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®