Unlike SST, where a DP controller is represented by a single encoder, MST requires an encoder instance for each stream.
Create one DRM encoder per MST stream, associate it with a stream ID, and initialize it with MST-specific encoder helper callbacks. This establishes the per-stream encoder infrastructure required for DP MST support. Signed-off-by: Abhinav Kumar <[email protected]> Signed-off-by: Yongxing Mou <[email protected]> --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 23 ++++++++++++++++++++++- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 15 +++++++++++++++ drivers/gpu/drm/msm/dp/dp_mst_drm.c | 20 ++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_mst_drm.h | 2 ++ drivers/gpu/drm/msm/msm_drv.h | 9 +++++++++ 5 files changed, 68 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 004d5fc460a8..533109b4365c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2744,6 +2744,24 @@ static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = { .atomic_enable = dpu_encoder_virt_atomic_enable, }; +static void dpu_encoder_mst_atomic_enable(struct drm_encoder *enc, + struct drm_atomic_commit *state) +{ + dpu_encoder_virt_atomic_enable(enc, state); +} + +static void dpu_encoder_mst_atomic_disable(struct drm_encoder *enc, + struct drm_atomic_commit *state) +{ + dpu_encoder_virt_atomic_disable(enc, state); +} + +static const struct drm_encoder_helper_funcs dpu_mst_encoder_helper_funcs = { + .atomic_mode_set = dpu_encoder_virt_atomic_mode_set, + .atomic_enable = dpu_encoder_mst_atomic_enable, + .atomic_disable = dpu_encoder_mst_atomic_disable, +}; + static const struct drm_encoder_funcs dpu_encoder_funcs = { .debugfs_init = dpu_encoder_debugfs_init, }; @@ -2769,7 +2787,10 @@ struct drm_encoder *dpu_encoder_init(struct drm_device *dev, if (IS_ERR(dpu_enc)) return ERR_CAST(dpu_enc); - drm_encoder_helper_add(&dpu_enc->base, &dpu_encoder_helper_funcs); + if (drm_enc_mode == DRM_MODE_ENCODER_DPMST) + drm_encoder_helper_add(&dpu_enc->base, &dpu_mst_encoder_helper_funcs); + else + drm_encoder_helper_add(&dpu_enc->base, &dpu_encoder_helper_funcs); spin_lock_init(&dpu_enc->enc_spinlock); dpu_enc->enabled = false; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 7ee4e7e4d34a..4e18026cdff0 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -688,6 +688,21 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, return rc; } } + + for (int stream_id = 0; stream_cnt > 1 && stream_id < stream_cnt; stream_id++) { + info.stream_id = stream_id; + encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DPMST, &info); + if (IS_ERR(encoder)) { + DPU_ERROR("encoder init failed for dp mst display\n"); + return PTR_ERR(encoder); + } + + rc = msm_dp_mst_attach_encoder(priv->kms->dp[i], stream_id, encoder); + if (rc) { + DPU_ERROR("dp_mst attach_encoder failed, rc = %d\n", rc); + return rc; + } + } } return 0; diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.c b/drivers/gpu/drm/msm/dp/dp_mst_drm.c index 169b34f985c0..88687b97ed6e 100644 --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.c @@ -145,6 +145,26 @@ static int msm_dp_mst_encoder_stream_id(struct msm_dp_mst *mst, return -1; } +int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, unsigned int stream_id, + struct drm_encoder *encoder) +{ + struct msm_dp_mst *mst = dp_display->msm_dp_mst; + struct msm_dp_panel *dp_panel; + + dp_panel = msm_dp_display_get_panel(dp_display, stream_id); + if (!dp_panel) { + drm_err(dp_display->drm_dev, + "[MST] failed to allocate panel for stream %d\n", stream_id); + return -ENOMEM; + } + + mst->mst_encoders[stream_id].enc = encoder; + mst->mst_encoders[stream_id].stream_id = stream_id; + mst->mst_encoders[stream_id].dp_panel = dp_panel; + + return 0; +} + static struct drm_encoder * msm_dp_mst_atomic_best_encoder(struct drm_connector *connector, struct drm_atomic_commit *state) { diff --git a/drivers/gpu/drm/msm/dp/dp_mst_drm.h b/drivers/gpu/drm/msm/dp/dp_mst_drm.h index 7f35e7524cfd..3cbd2a674675 100644 --- a/drivers/gpu/drm/msm/dp/dp_mst_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_mst_drm.h @@ -9,5 +9,7 @@ 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); +int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, unsigned int stream_id, + struct drm_encoder *encoder); #endif /* _DP_MST_DRM_H_ */ diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index b14f097ae8cc..2ada4a7c1c08 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -360,6 +360,8 @@ 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); +int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, unsigned int stream_id, + struct drm_encoder *encoder); #else static inline int __init msm_dp_register(void) @@ -406,6 +408,13 @@ static inline void msm_dp_mst_unregister(struct msm_dp *dp_display) { } +static inline int msm_dp_mst_attach_encoder(struct msm_dp *dp_display, + unsigned int stream_id, + struct drm_encoder *encoder) +{ + return -EINVAL; +} + #endif #ifdef CONFIG_DRM_MSM_MDP4 -- 2.43.0
