From 3b90318d44f87a3582f876802253a7748d270385 Mon Sep 17 00:00:00 2001 From: Michael Strauss Date: Fri, 22 Apr 2022 15:40:34 -0400 Subject: drm/amd/display: Refactor LTTPR cap retrieval [WHY] Split LTTPR mode selection between platform support and downstream link support Reviewed-by: Wesley Chalmers Acked-by: Stylon Wang Signed-off-by: Michael Strauss Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 175 ++++++++++++--------- drivers/gpu/drm/amd/display/dc/dc_link.h | 2 + drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h | 3 +- .../drm/amd/display/include/link_service_types.h | 6 + 4 files changed, 113 insertions(+), 73 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 55a5a6a49fe2..5e49e346aa06 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -5097,16 +5097,13 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link) return true; } -bool dp_retrieve_lttpr_cap(struct dc_link *link) +void dp_retrieve_lttpr_cap(struct dc_link *link) { - uint8_t lttpr_dpcd_data[8]; bool allow_lttpr_non_transparent_mode = 0; - bool vbios_lttpr_enable = link->dc->caps.vbios_lttpr_enable; bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware; enum dc_status status = DC_ERROR_UNEXPECTED; - bool is_lttpr_present = false; - memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data)); + memset(link->lttpr_dpcd_data, '\0', sizeof(link->lttpr_dpcd_data)); if ((link->dc->config.allow_lttpr_non_transparent_mode.bits.DP2_0 && link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED)) { @@ -5116,88 +5113,118 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) allow_lttpr_non_transparent_mode = 1; } + link->lttpr_mode = LTTPR_MODE_NON_LTTPR; + link->lttpr_support = LTTPR_UNSUPPORTED; + /* - * Logic to determine LTTPR mode + * Logic to determine LTTPR support */ - link->lttpr_mode = LTTPR_MODE_NON_LTTPR; - if (vbios_lttpr_enable && vbios_lttpr_interop) - link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; - else if (!vbios_lttpr_enable && vbios_lttpr_interop) { - if (allow_lttpr_non_transparent_mode) - link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; - else - link->lttpr_mode = LTTPR_MODE_TRANSPARENT; - } else if (!vbios_lttpr_enable && !vbios_lttpr_interop) { - if (!allow_lttpr_non_transparent_mode || !link->dc->caps.extended_aux_timeout_support) - link->lttpr_mode = LTTPR_MODE_NON_LTTPR; - else - link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; - } + if (vbios_lttpr_interop) + link->lttpr_support = LTTPR_SUPPORTED; + else if (link->dc->config.allow_lttpr_non_transparent_mode.raw == 0 + || !link->dc->caps.extended_aux_timeout_support) + link->lttpr_support = LTTPR_UNSUPPORTED; + else + link->lttpr_support = LTTPR_CHECK_EXT_SUPPORT; + #if defined(CONFIG_DRM_AMD_DC_DCN) /* Check DP tunnel LTTPR mode debug option. */ if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && link->dc->debug.dpia_debug.bits.force_non_lttpr) - link->lttpr_mode = LTTPR_MODE_NON_LTTPR; + link->lttpr_support = LTTPR_UNSUPPORTED; #endif - if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT || link->lttpr_mode == LTTPR_MODE_TRANSPARENT) { + if (link->lttpr_support > LTTPR_UNSUPPORTED) { /* By reading LTTPR capability, RX assumes that we will enable * LTTPR extended aux timeout if LTTPR is present. */ status = core_link_read_dpcd( link, DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV, - lttpr_dpcd_data, - sizeof(lttpr_dpcd_data)); - if (status != DC_OK) { - DC_LOG_DP2("%s: Read LTTPR caps data failed.\n", __func__); - link->lttpr_mode = LTTPR_MODE_NON_LTTPR; - return false; - } + link->lttpr_dpcd_data, + sizeof(link->lttpr_dpcd_data)); + } +} - link->dpcd_caps.lttpr_caps.revision.raw = - lttpr_dpcd_data[DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - - link->dpcd_caps.lttpr_caps.max_link_rate = - lttpr_dpcd_data[DP_MAX_LINK_RATE_PHY_REPEATER - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - - link->dpcd_caps.lttpr_caps.phy_repeater_cnt = - lttpr_dpcd_data[DP_PHY_REPEATER_CNT - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - - link->dpcd_caps.lttpr_caps.max_lane_count = - lttpr_dpcd_data[DP_MAX_LANE_COUNT_PHY_REPEATER - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - - link->dpcd_caps.lttpr_caps.mode = - lttpr_dpcd_data[DP_PHY_REPEATER_MODE - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - - link->dpcd_caps.lttpr_caps.max_ext_timeout = - lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - - link->dpcd_caps.lttpr_caps.main_link_channel_coding.raw = - lttpr_dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - - link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.raw = - lttpr_dpcd_data[DP_PHY_REPEATER_128b_132b_RATES - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - - /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */ - is_lttpr_present = (link->dpcd_caps.lttpr_caps.max_lane_count > 0 && - link->dpcd_caps.lttpr_caps.phy_repeater_cnt < 0xff && - link->dpcd_caps.lttpr_caps.max_lane_count <= 4 && - link->dpcd_caps.lttpr_caps.revision.raw >= 0x14); - if (is_lttpr_present) { - CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: "); - configure_lttpr_mode_transparent(link); - } else - link->lttpr_mode = LTTPR_MODE_NON_LTTPR; +bool dp_parse_lttpr_mode(struct dc_link *link) +{ + bool dpcd_allow_lttpr_non_transparent_mode = false; + bool is_lttpr_present = false; + + bool vbios_lttpr_enable = link->dc->caps.vbios_lttpr_enable; + + if ((link->dc->config.allow_lttpr_non_transparent_mode.bits.DP2_0 && + link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED)) { + dpcd_allow_lttpr_non_transparent_mode = true; + } else if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A && + !link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) { + dpcd_allow_lttpr_non_transparent_mode = true; } + + /* + * Logic to determine LTTPR mode + */ + if (link->lttpr_support == LTTPR_SUPPORTED) + if (vbios_lttpr_enable) + link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; + else if (dpcd_allow_lttpr_non_transparent_mode) + link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; + else + link->lttpr_mode = LTTPR_MODE_TRANSPARENT; + else // lttpr_support == LTTPR_CHECK_EXT_SUPPORT + if (dpcd_allow_lttpr_non_transparent_mode) { + link->lttpr_support = LTTPR_SUPPORTED; + link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; + } else { + link->lttpr_support = LTTPR_UNSUPPORTED; + } + + if (link->lttpr_support == LTTPR_UNSUPPORTED) + return false; + + link->dpcd_caps.lttpr_caps.revision.raw = + link->lttpr_dpcd_data[DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + + link->dpcd_caps.lttpr_caps.max_link_rate = + link->lttpr_dpcd_data[DP_MAX_LINK_RATE_PHY_REPEATER - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + + link->dpcd_caps.lttpr_caps.phy_repeater_cnt = + link->lttpr_dpcd_data[DP_PHY_REPEATER_CNT - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + + link->dpcd_caps.lttpr_caps.max_lane_count = + link->lttpr_dpcd_data[DP_MAX_LANE_COUNT_PHY_REPEATER - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + + link->dpcd_caps.lttpr_caps.mode = + link->lttpr_dpcd_data[DP_PHY_REPEATER_MODE - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + + link->dpcd_caps.lttpr_caps.max_ext_timeout = + link->lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + + link->dpcd_caps.lttpr_caps.main_link_channel_coding.raw = + link->lttpr_dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + + link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.raw = + link->lttpr_dpcd_data[DP_PHY_REPEATER_128B132B_RATES - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + + + /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */ + is_lttpr_present = (link->dpcd_caps.lttpr_caps.max_lane_count > 0 && + link->dpcd_caps.lttpr_caps.max_lane_count <= 4 && + link->dpcd_caps.lttpr_caps.revision.raw >= 0x14); + if (is_lttpr_present) { + CONN_DATA_DETECT(link, link->lttpr_dpcd_data, sizeof(link->lttpr_dpcd_data), "LTTPR Caps: "); + configure_lttpr_mode_transparent(link); + } else + link->lttpr_mode = LTTPR_MODE_NON_LTTPR; + return is_lttpr_present; } @@ -5349,7 +5376,8 @@ static bool retrieve_link_cap(struct dc_link *link) status = wa_try_to_wake_dprx(link, timeout_ms); } - is_lttpr_present = dp_retrieve_lttpr_cap(link); + dp_retrieve_lttpr_cap(link); + /* Read DP tunneling information. */ status = dpcd_get_tunneling_device_data(link); @@ -5385,6 +5413,9 @@ static bool retrieve_link_cap(struct dc_link *link) return false; } + if (link->lttpr_support > LTTPR_UNSUPPORTED) + is_lttpr_present = dp_parse_lttpr_mode(link); + if (!is_lttpr_present) dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD); diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index a3c37ee3f849..251f2bbc96b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -129,6 +129,8 @@ struct dc_link { bool link_state_valid; bool aux_access_disabled; bool sync_lt_in_progress; + uint8_t lttpr_dpcd_data[8]; + enum lttpr_support lttpr_support; enum lttpr_mode lttpr_mode; bool is_internal_display; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 44f167d2584f..78f09893c118 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -217,7 +217,8 @@ void disable_dp_hpo_output(struct dc_link *link, void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable); bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx); -bool dp_retrieve_lttpr_cap(struct dc_link *link); +void dp_retrieve_lttpr_cap(struct dc_link *link); +bool dp_apply_lttpr_mode(struct dc_link *link); void edp_panel_backlight_power_on(struct dc_link *link); void dp_receiver_power_ctrl(struct dc_link *link, bool on); void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode); diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index 447a56286dd0..9f465b4d626e 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -80,6 +80,12 @@ enum link_training_result { DP_128b_132b_CDS_DONE_TIMEOUT, }; +enum lttpr_support { + LTTPR_UNSUPPORTED, + LTTPR_CHECK_EXT_SUPPORT, + LTTPR_SUPPORTED, +}; + enum lttpr_mode { LTTPR_MODE_NON_LTTPR, LTTPR_MODE_TRANSPARENT, -- cgit