From: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
To: Rob Clark <robin.clark@oss.qualcomm.com>,
Dmitry Baryshkov <lumag@kernel.org>,
Abhinav Kumar <abhinav.kumar@linux.dev>,
Jessica Zhang <jesszhan0024@gmail.com>,
Sean Paul <sean@poorly.run>,
Marijn Suijten <marijn.suijten@somainline.org>,
David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>,
Andrzej Hajda <andrzej.hajda@intel.com>,
Neil Armstrong <neil.armstrong@linaro.org>,
Robert Foss <rfoss@kernel.org>,
Laurent Pinchart <Laurent.pinchart@ideasonboard.com>,
Jonas Karlman <jonas@kwiboo.se>,
Jernej Skrabec <jernej.skrabec@gmail.com>,
Luca Ceresoli <luca.ceresoli@bootlin.com>,
Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Maxime Ripard <mripard@kernel.org>,
Thomas Zimmermann <tzimmermann@suse.de>
Cc: linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org,
freedreno@lists.freedesktop.org, linux-kernel@vger.kernel.org
Subject: [PATCH 04/24] drm/msm: introduce the struct msm_display interface
Date: Wed, 22 Jul 2026 09:36:19 +0300 [thread overview]
Message-ID: <20260722-drm-msm-display-interface-v1-4-368c10fe62fd@oss.qualcomm.com> (raw)
In-Reply-To: <20260722-drm-msm-display-interface-v1-0-368c10fe62fd@oss.qualcomm.com>
The common connector setup in msm_kms_init_connectors() calls the
type-specific msm_dsi_modeset_init(), msm_dp_modeset_init() and
msm_hdmi_modeset_init() functions, so it has to know about each concrete
sub-block type.
Introduce a small struct msm_display interface with a modeset_init()
callback, embedded in struct hdmi, struct msm_dsi and struct msm_dp. Each
sub-block registers its ops and provides a msm_*_get_display() accessor;
the common code then dispatches through display->funcs->modeset_init()
without knowing the concrete type. Further per-sub-block operations will
be folded into this interface in following patches.
No functional change intended.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/gpu/drm/msm/dp/dp_display.c | 17 ++++++++--
drivers/gpu/drm/msm/dp/dp_display.h | 2 ++
drivers/gpu/drm/msm/dsi/dsi.c | 18 ++++++++--
drivers/gpu/drm/msm/dsi/dsi.h | 2 ++
drivers/gpu/drm/msm/hdmi/hdmi.c | 13 +++++++-
drivers/gpu/drm/msm/hdmi/hdmi.h | 2 ++
drivers/gpu/drm/msm/msm_drv.h | 50 ++++++++++++++++++----------
drivers/gpu/drm/msm/msm_kms.c | 66 ++++++++++++++++++-------------------
8 files changed, 115 insertions(+), 55 deletions(-)
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 5ae5eed7e010..79dd556e96c2 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -203,6 +203,8 @@ void msm_dp_display_signal_audio_complete(struct msm_dp *msm_dp_display)
complete_all(&dp->audio_comp);
}
+static const struct msm_display_funcs msm_dp_display_funcs;
+
static int msm_dp_display_bind(struct device *dev, struct device *master,
void *data)
{
@@ -212,6 +214,7 @@ static int msm_dp_display_bind(struct device *dev, struct device *master,
struct drm_device *drm = priv->dev;
dp->msm_dp_display.drm_dev = drm;
+ dp->msm_dp_display.display.funcs = &msm_dp_display_funcs;
priv->kms->dp[dp->id] = &dp->msm_dp_display;
dp->drm_dev = drm;
@@ -1317,9 +1320,10 @@ void msm_dp_display_debugfs_init(struct msm_dp *msm_dp_display, struct dentry *r
DRM_ERROR("failed to initialize debug, rc = %d\n", rc);
}
-int msm_dp_modeset_init(struct msm_dp *msm_dp_display, struct drm_device *dev,
- struct drm_encoder *encoder)
+static int msm_dp_modeset_init(struct msm_display *display,
+ struct drm_device *dev, struct drm_encoder *encoder)
{
+ struct msm_dp *msm_dp_display = container_of(display, struct msm_dp, display);
struct msm_dp_display_private *msm_dp_priv;
int ret;
@@ -1348,6 +1352,15 @@ int msm_dp_modeset_init(struct msm_dp *msm_dp_display, struct drm_device *dev,
return 0;
}
+static const struct msm_display_funcs msm_dp_display_funcs = {
+ .modeset_init = msm_dp_modeset_init,
+};
+
+struct msm_display *msm_dp_get_display(struct msm_dp *msm_dp_display)
+{
+ return msm_dp_display ? &msm_dp_display->display : NULL;
+}
+
void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
struct drm_atomic_commit *state)
{
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h
index 0b65e16c790d..20a71afb1f90 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -12,6 +12,8 @@
#define DP_MAX_PIXEL_CLK_KHZ 675000
struct msm_dp {
+ struct msm_display display;
+
struct drm_device *drm_dev;
struct platform_device *pdev;
struct drm_connector *connector;
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index 3c9f01ed6271..6cd844d08733 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -115,6 +115,8 @@ static struct msm_dsi *dsi_init(struct platform_device *pdev)
return ERR_PTR(ret);
}
+static const struct msm_display_funcs msm_dsi_display_funcs;
+
static int dsi_bind(struct device *dev, struct device *master, void *data)
{
struct msm_drm_private *priv = dev_get_drvdata(master);
@@ -136,6 +138,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
msm_dsi->next_bridge = ext_bridge;
}
+ msm_dsi->display.funcs = &msm_dsi_display_funcs;
priv->kms->dsi[msm_dsi->id] = msm_dsi;
return 0;
@@ -230,9 +233,11 @@ void __exit msm_dsi_unregister(void)
platform_driver_unregister(&dsi_driver);
}
-int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
- struct drm_encoder *encoder)
+static int msm_dsi_modeset_init(struct msm_display *display,
+ struct drm_device *dev,
+ struct drm_encoder *encoder)
{
+ struct msm_dsi *msm_dsi = container_of(display, struct msm_dsi, display);
int ret;
msm_dsi->dev = dev;
@@ -262,6 +267,15 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
return 0;
}
+static const struct msm_display_funcs msm_dsi_display_funcs = {
+ .modeset_init = msm_dsi_modeset_init,
+};
+
+struct msm_display *msm_dsi_get_display(struct msm_dsi *msm_dsi)
+{
+ return msm_dsi ? &msm_dsi->display : NULL;
+}
+
void msm_dsi_snapshot(struct msm_disp_state *disp_state, struct msm_dsi *msm_dsi)
{
msm_dsi_host_snapshot(disp_state, msm_dsi->host);
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 93c028a122f3..1d1bda0682db 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -32,6 +32,8 @@ enum msm_dsi_phy_usecase {
#define DSI_BUS_CLK_MAX 4
struct msm_dsi {
+ struct msm_display display;
+
struct drm_device *dev;
struct platform_device *pdev;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 474006084633..03367c6ba428 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -159,9 +159,10 @@ static int msm_hdmi_init(struct hdmi *hdmi)
* should be handled in msm_hdmi_init() so that failure happens from
* hdmi sub-device's probe.
*/
-int msm_hdmi_modeset_init(struct hdmi *hdmi,
+static int msm_hdmi_modeset_init(struct msm_display *display,
struct drm_device *dev, struct drm_encoder *encoder)
{
+ struct hdmi *hdmi = container_of(display, struct hdmi, display);
int ret;
hdmi->dev = dev;
@@ -210,6 +211,15 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
return ret;
}
+static const struct msm_display_funcs msm_hdmi_display_funcs = {
+ .modeset_init = msm_hdmi_modeset_init,
+};
+
+struct msm_display *msm_hdmi_get_display(struct hdmi *hdmi)
+{
+ return hdmi ? &hdmi->display : NULL;
+}
+
/*
* The hdmi device:
*/
@@ -243,6 +253,7 @@ static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
err = msm_hdmi_init(hdmi);
if (err)
return err;
+ hdmi->display.funcs = &msm_hdmi_display_funcs;
priv->kms->hdmi = hdmi;
return 0;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 49433f7727c3..f24444610fe1 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -31,6 +31,8 @@ struct hdmi_audio {
struct hdmi_hdcp_ctrl;
struct hdmi {
+ struct msm_display display;
+
struct drm_device *dev;
struct platform_device *pdev;
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 0ec0622d9217..dbd955091ce7 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -274,17 +274,39 @@ int msm_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,
.fbdev_probe = NULL
#endif
+struct msm_display;
+
+/**
+ * struct msm_display_funcs - ops provided by a display sub-block (DSI/DP/HDMI)
+ * @modeset_init: create the bridge and connector for the sub-block, attaching
+ * to @encoder.
+ */
+struct msm_display_funcs {
+ int (*modeset_init)(struct msm_display *display, struct drm_device *dev,
+ struct drm_encoder *encoder);
+};
+
+/**
+ * struct msm_display - common interface to a display sub-block
+ * @funcs: sub-block provided ops
+ *
+ * Embedded in each sub-block (&struct hdmi, &struct msm_dsi, &struct msm_dp)
+ * so that common KMS code can set up their connectors without knowing the
+ * concrete type.
+ */
+struct msm_display {
+ const struct msm_display_funcs *funcs;
+};
+
struct hdmi;
#ifdef CONFIG_DRM_MSM_HDMI
-int msm_hdmi_modeset_init(struct hdmi *hdmi, struct drm_device *dev,
- struct drm_encoder *encoder);
+struct msm_display *msm_hdmi_get_display(struct hdmi *hdmi);
void __init msm_hdmi_register(void);
void __exit msm_hdmi_unregister(void);
#else
-static inline int msm_hdmi_modeset_init(struct hdmi *hdmi, struct drm_device *dev,
- struct drm_encoder *encoder)
+static inline struct msm_display *msm_hdmi_get_display(struct hdmi *hdmi)
{
- return -EINVAL;
+ return NULL;
}
static inline void __init msm_hdmi_register(void) {}
static inline void __exit msm_hdmi_unregister(void) {}
@@ -296,8 +318,7 @@ int dsi_dev_attach(struct platform_device *pdev);
void dsi_dev_detach(struct platform_device *pdev);
void __init msm_dsi_register(void);
void __exit msm_dsi_unregister(void);
-int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
- struct drm_encoder *encoder);
+struct msm_display *msm_dsi_get_display(struct msm_dsi *msm_dsi);
void msm_dsi_snapshot(struct msm_disp_state *disp_state, struct msm_dsi *msm_dsi);
bool msm_dsi_is_cmd_mode(struct msm_dsi *msm_dsi);
bool msm_dsi_is_bonded_dsi(struct msm_dsi *msm_dsi);
@@ -312,11 +333,9 @@ static inline void __init msm_dsi_register(void)
static inline void __exit msm_dsi_unregister(void)
{
}
-static inline int msm_dsi_modeset_init(struct msm_dsi *msm_dsi,
- struct drm_device *dev,
- struct drm_encoder *encoder)
+static inline struct msm_display *msm_dsi_get_display(struct msm_dsi *msm_dsi)
{
- return -EINVAL;
+ return NULL;
}
static inline void msm_dsi_snapshot(struct msm_disp_state *disp_state, struct msm_dsi *msm_dsi)
{
@@ -353,8 +372,7 @@ struct msm_dp;
#ifdef CONFIG_DRM_MSM_DP
int __init msm_dp_register(void);
void __exit msm_dp_unregister(void);
-int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
- struct drm_encoder *encoder);
+struct msm_display *msm_dp_get_display(struct msm_dp *dp_display);
void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp_display);
bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display,
const struct drm_display_mode *mode);
@@ -368,11 +386,9 @@ static inline int __init msm_dp_register(void)
static inline void __exit msm_dp_unregister(void)
{
}
-static inline int msm_dp_modeset_init(struct msm_dp *dp_display,
- struct drm_device *dev,
- struct drm_encoder *encoder)
+static inline struct msm_display *msm_dp_get_display(struct msm_dp *dp_display)
{
- return -EINVAL;
+ return NULL;
}
static inline void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp_display)
diff --git a/drivers/gpu/drm/msm/msm_kms.c b/drivers/gpu/drm/msm/msm_kms.c
index 87530145e82b..3f855f9b3d06 100644
--- a/drivers/gpu/drm/msm/msm_kms.c
+++ b/drivers/gpu/drm/msm/msm_kms.c
@@ -260,9 +260,24 @@ void msm_drm_kms_uninit(struct device *dev)
kms->funcs->destroy(kms);
}
+static int msm_display_modeset_init(struct msm_display *display,
+ struct drm_device *ddev,
+ struct drm_encoder *encoder)
+{
+ if (!display)
+ return 0;
+
+ return display->funcs->modeset_init(display, ddev, encoder);
+}
+
/*
- * Set up the bridges and connectors for the display sub-blocks, using the
- * encoders the backend created in ->kms_init().
+ * Set up the bridges and connectors for the display sub-blocks, dispatching
+ * through the common display interface using the encoders the backend created
+ * in ->kms_init().
+ *
+ * The slave link of a bonded DSI pair shares its master's encoder and creates
+ * no connector of its own; its ->modeset_init() handles that internally, so it
+ * needs no special-casing here.
*/
static int msm_kms_init_connectors(struct drm_device *ddev)
{
@@ -270,45 +285,30 @@ static int msm_kms_init_connectors(struct drm_device *ddev)
struct msm_kms *kms = priv->kms;
int i, ret;
- /*
- * The slave link of a bonded DSI pair shares its master's encoder and
- * creates no connector of its own; msm_dsi_modeset_init() handles that
- * internally, so it needs no special-casing here.
- */
for (i = 0; i < ARRAY_SIZE(kms->dsi); i++) {
- if (!kms->dsi[i])
- continue;
-
- ret = msm_dsi_modeset_init(kms->dsi[i], ddev, kms->dsi_encoder[i]);
- if (ret) {
- DRM_DEV_ERROR(ddev->dev,
- "modeset_init failed for dsi[%d]: %d\n", i, ret);
- return ret;
- }
+ ret = msm_display_modeset_init(msm_dsi_get_display(kms->dsi[i]),
+ ddev, kms->dsi_encoder[i]);
+ if (ret)
+ goto fail;
}
for (i = 0; i < ARRAY_SIZE(kms->dp); i++) {
- if (!kms->dp[i])
- continue;
-
- ret = msm_dp_modeset_init(kms->dp[i], ddev, kms->dp_encoder[i]);
- if (ret) {
- DRM_DEV_ERROR(ddev->dev,
- "modeset_init failed for dp[%d]: %d\n", i, ret);
- return ret;
- }
+ ret = msm_display_modeset_init(msm_dp_get_display(kms->dp[i]),
+ ddev, kms->dp_encoder[i]);
+ if (ret)
+ goto fail;
}
- if (kms->hdmi) {
- ret = msm_hdmi_modeset_init(kms->hdmi, ddev, kms->hdmi_encoder);
- if (ret) {
- DRM_DEV_ERROR(ddev->dev,
- "modeset_init failed for HDMI: %d\n", ret);
- return ret;
- }
- }
+ ret = msm_display_modeset_init(msm_hdmi_get_display(kms->hdmi),
+ ddev, kms->hdmi_encoder);
+ if (ret)
+ goto fail;
return 0;
+
+fail:
+ DRM_DEV_ERROR(ddev->dev, "modeset_init failed: %d\n", ret);
+ return ret;
}
int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv)
--
2.47.3
next prev parent reply other threads:[~2026-07-22 6:36 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-22 6:36 [PATCH 00/24] " Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 01/24] drm/msm/dp: reject YUV420-only modes without VSC SDP support Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 02/24] drm/msm/dp: drop the always-true yuv_supported argument Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 03/24] drm/msm: create the display connectors from common code Dmitry Baryshkov
2026-07-22 6:36 ` Dmitry Baryshkov [this message]
2026-07-22 6:36 ` [PATCH 05/24] drm/msm: route the display snapshot through the msm_display interface Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 06/24] drm/msm/hdmi: capture the HDMI registers in the display snapshot Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 07/24] drm/msm: add the wide_bus_enabled callback to msm_display Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 08/24] drm/msm: add the needs_periph_flush " Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 09/24] drm/msm: add the is_cmd_mode " Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 10/24] drm/msm: add the get_dsc_config " Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 11/24] drm/msm: add the get_te_source " Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 12/24] drm/msm: add is_bonded and needs_encoder callbacks " Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 13/24] drm/msm/hdmi: use dev_get_drvdata() in msm_hdmi_unbind() Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 14/24] drm/msm: store the display sub-blocks as struct msm_display Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 15/24] drm/msm/dp: do not reject wide-bus modes while a YUV420 mode is active Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 16/24] drm/msm/dp: remove cached drm_edid from panel Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 17/24] drm/msm/dp: drop deprecated .mode_set() and use .atomic_pre_enable Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 18/24] drm/msm/hdmi: cache is_hdmi instead of storing the connector Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 19/24] drm/msm/dp: drop redundant panel->connector Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 20/24] drm/msm/dp: use drm_display_info in mode_valid callbacks Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 21/24] drm/msm/dp: guard subconnector setup on the connector type Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 22/24] drm/msm/dp: stop storing the connector in struct msm_dp Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 23/24] drm/msm: create the bridge connectors from common code Dmitry Baryshkov
2026-07-22 6:36 ` [PATCH 24/24] drm/bridge-connector: attach the DP subconnector property Dmitry Baryshkov
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=20260722-drm-msm-display-interface-v1-4-368c10fe62fd@oss.qualcomm.com \
--to=dmitry.baryshkov@oss.qualcomm.com \
--cc=Laurent.pinchart@ideasonboard.com \
--cc=abhinav.kumar@linux.dev \
--cc=airlied@gmail.com \
--cc=andrzej.hajda@intel.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=freedreno@lists.freedesktop.org \
--cc=jernej.skrabec@gmail.com \
--cc=jesszhan0024@gmail.com \
--cc=jonas@kwiboo.se \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luca.ceresoli@bootlin.com \
--cc=lumag@kernel.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=marijn.suijten@somainline.org \
--cc=mripard@kernel.org \
--cc=neil.armstrong@linaro.org \
--cc=rfoss@kernel.org \
--cc=robin.clark@oss.qualcomm.com \
--cc=sean@poorly.run \
--cc=simona@ffwll.ch \
--cc=tzimmermann@suse.de \
/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®