diff options
author | Jimmy Kizito <Jimmy.Kizito@amd.com> | 2021-10-20 12:27:06 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2022-07-05 16:12:45 -0400 |
commit | 6366b00346c0fe8ae95d91eed3dd2d04f77729e7 (patch) | |
tree | 33365324fc36ce03a698d4f761be0a7e69bdfd61 | |
parent | e73b386e75586f28b9b58641938ae0feb340bca0 (diff) | |
download | linux-6366b00346c0fe8ae95d91eed3dd2d04f77729e7.tar.bz2 |
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: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Jimmy Kizito <Jimmy.Kizito@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c | 32 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h | 5 |
4 files changed, 44 insertions, 5 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 34a3e1eeb5c4..8ed208e5def2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.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); - 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; + } dc_trigger_sync(dc, context); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c index 639a0a276a08..614f022d1cff 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c @@ -292,6 +292,7 @@ void link_enc_cfg_link_encs_assign( int j; 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. */ for (i = 0; i < dc->current_state->stream_count; i++) @@ -561,6 +562,31 @@ struct link_encoder *link_enc_cfg_get_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 is_avail = true; @@ -595,6 +621,7 @@ bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state) uint8_t dig_stream_count = 0; int matching_stream_ptrs = 0; int eng_ids_per_ep_id[MAX_PIPES] = {0}; + int ep_ids_per_eng_id[MAX_PIPES] = {0}; int valid_bitmap = 0; /* (1) No. valid entries same as stream count. */ @@ -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; eng_ids_per_ep_id[i]++; + ep_ids_per_eng_id[i]++; for (j = 0; j < MAX_PIPES; j++) { struct link_enc_assignment assignment_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) assignment_i.eng_id != assignment_j.eng_id) { valid_uniqueness = false; 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]++; } } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 332110bb1286..b67fdb31f75f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -3015,12 +3015,11 @@ bool pipe_need_reprogram( if (pipe_ctx_old->stream->ctx->dc->res_pool->funcs->link_encs_assign) { bool need_reprogram = false; 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_cfg_get_link_enc_used_by_stream(dc, pipe_ctx_old->stream) != pipe_ctx->stream->link_enc) + if (link_enc_prev != pipe_ctx->stream->link_enc) need_reprogram = true; - dc->current_state->res_ctx.link_enc_cfg_ctx.mode = mode; return need_reprogram; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h b/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h index 7beb14169f92..dc650be3837e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h @@ -104,6 +104,11 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream( /* Return DIG link encoder. NULL if unused. */ 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. */ bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id, struct dc_link *link); |