Add a mechanism to retry Link Training 2 by lowering the pattern level when the link training #2 first attempt fails. This approach enhances compatibility, particularly addressing issues caused by certain hub configurations. Signed-off-by: Xiangxu Yin <quic_xiangxuy@xxxxxxxxxxx> --- drivers/gpu/drm/msm/dp/dp_ctrl.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 49c8ce9b2d0e57a613e50865be3fe98e814d425a..b1862294cb98c9f756b0108b7670cb42de37bae4 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1220,7 +1220,7 @@ static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl) } static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, - int *training_step) + int *training_step, bool downgrade) { int tries = 0, ret = 0; u8 pattern; @@ -1243,6 +1243,28 @@ static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl, state_ctrl_bit = 2; } + /* + * DP link training uses the highest allowed pattern by default. + * If it fails, the pattern is downgraded to improve cable and monitor compatibility. + */ + if (downgrade) { + switch (pattern) { + case DP_TRAINING_PATTERN_4: + pattern = DP_TRAINING_PATTERN_3; + state_ctrl_bit = 3; + break; + case DP_TRAINING_PATTERN_3: + pattern = DP_TRAINING_PATTERN_2; + state_ctrl_bit = 2; + break; + default: + break; + } + } + + drm_dbg_dp(ctrl->drm_dev, "pattern(%d) state_ctrl_bit(%d) downgrade(%d)\n", + pattern, state_ctrl_bit, downgrade); + ret = msm_dp_catalog_ctrl_set_pattern_state_bit(ctrl->catalog, state_ctrl_bit); if (ret) return ret; @@ -1311,10 +1333,14 @@ static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl, /* print success info as this is a result of user initiated action */ drm_dbg_dp(ctrl->drm_dev, "link training #1 successful\n"); - ret = msm_dp_ctrl_link_train_2(ctrl, training_step); + ret = msm_dp_ctrl_link_train_2(ctrl, training_step, false); if (ret) { - DRM_ERROR("link training #2 failed. ret=%d\n", ret); - goto end; + drm_dbg_dp(ctrl->drm_dev, "link training #2 failed, retry downgrade.\n"); + ret = msm_dp_ctrl_link_train_2(ctrl, training_step, true); + if (ret) { + DRM_ERROR("link training #2 failed. ret=%d\n", ret); + goto end; + } } /* print success info as this is a result of user initiated action */ -- 2.25.1