diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c index 769b782a9b84..ee290ec247de 100644 --- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c +++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c @@ -27,6 +27,7 @@ #include "link/protocols/link_dp_training.h" #include "link/protocols/link_dp_phy.h" #include "link/protocols/link_dp_training_fixed_vs_pe_retimer.h" +#include "link/link_dpms.h" #include "resource.h" #include "dm_helpers.h" #include "dc_dmub_srv.h" @@ -77,37 +78,26 @@ void dp_retrain_link_dp_test(struct dc_link *link, struct dc_link_settings *link_setting, bool skip_video_pattern) { - struct pipe_ctx *pipe; - unsigned int i; + struct pipe_ctx *pipes[MAX_PIPES]; + struct dc_state *state = link->dc->current_state; + uint8_t count; + int i; udelay(100); - for (i = 0; i < MAX_PIPES; i++) { - pipe = &link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe->stream != NULL && - pipe->stream->link == link && - !pipe->stream->dpms_off && - !pipe->top_pipe && !pipe->prev_odm_pipe) { - link_set_dpms_off(pipe); - pipe->link_config.dp_link_settings = *link_setting; - update_dp_encoder_resources_for_test_harness( - link->dc, - pipe->stream->ctx->dc->current_state, - pipe); - } + link_get_master_pipes_with_dpms_on(link, state, &count, pipes); + + for (i = 0; i < count; i++) { + link_set_dpms_off(pipes[i]); + pipes[i]->link_config.dp_link_settings = *link_setting; + update_dp_encoder_resources_for_test_harness( + link->dc, + state, + pipes[i]); } - for (i = 0; i < MAX_PIPES; i++) { - pipe = &link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe->stream != NULL && - pipe->stream->link == link && - !pipe->stream->dpms_off && - !pipe->top_pipe && !pipe->prev_odm_pipe) { - link_set_dpms_on( - pipe->stream->ctx->dc->current_state, - pipe); - } - } + for (i = count-1; i >= 0; i--) + link_set_dpms_on(state, pipes[i]); } static void dp_test_send_link_training(struct dc_link *link) diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c index 63e75c392031..001a4ac9bfcf 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c @@ -30,6 +30,7 @@ * directly from connected receivers. */ +#include "link_dpms.h" #include "link_detection.h" #include "link_hwss.h" #include "protocols/link_edp_panel_control.h" @@ -755,34 +756,6 @@ static void restore_phy_clocks_for_destructive_link_verification(const struct 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; - struct link_resource link_res = {0}; - - 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); - } - } - - /* link can be also enabled by vbios. In this case it is not recorded - * in pipe_ctx. Disable link phy here to make sure it is completely off - */ - dp_disable_link_phy(link, &link_res, link->connector_signal); -} - static void verify_link_capability_destructive(struct dc_link *link, struct dc_sink *sink, enum dc_detect_reason reason) @@ -796,7 +769,7 @@ static void verify_link_capability_destructive(struct dc_link *link, 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); + link_set_all_streams_dpms_off_for_link(link); dp_verify_link_cap_with_retries( link, &known_limit_link_setting, LINK_TRAINING_MAX_VERIFY_RETRY); diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c index 618fd552cb3d..026683ce24a4 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c @@ -140,12 +140,76 @@ void link_blank_dp_stream(struct dc_link *link, bool hw_init) } } +void link_set_all_streams_dpms_off_for_link(struct dc_link *link) +{ + struct pipe_ctx *pipes[MAX_PIPES]; + struct dc_state *state = link->dc->current_state; + uint8_t count; + int i; + struct dc_stream_update stream_update; + bool dpms_off = true; + struct link_resource link_res = {0}; + + memset(&stream_update, 0, sizeof(stream_update)); + stream_update.dpms_off = &dpms_off; + + link_get_master_pipes_with_dpms_on(link, state, &count, pipes); + + for (i = 0; i < count; i++) { + stream_update.stream = pipes[i]->stream; + dc_commit_updates_for_stream(link->ctx->dc, NULL, 0, + pipes[i]->stream, &stream_update, + state); + } + + /* link can be also enabled by vbios. In this case it is not recorded + * in pipe_ctx. Disable link phy here to make sure it is completely off + */ + dp_disable_link_phy(link, &link_res, link->connector_signal); +} + void link_resume(struct dc_link *link) { if (link->connector_signal != SIGNAL_TYPE_VIRTUAL) program_hpd_filter(link); } +/* This function returns true if the pipe is used to feed video signal directly + * to the link. + */ +static bool is_master_pipe_for_link(const struct dc_link *link, + const struct pipe_ctx *pipe) +{ + return (pipe->stream && + pipe->stream->link && + pipe->stream->link == link && + pipe->top_pipe == NULL && + pipe->prev_odm_pipe == NULL); +} + +/* + * This function finds all master pipes feeding to a given link with dpms set to + * on in given dc state. + */ +void link_get_master_pipes_with_dpms_on(const struct dc_link *link, + struct dc_state *state, + uint8_t *count, + struct pipe_ctx *pipes[MAX_PIPES]) +{ + int i; + struct pipe_ctx *pipe = NULL; + + *count = 0; + for (i = 0; i < MAX_PIPES; i++) { + pipe = &state->res_ctx.pipe_ctx[i]; + + if (is_master_pipe_for_link(link, pipe) && + pipe->stream->dpms_off == false) { + pipes[(*count)++] = pipe; + } + } +} + static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx, enum engine_id eng_id, struct ext_hdmi_settings *settings) @@ -2176,6 +2240,8 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) struct dc_link *link = stream->sink->link; struct vpg *vpg = pipe_ctx->stream_res.stream_enc->vpg; + ASSERT(is_master_pipe_for_link(link, pipe_ctx)); + if (link_is_dp_128b_132b_signal(pipe_ctx)) vpg = pipe_ctx->stream_res.hpo_dp_stream_enc->vpg; @@ -2280,6 +2346,8 @@ void link_set_dpms_on( struct vpg *vpg = pipe_ctx->stream_res.stream_enc->vpg; const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); + ASSERT(is_master_pipe_for_link(link, pipe_ctx)); + if (link_is_dp_128b_132b_signal(pipe_ctx)) vpg = pipe_ctx->stream_res.hpo_dp_stream_enc->vpg; @@ -2463,4 +2531,3 @@ void link_set_dpms_on( set_avmute(pipe_ctx, false); } } - diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.h b/drivers/gpu/drm/amd/display/dc/link/link_dpms.h index 7ce0124ed7d1..33d312dabdb8 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.h +++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.h @@ -32,4 +32,9 @@ bool link_set_dsc_pps_packet(struct pipe_ctx *pipe_ctx, struct fixed31_32 link_calculate_sst_avg_time_slots_per_mtp( const struct dc_stream_state *stream, const struct dc_link *link); +void link_set_all_streams_dpms_off_for_link(struct dc_link *link); +void link_get_master_pipes_with_dpms_on(const struct dc_link *link, + struct dc_state *state, + uint8_t *count, + struct pipe_ctx *pipes[MAX_PIPES]); #endif /* __DC_LINK_DPMS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c index eff23b7b324a..9d80427520cf 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c @@ -34,6 +34,7 @@ #include "link_dp_training.h" #include "link_dp_capability.h" #include "link/accessories/link_dp_trace.h" +#include "link/link_dpms.h" #include "dm_helpers.h" #define DC_LOGGER_INIT(logger) @@ -175,40 +176,27 @@ static bool handle_hpd_irq_psr_sink(struct dc_link *link) void dc_link_dp_handle_link_loss(struct dc_link *link) { + struct pipe_ctx *pipes[MAX_PIPES]; + struct dc_state *state = link->dc->current_state; + uint8_t count; int i; - struct pipe_ctx *pipe_ctx; - 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->link == link) - break; - } + link_get_master_pipes_with_dpms_on(link, state, &count, pipes); - if (pipe_ctx == NULL || pipe_ctx->stream == NULL) - return; + for (i = 0; i < count; i++) + link_set_dpms_off(pipes[i]); - 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) - link_set_dpms_off(pipe_ctx); - } - - 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) { - // Always use max settings here for DP 1.4a LL Compliance CTS - if (link->is_automated) { - pipe_ctx->link_config.dp_link_settings.lane_count = - link->verified_link_cap.lane_count; - pipe_ctx->link_config.dp_link_settings.link_rate = - link->verified_link_cap.link_rate; - pipe_ctx->link_config.dp_link_settings.link_spread = - link->verified_link_cap.link_spread; - } - link_set_dpms_on(link->dc->current_state, pipe_ctx); + for (i = count - 1; i >= 0; i--) { + // Always use max settings here for DP 1.4a LL Compliance CTS + if (link->is_automated) { + pipes[i]->link_config.dp_link_settings.lane_count = + link->verified_link_cap.lane_count; + pipes[i]->link_config.dp_link_settings.link_rate = + link->verified_link_cap.link_rate; + pipes[i]->link_config.dp_link_settings.link_spread = + link->verified_link_cap.link_spread; } + link_set_dpms_on(link->dc->current_state, pipes[i]); } }