Each KMS backend (mdp4, mdp5, dpu1) open-codes the loop over the DSI, DP and HDMI sub-blocks and the calls to msm_dsi_modeset_init(), msm_dp_modeset_init() and msm_hdmi_modeset_init() that build the bridges and connectors. The dispatch, including the bonded-DSI handling, is duplicated three times with subtle variations.
The encoder each sub-block is attached to is genuinely backend-specific (the DPU builds a display-info descriptor, MDP5 requests a CTL, MDP4 uses fixed CRTC masks), but the connector setup that follows is not. Have each backend only create the encoder and record it in struct msm_kms, and move the msm_*_modeset_init() dispatch into a common msm_kms_init_connectors() called from msm_drm_kms_init() after the backend's ->hw_init(), where the encoders and, on DPU, the GEM address space (kms->vm) that msm_dsi_host_modeset_init() allocates the DSI TX buffer from are set up. No functional change intended. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Dmitry Baryshkov <[email protected]> --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 34 ++++-------------- drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c | 18 +++------- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 9 +++-- drivers/gpu/drm/msm/msm_kms.c | 60 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/msm_kms.h | 3 ++ 5 files changed, 78 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index ede935a426d1..42dff1a98292 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -627,21 +627,11 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev, return PTR_ERR(encoder); } - rc = msm_dsi_modeset_init(priv->kms->dsi[i], dev, encoder); - if (rc) { - DPU_ERROR("modeset_init failed for dsi[%d], rc = %d\n", - i, rc); - break; - } - - if (msm_dsi_is_bonded_dsi(priv->kms->dsi[i]) && priv->kms->dsi[other]) { - rc = msm_dsi_modeset_init(priv->kms->dsi[other], dev, encoder); - if (rc) { - DPU_ERROR("modeset_init failed for dsi[%d], rc = %d\n", - other, rc); - break; - } - } + /* + * A bonded pair is driven by a single encoder; the connector + * setup for both hosts is handled from common code later. + */ + priv->kms->dsi_encoder[i] = encoder; } return rc; @@ -653,7 +643,6 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, { struct drm_encoder *encoder = NULL; struct msm_display_info info; - int rc; int i; for (i = 0; i < ARRAY_SIZE(priv->kms->dp); i++) { @@ -671,11 +660,7 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, return PTR_ERR(encoder); } - rc = msm_dp_modeset_init(priv->kms->dp[i], dev, encoder); - if (rc) { - DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc); - return rc; - } + priv->kms->dp_encoder[i] = encoder; } return 0; @@ -687,7 +672,6 @@ static int _dpu_kms_initialize_hdmi(struct drm_device *dev, { struct drm_encoder *encoder = NULL; struct msm_display_info info; - int rc; if (!priv->kms->hdmi) return 0; @@ -703,11 +687,7 @@ static int _dpu_kms_initialize_hdmi(struct drm_device *dev, return PTR_ERR(encoder); } - rc = msm_hdmi_modeset_init(priv->kms->hdmi, dev, encoder); - if (rc) { - DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc); - return rc; - } + priv->kms->hdmi_encoder = encoder; return 0; } diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c index 7726edb0d4ed..cd566a287f6f 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c @@ -243,14 +243,9 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms, /* DTV can be hooked to DMA_E: */ encoder->possible_crtcs = 1 << 1; - if (priv->kms->hdmi) { - /* Construct bridge/connector for HDMI: */ - ret = msm_hdmi_modeset_init(priv->kms->hdmi, dev, encoder); - if (ret) { - DRM_DEV_ERROR(dev->dev, "failed to initialize HDMI: %d\n", ret); - return ret; - } - } + /* the bridge/connector for HDMI is set up from common code */ + if (priv->kms->hdmi) + priv->kms->hdmi_encoder = encoder; break; case DRM_MODE_ENCODER_DSI: @@ -271,12 +266,7 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms, /* TODO: Add DMA_S later? */ encoder->possible_crtcs = 1 << DMA_P; - ret = msm_dsi_modeset_init(priv->kms->dsi[dsi_id], dev, encoder); - if (ret) { - DRM_DEV_ERROR(dev->dev, "failed to initialize DSI: %d\n", - ret); - return ret; - } + priv->kms->dsi_encoder[dsi_id] = encoder; break; default: diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index 0a004ab9fc85..68b71a7c6666 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -330,7 +330,7 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, break; } - ret = msm_hdmi_modeset_init(priv->kms->hdmi, dev, encoder); + priv->kms->hdmi_encoder = encoder; break; case INTF_DSI: { @@ -360,10 +360,9 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, break; } - ret = msm_dsi_modeset_init(priv->kms->dsi[dsi_id], dev, encoder); - if (!ret) - mdp5_encoder_set_intf_mode(encoder, - msm_dsi_is_cmd_mode(priv->kms->dsi[dsi_id])); + priv->kms->dsi_encoder[dsi_id] = encoder; + mdp5_encoder_set_intf_mode(encoder, + msm_dsi_is_cmd_mode(priv->kms->dsi[dsi_id])); break; } diff --git a/drivers/gpu/drm/msm/msm_kms.c b/drivers/gpu/drm/msm/msm_kms.c index e5d0ea629448..87530145e82b 100644 --- a/drivers/gpu/drm/msm/msm_kms.c +++ b/drivers/gpu/drm/msm/msm_kms.c @@ -260,6 +260,57 @@ void msm_drm_kms_uninit(struct device *dev) kms->funcs->destroy(kms); } +/* + * Set up the bridges and connectors for the display sub-blocks, using the + * encoders the backend created in ->kms_init(). + */ +static int msm_kms_init_connectors(struct drm_device *ddev) +{ + struct msm_drm_private *priv = ddev->dev_private; + 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; + } + } + + 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; + } + } + + 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; + } + } + + return 0; +} + int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv) { struct msm_drm_private *priv = dev_get_drvdata(dev); @@ -298,6 +349,15 @@ int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv) goto err_msm_uninit; } + /* + * The backend created the encoders for each display sub-block in + * ->hw_init(); now set up the bridges and connectors for them from + * common code. + */ + ret = msm_kms_init_connectors(ddev); + if (ret) + goto err_msm_uninit; + drm_helper_move_panel_connectors_to_head(ddev); drm_for_each_crtc(crtc, ddev) { diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index f25b31e502d2..06646091604a 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -140,10 +140,13 @@ struct msm_kms { struct drm_device *dev; struct hdmi *hdmi; + struct drm_encoder *hdmi_encoder; struct msm_dsi *dsi[MSM_DSI_CONTROLLER_COUNT]; + struct drm_encoder *dsi_encoder[MSM_DSI_CONTROLLER_COUNT]; struct msm_dp *dp[MSM_DP_CONTROLLER_COUNT]; + struct drm_encoder *dp_encoder[MSM_DP_CONTROLLER_COUNT]; /* irq number to be passed on to msm_irq_install */ int irq; -- 2.47.3
