Hi,
Rico tried to send out some fixups recently for some navi3x hangs, but made some process mistakes with the series. It's an important series as it has a variety of people indicating problems, even as recently as 6.1.45 that it confirms to fix.
Some of Rico's selected patches were already merged, so they're dropped from the series.
Link: https://lore.kernel.org/stable/20230807022055.2798020-1-tianci.yin@amd.com/ Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2760
Thanks!
Alex Deucher (1): drm/amd/display: fix the build when DRM_AMD_DC_DCN is not set
Alvin Lee (2): drm/amd/display: Disable phantom OTG after enable for plane disable drm/amd/display: Retain phantom plane/stream if validation fails
Aurabindo Pillai (1): drm/amd/display: trigger timing sync only if TG is running
Rodrigo Siqueira (6): drm/amd/display: Handle virtual hardware detect drm/amd/display: Add function for validate and update new stream drm/amd/display: Handle seamless boot stream drm/amd/display: Update OTG instance in the commit stream drm/amd/display: Avoid ABM when ODM combine is enabled for eDP drm/amd/display: Use update plane and stream routine for DCN32x
drivers/gpu/drm/amd/display/dc/core/dc.c | 74 +++++- .../gpu/drm/amd/display/dc/core/dc_resource.c | 234 +++++++++++++++++- drivers/gpu/drm/amd/display/dc/dc.h | 6 + .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 + .../gpu/drm/amd/display/dc/dcn32/dcn32_optc.c | 8 + .../drm/amd/display/dc/dcn32/dcn32_resource.c | 22 ++ .../drm/amd/display/dc/dcn32/dcn32_resource.h | 3 + .../amd/display/dc/dcn321/dcn321_resource.c | 1 + .../gpu/drm/amd/display/dc/inc/core_types.h | 1 + .../amd/display/dc/inc/hw/timing_generator.h | 1 + 10 files changed, 341 insertions(+), 15 deletions(-)
From: Rodrigo Siqueira Rodrigo.Siqueira@amd.com
If virtual hardware is detected, there is no reason to run the full dc_commit_streams process, and DC can return true immediately.
Reviewed-by: Harry Wentland harry.wentland@amd.com Signed-off-by: Rodrigo Siqueira Rodrigo.Siqueira@amd.com Co-developed-by: Aurabindo Pillai aurabindo.pillai@amd.com Signed-off-by: Aurabindo Pillai aurabindo.pillai@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 987b96eb860036ab79051fb271f7fbdc01c9daf5) Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8f9c60ed6f8b..9b7ddd0e10a5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1942,6 +1942,9 @@ enum dc_status dc_commit_streams(struct dc *dc, struct pipe_ctx *pipe; bool handle_exit_odm2to1 = false;
+ if (dc->ctx->dce_environment == DCE_ENV_VIRTUAL_HW) + return res; + if (!streams_changed(dc, streams, stream_count)) return res;
From: Rodrigo Siqueira Rodrigo.Siqueira@amd.com
DC stream can be seen as a representation of the DCN backend or the data struct that represents the center of the display pipeline. The front end (i.e., planes) is connected to the DC stream, and in its turn, streams are connected to the DC link. Due to this dynamic, DC must handle the following scenarios:
1. A stream is removed; 2. A new stream is created; 3. An unchanged stream had some updates on its planes.
These combinations require that the new stream data struct become updated and has a valid global state. For handling multiple corner cases associated with stream operations, this commit introduces a function dedicated to manipulating stream changes and invokes the state validation function after that.
Reviewed-by: Harry Wentland harry.wentland@amd.com Signed-off-by: Rodrigo Siqueira Rodrigo.Siqueira@amd.com Co-developed-by: Aurabindo Pillai aurabindo.pillai@amd.com Signed-off-by: Aurabindo Pillai aurabindo.pillai@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit a5e39ae27c3a305c6aafc0e423b0cb2c677facde) Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/gpu/drm/amd/display/dc/core/dc.c | 16 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 219 +++++++++++++++++- drivers/gpu/drm/amd/display/dc/dc.h | 6 + 3 files changed, 227 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9b7ddd0e10a5..753c07ab54ed 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1987,21 +1987,17 @@ enum dc_status dc_commit_streams(struct dc *dc,
dc_resource_state_copy_construct_current(dc, context);
- /* - * Previous validation was perfomred with fast_validation = true and - * the full DML state required for hardware programming was skipped. - * - * Re-validate here to calculate these parameters / watermarks. - */ - res = dc_validate_global_state(dc, context, false); + res = dc_validate_with_context(dc, set, stream_count, context, false); if (res != DC_OK) { - DC_LOG_ERROR("DC commit global validation failure: %s (%d)", - dc_status_to_str(res), res); - return res; + BREAK_TO_DEBUGGER(); + goto fail; }
res = dc_commit_state_no_check(dc, context);
+fail: + dc_release_state(context); + context_alloc_fail:
DC_LOG_DC("%s Finished.\n", __func__); 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 a26e52abc989..613db2da353a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2616,15 +2616,226 @@ bool dc_resource_is_dsc_encoding_supported(const struct dc *dc) return dc->res_pool->res_cap->num_dsc > 0; }
+static bool planes_changed_for_existing_stream(struct dc_state *context, + struct dc_stream_state *stream, + const struct dc_validation_set set[], + int set_count) +{ + int i, j; + struct dc_stream_status *stream_status = NULL; + + for (i = 0; i < context->stream_count; i++) { + if (context->streams[i] == stream) { + stream_status = &context->stream_status[i]; + break; + } + } + + if (!stream_status) + ASSERT(0); + + for (i = 0; i < set_count; i++) + if (set[i].stream == stream) + break; + + if (i == set_count) + ASSERT(0); + + if (set[i].plane_count != stream_status->plane_count) + return true; + + for (j = 0; j < set[i].plane_count; j++) + if (set[i].plane_states[j] != stream_status->plane_states[j]) + return true; + + return false; +} + +/** + * dc_validate_with_context - Validate and update the potential new stream in the context object + * + * @dc: Used to get the current state status + * @set: An array of dc_validation_set with all the current streams reference + * @set_count: Total of streams + * @context: New context + * @fast_validate: Enable or disable fast validation + * + * This function updates the potential new stream in the context object. It + * creates multiple lists for the add, remove, and unchanged streams. In + * particular, if the unchanged streams have a plane that changed, it is + * necessary to remove all planes from the unchanged streams. In summary, this + * function is responsible for validating the new context. + * + * Return: + * In case of success, return DC_OK (1), otherwise, return a DC error. + */ +enum dc_status dc_validate_with_context(struct dc *dc, + const struct dc_validation_set set[], + int set_count, + struct dc_state *context, + bool fast_validate) +{ + struct dc_stream_state *unchanged_streams[MAX_PIPES] = { 0 }; + struct dc_stream_state *del_streams[MAX_PIPES] = { 0 }; + struct dc_stream_state *add_streams[MAX_PIPES] = { 0 }; + int old_stream_count = context->stream_count; + enum dc_status res = DC_ERROR_UNEXPECTED; + int unchanged_streams_count = 0; + int del_streams_count = 0; + int add_streams_count = 0; + bool found = false; + int i, j, k; + + DC_LOGGER_INIT(dc->ctx->logger); + + /* First build a list of streams to be remove from current context */ + for (i = 0; i < old_stream_count; i++) { + struct dc_stream_state *stream = context->streams[i]; + + for (j = 0; j < set_count; j++) { + if (stream == set[j].stream) { + found = true; + break; + } + } + + if (!found) + del_streams[del_streams_count++] = stream; + + found = false; + } + + /* Second, build a list of new streams */ + for (i = 0; i < set_count; i++) { + struct dc_stream_state *stream = set[i].stream; + + for (j = 0; j < old_stream_count; j++) { + if (stream == context->streams[j]) { + found = true; + break; + } + } + + if (!found) + add_streams[add_streams_count++] = stream; + + found = false; + } + + /* Build a list of unchanged streams which is necessary for handling + * planes change such as added, removed, and updated. + */ + for (i = 0; i < set_count; i++) { + /* Check if stream is part of the delete list */ + for (j = 0; j < del_streams_count; j++) { + if (set[i].stream == del_streams[j]) { + found = true; + break; + } + } + + if (!found) { + /* Check if stream is part of the add list */ + for (j = 0; j < add_streams_count; j++) { + if (set[i].stream == add_streams[j]) { + found = true; + break; + } + } + } + + if (!found) + unchanged_streams[unchanged_streams_count++] = set[i].stream; + + found = false; + } + + /* Remove all planes for unchanged streams if planes changed */ + for (i = 0; i < unchanged_streams_count; i++) { + if (planes_changed_for_existing_stream(context, + unchanged_streams[i], + set, + set_count)) { + if (!dc_rem_all_planes_for_stream(dc, + unchanged_streams[i], + context)) { + res = DC_FAIL_DETACH_SURFACES; + goto fail; + } + } + } + + /* Remove all planes for removed streams and then remove the streams */ + for (i = 0; i < del_streams_count; i++) { + /* Need to cpy the dwb data from the old stream in order to efc to work */ + if (del_streams[i]->num_wb_info > 0) { + for (j = 0; j < add_streams_count; j++) { + if (del_streams[i]->sink == add_streams[j]->sink) { + add_streams[j]->num_wb_info = del_streams[i]->num_wb_info; + for (k = 0; k < del_streams[i]->num_wb_info; k++) + add_streams[j]->writeback_info[k] = del_streams[i]->writeback_info[k]; + } + } + } + + if (!dc_rem_all_planes_for_stream(dc, del_streams[i], context)) { + res = DC_FAIL_DETACH_SURFACES; + goto fail; + } + + res = dc_remove_stream_from_ctx(dc, context, del_streams[i]); + if (res != DC_OK) + goto fail; + } + + /* Add new streams and then add all planes for the new stream */ + for (i = 0; i < add_streams_count; i++) { + calculate_phy_pix_clks(add_streams[i]); + res = dc_add_stream_to_ctx(dc, context, add_streams[i]); + if (res != DC_OK) + goto fail; + + if (!add_all_planes_for_stream(dc, add_streams[i], set, set_count, context)) { + res = DC_FAIL_ATTACH_SURFACES; + goto fail; + } + } + + /* Add all planes for unchanged streams if planes changed */ + for (i = 0; i < unchanged_streams_count; i++) { + if (planes_changed_for_existing_stream(context, + unchanged_streams[i], + set, + set_count)) { + if (!add_all_planes_for_stream(dc, unchanged_streams[i], set, set_count, context)) { + res = DC_FAIL_ATTACH_SURFACES; + goto fail; + } + } + } + + res = dc_validate_global_state(dc, context, fast_validate); + +fail: + if (res != DC_OK) + DC_LOG_WARNING("%s:resource validation failed, dc_status:%d\n", + __func__, + res); + + return res; +}
/** - * dc_validate_global_state() - Determine if HW can support a given state - * Checks HW resource availability and bandwidth requirement. + * dc_validate_global_state() - Determine if hardware can support a given state + * * @dc: dc struct for this driver * @new_ctx: state to be validated * @fast_validate: set to true if only yes/no to support matters * - * Return: DC_OK if the result can be programmed. Otherwise, an error code. + * Checks hardware resource availability and bandwidth requirement. + * + * Return: + * DC_OK if the result can be programmed. Otherwise, an error code. */ enum dc_status dc_validate_global_state( struct dc *dc, @@ -3757,4 +3968,4 @@ bool dc_resource_acquire_secondary_pipe_for_mpc_odm( }
return true; -} \ No newline at end of file +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6409b8d8ff71..a4540f83aae5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1298,6 +1298,12 @@ enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *pla
void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info);
+enum dc_status dc_validate_with_context(struct dc *dc, + const struct dc_validation_set set[], + int set_count, + struct dc_state *context, + bool fast_validate); + bool dc_set_generic_gpio_for_stereo(bool enable, struct gpio_service *gpio_service);
From: Rodrigo Siqueira Rodrigo.Siqueira@amd.com
A seamless boot stream has hardware resources assigned to it, and adding a new stream means rebuilding the current assignment. It is desirable to avoid this situation since it may cause light-up issues on the VGA monitor on USB-C. This commit swaps the seamless boot stream to pipe 0 (if necessary) to ensure that the pipe context matches.
Reviewed-by: Harry Wentland harry.wentland@amd.com Signed-off-by: Rodrigo Siqueira Rodrigo.Siqueira@amd.com Co-developed-by: Aurabindo Pillai aurabindo.pillai@amd.com Signed-off-by: Aurabindo Pillai aurabindo.pillai@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 170390e587a69b2a24abac39eb3ae6ec28a4d7f2) Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
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 613db2da353a..66923f51037a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2788,6 +2788,21 @@ enum dc_status dc_validate_with_context(struct dc *dc, goto fail; }
+ /* Swap seamless boot stream to pipe 0 (if needed) to ensure pipe_ctx + * matches. This may change in the future if seamless_boot_stream can be + * multiple. + */ + for (i = 0; i < add_streams_count; i++) { + mark_seamless_boot_stream(dc, add_streams[i]); + if (add_streams[i]->apply_seamless_boot_optimization && i != 0) { + struct dc_stream_state *temp = add_streams[0]; + + add_streams[0] = add_streams[i]; + add_streams[i] = temp; + break; + } + } + /* Add new streams and then add all planes for the new stream */ for (i = 0; i < add_streams_count; i++) { calculate_phy_pix_clks(add_streams[i]);
From: Rodrigo Siqueira Rodrigo.Siqueira@amd.com
OTG instance is not updated in dc_commit_state_no_check for newly committed streams because mode_change is not set. Notice that OTG update is part of the software state, and after hardware programming, it must be updated; for this reason, this commit updates the OTG offset right after hardware programming.
Reviewed-by: Harry Wentland harry.wentland@amd.com Signed-off-by: Rodrigo Siqueira Rodrigo.Siqueira@amd.com Co-developed-by: Aurabindo Pillai aurabindo.pillai@amd.com Signed-off-by: Aurabindo Pillai aurabindo.pillai@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit eef019eabc3cd0fddcffefbf67806a4d8cca29bb) Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 753c07ab54ed..5d0a44e2ef90 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1995,6 +1995,12 @@ enum dc_status dc_commit_streams(struct dc *dc,
res = dc_commit_state_no_check(dc, context);
+ for (i = 0; i < stream_count; i++) { + for (j = 0; j < context->stream_count; j++) + if (streams[i]->stream_id == context->streams[j]->stream_id) + streams[i]->out.otg_offset = context->stream_status[j].primary_otg_inst; + } + fail: dc_release_state(context);
From: Rodrigo Siqueira Rodrigo.Siqueira@amd.com
ODM to combine on the eDP panel with ABM causes the color difference to the panel since the ABM module only sets one pipe. Hence, this commit blocks ABM in case of ODM combined on eDP.
Reviewed-by: Harry Wentland harry.wentland@amd.com Signed-off-by: Rodrigo Siqueira Rodrigo.Siqueira@amd.com Co-developed-by: Aurabindo Pillai aurabindo.pillai@amd.com Signed-off-by: Aurabindo Pillai aurabindo.pillai@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 7fffb03b4045c862f904a88b852dc509c4e46406) Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/gpu/drm/amd/display/dc/core/dc.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5d0a44e2ef90..8c9843009176 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1996,9 +1996,19 @@ enum dc_status dc_commit_streams(struct dc *dc, res = dc_commit_state_no_check(dc, context);
for (i = 0; i < stream_count; i++) { - for (j = 0; j < context->stream_count; j++) + for (j = 0; j < context->stream_count; j++) { if (streams[i]->stream_id == context->streams[j]->stream_id) streams[i]->out.otg_offset = context->stream_status[j].primary_otg_inst; + + if (dc_is_embedded_signal(streams[i]->signal)) { + struct dc_stream_status *status = dc_stream_get_status_from_state(context, streams[i]); + + if (dc->hwss.is_abm_supported) + status->is_abm_supported = dc->hwss.is_abm_supported(dc, context, streams[i]); + else + status->is_abm_supported = true; + } + } }
fail:
From: Rodrigo Siqueira Rodrigo.Siqueira@amd.com
Sub-viewport (Subvp) feature is used for changing MCLK without causing any display artifact, requiring special treatment from the plane and stream perspective since DC needs to read data from the cache when using subvp. However, the function dc_commit_updates_for_stream does not provide all the support needed by this feature which will make this function legacy at some point. For this reason, this commit enables dc_update_planes_and_stream for ASICs that support this feature but preserves the old behavior for other ASICs. However, dc_update_planes_and_stream should replace dc_commit_updates_for_stream for all ASICs since it does most of the tasks executed by dc_commit_updates_for_stream with other extra operations, but we need to run tests before making this change.
Reviewed-by: Harry Wentland harry.wentland@amd.com Signed-off-by: Rodrigo Siqueira Rodrigo.Siqueira@amd.com Co-developed-by: Aurabindo Pillai aurabindo.pillai@amd.com Signed-off-by: Aurabindo Pillai aurabindo.pillai@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit dddde627807c22d6f15f4417eb395b13a1ca88f9) Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/gpu/drm/amd/display/dc/core/dc.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8c9843009176..c9ed0346b88c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -4002,6 +4002,18 @@ void dc_commit_updates_for_stream(struct dc *dc, struct dc_context *dc_ctx = dc->ctx; int i, j;
+ /* TODO: Since change commit sequence can have a huge impact, + * we decided to only enable it for DCN3x. However, as soon as + * we get more confident about this change we'll need to enable + * the new sequence for all ASICs. + */ + if (dc->ctx->dce_version >= DCN_VERSION_3_2) { + dc_update_planes_and_stream(dc, srf_updates, + surface_count, stream, + stream_update); + return; + } + stream_status = dc_stream_get_status(stream); context = dc->current_state;
From: Alvin Lee Alvin.Lee2@amd.com
[Description] - Need to disable phantom OTG after it's enabled in order to restore it to it's original state. - If it's enabled and then an MCLK switch comes in we may not prefetch the correct data since the phantom OTG could already be in the middle of the frame.
Reviewed-by: Jun Lei Jun.Lei@amd.com Acked-by: Alan Liu HaoPing.Liu@amd.com Signed-off-by: Alvin Lee Alvin.Lee2@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit dc55b106ad477c67f969f3432d9070c6846fb557) Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/gpu/drm/amd/display/dc/core/dc.c | 14 +++++++++++++- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c | 8 ++++++++ .../drm/amd/display/dc/inc/hw/timing_generator.h | 1 + 3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c9ed0346b88c..f16a9e410d16 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1079,6 +1079,7 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) struct dc_state *dangling_context = dc_create_state(dc); struct dc_state *current_ctx; struct pipe_ctx *pipe; + struct timing_generator *tg;
if (dangling_context == NULL) return; @@ -1122,6 +1123,7 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
if (should_disable && old_stream) { pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + tg = pipe->stream_res.tg; /* When disabling plane for a phantom pipe, we must turn on the * phantom OTG so the disable programming gets the double buffer * update. Otherwise the pipe will be left in a partially disabled @@ -1129,7 +1131,8 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) * again for different use. */ if (old_stream->mall_stream_config.type == SUBVP_PHANTOM) { - pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg); + if (tg->funcs->enable_crtc) + tg->funcs->enable_crtc(tg); } dc_rem_all_planes_for_stream(dc, old_stream, dangling_context); disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context); @@ -1146,6 +1149,15 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) dc->hwss.interdependent_update_lock(dc, dc->current_state, false); dc->hwss.post_unlock_program_front_end(dc, dangling_context); } + /* We need to put the phantom OTG back into it's default (disabled) state or we + * can get corruption when transition from one SubVP config to a different one. + * The OTG is set to disable on falling edge of VUPDATE so the plane disable + * will still get it's double buffer update. + */ + if (old_stream->mall_stream_config.type == SUBVP_PHANTOM) { + if (tg->funcs->disable_phantom_crtc) + tg->funcs->disable_phantom_crtc(tg); + } } }
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c index fe941b103de8..a974f86e718a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c @@ -167,6 +167,13 @@ static void optc32_phantom_crtc_post_enable(struct timing_generator *optc) REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, 1, 100000); }
+static void optc32_disable_phantom_otg(struct timing_generator *optc) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_UPDATE(OTG_CONTROL, OTG_MASTER_EN, 0); +} + static void optc32_set_odm_bypass(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing) { @@ -260,6 +267,7 @@ static struct timing_generator_funcs dcn32_tg_funcs = { .enable_crtc = optc32_enable_crtc, .disable_crtc = optc32_disable_crtc, .phantom_crtc_post_enable = optc32_phantom_crtc_post_enable, + .disable_phantom_crtc = optc32_disable_phantom_otg, /* used by enable_timing_synchronization. Not need for FPGA */ .is_counter_moving = optc1_is_counter_moving, .get_position = optc1_get_position, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index f96fb425345e..974f2c118a44 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -184,6 +184,7 @@ struct timing_generator_funcs { bool (*disable_crtc)(struct timing_generator *tg); #ifdef CONFIG_DRM_AMD_DC_DCN void (*phantom_crtc_post_enable)(struct timing_generator *tg); + void (*disable_phantom_crtc)(struct timing_generator *tg); #endif bool (*immediate_disable_crtc)(struct timing_generator *tg); bool (*is_counter_moving)(struct timing_generator *tg);
From: Alvin Lee Alvin.Lee2@amd.com
[Description] - If we fail validation, we should retain the phantom stream/planes - Full updates assume that phantom pipes will be fully removed, but if validation fails we keep the phantom pipes - Therefore we have to retain the plane/stream if validation fails (since the refcount is decremented before validation, and the expectation is that it's fully freed when the old dc_state is released)
Reviewed-by: Jun Lei Jun.Lei@amd.com Acked-by: Brian Chang Brian.Chang@amd.com Signed-off-by: Alvin Lee Alvin.Lee2@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 9b216b7e38f5381bcc3ad21c5ac614aa577ab8f2) Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/gpu/drm/amd/display/dc/core/dc.c | 13 +++++++++++ .../drm/amd/display/dc/dcn32/dcn32_resource.c | 22 +++++++++++++++++++ .../drm/amd/display/dc/dcn32/dcn32_resource.h | 3 +++ .../amd/display/dc/dcn321/dcn321_resource.c | 1 + .../gpu/drm/amd/display/dc/inc/core_types.h | 1 + 5 files changed, 40 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f16a9e410d16..674ab6d9b31e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3149,6 +3149,19 @@ static bool update_planes_and_stream_state(struct dc *dc,
if (update_type == UPDATE_TYPE_FULL) { if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) { + /* For phantom pipes we remove and create a new set of phantom pipes + * for each full update (because we don't know if we'll need phantom + * pipes until after the first round of validation). However, if validation + * fails we need to keep the existing phantom pipes (because we don't update + * the dc->current_state). + * + * The phantom stream/plane refcount is decremented for validation because + * we assume it'll be removed (the free comes when the dc_state is freed), + * but if validation fails we have to increment back the refcount so it's + * consistent. + */ + if (dc->res_pool->funcs->retain_phantom_pipes) + dc->res_pool->funcs->retain_phantom_pipes(dc, dc->current_state); BREAK_TO_DEBUGGER(); goto fail; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index 814620e6638f..2b8700b291a4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -1719,6 +1719,27 @@ static struct dc_stream_state *dcn32_enable_phantom_stream(struct dc *dc, return phantom_stream; }
+void dcn32_retain_phantom_pipes(struct dc *dc, struct dc_state *context) +{ + int i; + struct dc_plane_state *phantom_plane = NULL; + struct dc_stream_state *phantom_stream = NULL; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + + if (!pipe->top_pipe && !pipe->prev_odm_pipe && + pipe->plane_state && pipe->stream && + pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) { + phantom_plane = pipe->plane_state; + phantom_stream = pipe->stream; + + dc_plane_state_retain(phantom_plane); + dc_stream_retain(phantom_stream); + } + } +} + // return true if removed piped from ctx, false otherwise bool dcn32_remove_phantom_pipes(struct dc *dc, struct dc_state *context) { @@ -2035,6 +2056,7 @@ static struct resource_funcs dcn32_res_pool_funcs = { .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, .add_phantom_pipes = dcn32_add_phantom_pipes, .remove_phantom_pipes = dcn32_remove_phantom_pipes, + .retain_phantom_pipes = dcn32_retain_phantom_pipes, };
static uint32_t read_pipe_fuses(struct dc_context *ctx) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h index 615244a1f95d..026cf13d203f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h @@ -83,6 +83,9 @@ bool dcn32_release_post_bldn_3dlut( bool dcn32_remove_phantom_pipes(struct dc *dc, struct dc_state *context);
+void dcn32_retain_phantom_pipes(struct dc *dc, + struct dc_state *context); + void dcn32_add_phantom_pipes(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c index 213ff3672bd5..aed92ced7b76 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c @@ -1619,6 +1619,7 @@ static struct resource_funcs dcn321_res_pool_funcs = { .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, .add_phantom_pipes = dcn32_add_phantom_pipes, .remove_phantom_pipes = dcn32_remove_phantom_pipes, + .retain_phantom_pipes = dcn32_retain_phantom_pipes, };
static uint32_t read_pipe_fuses(struct dc_context *ctx) diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 9498105c98ab..5fa7c4772af4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -234,6 +234,7 @@ struct resource_funcs { unsigned int index);
bool (*remove_phantom_pipes)(struct dc *dc, struct dc_state *context); + void (*retain_phantom_pipes)(struct dc *dc, struct dc_state *context); void (*get_panel_config_defaults)(struct dc_panel_config *panel_config); };
From: Alex Deucher alexander.deucher@amd.com
Move the new callback outside of the guard.
Fixes: dc55b106ad47 ("drm/amd/display: Disable phantom OTG after enable for plane disable") CC: Alvin Lee Alvin.Lee2@amd.com CC: Alan Liu HaoPing.Liu@amd.com Reviewed-by: Harry Wentland harry.wentland@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 5ca9b33ece9aa048b6ec9411f054e1b781662327) Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 974f2c118a44..789cf9406ca5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -184,8 +184,8 @@ struct timing_generator_funcs { bool (*disable_crtc)(struct timing_generator *tg); #ifdef CONFIG_DRM_AMD_DC_DCN void (*phantom_crtc_post_enable)(struct timing_generator *tg); - void (*disable_phantom_crtc)(struct timing_generator *tg); #endif + void (*disable_phantom_crtc)(struct timing_generator *tg); bool (*immediate_disable_crtc)(struct timing_generator *tg); bool (*is_counter_moving)(struct timing_generator *tg); void (*get_position)(struct timing_generator *tg,
From: Aurabindo Pillai aurabindo.pillai@amd.com
[Why&How] If the timing generator isnt running, it does not make sense to trigger a sync on the corresponding OTG. Check this condition before starting. Otherwise, this will cause error like:
*ERROR* GSL: Timeout on reset trigger!
Fixes: dc55b106ad47 ("drm/amd/display: Disable phantom OTG after enable for plane disable") Signed-off-by: Aurabindo Pillai aurabindo.pillai@amd.com Reviewed-by: Rodrigo Siqueira Rodrigo.Siqueira@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com (cherry picked from commit 6066aaf74f510fc171dbe9375153aee2d60d37aa) NOTE: This is also 5f9f97c02dd2 ("drm/amd/display: trigger timing sync only if TG is running") Signed-off-by: Mario Limonciello mario.limonciello@amd.com --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index a6fde27d1347..394027118963 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2284,6 +2284,12 @@ void dcn10_enable_timing_synchronization( opp = grouped_pipes[i]->stream_res.opp; tg = grouped_pipes[i]->stream_res.tg; tg->funcs->get_otg_active_size(tg, &width, &height); + + if (!tg->funcs->is_tg_enabled(tg)) { + DC_SYNC_INFO("Skipping timing sync on disabled OTG\n"); + return; + } + if (opp->funcs->opp_program_dpg_dimensions) opp->funcs->opp_program_dpg_dimensions(opp, width, 2*(height) + 1); }
On Fri, Aug 11, 2023 at 04:06:58PM -0500, Mario Limonciello wrote:
Hi,
Rico tried to send out some fixups recently for some navi3x hangs, but made some process mistakes with the series. It's an important series as it has a variety of people indicating problems, even as recently as 6.1.45 that it confirms to fix.
Some of Rico's selected patches were already merged, so they're dropped from the series.
Link: https://lore.kernel.org/stable/20230807022055.2798020-1-tianci.yin@amd.com/ Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2760
Thanks!
Now queued up, thanks.
greg k-h
linux-stable-mirror@lists.linaro.org