From: Harry Wentland <harry.wentland@amd.com>
To: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>,
amd-gfx@lists.freedesktop.org
Cc: Alex Deucher <alexander.deucher@amd.com>,
Aurabindo Pillai <aurabindo.pillai@amd.com>,
Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Subject: Re: [PATCH 1/3] drm/amd/display: Add functions for new DC commit sequence
Date: Tue, 11 Oct 2022 14:47:16 -0400 [thread overview]
Message-ID: <16411ae3-9cf2-b10a-1de4-131bd76e6830@amd.com> (raw)
In-Reply-To: <20221011181140.94595-2-Rodrigo.Siqueira@amd.com>
On 2022-10-11 14:11, Rodrigo Siqueira wrote:
> Since DCN32, our DC commit become more complex and requires more
> adjustments to work well with some features. This is a preparation work
> for replacing dc_commit_state and dc_commit_updates_for_stream with
> dc_update_planes_and_stream and dc_update_planes_and_stream
I think you mean
"dc_commit_streams and dc_update_planes_and_stream"
Harry
> respectively.
>
> Cc: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
> Cc: 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>
> ---
> drivers/gpu/drm/amd/display/dc/core/dc.c | 92 ++++++++
> .../gpu/drm/amd/display/dc/core/dc_resource.c | 204 +++++++++++++++++-
> drivers/gpu/drm/amd/display/dc/dc.h | 6 +
> drivers/gpu/drm/amd/display/dc/dc_stream.h | 11 +-
> 4 files changed, 308 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 660316a536f7..ad3aafb73cba 100644
> --- a/drivers/gpu/drm/amd/display/dc/core/dc.c
> +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
> @@ -59,6 +59,7 @@
>
> #include "dc_link_dp.h"
> #include "dc_dmub_srv.h"
> +#include "dc_stream.h"
>
> #include "dsc.h"
>
> @@ -1505,6 +1506,25 @@ static bool context_changed(
> return false;
> }
>
> +static bool streams_changed(struct dc *dc,
> + struct dc_stream_state *streams[],
> + uint8_t stream_count)
> +{
> + uint8_t i;
> +
> + if (stream_count != dc->current_state->stream_count)
> + return true;
> +
> + for (i = 0; i < dc->current_state->stream_count; i++) {
> + if (dc->current_state->streams[i] != streams[i])
> + return true;
> + if (!streams[i]->link->link_state_valid)
> + return true;
> + }
> +
> + return false;
> +}
> +
> bool dc_validate_boot_timing(const struct dc *dc,
> const struct dc_sink *sink,
> struct dc_crtc_timing *crtc_timing)
> @@ -1923,6 +1943,78 @@ bool dc_commit_state(struct dc *dc, struct dc_state *context)
> return (result == DC_OK);
> }
>
> +enum dc_status dc_commit_streams(struct dc *dc,
> + struct dc_stream_state *streams[],
> + uint8_t stream_count)
> +{
> + int i, j;
> + struct dc_state *context;
> + enum dc_status res = DC_OK;
> + struct dc_validation_set set[MAX_STREAMS] = {0};
> +
> + if (dc->ctx->dce_environment == DCE_ENV_VIRTUAL_HW)
> + return res;
> +
> + if (!streams_changed(dc, streams, stream_count))
> + return res;
> +
> + DC_LOG_DC("%s: %d streams\n", __func__, stream_count);
> +
> + for (i = 0; i < stream_count; i++) {
> + struct dc_stream_state *stream = streams[i];
> + struct dc_stream_status *status = dc_stream_get_status(stream);
> +
> + dc_stream_log(dc, stream);
> +
> + set[i].stream = stream;
> +
> + if (status) {
> + set[i].plane_count = status->plane_count;
> + for (j = 0; j < status->plane_count; j++)
> + set[i].plane_states[j] = status->plane_states[j];
> + }
> + }
> +
> + context = dc_create_state(dc);
> + if (!context)
> + goto context_alloc_fail;
> +
> + dc_resource_state_copy_construct_current(dc, context);
> +
> + res = dc_validate_with_context(dc, set, stream_count, context, false);
> + if (res != DC_OK) {
> + BREAK_TO_DEBUGGER();
> + goto fail;
> + }
> +
> + 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;
> +
> + 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:
> + dc_release_state(context);
> +
> +context_alloc_fail:
> +
> + DC_LOG_DC("%s Finished.\n", __func__);
> +
> + return res;
> +}
> +
> bool dc_acquire_release_mpc_3dlut(
> struct dc *dc, bool acquire,
> struct dc_stream_state *stream,
> 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 fd8db482e56f..0c58a19e9115 100644
> --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
> +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
> @@ -2593,6 +2593,208 @@ 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;
> +}
> +
> +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 remove from context all deleted streams */
> + 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;
> + }
> +
> + /* Now add 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 array of unchanged streams, it is needed to handle
> + * planes only changes (added/removed/updated)
> + */
> + for (i = 0; i < set_count; i++) {
> + for (j = 0; j < del_streams_count; j++) {
> + if (set[i].stream == del_streams[j]) {
> + found = true;
> + break;
> + }
> + }
> +
> + if (!found) {
> + 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;
> + }
> +
> + /* 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]);
> + 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
> @@ -3734,4 +3936,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 bfc5474c0f4c..2753d9eabd16 100644
> --- a/drivers/gpu/drm/amd/display/dc/dc.h
> +++ b/drivers/gpu/drm/amd/display/dc/dc.h
> @@ -1286,6 +1286,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);
>
> diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
> index 9e6025c98db9..d5b3c80635ea 100644
> --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
> +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
> @@ -378,10 +378,9 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
> uint32_t *h_position,
> uint32_t *v_position);
>
> -enum dc_status dc_add_stream_to_ctx(
> - struct dc *dc,
> - struct dc_state *new_ctx,
> - struct dc_stream_state *stream);
> +enum dc_status dc_add_stream_to_ctx(struct dc *dc,
> + struct dc_state *new_ctx,
> + struct dc_stream_state *stream);
>
> enum dc_status dc_remove_stream_from_ctx(
> struct dc *dc,
> @@ -445,6 +444,10 @@ enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream)
> * Phy, Encoder, Timing Generator are programmed and enabled.
> * New streams are enabled with blank stream; no memory read.
> */
> +enum dc_status dc_commit_streams(struct dc *dc,
> + struct dc_stream_state *streams[],
> + uint8_t stream_count);
> +
> /*
> * Enable stereo when commit_streams is not required,
> * for example, frame alternate.
next prev parent reply other threads:[~2022-10-11 18:47 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-11 18:11 [PATCH 0/3] Update DC commit sequence Rodrigo Siqueira
2022-10-11 18:11 ` [PATCH 1/3] drm/amd/display: Add functions for new " Rodrigo Siqueira
2022-10-11 18:47 ` Harry Wentland [this message]
2022-10-11 18:11 ` [PATCH 2/3] drm/amd/display: Enable new commit sequence only for DCN32x Rodrigo Siqueira
2022-10-11 22:08 ` Harry Wentland
2022-10-11 18:11 ` [PATCH 3/3] drm/amd/display: Move dc_state copy in commit_tail after dc_commit_state Rodrigo Siqueira
2022-10-11 22:03 ` Harry Wentland
2022-10-11 18:52 ` [PATCH 0/3] Update DC commit sequence Wheeler, Daniel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=16411ae3-9cf2-b10a-1de4-131bd76e6830@amd.com \
--to=harry.wentland@amd.com \
--cc=Rodrigo.Siqueira@amd.com \
--cc=alexander.deucher@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=aurabindo.pillai@amd.com \
--cc=nicholas.kazlauskas@amd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.