Commit 6366b003 authored by Jimmy Kizito's avatar Jimmy Kizito Committed by Alex Deucher

drm/amd/display: Maintain consistent mode of operation during encoder assignment

[Why]
While applying a state to hardware, there is a transition period where
the back-end is reset using the old state; then enabled using the new
state.

Generally, the link encoder configuration module queries
stream-to-encoder assignments in either the new or old state based on a
mode variable. During the transition there is a need to query both
states, however toggling this mode variable can lead to incorrect
programming of encoders.

[How]
- Add new function to explicity query stream-to-encoder assignment
in the current state rather than intermittently switch the mode
of operation of the link encoder assignment module.
- Add additional checks for encoder assignment defects.
- Explicitly reset the mode of operation if application of state
to hardware ends prematurely.
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@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 e73b386e
...@@ -1750,8 +1750,11 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c ...@@ -1750,8 +1750,11 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
result = dc->hwss.apply_ctx_to_hw(dc, context); result = dc->hwss.apply_ctx_to_hw(dc, context);
if (result != DC_OK) if (result != DC_OK) {
/* Application of dc_state to hardware stopped. */
dc->current_state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_STEADY;
return result; return result;
}
dc_trigger_sync(dc, context); dc_trigger_sync(dc, context);
......
...@@ -292,6 +292,7 @@ void link_enc_cfg_link_encs_assign( ...@@ -292,6 +292,7 @@ void link_enc_cfg_link_encs_assign(
int j; int j;
ASSERT(state->stream_count == stream_count); ASSERT(state->stream_count == stream_count);
ASSERT(dc->current_state->res_ctx.link_enc_cfg_ctx.mode == LINK_ENC_CFG_STEADY);
/* Release DIG link encoder resources before running assignment algorithm. */ /* Release DIG link encoder resources before running assignment algorithm. */
for (i = 0; i < dc->current_state->stream_count; i++) for (i = 0; i < dc->current_state->stream_count; i++)
...@@ -561,6 +562,31 @@ struct link_encoder *link_enc_cfg_get_link_enc( ...@@ -561,6 +562,31 @@ struct link_encoder *link_enc_cfg_get_link_enc(
return link_enc; return link_enc;
} }
struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream_current(
struct dc *dc,
const struct dc_stream_state *stream)
{
struct link_encoder *link_enc = NULL;
struct display_endpoint_id ep_id;
int i;
ep_id = (struct display_endpoint_id) {
.link_id = stream->link->link_id,
.ep_type = stream->link->ep_type};
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 == true && are_ep_ids_equal(&assignment.ep_id, &ep_id)) {
link_enc = stream->link->dc->res_pool->link_encoders[assignment.eng_id - ENGINE_ID_DIGA];
break;
}
}
return link_enc;
}
bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id, struct dc_link *link) bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id, struct dc_link *link)
{ {
bool is_avail = true; bool is_avail = true;
...@@ -595,6 +621,7 @@ bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state) ...@@ -595,6 +621,7 @@ bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state)
uint8_t dig_stream_count = 0; uint8_t dig_stream_count = 0;
int matching_stream_ptrs = 0; int matching_stream_ptrs = 0;
int eng_ids_per_ep_id[MAX_PIPES] = {0}; int eng_ids_per_ep_id[MAX_PIPES] = {0};
int ep_ids_per_eng_id[MAX_PIPES] = {0};
int valid_bitmap = 0; int valid_bitmap = 0;
/* (1) No. valid entries same as stream count. */ /* (1) No. valid entries same as stream count. */
...@@ -630,6 +657,7 @@ bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state) ...@@ -630,6 +657,7 @@ bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state)
struct display_endpoint_id ep_id_i = assignment_i.ep_id; struct display_endpoint_id ep_id_i = assignment_i.ep_id;
eng_ids_per_ep_id[i]++; eng_ids_per_ep_id[i]++;
ep_ids_per_eng_id[i]++;
for (j = 0; j < MAX_PIPES; j++) { for (j = 0; j < MAX_PIPES; j++) {
struct link_enc_assignment assignment_j = struct link_enc_assignment assignment_j =
state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[j]; state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[j];
...@@ -644,6 +672,10 @@ bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state) ...@@ -644,6 +672,10 @@ bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state)
assignment_i.eng_id != assignment_j.eng_id) { assignment_i.eng_id != assignment_j.eng_id) {
valid_uniqueness = false; valid_uniqueness = false;
eng_ids_per_ep_id[i]++; eng_ids_per_ep_id[i]++;
} else if (!are_ep_ids_equal(&ep_id_i, &ep_id_j) &&
assignment_i.eng_id == assignment_j.eng_id) {
valid_uniqueness = false;
ep_ids_per_eng_id[i]++;
} }
} }
} }
......
...@@ -3015,12 +3015,11 @@ bool pipe_need_reprogram( ...@@ -3015,12 +3015,11 @@ bool pipe_need_reprogram(
if (pipe_ctx_old->stream->ctx->dc->res_pool->funcs->link_encs_assign) { if (pipe_ctx_old->stream->ctx->dc->res_pool->funcs->link_encs_assign) {
bool need_reprogram = false; bool need_reprogram = false;
struct dc *dc = pipe_ctx_old->stream->ctx->dc; struct dc *dc = pipe_ctx_old->stream->ctx->dc;
enum link_enc_cfg_mode mode = dc->current_state->res_ctx.link_enc_cfg_ctx.mode; struct link_encoder *link_enc_prev =
link_enc_cfg_get_link_enc_used_by_stream_current(dc, pipe_ctx_old->stream);
dc->current_state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_STEADY; if (link_enc_prev != pipe_ctx->stream->link_enc)
if (link_enc_cfg_get_link_enc_used_by_stream(dc, pipe_ctx_old->stream) != pipe_ctx->stream->link_enc)
need_reprogram = true; need_reprogram = true;
dc->current_state->res_ctx.link_enc_cfg_ctx.mode = mode;
return need_reprogram; return need_reprogram;
} }
......
...@@ -104,6 +104,11 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream( ...@@ -104,6 +104,11 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream(
/* Return DIG link encoder. NULL if unused. */ /* Return DIG link encoder. NULL if unused. */
struct link_encoder *link_enc_cfg_get_link_enc(const struct dc_link *link); struct link_encoder *link_enc_cfg_get_link_enc(const struct dc_link *link);
/* Return DIG link encoder used by stream in current/previous state. NULL if unused. */
struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream_current(
struct dc *dc,
const struct dc_stream_state *stream);
/* Return true if encoder available to use. */ /* Return true if encoder available to use. */
bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id, struct dc_link *link); bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id, struct dc_link *link);
......
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