--- /dev/null
+From stable-owner@vger.kernel.org Fri Aug 11 23:09:25 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Fri, 11 Aug 2023 16:07:00 -0500
+Subject: drm/amd/display: Add function for validate and update new stream
+To: <stable@vger.kernel.org>
+Cc: <Tianci.Yin@amd.com>, <Richard.Gong@amd.com>, <Aurabindo.Pillai@amd.com>, Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230811210708.14512-3-mario.limonciello@amd.com>
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+commit a5e39ae27c3a305c6aafc0e423b0cb2c677facde upstream
+
+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>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 16 -
+ drivers/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(-)
+
+--- 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_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__);
+--- 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_support
+ 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_global_state() - Determine if HW can support a given state
+- * Checks HW resource availability and bandwidth requirement.
++ * 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 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_
+ }
+
+ return true;
+-}
+\ No newline at end of file
++}
+--- 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
+
+ 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);
+
--- /dev/null
+From stable-owner@vger.kernel.org Fri Aug 11 23:09:25 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Fri, 11 Aug 2023 16:07:03 -0500
+Subject: drm/amd/display: Avoid ABM when ODM combine is enabled for eDP
+To: <stable@vger.kernel.org>
+Cc: <Tianci.Yin@amd.com>, <Richard.Gong@amd.com>, <Aurabindo.Pillai@amd.com>, Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230811210708.14512-6-mario.limonciello@amd.com>
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+commit 7fffb03b4045c862f904a88b852dc509c4e46406 upstream
+
+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>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- 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
+ 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:
--- /dev/null
+From stable-owner@vger.kernel.org Fri Aug 11 23:09:25 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Fri, 11 Aug 2023 16:07:05 -0500
+Subject: drm/amd/display: Disable phantom OTG after enable for plane disable
+To: <stable@vger.kernel.org>
+Cc: <Tianci.Yin@amd.com>, <Richard.Gong@amd.com>, <Aurabindo.Pillai@amd.com>, Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230811210708.14512-8-mario.limonciello@amd.com>
+
+From: Alvin Lee <Alvin.Lee2@amd.com>
+
+commit dc55b106ad477c67f969f3432d9070c6846fb557 upstream
+
+[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>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 14 +++++++++++++-
+ drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c | 8 ++++++++
+ drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h | 1 +
+ 3 files changed, 22 insertions(+), 1 deletion(-)
+
+--- 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(struc
+ 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(struc
+
+ 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(struc
+ * 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(struc
+ 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);
++ }
+ }
+ }
+
+--- 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_ena
+ 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 dcn
+ .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,
+--- 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);
--- /dev/null
+From stable-owner@vger.kernel.org Fri Aug 11 23:09:25 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Fri, 11 Aug 2023 16:07:07 -0500
+Subject: drm/amd/display: fix the build when DRM_AMD_DC_DCN is not set
+To: <stable@vger.kernel.org>
+Cc: <Tianci.Yin@amd.com>, <Richard.Gong@amd.com>, <Aurabindo.Pillai@amd.com>, Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230811210708.14512-10-mario.limonciello@amd.com>
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 5ca9b33ece9aa048b6ec9411f054e1b781662327 upstream
+
+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>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- 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,
--- /dev/null
+From stable-owner@vger.kernel.org Fri Aug 11 23:09:25 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Fri, 11 Aug 2023 16:07:01 -0500
+Subject: drm/amd/display: Handle seamless boot stream
+To: <stable@vger.kernel.org>
+Cc: <Tianci.Yin@amd.com>, <Richard.Gong@amd.com>, <Aurabindo.Pillai@amd.com>, Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230811210708.14512-4-mario.limonciello@amd.com>
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+commit 170390e587a69b2a24abac39eb3ae6ec28a4d7f2 upstream
+
+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>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+--- 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(
+ 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]);
--- /dev/null
+From stable-owner@vger.kernel.org Fri Aug 11 23:09:26 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Fri, 11 Aug 2023 16:06:59 -0500
+Subject: drm/amd/display: Handle virtual hardware detect
+To: <stable@vger.kernel.org>
+Cc: <Tianci.Yin@amd.com>, <Richard.Gong@amd.com>, <Aurabindo.Pillai@amd.com>, Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230811210708.14512-2-mario.limonciello@amd.com>
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+commit 987b96eb860036ab79051fb271f7fbdc01c9daf5 upstream
+
+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>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- 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
+ 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;
+
--- /dev/null
+From stable-owner@vger.kernel.org Fri Aug 11 23:09:25 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Fri, 11 Aug 2023 16:07:06 -0500
+Subject: drm/amd/display: Retain phantom plane/stream if validation fails
+To: <stable@vger.kernel.org>
+Cc: <Tianci.Yin@amd.com>, <Richard.Gong@amd.com>, <Aurabindo.Pillai@amd.com>, Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230811210708.14512-9-mario.limonciello@amd.com>
+
+From: Alvin Lee <Alvin.Lee2@amd.com>
+
+commit 9b216b7e38f5381bcc3ad21c5ac614aa577ab8f2 upstream
+
+[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>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 13 +++++++++
+ drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c | 22 ++++++++++++++++
+ drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h | 3 ++
+ drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c | 1
+ drivers/gpu/drm/amd/display/dc/inc/core_types.h | 1
+ 5 files changed, 40 insertions(+)
+
+--- 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_sta
+
+ 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;
+ }
+--- 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_ena
+ 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_p
+ .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)
+--- 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,
+--- 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_
+ .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)
+--- 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);
+ };
+
--- /dev/null
+From stable-owner@vger.kernel.org Fri Aug 11 23:09:25 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Fri, 11 Aug 2023 16:07:08 -0500
+Subject: drm/amd/display: trigger timing sync only if TG is running
+To: <stable@vger.kernel.org>
+Cc: <Tianci.Yin@amd.com>, <Richard.Gong@amd.com>, <Aurabindo.Pillai@amd.com>, Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230811210708.14512-11-mario.limonciello@amd.com>
+
+From: Aurabindo Pillai <aurabindo.pillai@amd.com>
+
+commit 6066aaf74f510fc171dbe9375153aee2d60d37aa upstream
+
+[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>
+[ 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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- 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);
+ }
--- /dev/null
+From stable-owner@vger.kernel.org Fri Aug 11 23:09:25 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Fri, 11 Aug 2023 16:07:02 -0500
+Subject: drm/amd/display: Update OTG instance in the commit stream
+To: <stable@vger.kernel.org>
+Cc: <Tianci.Yin@amd.com>, <Richard.Gong@amd.com>, <Aurabindo.Pillai@amd.com>, Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230811210708.14512-5-mario.limonciello@amd.com>
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+commit eef019eabc3cd0fddcffefbf67806a4d8cca29bb upstream
+
+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>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- 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
+
+ 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);
+
--- /dev/null
+From stable-owner@vger.kernel.org Fri Aug 11 23:09:25 2023
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Fri, 11 Aug 2023 16:07:04 -0500
+Subject: drm/amd/display: Use update plane and stream routine for DCN32x
+To: <stable@vger.kernel.org>
+Cc: <Tianci.Yin@amd.com>, <Richard.Gong@amd.com>, <Aurabindo.Pillai@amd.com>, Mario Limonciello <mario.limonciello@amd.com>
+Message-ID: <20230811210708.14512-7-mario.limonciello@amd.com>
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+commit dddde627807c22d6f15f4417eb395b13a1ca88f9 upstream
+
+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>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- 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
+ 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;
+
drm-amd-pm-expose-swctf-threshold-setting-for-legacy-powerplay.patch
drm-amd-pm-fulfill-powerplay-peak-profiling-mode-shader-memory-clock-settings.patch
drm-amd-pm-avoid-unintentional-shutdown-due-to-temperature-momentary-fluctuation.patch
+drm-amd-display-handle-virtual-hardware-detect.patch
+drm-amd-display-add-function-for-validate-and-update-new-stream.patch
+drm-amd-display-handle-seamless-boot-stream.patch
+drm-amd-display-update-otg-instance-in-the-commit-stream.patch
+drm-amd-display-avoid-abm-when-odm-combine-is-enabled-for-edp.patch
+drm-amd-display-use-update-plane-and-stream-routine-for-dcn32x.patch
+drm-amd-display-disable-phantom-otg-after-enable-for-plane-disable.patch
+drm-amd-display-retain-phantom-plane-stream-if-validation-fails.patch
+drm-amd-display-fix-the-build-when-drm_amd_dc_dcn-is-not-set.patch
+drm-amd-display-trigger-timing-sync-only-if-tg-is-running.patch