--- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -251,16 +251,34 @@ int rc, lttpr_count; if (drm_dp_read_lttpr_common_caps(dp->aux, dpcd, dp->link->lttpr_common_caps)) - return 0; + goto no_lttpr; + + /* + * Some sinks without LTTPR support (e.g. DP->HDMI converters) mirror + * their receiver caps at 0xf0000 instead of NAKing the read. Only + * trust the block if it carries a valid LTTPR structure revision and + * repeater count: otherwise the caps would clamp the link to whatever + * lands in the "max lane count"/"max link rate" slots, and writing + * PHY_REPEATER_MODE would end up in the sink's own DPCD. + */ + if (dp->link->lttpr_common_caps[0] < 0x14) + goto no_lttpr; lttpr_count = drm_dp_lttpr_count(dp->link->lttpr_common_caps); + if (lttpr_count < 0) + goto no_lttpr; + rc = drm_dp_lttpr_init(dp->aux, lttpr_count); if (rc) { DRM_ERROR("failed to set LTTPRs transparency mode, rc=%d\n", rc); - return 0; + goto no_lttpr; } return lttpr_count; + +no_lttpr: + memset(dp->link->lttpr_common_caps, 0, sizeof(dp->link->lttpr_common_caps)); + return 0; } static int msm_dp_display_process_hpd_high(struct msm_dp_display_private *dp) --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -101,6 +101,12 @@ msm_dp_panel->vsc_sdp_supported = drm_dp_vsc_sdp_supported(panel->aux, dpcd); link_info = &msm_dp_panel->link_info; + /* + * Everything below is derived from the current sink. Start from + * scratch so a rate from a previous sink (the fallback path only runs + * when rate is 0) does not stick across unplug/replug. + */ + memset(link_info, 0, sizeof(*link_info)); link_info->revision = dpcd[DP_DPCD_REV]; major = (link_info->revision >> 4) & 0x0f; minor = link_info->revision & 0x0f;