[PATCH 04/24] drm/msm: introduce the struct msm_display interface
From: Dmitry Baryshkov
Date: Wed Jul 22 2026 - 02:43:17 EST
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@xxxxxxxxxxxxxxxx>
---
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