diff options
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_link.c | 362 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 164 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dc.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h | 7 |
5 files changed, 259 insertions, 291 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index e5d63b0d2594..af2d7f3abfca 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -720,35 +720,8 @@ static bool detect_dp(struct dc_link *link, sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT; if (!detect_dp_sink_caps(link)) return false; - if (is_mst_supported(link)) { - sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST; - link->type = dc_connection_mst_branch; - dal_ddc_service_set_transaction_type(link->ddc, - sink_caps->transaction_type); - -#if defined(CONFIG_DRM_AMD_DC_DCN) - /* Apply work around for tunneled MST on certain USB4 docks. Always use DSC if dock - * reports DSC support. - */ - if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && - link->type == dc_connection_mst_branch && - link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 && - link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT && - !link->dc->debug.dpia_debug.bits.disable_mst_dsc_work_around) - link->wa_flags.dpia_mst_dsc_always_on = true; -#endif - -#if defined(CONFIG_DRM_AMD_DC_HDCP) - /* In case of fallback to SST when topology discovery below fails - * HDCP caps will be querried again later by the upper layer (caller - * of this function). */ - query_hdcp_capability(SIGNAL_TYPE_DISPLAY_PORT_MST, link); -#endif - } - - if (link->type != dc_connection_mst_branch && - is_dp_branch_device(link)) + if (is_dp_branch_device(link)) /* DP SST branch */ link->type = dc_connection_sst_branch; } else { @@ -824,15 +797,215 @@ static bool wait_for_entering_dp_alt_mode(struct dc_link *link) return false; } -/* - * dc_link_detect() - Detect if a sink is attached to a given link +static void apply_dpia_mst_dsc_always_on_wa(struct dc_link *link) +{ +#if defined(CONFIG_DRM_AMD_DC_DCN) + /* Apply work around for tunneled MST on certain USB4 docks. Always use DSC if dock + * reports DSC support. + */ + if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && + link->type == dc_connection_mst_branch && + link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 && + link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT && + !link->dc->debug.dpia_debug.bits.disable_mst_dsc_work_around) + link->wa_flags.dpia_mst_dsc_always_on = true; +#endif +} + +static void revert_dpia_mst_dsc_always_on_wa(struct dc_link *link) +{ + /* Disable work around which keeps DSC on for tunneled MST on certain USB4 docks. */ + if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) + link->wa_flags.dpia_mst_dsc_always_on = false; +} + +static bool discover_dp_mst_topology(struct dc_link *link, enum dc_detect_reason reason) +{ + DC_LOGGER_INIT(link->ctx->logger); + + LINK_INFO("link=%d, mst branch is now Connected\n", + link->link_index); + + apply_dpia_mst_dsc_always_on_wa(link); + link->type = dc_connection_mst_branch; + dm_helpers_dp_update_branch_info(link->ctx, link); + if (dm_helpers_dp_mst_start_top_mgr(link->ctx, + link, reason == DETECT_REASON_BOOT)) { + link_disconnect_sink(link); + } else { + link->type = dc_connection_sst_branch; + } + + return link->type == dc_connection_mst_branch; +} + +static void reset_cur_dp_mst_topology(struct dc_link *link) +{ + DC_LOGGER_INIT(link->ctx->logger); + + LINK_INFO("link=%d, mst branch is now Disconnected\n", + link->link_index); + + revert_dpia_mst_dsc_always_on_wa(link); + dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); + + link->mst_stream_alloc_table.stream_count = 0; + memset(link->mst_stream_alloc_table.stream_allocations, + 0, + sizeof(link->mst_stream_alloc_table.stream_allocations)); +} + +static bool should_prepare_phy_clocks_for_link_verification(const struct dc *dc, + enum dc_detect_reason reason) +{ + int i; + bool can_apply_seamless_boot = false; + + for (i = 0; i < dc->current_state->stream_count; i++) { + if (dc->current_state->streams[i]->apply_seamless_boot_optimization) { + can_apply_seamless_boot = true; + break; + } + } + + return !can_apply_seamless_boot && reason != DETECT_REASON_BOOT; +} + +static void prepare_phy_clocks_for_destructive_link_verification(const struct dc *dc) +{ +#if defined(CONFIG_DRM_AMD_DC_DCN) + dc_z10_restore(dc); +#endif + clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr); +} + +static void restore_phy_clocks_for_destructive_link_verification(const struct dc *dc) +{ + clk_mgr_optimize_pwr_state(dc, dc->clk_mgr); +} + +static void set_all_streams_dpms_off_for_link(struct dc_link *link) +{ + int i; + struct pipe_ctx *pipe_ctx; + struct dc_stream_update stream_update; + bool dpms_off = true; + + memset(&stream_update, 0, sizeof(stream_update)); + stream_update.dpms_off = &dpms_off; + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off && + pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) { + stream_update.stream = pipe_ctx->stream; + dc_commit_updates_for_stream(link->ctx->dc, NULL, 0, + pipe_ctx->stream, &stream_update, + link->ctx->dc->current_state); + } + } +} + +static void verify_link_capability_destructive(struct dc_link *link, + struct dc_sink *sink, + enum dc_detect_reason reason) +{ + struct link_resource link_res = { 0 }; + bool should_prepare_phy_clocks = + should_prepare_phy_clocks_for_link_verification(link->dc, reason); + + if (should_prepare_phy_clocks) + prepare_phy_clocks_for_destructive_link_verification(link->dc); + + + if (dc_is_dp_signal(link->local_sink->sink_signal)) { + struct dc_link_settings known_limit_link_setting = + dp_get_max_link_cap(link); + + set_all_streams_dpms_off_for_link(link); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&known_limit_link_setting) == + DP_128b_132b_ENCODING) + link_res.hpo_dp_link_enc = resource_get_hpo_dp_link_enc_for_det_lt( + &link->dc->current_state->res_ctx, + link->dc->res_pool, + link); +#endif + dp_verify_link_cap_with_retries( + link, &link_res, &known_limit_link_setting, + LINK_TRAINING_MAX_VERIFY_RETRY); + } else { + ASSERT(0); + } + + if (should_prepare_phy_clocks) + restore_phy_clocks_for_destructive_link_verification(link->dc); +} + +static void verify_link_capability_non_destructive(struct dc_link *link) +{ + if (dc_is_dp_signal(link->local_sink->sink_signal)) { + if (dc_is_embedded_signal(link->local_sink->sink_signal) || + link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) + /* TODO - should we check link encoder's max link caps here? + * How do we know which link encoder to check from? + */ + link->verified_link_cap = link->reported_link_cap; + else + link->verified_link_cap = dp_get_max_link_cap(link); + } +} + +static bool should_verify_link_capability_destructively(struct dc_link *link, + enum dc_detect_reason reason) +{ + bool destrictive = false; + struct dc_link_settings max_link_cap; + bool is_link_enc_unavailable = link->link_enc && + link->dc->res_pool->funcs->link_encs_assign && + !link_enc_cfg_is_link_enc_avail( + link->ctx->dc, + link->link_enc->preferred_engine, + link); + + if (dc_is_dp_signal(link->local_sink->sink_signal)) { + max_link_cap = dp_get_max_link_cap(link); + destrictive = true; + + if (link->dc->debug.skip_detection_link_training || + dc_is_embedded_signal(link->local_sink->sink_signal) || + link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) { + destrictive = false; + } else if (dp_get_link_encoding_format(&max_link_cap) == + DP_8b_10b_ENCODING) { + if (link->dpcd_caps.is_mst_capable || + is_link_enc_unavailable) { + destrictive = false; + } + } + } + + return destrictive; +} + +static void verify_link_capability(struct dc_link *link, struct dc_sink *sink, + enum dc_detect_reason reason) +{ + if (should_verify_link_capability_destructively(link, reason)) + verify_link_capability_destructive(link, sink, reason); + else + verify_link_capability_non_destructive(link); +} + + +/** + * detect_link_and_local_sink() - Detect if a sink is attached to a given link * * link->local_sink is created or destroyed as needed. * - * This does not create remote sinks but will trigger DM - * to start MST detection if a branch is detected. + * This does not create remote sinks. */ -static bool dc_link_detect_helper(struct dc_link *link, +static bool detect_link_and_local_sink(struct dc_link *link, enum dc_detect_reason reason) { struct dc_sink_init_data sink_init_data = { 0 }; @@ -848,9 +1021,7 @@ static bool dc_link_detect_helper(struct dc_link *link, struct dpcd_caps prev_dpcd_caps; enum dc_connection_type new_connection_type = dc_connection_none; enum dc_connection_type pre_connection_type = dc_connection_none; - bool perform_dp_seamless_boot = false; const uint32_t post_oui_delay = 30; // 30ms - struct link_resource link_res = { 0 }; DC_LOGGER_INIT(link->ctx->logger); @@ -944,61 +1115,6 @@ static bool dc_link_detect_helper(struct dc_link *link, return false; } -#if defined(CONFIG_DRM_AMD_DC_DCN) - if (dp_get_link_encoding_format(&link->reported_link_cap) == DP_128b_132b_ENCODING) - link_res.hpo_dp_link_enc = resource_get_hpo_dp_link_enc_for_det_lt( - &link->dc->current_state->res_ctx, - link->dc->res_pool, - link); -#endif - - if (link->type == dc_connection_mst_branch) { - LINK_INFO("link=%d, mst branch is now Connected\n", - link->link_index); - /* Need to setup mst link_cap struct here - * otherwise dc_link_detect() will leave mst link_cap - * empty which leads to allocate_mst_payload() has "0" - * pbn_per_slot value leading to exception on dc_fixpt_div() - */ - dp_verify_mst_link_cap(link, &link_res); - - /* - * This call will initiate MST topology discovery. Which - * will detect MST ports and add new DRM connector DRM - * framework. Then read EDID via remote i2c over aux. In - * the end, will notify DRM detect result and save EDID - * into DRM framework. - * - * .detect is called by .fill_modes. - * .fill_modes is called by user mode ioctl - * DRM_IOCTL_MODE_GETCONNECTOR. - * - * .get_modes is called by .fill_modes. - * - * call .get_modes, AMDGPU DM implementation will create - * new dc_sink and add to dc_link. For long HPD plug - * in/out, MST has its own handle. - * - * Therefore, just after dc_create, link->sink is not - * created for MST until user mode app calls - * DRM_IOCTL_MODE_GETCONNECTOR. - * - * Need check ->sink usages in case ->sink = NULL - * TODO: s3 resume check - */ - - dm_helpers_dp_update_branch_info(link->ctx, link); - if (dm_helpers_dp_mst_start_top_mgr(link->ctx, - link, reason == DETECT_REASON_BOOT)) { - if (prev_sink) - dc_sink_release(prev_sink); - return false; - } else { - link->type = dc_connection_sst_branch; - sink_caps.signal = SIGNAL_TYPE_DISPLAY_PORT; - } - } - /* Active SST downstream branch device unplug*/ if (link->type == dc_connection_sst_branch && link->dpcd_caps.sink_count.bits.SINK_COUNT == 0) { @@ -1019,7 +1135,6 @@ static bool dc_link_detect_helper(struct dc_link *link, if (pre_connection_type == dc_connection_mst_branch && link->type != dc_connection_mst_branch) dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); - break; } @@ -1108,13 +1223,6 @@ static bool dc_link_detect_helper(struct dc_link *link, #if defined(CONFIG_DRM_AMD_DC_HDCP) query_hdcp_capability(sink->sink_signal, link); #endif - - // verify link cap for SST non-seamless boot - if (!perform_dp_seamless_boot) - dp_verify_link_cap_with_retries(link, - &link_res, - &link->reported_link_cap, - LINK_TRAINING_MAX_VERIFY_RETRY); } else { // If edid is the same, then discard new sink and revert back to original sink if (same_edid) { @@ -1174,27 +1282,6 @@ static bool dc_link_detect_helper(struct dc_link *link, } } else { /* From Connected-to-Disconnected. */ - if (link->type == dc_connection_mst_branch) { - LINK_INFO("link=%d, mst branch is now Disconnected\n", - link->link_index); - - /* Disable work around which keeps DSC on for tunneled MST on certain USB4 docks. */ - if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) - link->wa_flags.dpia_mst_dsc_always_on = false; - - dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); - - link->mst_stream_alloc_table.stream_count = 0; - memset(link->mst_stream_alloc_table.stream_allocations, - 0, - sizeof(link->mst_stream_alloc_table.stream_allocations)); - } - -#if defined(CONFIG_DRM_AMD_DC_DCN) - if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING) - reset_dp_hpo_stream_encoders_for_link(link); -#endif - link->type = dc_connection_none; sink_caps.signal = SIGNAL_TYPE_NONE; /* When we unplug a passive DP-HDMI dongle connection, dongle_max_pix_clk @@ -1219,33 +1306,26 @@ static bool dc_link_detect_helper(struct dc_link *link, bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) { - const struct dc *dc = link->dc; - bool ret; - bool can_apply_seamless_boot = false; - int i; - - for (i = 0; i < dc->current_state->stream_count; i++) { - if (dc->current_state->streams[i]->apply_seamless_boot_optimization) { - can_apply_seamless_boot = true; - break; - } - } + bool is_local_sink_detect_success; + bool is_remote_sink_detect_required = false; + enum dc_connection_type pre_link_type = link->type; -#if defined(CONFIG_DRM_AMD_DC_DCN) - dc_z10_restore(dc); -#endif + is_local_sink_detect_success = detect_link_and_local_sink(link, reason); - /* get out of low power state */ - if (!can_apply_seamless_boot && reason != DETECT_REASON_BOOT) - clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr); + if (is_local_sink_detect_success && link->local_sink) + verify_link_capability(link, link->local_sink, reason); - ret = dc_link_detect_helper(link, reason); + if (is_local_sink_detect_success && link->local_sink && + dc_is_dp_signal(link->local_sink->sink_signal) && + link->dpcd_caps.is_mst_capable) + is_remote_sink_detect_required = discover_dp_mst_topology(link, reason); - /* Go back to power optimized state */ - if (!can_apply_seamless_boot && reason != DETECT_REASON_BOOT) - clk_mgr_optimize_pwr_state(dc, dc->clk_mgr); + if (is_local_sink_detect_success && + pre_link_type == dc_connection_mst_branch && + link->type != dc_connection_mst_branch) + reset_cur_dp_mst_topology(link); - return ret; + return is_local_sink_detect_success && !is_remote_sink_detect_required; } bool dc_link_get_hpd_state(struct dc_link *dc_link) 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 6f6929435885..8dc03c41fabf 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 @@ -104,9 +104,6 @@ static bool decide_fallback_link_setting( struct dc_link_settings initial_link_settings, struct dc_link_settings *current_link_setting, enum link_training_result training_result); -static struct dc_link_settings get_common_supported_link_settings( - struct dc_link_settings link_setting_a, - struct dc_link_settings link_setting_b); static void maximize_lane_settings(const struct link_training_settings *lt_settings, struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]); static void override_lane_settings(const struct link_training_settings *lt_settings, @@ -3186,13 +3183,11 @@ bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_ return false; } -static struct dc_link_settings get_max_link_cap(struct dc_link *link, - const struct link_resource *link_res) + +struct dc_link_settings dp_get_max_link_cap(struct dc_link *link) { struct dc_link_settings max_link_cap = {0}; -#if defined(CONFIG_DRM_AMD_DC_DCN) enum dc_link_rate lttpr_max_link_rate; -#endif struct link_encoder *link_enc = NULL; /* Links supporting dynamically assigned link encoder will be assigned next @@ -3210,13 +3205,6 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link, /* get max link encoder capability */ if (link_enc) link_enc->funcs->get_max_link_cap(link_enc, &max_link_cap); -#if defined(CONFIG_DRM_AMD_DC_DCN) - if (max_link_cap.link_rate >= LINK_RATE_UHBR10) { - if (!link_res->hpo_dp_link_enc || - link->dc->debug.disable_uhbr) - max_link_cap.link_rate = LINK_RATE_HIGH3; - } -#endif /* Lower link settings based on sink's link cap */ if (link->reported_link_cap.lane_count < max_link_cap.lane_count) @@ -3236,22 +3224,21 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link, if (link->lttpr_mode != LTTPR_MODE_NON_LTTPR) { if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count) max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count; - -#if defined(CONFIG_DRM_AMD_DC_DCN) lttpr_max_link_rate = get_lttpr_max_link_rate(link); if (lttpr_max_link_rate < max_link_cap.link_rate) max_link_cap.link_rate = lttpr_max_link_rate; -#else - if (link->dpcd_caps.lttpr_caps.max_link_rate < max_link_cap.link_rate) - max_link_cap.link_rate = link->dpcd_caps.lttpr_caps.max_link_rate; -#endif DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n", __func__, max_link_cap.lane_count, max_link_cap.link_rate); } + + if (dp_get_link_encoding_format(&max_link_cap) == DP_128b_132b_ENCODING && + link->dc->debug.disable_uhbr) + max_link_cap.link_rate = LINK_RATE_HIGH3; + return max_link_cap; } @@ -3376,10 +3363,9 @@ bool dp_verify_link_cap( struct dc_link_settings *known_limit_link_setting, int *fail_count) { - struct dc_link_settings max_link_cap = {0}; struct dc_link_settings cur_link_setting = {0}; struct dc_link_settings *cur = &cur_link_setting; - struct dc_link_settings initial_link_settings = {0}; + struct dc_link_settings initial_link_settings = *known_limit_link_setting; bool success; bool skip_link_training; bool skip_video_pattern; @@ -3387,28 +3373,6 @@ bool dp_verify_link_cap( enum link_training_result status; union hpd_irq_data irq_data; - /* link training starts with the maximum common settings - * supported by both sink and ASIC. - */ - max_link_cap = get_max_link_cap(link, link_res); - initial_link_settings = get_common_supported_link_settings( - *known_limit_link_setting, - max_link_cap); - - /* Accept reported capabilities if link supports flexible encoder mapping or encoder already in use. */ - if (link->dc->debug.skip_detection_link_training || - link->is_dig_mapping_flexible) { - /* TODO - should we check link encoder's max link caps here? - * How do we know which link encoder to check from? - */ - link->verified_link_cap = *known_limit_link_setting; - return true; - } else if (link->link_enc && link->dc->res_pool->funcs->link_encs_assign && - !link_enc_cfg_is_link_enc_avail(link->ctx->dc, link->link_enc->preferred_engine, link)) { - link->verified_link_cap = initial_link_settings; - return true; - } - memset(&irq_data, 0, sizeof(irq_data)); success = false; skip_link_training = false; @@ -3420,10 +3384,6 @@ bool dp_verify_link_cap( core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant)); } -#if defined(CONFIG_DRM_AMD_DC_DCN) - if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING) - reset_dp_hpo_stream_encoders_for_link(link); -#endif /* TODO implement override and monitor patch later */ /* try to train the link from high to low to @@ -3540,79 +3500,32 @@ bool dp_verify_link_cap_with_retries( return success; } -bool dp_verify_mst_link_cap( - struct dc_link *link, const struct link_resource *link_res) -{ - struct dc_link_settings max_link_cap = {0}; - - if (dp_get_link_encoding_format(&link->reported_link_cap) == - DP_8b_10b_ENCODING) { - max_link_cap = get_max_link_cap(link, link_res); - link->verified_link_cap = get_common_supported_link_settings( - link->reported_link_cap, - max_link_cap); - } -#if defined(CONFIG_DRM_AMD_DC_DCN) - else if (dp_get_link_encoding_format(&link->reported_link_cap) == - DP_128b_132b_ENCODING) { - dp_verify_link_cap_with_retries(link, - link_res, - &link->reported_link_cap, - LINK_TRAINING_MAX_VERIFY_RETRY); - } -#endif - return true; -} - -static struct dc_link_settings get_common_supported_link_settings( - struct dc_link_settings link_setting_a, - struct dc_link_settings link_setting_b) +/* in DP compliance test, DPR-120 may have + * a random value in its MAX_LINK_BW dpcd field. + * We map it to the maximum supported link rate that + * is smaller than MAX_LINK_BW in this case. + */ +static enum dc_link_rate get_link_rate_from_max_link_bw( + uint8_t max_link_bw) { - struct dc_link_settings link_settings = {0}; + enum dc_link_rate link_rate; - link_settings.lane_count = - (link_setting_a.lane_count <= - link_setting_b.lane_count) ? - link_setting_a.lane_count : - link_setting_b.lane_count; - link_settings.link_rate = - (link_setting_a.link_rate <= - link_setting_b.link_rate) ? - link_setting_a.link_rate : - link_setting_b.link_rate; - link_settings.link_spread = LINK_SPREAD_DISABLED; - - /* in DP compliance test, DPR-120 may have - * a random value in its MAX_LINK_BW dpcd field. - * We map it to the maximum supported link rate that - * is smaller than MAX_LINK_BW in this case. - */ -#if defined(CONFIG_DRM_AMD_DC_DCN) - if (link_settings.link_rate > LINK_RATE_UHBR20) { - link_settings.link_rate = LINK_RATE_UHBR20; - } else if (link_settings.link_rate < LINK_RATE_UHBR20 && - link_settings.link_rate > LINK_RATE_UHBR13_5) { - link_settings.link_rate = LINK_RATE_UHBR13_5; - } else if (link_settings.link_rate < LINK_RATE_UHBR10 && - link_settings.link_rate > LINK_RATE_HIGH3) { -#else - if (link_settings.link_rate > LINK_RATE_HIGH3) { -#endif - link_settings.link_rate = LINK_RATE_HIGH3; - } else if (link_settings.link_rate < LINK_RATE_HIGH3 - && link_settings.link_rate > LINK_RATE_HIGH2) { - link_settings.link_rate = LINK_RATE_HIGH2; - } else if (link_settings.link_rate < LINK_RATE_HIGH2 - && link_settings.link_rate > LINK_RATE_HIGH) { - link_settings.link_rate = LINK_RATE_HIGH; - } else if (link_settings.link_rate < LINK_RATE_HIGH - && link_settings.link_rate > LINK_RATE_LOW) { - link_settings.link_rate = LINK_RATE_LOW; - } else if (link_settings.link_rate < LINK_RATE_LOW) { - link_settings.link_rate = LINK_RATE_UNKNOWN; + if (max_link_bw >= LINK_RATE_HIGH3) { + link_rate = LINK_RATE_HIGH3; + } else if (max_link_bw < LINK_RATE_HIGH3 + && max_link_bw >= LINK_RATE_HIGH2) { + link_rate = LINK_RATE_HIGH2; + } else if (max_link_bw < LINK_RATE_HIGH2 + && max_link_bw >= LINK_RATE_HIGH) { + link_rate = LINK_RATE_HIGH; + } else if (max_link_bw < LINK_RATE_HIGH + && max_link_bw >= LINK_RATE_LOW) { + link_rate = LINK_RATE_LOW; + } else { + link_rate = LINK_RATE_UNKNOWN; } - return link_settings; + return link_rate; } static inline bool reached_minimum_lane_count(enum dc_lane_count lane_count) @@ -5516,6 +5429,9 @@ static bool retrieve_link_cap(struct dc_link *link) read_dp_device_vendor_id(link); + /* TODO - decouple raw mst capability from policy decision */ + link->dpcd_caps.is_mst_capable = is_mst_supported(link); + get_active_converter_info(ds_port.byte, link); dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data)); @@ -5534,8 +5450,8 @@ static bool retrieve_link_cap(struct dc_link *link) link->reported_link_cap.lane_count = link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT; - link->reported_link_cap.link_rate = dpcd_data[ - DP_MAX_LINK_RATE - DP_DPCD_REV]; + link->reported_link_cap.link_rate = get_link_rate_from_max_link_bw( + dpcd_data[DP_MAX_LINK_RATE - DP_DPCD_REV]); link->reported_link_cap.link_spread = link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ? LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED; @@ -5759,14 +5675,6 @@ bool dp_overwrite_extended_receiver_cap(struct dc_link *link) bool detect_dp_sink_caps(struct dc_link *link) { return retrieve_link_cap(link); - - /* dc init_hw has power encoder using default - * signal for connector. For native DP, no - * need to power up encoder again. If not native - * DP, hw_init may need check signal or power up - * encoder here. - */ - /* TODO save sink caps in link->sink */ } static enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in_khz) @@ -5844,8 +5752,6 @@ void detect_edp_sink_caps(struct dc_link *link) } } } - link->verified_link_cap = link->reported_link_cap; - core_link_read_dpcd(link, DP_EDP_BACKLIGHT_ADJUSTMENT_CAP, &backlight_adj_cap, sizeof(backlight_adj_cap)); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 45d03d3a95c3..e2409c14df34 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -897,21 +897,5 @@ void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable) } } -void reset_dp_hpo_stream_encoders_for_link(struct dc_link *link) -{ - const struct dc *dc = link->dc; - struct dc_state *state = dc->current_state; - uint8_t i; - - for (i = 0; i < MAX_PIPES; i++) { - if (state->res_ctx.pipe_ctx[i].stream_res.hpo_dp_stream_enc && - state->res_ctx.pipe_ctx[i].stream && - state->res_ctx.pipe_ctx[i].stream->link == link && - !state->res_ctx.pipe_ctx[i].stream->dpms_off) { - setup_dp_hpo_stream(&state->res_ctx.pipe_ctx[i], false); - } - } -} - #undef DC_LOGGER #endif diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 235e33f73913..5ba6abdbd3aa 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1212,6 +1212,7 @@ struct dpcd_caps { bool is_branch_dev; /* Dongle's downstream count. */ union sink_count sink_count; + bool is_mst_capable; /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ struct dc_dongle_caps dongle_caps; 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 cd52813a8432..b18c8198f66d 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 @@ -54,6 +54,8 @@ enum { PEAK_FACTOR_X1000 = 1006, }; +struct dc_link_settings dp_get_max_link_cap(struct dc_link *link); + bool dp_verify_link_cap( struct dc_link *link, const struct link_resource *link_res, @@ -66,10 +68,6 @@ bool dp_verify_link_cap_with_retries( struct dc_link_settings *known_limit_link_setting, int attempts); -bool dp_verify_mst_link_cap( - struct dc_link *link, - const struct link_resource *link_res); - bool dp_validate_mode_timing( struct dc_link *link, const struct dc_crtc_timing *timing); @@ -222,7 +220,6 @@ void disable_dp_hpo_output(struct dc_link *link, enum signal_type signal); void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable); bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx); -void reset_dp_hpo_stream_encoders_for_link(struct dc_link *link); bool dp_retrieve_lttpr_cap(struct dc_link *link); void edp_panel_backlight_power_on(struct dc_link *link); |