Commit 6b6d12b6 authored by Jimmy Kizito's avatar Jimmy Kizito Committed by Alex Deucher

drm/amd/display: Fix entry into transient encoder assignment mode.

[Why]
In some scenarios it is possible for the encoder assignment module to be
set to "transient" mode even though there are no new encoder
assignments.

This can lead to incorrect results when querying encoder assignment,
which in turn can cause incorrect displays to be manipulated.

[How]
Only allow encoder assignment to be in transient mode of operation when
there are valid new encoder assignments.
Reviewed-by: default avatarMeenakshikumar Somasundaram <Meenakshikumar.Somasundaram@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarHamza Mahfooz <hamza.mahfooz@amd.com>
Signed-off-by: default avatarJimmy Kizito <Jimmy.Kizito@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent d4965c53
......@@ -2812,8 +2812,8 @@ bool perform_link_training_with_retries(
j = 0;
while (j < attempts && fail_count < (attempts * 10)) {
DC_LOG_HW_LINK_TRAINING("%s: Beginning link training attempt %u of %d @ rate(%d) x lane(%d)\n",
__func__, (unsigned int)j + 1, attempts, cur_link_settings.link_rate,
DC_LOG_HW_LINK_TRAINING("%s: Beginning link(%d) training attempt %u of %d @ rate(%d) x lane(%d)\n",
__func__, link->link_index, (unsigned int)j + 1, attempts, cur_link_settings.link_rate,
cur_link_settings.lane_count);
dp_enable_link_phy(
......@@ -2883,8 +2883,8 @@ bool perform_link_training_with_retries(
break;
}
DC_LOG_WARNING("%s: Link training attempt %u of %d failed @ rate(%d) x lane(%d)\n",
__func__, (unsigned int)j + 1, attempts, cur_link_settings.link_rate,
DC_LOG_WARNING("%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d)\n",
__func__, link->link_index, (unsigned int)j + 1, attempts, cur_link_settings.link_rate,
cur_link_settings.lane_count);
dp_disable_link_phy(link, &pipe_ctx->link_res, signal);
......@@ -2927,8 +2927,13 @@ bool perform_link_training_with_retries(
*/
req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing);
link_bw = dc_link_bandwidth_kbps(link, &cur_link_settings);
if (req_bw > link_bw)
break;
is_link_bw_low = (req_bw > link_bw);
is_link_bw_min = ((cur_link_settings.link_rate <= LINK_RATE_LOW) &&
(cur_link_settings.lane_count <= LANE_COUNT_ONE));
if (is_link_bw_low)
DC_LOG_WARNING(
"%s: Link(%d) bandwidth too low after fallback req_bw(%d) > link_bw(%d)\n",
__func__, link->link_index, req_bw, link_bw);
}
msleep(delay_between_attempts);
......
......@@ -26,6 +26,8 @@
#include "resource.h"
#include "dc_link_dp.h"
#define DC_LOGGER dc->ctx->logger
/* Check whether stream is supported by DIG link encoders. */
static bool is_dig_link_enc_stream(struct dc_stream_state *stream)
{
......@@ -383,6 +385,30 @@ void link_enc_cfg_link_encs_assign(
state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i];
}
/* Log encoder assignments. */
for (i = 0; i < MAX_PIPES; i++) {
struct link_enc_assignment assignment =
dc->current_state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i];
if (assignment.valid)
DC_LOG_DEBUG("%s: CUR %s(%d) - enc_id(%d)\n",
__func__,
assignment.ep_id.ep_type == DISPLAY_ENDPOINT_PHY ? "PHY" : "DPIA",
assignment.ep_id.link_id.enum_id - 1,
assignment.eng_id);
}
for (i = 0; i < MAX_PIPES; i++) {
struct link_enc_assignment assignment =
state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i];
if (assignment.valid)
DC_LOG_DEBUG("%s: NEW %s(%d) - enc_id(%d)\n",
__func__,
assignment.ep_id.ep_type == DISPLAY_ENDPOINT_PHY ? "PHY" : "DPIA",
assignment.ep_id.link_id.enum_id - 1,
assignment.eng_id);
}
/* Current state mode will be set to steady once this state committed. */
state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_STEADY;
}
......@@ -658,8 +684,25 @@ bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state)
((valid_uniqueness & 0x1) << 2) |
((valid_avail & 0x1) << 3) |
((valid_streams & 0x1) << 4);
dm_error("Invalid link encoder assignments: 0x%x\n", valid_bitmap);
DC_LOG_ERROR("%s: Invalid link encoder assignments - 0x%x\n", __func__, valid_bitmap);
}
return is_valid;
}
void link_enc_cfg_set_transient_mode(struct dc *dc, struct dc_state *current_state, struct dc_state *new_state)
{
int i = 0;
int num_transient_assignments = 0;
for (i = 0; i < MAX_PIPES; i++) {
if (current_state->res_ctx.link_enc_cfg_ctx.transient_assignments[i].valid)
num_transient_assignments++;
}
/* Only enter transient mode if the new encoder assignments are valid. */
if (new_state->stream_count == num_transient_assignments) {
current_state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_TRANSIENT;
DC_LOG_DEBUG("%s: current_state(%p) mode(%d)\n", __func__, current_state, LINK_ENC_CFG_TRANSIENT);
}
}
......@@ -458,6 +458,7 @@ void dcn31_link_encoder_enable_dp_output(
/* Enable transmitter and encoder. */
if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) {
DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine);
dcn20_link_encoder_enable_dp_output(enc, link_settings, clock_source);
} else {
......@@ -489,6 +490,7 @@ void dcn31_link_encoder_enable_dp_output(
return;
}
DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id);
link_dpia_control(enc->ctx, &dpia_control);
}
}
......@@ -503,6 +505,7 @@ void dcn31_link_encoder_enable_dp_mst_output(
/* Enable transmitter and encoder. */
if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) {
DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine);
dcn10_link_encoder_enable_dp_mst_output(enc, link_settings, clock_source);
} else {
......@@ -534,6 +537,7 @@ void dcn31_link_encoder_enable_dp_mst_output(
return;
}
DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id);
link_dpia_control(enc->ctx, &dpia_control);
}
}
......@@ -547,6 +551,7 @@ void dcn31_link_encoder_disable_output(
/* Disable transmitter and encoder. */
if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) {
DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine);
dcn10_link_encoder_disable_output(enc, signal);
} else {
......@@ -578,6 +583,7 @@ void dcn31_link_encoder_disable_output(
return;
}
DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id);
link_dpia_control(enc->ctx, &dpia_control);
link_encoder_disable(enc10);
......
......@@ -613,7 +613,7 @@ void dcn31_reset_hw_ctx_wrap(
}
/* New dc_state in the process of being applied to hardware. */
dc->current_state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_TRANSIENT;
link_enc_cfg_set_transient_mode(dc, dc->current_state, context);
}
void dcn31_setup_hpo_hw_control(const struct dce_hwseq *hws, bool enable)
......
......@@ -110,4 +110,11 @@ bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id, struct
/* Returns true if encoder assignments in supplied state pass validity checks. */
bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state);
/* Set the link encoder assignment mode for the current_state to LINK_ENC_CFG_TRANSIENT mode.
* This indicates that a new_state is in the process of being applied to hardware.
* During this transition, old and new encoder assignments should be accessible from the old_state.
* Only allow transition into transient mode if new encoder assignments are valid.
*/
void link_enc_cfg_set_transient_mode(struct dc *dc, struct dc_state *current_state, struct dc_state *new_state);
#endif /* DC_INC_LINK_ENC_CFG_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment