[PATCH 04/41] drm/amd/display: Dependent changes for DCN6

<[email protected]> Fri, 31 Jul 2026 17:12:25 -0400
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
From: Aurabindo Pillai <[email protected]>

changes needed to enable DCN6 asic

Signed-off-by: Aurabindo Pillai <[email protected]>
Signed-off-by: Roman Li <[email protected]>
Reviewed-by: Ivan Lipski <[email protected]>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_audio.h   |   2 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |   6 +
 .../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c  |  15 +
 drivers/gpu/drm/amd/display/dc/core/dc.c      |  10 +-
 .../drm/amd/display/dc/core/dc_hw_sequencer.c | 410 +++++++++++++++
 .../gpu/drm/amd/display/dc/core/dc_resource.c |  47 ++
 .../gpu/drm/amd/display/dc/core/dc_state.c    |  12 +
 .../gpu/drm/amd/display/dc/core/dc_stream.c   |  24 +
 drivers/gpu/drm/amd/display/dc/dc.h           |  26 +-
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c  |  44 ++
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h  |  23 +
 drivers/gpu/drm/amd/display/dc/dc_helper.c    |   2 +
 drivers/gpu/drm/amd/display/dc/dc_hw_types.h  |  53 +-
 .../gpu/drm/amd/display/dc/dc_spl_translate.c |  32 +-
 .../gpu/drm/amd/display/dc/dc_state_priv.h    |   1 +
 drivers/gpu/drm/amd/display/dc/dc_stream.h    |   5 +
 drivers/gpu/drm/amd/display/dc/dc_types.h     |  10 +
 .../amd/display/dc/dccg/dcn20/dcn20_dccg.h    |  10 +
 .../drm/amd/display/dc/dce/dce_clock_source.c |  24 +
 .../drm/amd/display/dc/dce/dce_clock_source.h |   9 +
 .../display/dc/dio/dcn10/dcn10_link_encoder.h |  16 +
 .../dc/dio/dcn401/dcn401_dio_link_encoder.c   |  15 +
 .../dc/dio/dcn401/dcn401_dio_link_encoder.h   |  10 +
 drivers/gpu/drm/amd/display/dc/dm_helpers.h   |   8 +
 .../dml2_0/dml21/dml21_translation_helper.c   |  57 +-
 .../amd/display/dc/dml2_0/dml21/dml21_utils.c | 129 ++++-
 .../dml21/inc/dml_top_display_cfg_types.h     |  10 +
 .../dml21/inc/dml_top_soc_parameter_types.h   |   2 +
 .../dc/dml2_0/dml21/inc/dml_top_types.h       |  45 ++
 .../src/dml2_core/dml2_core_dcn4_calcs.c      |   1 +
 .../dml21/src/dml2_core/dml2_core_factory.c   |  25 +
 .../src/dml2_core/dml2_core_shared_types.h    | 160 ++++++
 .../dml21/src/dml2_dpmm/dml2_dpmm_factory.c   |  12 +
 .../dml21/src/dml2_mcg/dml2_mcg_factory.c     |   5 +
 .../dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c  |  57 ++
 .../dml21/src/dml2_pmo/dml2_pmo_factory.c     |  34 ++
 .../dml21/src/dml2_top/dml2_top_interfaces.c  |   7 +
 .../src/inc/dml2_internal_shared_types.h      | 485 ++++++++++++++++++
 .../drm/amd/display/dc/dml2_0/dml2_wrapper.h  |   8 +
 .../amd/display/dc/dpp/dcn401/dcn401_dpp.h    |  41 ++
 .../display/dc/dpp/dcn401/dcn401_dpp_dscl.c   |  26 +-
 .../drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c  |   7 +-
 .../drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h  |   6 +
 .../gpu/drm/amd/display/dc/gpio/ddc_regs.h    |  15 +
 drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c  | 302 +++++++++++
 drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h  |  28 +
 .../gpu/drm/amd/display/dc/gpio/hw_factory.c  |   4 +
 .../drm/amd/display/dc/gpio/hw_translate.c    |   4 +
 .../gpu/drm/amd/display/dc/hdcp/hdcp_msg.c    |   9 +
 .../display/dc/hubbub/dcn10/dcn10_hubbub.h    | 108 ++++
 .../amd/display/dc/hubp/dcn20/dcn20_hubp.h    |  29 ++
 .../drm/amd/display/dc/hwss/dce/dce_hwseq.h   |   9 +
 .../amd/display/dc/hwss/dce110/dce110_hwseq.c |  11 +
 .../amd/display/dc/hwss/dcn10/dcn10_hwseq.c   |   3 +-
 .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c   |   3 +-
 .../amd/display/dc/hwss/dcn30/dcn30_hwseq.c   |   3 +-
 .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c   |   5 +-
 .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c   |   1 +
 .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c |  32 ++
 .../drm/amd/display/dc/hwss/hw_sequencer.h    |  17 +
 .../gpu/drm/amd/display/dc/inc/core_types.h   |   1 +
 .../amd/display/dc/inc/hw/clk_mgr_internal.h  |  22 +
 .../amd/display/dc/inc/hw/cursor_reg_cache.h  |   3 +-
 drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h   |   7 +
 .../drm/amd/display/dc/inc/hw/link_encoder.h  |   6 +
 .../gpu/drm/amd/display/dc/inc/hw/transform.h |   1 +
 drivers/gpu/drm/amd/display/dc/inc/resource.h |   2 +
 .../drm/amd/display/dc/link/link_detection.c  |  29 ++
 .../drm/amd/display/dc/link/link_factory.c    |   5 +
 .../amd/display/dc/link/protocols/link_ddc.c  |   8 +
 .../display/dc/link/protocols/link_hdmi_frl.c |   5 +
 .../amd/display/dc/optc/dcn42/dcn42_optc.c    |   4 +-
 .../amd/display/dc/optc/dcn42/dcn42_optc.h    |   2 +
 .../dc/resource/dcn10/dcn10_resource.c        |   1 +
 .../dc/resource/dcn20/dcn20_resource.c        |   1 +
 .../dc/resource/dcn201/dcn201_resource.c      |   1 +
 .../dc/resource/dcn21/dcn21_resource.c        |   1 +
 .../dc/resource/dcn30/dcn30_resource.c        |   1 +
 .../dc/resource/dcn301/dcn301_resource.c      |   1 +
 .../dc/resource/dcn302/dcn302_resource.c      |   1 +
 .../dc/resource/dcn303/dcn303_resource.c      |   1 +
 .../dc/resource/dcn314/dcn314_resource.c      |   1 +
 .../dc/resource/dcn315/dcn315_resource.c      |   1 +
 .../dc/resource/dcn32/dcn32_resource.c        |   1 +
 .../dc/resource/dcn321/dcn321_resource.c      |   1 +
 .../dc/resource/dcn35/dcn35_resource.c        |   1 +
 .../dc/resource/dcn351/dcn351_resource.c      |   1 +
 .../dc/resource/dcn36/dcn36_resource.c        |   1 +
 .../dc/resource/dcn401/dcn401_resource.c      |  33 +-
 .../dc/resource/dcn401/dcn401_resource.h      |   4 +
 .../dc/resource/dcn42/dcn42_resource.c        |   1 +
 .../soc_and_ip_translator.c                   |   4 +
 drivers/gpu/drm/amd/display/dmub/dmub_srv.h   |   5 +
 .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h   | 175 ++++++-
 .../gpu/drm/amd/display/dmub/src/dmub_srv.c   |  52 ++
 .../gpu/drm/amd/display/include/dal_asic_id.h |  18 +
 96 files changed, 2871 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_audio.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_audio.h
index e57e2ed20d56..7ccb026ece56 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_audio.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_audio.h
@@ -28,7 +28,7 @@
 
 struct amdgpu_device;
 struct drm_device;
-struct drm_atomic_state;
+struct drm_atomic_commit;
 struct drm_connector;
 struct audio_info;
 struct dc_sink;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index c720c319e795..d451082552e8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -1903,3 +1903,9 @@ void dm_helpers_mccs_vcp_set(struct dc_context *ctx, struct dc_link *link,
 }
 EXPORT_IF_KUNIT(dm_helpers_mccs_vcp_set);
 
+bool dm_helpers_submit_i2c_over_aux(struct ddc_service *ddc, uint32_t address, uint8_t offset,
+				    uint8_t *cmdBuffer, uint32_t len, bool read)
+{
+	//TODO: Implement this
+	return false;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
index 2a1353cb7e7d..e2148cb3b8ab 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
@@ -50,6 +50,7 @@
 #include "dcn401/dcn401_clk_mgr.h"
 #include "dcn42/dcn42_clk_mgr.h"
 #include "dcn42b/dcn42b_clk_mgr.h"
+#include "dcn60/dcn60_clk_mgr.h"
 
 int clk_mgr_helper_get_active_display_cnt(
 		struct dc *dc,
@@ -387,6 +388,17 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
 		return &clk_mgr->base.base;
 	}
 	break;
+	case AMDGPU_FAMILY_GC_13_0_1: {
+		struct clk_mgr_internal *clk_mgr = dcn60_clk_mgr_construct(ctx, dccg);
+
+		if (clk_mgr == NULL) {
+			BREAK_TO_DEBUGGER();
+			return NULL;
+		}
+
+		return &clk_mgr->base;
+	}
+
 #endif	/* CONFIG_DRM_AMD_DC_FP */
 	default:
 		ASSERT(0); /* Unknown Asic */
@@ -451,6 +463,9 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base)
 	case AMDGPU_FAMILY_GC_11_5_4:
 		dcn42_clk_mgr_destroy(clk_mgr);
 		break;
+	case AMDGPU_FAMILY_GC_13_0_1:
+		dcn60_clk_mgr_destroy(clk_mgr);
+		break;
 
 	default:
 		break;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 6c1a8ecc2cb5..7f378b5e896c 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -3099,7 +3099,8 @@ static struct dc_update_descriptor det_surface_update(
 			update_bits->gamut_remap_change ||
 			update_bits->input_csc_change ||
 			update_bits->cm_hist_change ||
-			update_bits->coeff_reduction_change)) {
+			update_bits->coeff_reduction_change ||
+			update_bits->cursor_csc_color_matrix_change)) {
 		elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
 	}
 	return overall_type;
@@ -3403,6 +3404,10 @@ static void copy_surface_update_to_plane(
 				srf_update->plane_info->dcc;
 		surface->layer_index =
 				srf_update->plane_info->layer_index;
+		surface->scaling_linearity =
+				srf_update->plane_info->scaling_linearity;
+		surface->cositing =
+				srf_update->plane_info->cositing;
 	}
 
 	if (srf_update->gamma) {
@@ -3658,6 +3663,9 @@ static void copy_stream_update_to_stream(struct dc *dc,
 	if (update->sharpening_required)
 		stream->sharpening_required = *update->sharpening_required;
 
+	if (update->blending_linearity)
+		stream->blending_linearity = *update->blending_linearity;
+
 	if (update->drr_trigger_mode) {
 		stream->drr_trigger_mode = *update->drr_trigger_mode;
 	}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index 11411fa94665..8878652434d2 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -41,6 +41,7 @@
 #include "dcn10/dcn10_hubbub.h"
 #include "dce/dmub_hw_lock_mgr.h"
 #include "link_service.h"
+#include "custom_float.h"
 
 #define MAX_NUM_MCACHE 8
 
@@ -729,6 +730,386 @@ void get_fams2_visual_confirm_color(
 	}
 }
 
+static bool get_update_dchubp_dpp_flags_status(struct pipe_ctx *pipe)
+{
+	if (!pipe->plane_state) {
+		return false;
+	}
+
+	if ((pipe->update_flags.raw ||
+		dc_pipe_update_bits_is_any_set(&pipe->plane_state->update_bits) ||
+		pipe->stream->update_flags.raw)) {
+		return true;
+	}
+
+	return false;
+}
+
+// Function to check if any update flags are set
+static bool get_pipe_update_bits_status(struct pipe_ctx *pipe, struct dc_plane_state *plane, struct dc_stream_state *stream)
+{
+	(void)stream;
+	if (plane) {
+		return (pipe->update_flags.bits.enable ||
+			pipe->update_flags.bits.plane_changed ||
+			pipe->update_flags.bits.opp_changed ||
+			plane->update_bits.pixel_format_change ||
+			plane->update_bits.horizontal_mirror_change ||
+			plane->update_bits.rotation_change ||
+			plane->update_bits.swizzle_change ||
+			plane->update_bits.dcc_change ||
+			plane->update_bits.bpp_change ||
+			plane->update_bits.scaling_change ||
+			plane->update_bits.plane_size_change);
+	}
+	return false;
+}
+
+void hwss_build_full_sequence(struct dc *dc,
+	struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE],
+	unsigned int *num_steps,
+	struct dc_state *context, bool program_phantom_pipe)
+{
+	(void)program_phantom_pipe;
+	struct dc_plane_state *plane = NULL;
+	struct dc_stream_state *stream = NULL;
+	struct pipe_ctx *current_pipe = NULL;
+	struct pipe_ctx *pipe = NULL;
+	struct dce_hwseq *hws = dc->hwseq;
+	unsigned int i;
+	*num_steps = 0; // Initialize to 0
+	struct block_sequence_state seq_state = { .steps = block_sequence, .num_steps = num_steps };
+
+	for (i = 0; i < dc->res_pool->pipe_count; i++)
+		dc->hwss.detect_pipe_changes(dc->current_state, context, &dc->current_state->res_ctx.pipe_ctx[i],
+			&context->res_ctx.pipe_ctx[i]);
+
+	/* Program triplebuffer if enabled */
+	if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
+		for (i = 0; i < dc->res_pool->pipe_count; i++) {
+			pipe = &context->res_ctx.pipe_ctx[i];
+
+			if (pipe->plane_state) {
+				/* Turn off triple buffer for full update */
+				hwss_add_hubp_program_triplebuffer(&seq_state, dc, pipe, pipe->plane_state->triplebuffer_flips);
+			}
+		}
+	}
+
+	/* Count hubp usage and force pstate change if needed */
+	unsigned int prev_hubp_count = 0;
+	unsigned int hubp_count = 0;
+
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		if (dc->current_state->res_ctx.pipe_ctx[i].plane_state)
+			prev_hubp_count++;
+		if (context->res_ctx.pipe_ctx[i].plane_state)
+			hubp_count++;
+	}
+
+	if (prev_hubp_count == 0 && hubp_count > 0) {
+		if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
+			hwss_add_hubbub_force_pstate_change_control(&seq_state, dc->res_pool->hubbub, true, false);
+	}
+
+	/* When disabling phantom pipes, turn on phantom OTG first */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		struct dc_stream_state *pipe_stream = dc->current_state->res_ctx.pipe_ctx[i].stream;
+
+		pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+		if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable && pipe_stream &&
+			dc_state_get_pipe_subvp_type(dc->current_state, pipe) == SUBVP_PHANTOM) {
+			struct timing_generator *tg = dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg;
+
+			if (tg->funcs->enable_crtc) {
+				if (dc->hwseq->funcs.blank_pixel_data_sequence)
+					dc->hwseq->funcs.blank_pixel_data_sequence(dc, pipe, true, &seq_state);
+				hwss_add_tg_enable_crtc(&seq_state, tg);
+			}
+		}
+	}
+
+	/* OTG blank before disabling all front ends */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable
+				&& !context->res_ctx.pipe_ctx[i].top_pipe
+				&& !context->res_ctx.pipe_ctx[i].prev_odm_pipe
+				&& context->res_ctx.pipe_ctx[i].stream) {
+
+			if (dc->hwseq->funcs.blank_pixel_data_sequence) {
+				dc->hwseq->funcs.blank_pixel_data_sequence(dc, &context->res_ctx.pipe_ctx[i],
+					true, &seq_state);
+			}
+		}
+	}
+
+	/* Disconnect mpcc for pipes being disabled or with opp changes */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable
+			|| context->res_ctx.pipe_ctx[i].update_flags.bits.opp_changed) {
+			struct hubbub *hubbub = dc->res_pool->hubbub;
+
+			/* Phantom pipe DET should be 0, but if a pipe in use is being transitioned to phantom
+			 * then we want to do the programming here (effectively it's being disabled). If we do
+			 * the programming later the DET won't be updated until the OTG for the phantom pipe is
+			 * turned on (i.e. in an MCLK switch) which can come in too late and cause issues with
+			 * DET allocation.
+			 */
+			if ((context->res_ctx.pipe_ctx[i].update_flags.bits.disable ||
+					(context->res_ctx.pipe_ctx[i].plane_state &&
+					dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) ==
+					SUBVP_PHANTOM))) {
+
+				if (hubbub->funcs->program_det_size) {
+					hwss_add_hubp_program_det_size(&seq_state, hubbub,
+						dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
+				}
+
+				if (dc->res_pool->hubbub->funcs->program_det_segments) {
+					hwss_add_hubp_program_det_segments(&seq_state, hubbub,
+						dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
+				}
+			}
+
+			if (hws->funcs.plane_atomic_disconnect_sequence)
+				hws->funcs.plane_atomic_disconnect_sequence(dc, dc->current_state,
+					&dc->current_state->res_ctx.pipe_ctx[i], &seq_state);
+		}
+	}
+
+	/* update ODM for blanked OTG master pipes */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		pipe = &context->res_ctx.pipe_ctx[i];
+		if (resource_is_pipe_type(pipe, OTG_MASTER) &&
+				!resource_is_pipe_type(pipe, DPP_PIPE) &&
+				pipe->update_flags.bits.odm) {
+			if (hws->funcs.update_odm_sequence)
+				hws->funcs.update_odm_sequence(dc, context, pipe, &seq_state);
+		}
+	}
+
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		pipe = &context->res_ctx.pipe_ctx[i];
+		if (pipe->update_flags.bits.disable) {
+			struct cm_hist_control hist_disable = { .channels_enabled = 0 };
+
+			hwss_add_dpp_program_cm_hist(&seq_state, pipe->plane_res.dpp,
+				hist_disable, COLOR_SPACE_UNKNOWN);
+		}
+	}
+
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		pipe = &context->res_ctx.pipe_ctx[i];
+
+		if (pipe->plane_state && !pipe->top_pipe) {
+			while (pipe) {
+				if (pipe->stream &&
+						dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
+					if (hws->funcs.program_pipe_sequence)
+						hws->funcs.program_pipe_sequence(dc, pipe, context, &seq_state);
+				}
+
+				pipe = pipe->bottom_pipe;
+			}
+		}
+
+		/* Program secondary blending tree and writeback pipes */
+		pipe = &context->res_ctx.pipe_ctx[i];
+		if (!pipe->top_pipe && !pipe->prev_odm_pipe
+			&& pipe->stream && pipe->stream->num_wb_info > 0
+			&& (pipe->update_flags.raw || (pipe->plane_state && dc_pipe_update_bits_is_any_set(&pipe->plane_state->update_bits))
+				|| pipe->stream->update_flags.raw)) {
+
+			if (hws->funcs.program_all_writeback_pipes_in_tree_sequence)
+				hws->funcs.program_all_writeback_pipes_in_tree_sequence(dc, pipe->stream,
+					context, &seq_state);
+		}
+
+		/* Avoid underflow by check of pipe line read when adding 2nd plane. */
+		if (hws->wa.wait_hubpret_read_start_during_mpo_transition &&
+				!pipe->top_pipe &&
+				pipe->stream &&
+				pipe->plane_res.hubp->funcs->hubp_wait_pipe_read_start &&
+				dc->current_state->stream_status[0].plane_count == 1 &&
+				context->stream_status[0].plane_count > 1) {
+			hwss_add_hubp_wait_pipe_read_start(&seq_state, pipe->plane_res.hubp);
+		}
+	}
+
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		current_pipe = &context->res_ctx.pipe_ctx[i];
+
+		while (current_pipe) {
+			plane = current_pipe->plane_state;
+			stream = current_pipe->stream;
+			bool is_phantom = (dc_state_get_pipe_subvp_type(context, current_pipe) == SUBVP_PHANTOM);
+
+			if (get_update_dchubp_dpp_flags_status(current_pipe)) {
+				if (!is_phantom && plane && stream) {
+					if (get_pipe_update_bits_status(current_pipe, plane, stream)) {
+						struct plane_size size = plane->plane_size;
+
+						size.surface_size = current_pipe->plane_res.scl_data.viewport;
+						hwss_add_hubp_program_surface_config(&seq_state, current_pipe->plane_res.hubp,
+							plane->format, &plane->tiling_info, size, plane->rotation, &plane->dcc,
+							plane->horizontal_mirror, 0);
+					}
+
+					if (current_pipe->plane_res.hubp->funcs->hubp_program_mcache_id_and_split_coordinate)
+						hwss_add_hubp_program_mcache_id(&seq_state, current_pipe->plane_res.hubp, &current_pipe->mcache_regs);
+
+					if (current_pipe->plane_res.dpp->funcs->dpp_program_upsp) {
+						block_sequence[*num_steps].params.program_upsp_params.pipe_ctx = current_pipe;
+						block_sequence[*num_steps].func = DPP_PROGRAM_UPSP;
+						(*num_steps)++;
+					}
+				}
+			}
+			current_pipe = current_pipe->bottom_pipe;
+		}
+	}
+}
+
+void hwss_build_post_unlock_full_sequence(struct dc *dc,
+	struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE],
+	unsigned int *num_steps,
+	struct dc_state *context)
+{
+	unsigned int i;
+	struct dce_hwseq *hwseq = dc->hwseq;
+	*num_steps = 0; // Initialize to 0
+	struct block_sequence_state seq_state = { .steps = block_sequence, .num_steps = num_steps };
+
+	/* Reset OPP for pipes transitioning from OPP_HEAD to non-OPP_HEAD */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		if (resource_is_pipe_type(&dc->current_state->res_ctx.pipe_ctx[i], OPP_HEAD) &&
+				!resource_is_pipe_type(&context->res_ctx.pipe_ctx[i], OPP_HEAD)) {
+
+			if (dc->hwss.post_unlock_reset_opp_sequence)
+				dc->hwss.post_unlock_reset_opp_sequence(dc, &dc->current_state->res_ctx.pipe_ctx[i],
+					&seq_state);
+		}
+	}
+
+	/* Disable planes that are being disabled */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) {
+			if (dc->hwss.disable_plane_sequence)
+				dc->hwss.disable_plane_sequence(dc, dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i],
+					&seq_state);
+		}
+	}
+
+	/* Wait for flip pending on pipes being enabled */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+		if (pipe->plane_state && !pipe->top_pipe && pipe->update_flags.bits.enable &&
+			dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
+
+			unsigned int polling_interval_us;
+				polling_interval_us = 1;
+			hwss_add_hubp_wait_flip_pending(&seq_state, pipe->plane_res.hubp, 100000, polling_interval_us);
+		}
+	}
+
+	/* Wait for double buffer pending when ODM slice count increases */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+		struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+		if (resource_is_pipe_type(old_pipe, OTG_MASTER) && resource_is_pipe_type(pipe, OTG_MASTER) &&
+			resource_get_odm_slice_count(old_pipe) < resource_get_odm_slice_count(pipe) &&
+			dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
+
+			unsigned int polling_interval_us;
+			polling_interval_us = 1;
+			hwss_add_tg_wait_double_buffer_pending(&seq_state, pipe->stream_res.tg, 100000, polling_interval_us);
+		}
+	}
+
+	/* Force pstate change control to false */
+	if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
+		hwss_add_hubbub_force_pstate_change_control(&seq_state, dc->res_pool->hubbub, false, false);
+
+	/* Program phantom pipes */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+		if (pipe->plane_state && !pipe->top_pipe) {
+			while (pipe) {
+				if (pipe->stream && dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) {
+					/* Apply update flags for phantom pipes using existing HWS functions */
+					if (dc->hwss.apply_update_flags_for_phantom)
+						hwss_add_hws_apply_update_flags_for_phantom(&seq_state, pipe);
+					if (dc->hwss.update_phantom_vp_position)
+						hwss_add_hws_update_phantom_vp_position(&seq_state, dc, context, pipe);
+
+					/* Program the phantom pipe - use program_pipe_sequence if available */
+					if (dc->hwseq && dc->hwseq->funcs.program_pipe_sequence)
+						dc->hwseq->funcs.program_pipe_sequence(dc, pipe, context, &seq_state);
+				}
+				pipe = pipe->bottom_pipe;
+			}
+		}
+	}
+
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+		while (pipe) {
+			struct dc_plane_state *plane = pipe->plane_state;
+			struct dc_stream_state *stream = pipe->stream;
+			bool is_phantom = (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM);
+
+			if (get_update_dchubp_dpp_flags_status(pipe)) {
+				if (is_phantom && plane && stream) {
+					if (get_pipe_update_bits_status(pipe, plane, stream)) {
+						struct plane_size size = plane->plane_size;
+
+						size.surface_size = pipe->plane_res.scl_data.viewport;
+						hwss_add_hubp_program_surface_config(&seq_state, pipe->plane_res.hubp,
+							plane->format, &plane->tiling_info, size, plane->rotation, &plane->dcc,
+							plane->horizontal_mirror, 0);
+					}
+
+					if (pipe->plane_res.hubp->funcs->hubp_program_mcache_id_and_split_coordinate)
+						hwss_add_hubp_program_mcache_id(&seq_state, pipe->plane_res.hubp, &pipe->mcache_regs);
+				}
+			}
+			pipe = pipe->bottom_pipe;
+		}
+	}
+
+	/* Update force pstate if hwseq is available */
+	if (hwseq && hwseq->funcs.update_force_pstate)
+		hwss_add_update_force_pstate(&seq_state, dc, context);
+
+	/* Program MALL pipe configuration */
+	if (hwseq && hwseq->funcs.program_mall_pipe_config_sequence)
+		hwseq->funcs.program_mall_pipe_config_sequence(dc, context, &seq_state);
+
+	/* Apply DEDCN21 147 WA if needed */
+	if (hwseq && hwseq->wa.DEGVIDCN21)
+		hwss_add_hubbub_apply_dedcn21_147_wa(&seq_state, dc->res_pool->hubbub);
+
+	/* Handle stutter underflow WA during MPO transitions */
+	if (hwseq && hwseq->wa.disallow_self_refresh_during_multi_plane_transition &&
+			dc->current_state->stream_status[0].plane_count == 1 &&
+			context->stream_status[0].plane_count > 1) {
+
+		hwss_add_hubbub_allow_self_refresh_control(&seq_state, dc->res_pool->hubbub, false,
+			&hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied);
+
+		/* Get frame count for WA state tracking - this needs to be done immediately after the above call */
+		if (dc->res_pool->timing_generators[0]->funcs->get_frame_count) {
+			hwss_add_tg_get_frame_count(&seq_state, dc->res_pool->timing_generators[0],
+				&hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied_on_frame);
+		}
+	}
+}
+
 void hwss_build_fast_sequence(struct dc *dc,
 		struct dc_dmub_cmd *dc_dmub_cmd,
 		unsigned int dmub_cmd_count,
@@ -1058,6 +1439,16 @@ void hwss_build_fast_sequence(struct dc *dc,
 					(*num_steps)++;
 				}
 
+				if (current_mpc_pipe->plane_state->update_bits.lut_3d &&
+						current_mpc_pipe->plane_state->cm.flags.bits.lut3d_dma_enable &&
+						current_mpc_pipe->plane_state->cm.flags.bits.shaper_enable &&
+						current_mpc_pipe->plane_state->cm.flags.bits.lut3d_enable &&
+						current_mpc_pipe->plane_res.hubp->funcs->hubp_enable_3dlut_fl) {
+					block_sequence[*num_steps].params.hubp_enable_3dlut_fl_params.hubp =
+						current_mpc_pipe->plane_res.hubp;
+					block_sequence[*num_steps].func = HUBP_ENABLE_3DLUT_FL;
+					(*num_steps)++;
+				}
 				if (hws->funcs.set_input_transfer_func && current_mpc_pipe->plane_state->update_bits.gamma_change) {
 					block_sequence[*num_steps].params.set_input_transfer_func_params.dc = dc;
 					block_sequence[*num_steps].params.set_input_transfer_func_params.pipe_ctx = current_mpc_pipe;
@@ -1279,6 +1670,9 @@ void hwss_execute_sequence(struct dc *dc,
 		case DPP_SET_OUTPUT_TRANSFER_FUNC:
 			hws->funcs.set_output_transfer_func(&params->set_output_transfer_func_params);
 			break;
+		case DPP_PROGRAM_UPSP:
+			hwss_program_upsp(params);
+			break;
 		case MPC_UPDATE_VISUAL_CONFIRM:
 			dc->hwss.update_visual_confirm_color(params->update_visual_confirm_params.dc,
 					params->update_visual_confirm_params.pipe_ctx,
@@ -2448,6 +2842,22 @@ void hwss_program_bias_and_scale(union block_sequence_params *params)
 		dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
 }
 
+void hwss_program_upsp(union block_sequence_params *params)
+{
+	struct pipe_ctx *pipe_ctx = params->program_upsp_params.pipe_ctx;
+	struct dpp *dpp = pipe_ctx->plane_res.dpp;
+	struct dscl_prog_data *dscl_prog_data = &pipe_ctx->plane_res.scl_data.dscl_prog_data;
+
+	if (!dpp || !dscl_prog_data)
+		return;
+
+	if (dpp && dpp->funcs->dpp_program_upsp) {
+		// program upsampler
+		dpp->funcs->dpp_program_upsp(dpp,
+				dscl_prog_data);
+	}
+}
+
 void hwss_power_on_mpc_mem_pwr(union block_sequence_params *params)
 {
 	struct mpc *mpc = params->power_on_mpc_mem_pwr_params.mpc;
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 b970f152d67f..7eaaf38cd9ab 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -80,6 +80,7 @@
 #include "dcn401/dcn401_resource.h"
 #include "dcn42/dcn42_resource.h"
 #include "dcn42b/dcn42b_resource.h"
+#include "dcn60/dcn60_resource.h"
 #if defined(CONFIG_DRM_AMD_DC_FP)
 #include "dc_spl_translate.h"
 #endif
@@ -261,6 +262,9 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
 	case AMDGPU_FAMILY_GC_11_5_4:
 			dc_version = DCN_VERSION_4_2;
 	break;
+	case AMDGPU_FAMILY_GC_13_0_1:
+			dc_version = DCN_VERSION_6_0;
+		break;
 	default:
 		dc_version = DCE_VERSION_UNKNOWN;
 		break;
@@ -383,6 +387,9 @@ struct resource_pool *dc_create_resource_pool(struct dc  *dc,
 	case DCN_VERSION_4_2B:
 		res_pool = dcn42b_create_resource_pool(init_data, dc);
 		break;
+	case DCN_VERSION_6_0:
+		res_pool = dcn60_create_resource_pool(init_data, dc);
+		break;
 #endif /* CONFIG_DRM_AMD_DC_FP */
 	default:
 		break;
@@ -818,6 +825,36 @@ static enum dc_pixel_format convert_pixel_format_to_dalsurface(
 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
 		dal_pixel_format = PIXEL_FORMAT_420BPP10;
 		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P208:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P208:
+		dal_pixel_format = PIXEL_FORMAT_422BPP8;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P210:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P210:
+		dal_pixel_format = PIXEL_FORMAT_422BPP10;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P212:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P212:
+		dal_pixel_format = PIXEL_FORMAT_422BPP12;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_YCrYCb:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_YCbYCr:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrYCbY:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbYCrY:
+		dal_pixel_format = PIXEL_FORMAT_422BPP8;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCrYCb:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCbYCr:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CrYCbY:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CbYCrY:
+		dal_pixel_format = PIXEL_FORMAT_422BPP10;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCrYCb:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCbYCr:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CrYCbY:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CbYCrY:
+		dal_pixel_format = PIXEL_FORMAT_422BPP12;
+		break;
 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
 	default:
@@ -1516,6 +1553,15 @@ void resource_build_test_pattern_params(struct resource_context *res_ctx,
 	}
 }
 
+enum upsp_mode resource_is_upsp_required(enum surface_pixel_format format)
+{
+	if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN && format <= SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb) //420 Formats
+		return UPSP_HORIZONTAL_VERTICAL_UPSAMPLING;
+	if (format > SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb && format < SURFACE_PIXEL_FORMAT_SUBSAMPLE_END) //422 Formats
+		return UPSP_HORIZONTAL_UPSAMPLING_ONLY;
+	return UPSP_BYPASS;
+}
+
 bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
 {
 	const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
@@ -1561,6 +1607,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
 			pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
 
 		pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha;
+		pipe_ctx->plane_res.scl_data.upsp = resource_is_upsp_required(plane_state->format);
 
 		// Convert pipe_ctx to respective input params for SPL
 		translate_SPL_in_params_from_pipe_ctx(pipe_ctx, spl_in);
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
index b534b1a641af..666212cac105 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
@@ -1155,3 +1155,15 @@ bool dc_state_is_subvp_in_use(struct dc_state *state)
 
 	return false;
 }
+bool dc_state_is_alt_in_use(const struct dc *dc, const struct dc_state *state)
+{
+	uint32_t i;
+	const struct pipe_ctx *pipe;
+
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		pipe = &state->res_ctx.pipe_ctx[i];
+		if (pipe->p_state_type == P_STATE_ALT)
+			return true;
+	}
+	return false;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index cdcf140bc1bb..ce5b9e82db8d 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -405,6 +405,7 @@ bool dc_stream_program_cursor_attributes(
 {
 	struct dc  *dc;
 	bool reset_idle_optimizations = false;
+	bool should_release_dmub_hw_control_lock = false;
 
 	if (!stream)
 		return false;
@@ -413,6 +414,13 @@ bool dc_stream_program_cursor_attributes(
 
 	if (dc_stream_set_cursor_attributes(stream, attributes)) {
 		dc_z10_restore(dc);
+		if (dc->hwss.dmub_hw_control_lock) {
+			if (dc_state_is_alt_in_use(dc, dc->current_state) &&
+			    !dc_dmub_srv_is_cursor_offload_enabled(dc)) {
+				dc->hwss.dmub_hw_control_lock(dc, dc->current_state, true);
+				should_release_dmub_hw_control_lock = true;
+			}
+		}
 		/* disable idle optimizations while updating cursor */
 		if (dc->idle_optimizations_allowed) {
 			dc_allow_idle_optimizations(dc, false);
@@ -425,6 +433,10 @@ bool dc_stream_program_cursor_attributes(
 		if (reset_idle_optimizations && !dc->debug.disable_dmub_reallow_idle)
 			dc_allow_idle_optimizations(dc, true);
 
+		if (dc->hwss.dmub_hw_control_lock) {
+			if (should_release_dmub_hw_control_lock)
+				dc->hwss.dmub_hw_control_lock(dc, dc->current_state, false);
+		}
 		return true;
 	}
 
@@ -507,6 +519,7 @@ bool dc_stream_program_cursor_position(
 	struct dc *dc;
 	bool reset_idle_optimizations = false;
 	const struct dc_cursor_position *old_position;
+	bool should_release_dmub_hw_control_lock = false;
 
 	if (!stream)
 		return false;
@@ -517,6 +530,13 @@ bool dc_stream_program_cursor_position(
 	if (dc_stream_set_cursor_position(stream, position)) {
 		dc_z10_restore(dc);
 
+		if (dc->hwss.dmub_hw_control_lock) {
+			if (dc_state_is_alt_in_use(dc, dc->current_state) &&
+			    !dc_dmub_srv_is_cursor_offload_enabled(dc)) {
+				dc->hwss.dmub_hw_control_lock(dc, dc->current_state, true);
+				should_release_dmub_hw_control_lock = true;
+			}
+		}
 		/* disable idle optimizations if enabling cursor */
 		if (dc->idle_optimizations_allowed &&
 		    (!old_position->enable || dc->debug.exit_idle_opt_for_cursor_updates) &&
@@ -567,6 +587,10 @@ bool dc_stream_program_cursor_position(
 			}
 		}
 
+		if (dc->hwss.dmub_hw_control_lock) {
+			if (should_release_dmub_hw_control_lock)
+				dc->hwss.dmub_hw_control_lock(dc, dc->current_state, false);
+		}
 		return true;
 	}
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 63c0dec85697..cc029af0cef2 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -174,6 +174,13 @@ struct dc_plane_cap {
 		uint32_t fp16 : 1;
 		uint32_t p010 : 1;
 		uint32_t ayuv : 1;
+		uint32_t yuy2 : 1; // Packed 422 8bpc
+		uint32_t y210 : 1; // Packed 422 10bpc
+		uint32_t y212 : 1; // Packed 422 12bpc
+		uint32_t p208 : 1; // Planar 422 8bpc
+		uint32_t p210 : 1; // Planar 422 10bpc
+		uint32_t p212 : 1; // Planar 422 12bpc
+		/* Not all caps will be used/supported */
 	} pixel_format_support;
 	// max upscaling factor x1000
 	// upscaling factors are always >= 1
@@ -240,6 +247,7 @@ struct rom_curve_caps {
  * @ogam_ram: programmable out/blend gamma LUT
  * @ocsc: output color space conversion
  * @dgam_rom_for_yuv: pre-defined degamma LUT for YUV planes
+ * @upsp_pre_scaler: Ability to upsample 420/422 before scaling
  * @dgam_rom_caps: pre-definied curve caps for degamma 1D LUT
  * @ogam_rom_caps: pre-definied curve caps for regamma 1D LUT
  *
@@ -256,6 +264,7 @@ struct dpp_color_caps {
 	uint16_t ogam_ram : 1;
 	uint16_t ocsc : 1;
 	uint16_t dgam_rom_for_yuv : 1;
+	uint16_t upsp_pre_scaler : 1;
 	struct rom_curve_caps dgam_rom_caps;
 	struct rom_curve_caps ogam_rom_caps;
 };
@@ -617,6 +626,7 @@ struct dc_config {
 	bool unify_link_enc_assignment;
 	bool enable_cursor_offload;
 	bool dp_connector_no_native_i2c;
+	unsigned int link_index_with_no_ddc;
 	bool frame_update_cmd_version2;
 	struct spl_sharpness_range dcn_sharpness_range;
 	struct spl_sharpness_range dcn_override_sharpness_range;
@@ -785,6 +795,7 @@ struct dc_clocks {
 	 */
 	bool fw_based_mclk_switching;
 	bool fw_based_mclk_switching_shut_down;
+	bool alt_ch_pstate_switch;
 	int prev_num_ways;
 	enum dtm_pstate dtm_level;
 	int max_supported_dppclk_khz;
@@ -795,6 +806,18 @@ struct dc_clocks {
 	int idle_fclk_khz;
 	int subvp_prefetch_dramclk_khz;
 	int subvp_prefetch_fclk_khz;
+	/* deprecated: use _KBps variants — will be removed after DML update */
+	unsigned int utm_urgent_bandwidth_lb_Kbps;
+	unsigned int utm_nominal_bandwidth_lb_Kbps;
+	unsigned int utm_urgent_bandwidth_lb_KBps;
+	unsigned int utm_nominal_bandwidth_lb_KBps;
+	unsigned int utm_latency_ub_index;
+	unsigned int utm_lsdma_bandwidth_lb_KBps;
+	unsigned int utm_nominal_max_latency_ub_ns;
+	unsigned int utm_nominal_avg_latency_ub_ns;
+	/* deprecated: use _KBps variant — will be removed after DML update */
+	unsigned int required_avg_active_bandwidth_Kbps;
+	unsigned int required_avg_active_bandwidth_KBps;
 
 	/* Stutter efficiency is technically not clock values
 	 * but stored here so the values are part of the update_clocks call similar to num_ways
@@ -1739,7 +1762,7 @@ struct dc_plane_state {
 	bool adaptive_sharpness_en;
 	int adaptive_sharpness_policy;
 	unsigned int sharpness_level;
-	enum linear_light_scaling linear_light_scaling;
+	enum dc_scaling_linearity scaling_linearity;
 	unsigned int sdr_white_level_nits;
 	struct cm_hist_control cm_hist_control;
 	struct spl_sharpness_range sharpness_range;
@@ -1763,6 +1786,7 @@ struct dc_plane_info {
 	bool input_csc_enabled;
 	unsigned int layer_index;
 	enum chroma_cositing cositing;
+	enum dc_scaling_linearity scaling_linearity;
 };
 
 #include "dc_stream.h"
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
index 80a21d7cae90..47fa3d4265e0 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -2431,3 +2431,47 @@ void dc_dmub_srv_log_preos_dmcub_info(struct dc_dmub_srv *dc_dmub_srv)
 		DC_LOG_DEBUG("fb_offset					: 0x%016llx", dmub->preos_info.fb_offset);
 	}
 }
+
+bool dc_dmub_srv_ihc_set_dig_hdcp_interrupt_dest(
+	struct dc_dmub_srv *dc_dmub_srv,
+	uint8_t dig_id,
+	bool to_dmu)
+{
+	union dmub_rb_cmd cmd;
+
+	if (!dc_dmub_srv || !dc_dmub_srv->dmub)
+		return false;
+
+	memset(&cmd, 0, sizeof(cmd));
+
+	cmd.ihc.header.type = DMUB_CMD__IHC;
+	cmd.ihc.header.sub_type = DMUB_CMD__IHC_SET_DIG_HDCP_INTERRUPT_DEST;
+	cmd.ihc.header.payload_bytes = sizeof(cmd.ihc.data);
+
+	cmd.ihc.data.dig_id = dig_id;
+	cmd.ihc.data.to_dmu = to_dmu ? 1 : 0;
+
+	dc_wake_and_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+
+	return true;
+}
+
+void dc_dmub_srv_get_fams2_debug_meta(struct dc_dmub_srv *dc_dmub_srv)
+{
+	union dmub_rb_cmd cmd;
+
+	memset(&cmd, 0, sizeof(cmd));
+
+	cmd.ib_fams2_debug_meta.header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH;
+	cmd.ib_fams2_debug_meta.header.sub_type = DMUB_CMD__FAMS2_IB_DEBUG_META;
+
+	cmd.ib_fams2_debug_meta.ib_data.src.quad_part = dc_dmub_srv->dmub->ib_mem_gart.gpu_addr;
+	cmd.ib_fams2_debug_meta.ib_data.size = dc_dmub_srv->dmub->ib_mem_gart.size > 0xFFFF ?
+			0xFFFF : (uint16_t)dc_dmub_srv->dmub->ib_mem_gart.size;
+
+	/* flush any existing writes to the buffer to prevent conflicts */
+	dmub_srv_flush_buffer_mem(dc_dmub_srv->dmub, &dc_dmub_srv->dmub->ib_mem_gart);
+
+	dm_execute_dmub_cmd_list(dc_dmub_srv->ctx, 1, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
index 8bdaac0b0f98..6d15ed77c17d 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
@@ -401,4 +401,27 @@ void dc_dmub_srv_release_hw(const struct dc *dc);
  * @dc - pointer to DC object
  */
 void dc_dmub_srv_log_preos_dmcub_info(struct dc_dmub_srv *dc_dmub_srv);
+
+/**
+ * dc_dmub_srv_ihc_set_dig_hdcp_interrupt_dest() - Configure IHC interrupt destination.
+ * @dc_dmub_srv: DMUB service handle
+ * @dig_id: DIG engine ID (0-3)
+ * @to_dmu: Route interrupt to DMU (true) or not (false)
+ *
+ * Sends command to DMUB firmware to configure IHC interrupt routing
+ * for HDCP I2C transfer requests.
+ *
+ * Return: true on success, false on failure
+ */
+bool dc_dmub_srv_ihc_set_dig_hdcp_interrupt_dest(
+	struct dc_dmub_srv *dc_dmub_srv,
+	uint8_t dig_id,
+	bool to_dmu);
+
+/**
+ * dc_dmub_srv_get_fams2_debug_meta() - Queries for FAMS2 debug metadata from DMUB and logs it.
+ *
+ * @dc_dmub_srv - pointer to DMUB service object
+ */
+void dc_dmub_srv_get_fams2_debug_meta(struct dc_dmub_srv *dc_dmub_srv);
 #endif /* _DMUB_DC_SRV_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c
index cc7fea613d9e..c1d9c3ef0a4b 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c
@@ -530,6 +530,8 @@ char *dce_version_to_string(const int version)
 		return "DCN 4.2";
 	case DCN_VERSION_4_2B:
 		return "DCN 4.2B";
+	case DCN_VERSION_6_0:
+		return "DCN 6.0";
 	default:
 		return "Unknown";
 	}
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
index a0272ee92285..aeac5a45e13b 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -205,9 +205,32 @@ enum surface_pixel_format {
 	SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb,
 	SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr,
 	SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb,
+	/* Planar 422 Formats*/
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P208, // 8 bpc
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P208, // 8 bpc
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P210, // 10 bpc
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P210, // 10 bpc
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P212, // 12 bpc
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P212, // 12 bpc
 	SURFACE_PIXEL_FORMAT_SUBSAMPLE_END,
 	SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010 =
 		SURFACE_PIXEL_FORMAT_SUBSAMPLE_END,
+	/* packed 422 formats, they should reside here as the necessity for programming chroma parameters are determined wrt SURFACE_PIXEL_FORMAT_SUBSAMPLE_END*/
+	/* Packed 422 Format, 8bpc*/
+	SURFACE_PIXEL_FORMAT_VIDEO_422_YCrYCb,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_YCbYCr,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CrYCbY,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CbYCrY,
+	/* Packed 422 Format, 10bpc*/
+	SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCrYCb,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCbYCr,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CrYCbY,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CbYCrY,
+	/* Packed 422 Format, 12bpc*/
+	SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCrYCb,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCbYCr,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CrYCbY,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CbYCrY,
 	SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102,
 	SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888,
 	SURFACE_PIXEL_FORMAT_INVALID
@@ -230,13 +253,19 @@ enum dc_pixel_format {
 	/*video*/
 	PIXEL_FORMAT_420BPP8,
 	PIXEL_FORMAT_420BPP10,
+	// Align with SPL formats
+	PIXEL_FORMAT_422BPP8,
+	PIXEL_FORMAT_422BPP10,
+	PIXEL_FORMAT_422BPP12,
+	PIXEL_FORMAT_444BPP8,
+	PIXEL_FORMAT_444BPP10,
 	/*end of pixel format definition*/
 	PIXEL_FORMAT_INVALID,
 
 	PIXEL_FORMAT_GRPH_BEGIN = PIXEL_FORMAT_INDEX8,
 	PIXEL_FORMAT_GRPH_END = PIXEL_FORMAT_FP16,
 	PIXEL_FORMAT_VIDEO_BEGIN = PIXEL_FORMAT_420BPP8,
-	PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_420BPP10,
+	PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_444BPP10,
 	PIXEL_FORMAT_UNKNOWN
 };
 
@@ -651,6 +680,7 @@ struct dc_cursor_attributes {
 	enum dc_rotation_angle rotation_angle;
 
 	union dc_cursor_attribute_flags attribute_flags;
+	bool force_cursor_to_disp_pref;
 };
 
 struct dpp_cursor_attributes {
@@ -1249,5 +1279,26 @@ struct cm_hist {
 	uint32_t ch2[256];
 	uint32_t ch3[256];
 };
+
+enum pregam_mode {
+	PREGAM_BYPASS = 0,
+	PREGAM_DEGAM,
+	PREGAM_REGAM
+};
+
+enum degam_lut {
+	DEGAM_SRGB = 0,
+	DEGAM_GAMMA_22,
+	DEGAM_GAMMA_24,
+	DEGAM_GAMMA_26,
+	DEGAM_BT2020,
+	DEGAM_BT2100PQ,
+	DEGAM_BT2100HLG
+};
+
+enum regam_lut {
+	REGAM_20 = 0,
+	REGAM_24
+};
 #endif /* DC_HW_TYPES_H */
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
index bc55f10fba7c..76c0d62031b6 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
@@ -16,6 +16,9 @@ static struct spl_callbacks dcn32_spl_callbacks = {
 static struct spl_callbacks dcn401_spl_callbacks = {
 	.spl_calc_lb_num_partitions = dscl401_spl_calc_lb_num_partitions,
 };
+static struct spl_callbacks dcn50_spl_callbacks = {
+	.spl_calc_lb_num_partitions = dscl401_spl_calc_lb_num_partitions,
+};
 static void populate_splrect_from_rect(struct spl_rect *spl_rect, const struct rect *rect)
 {
 	spl_rect->x = rect->x;
@@ -71,6 +74,23 @@ static void populate_splformat_from_format(enum spl_pixel_format *spl_pixel_form
 	else
 		*spl_pixel_format = SPL_PIXEL_FORMAT_INVALID;
 }
+static void set_linear_light_scaling_preference(const struct dc_plane_state *plane_state, struct spl_in *spl_in)
+{
+	if (plane_state != NULL) {
+		switch (plane_state->scaling_linearity) {
+		case DC_SCALING_LINEARITY_LINEAR:
+			spl_in->lls_pref = LLS_PREF_YES;
+			break;
+		case DC_SCALING_LINEARITY_SOURCE:
+			spl_in->lls_pref = LLS_PREF_NO;
+			break;
+		default:
+			spl_in->lls_pref = LLS_PREF_DONT_CARE;
+			break;
+		}
+	} else
+		spl_in->lls_pref = LLS_PREF_DONT_CARE;
+}
 /// @brief Translate SPL input parameters from pipe context
 /// @param pipe_ctx
 /// @param spl_in
@@ -94,6 +114,9 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl
 	case DCN_VERSION_4_2B:
 		spl_in->callbacks = dcn401_spl_callbacks;
 		break;
+	case DCN_VERSION_6_0:
+		spl_in->callbacks = dcn50_spl_callbacks;
+		break;
 	default:
 		spl_in->callbacks = dcn2_spl_callbacks;
 	}
@@ -189,7 +212,14 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl
 	if (pipe_ctx->stream->ctx->dc->debug.force_lls > 0)
 		spl_in->lls_pref = pipe_ctx->stream->ctx->dc->debug.force_lls;
 	else
-		spl_in->lls_pref = plane_state->linear_light_scaling;
+		if ((plane_state->ctx->dce_version == DCN_VERSION_4_01) ||
+			(plane_state->ctx->dce_version == DCN_VERSION_4_2) ||
+			(plane_state->ctx->dce_version == DCN_VERSION_4_2B))
+			spl_in->lls_pref = LLS_PREF_DONT_CARE;
+		else
+			set_linear_light_scaling_preference(plane_state, spl_in);
+	/* Translate upsampling mode*/
+	spl_in->upsp_mode = pipe_ctx->plane_res.scl_data.upsp;
 	/* Translate chroma subsampling offset ( cositing ) */
 	if (pipe_ctx->stream->ctx->dc->debug.force_cositing)
 		spl_in->basic_in.cositing = pipe_ctx->stream->ctx->dc->debug.force_cositing - 1;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_state_priv.h b/drivers/gpu/drm/amd/display/dc/dc_state_priv.h
index 1d9bae56ff6a..191bb431991f 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_state_priv.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_state_priv.h
@@ -125,4 +125,5 @@ bool dc_state_can_clear_stream_cursor_subvp_limit(const struct dc_stream_state *
 
 bool dc_state_is_subvp_in_use(struct dc_state *state);
 
+bool dc_state_is_alt_in_use(const struct dc *dc, const struct dc_state *state);
 #endif /* _DC_STATE_PRIV_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index 4530f294f1c2..934ae381e730 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -329,6 +329,9 @@ struct dc_stream_state {
 
 	enum dc_drr_trigger_mode drr_trigger_mode;
 
+
+	enum dc_blending_linearity blending_linearity;
+	struct dc_update_scratch_space *update_scratch;
 	bool firmware_controlled_hdr_info_packet;
 };
 
@@ -380,6 +383,8 @@ struct dc_stream_update {
 	bool *scaler_sharpener_update;
 	bool *sharpening_required;
 
+	enum dc_blending_linearity *blending_linearity;
+
 	enum dc_drr_trigger_mode *drr_trigger_mode;
 };
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index 3edeb94fba23..b14d882e08d4 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -389,6 +389,16 @@ struct dc_csc_adjustments {
 	struct fixed31_32 hue;
 };
 
+enum dc_scaling_linearity {
+	DC_SCALING_LINEARITY_LINEAR,
+	DC_SCALING_LINEARITY_SOURCE,
+};
+
+enum dc_blending_linearity {
+	DC_BLENDING_LINEARITY_LINEAR,
+	DC_BLENDING_LINEARITY_SOURCE,
+};
+
 /* Scaling format */
 enum scaling_transformation {
 	SCALING_TRANSFORMATION_UNINITIALIZED,
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h
index 088cf305a772..cecfb0a68030 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h
@@ -377,6 +377,13 @@
 	type OTG3_DROP_PIXEL;\
 	type RESYNC_FIFO_LEVEL_ADJUST_EN;
 
+#define DCCG60_REG_FIELD_LIST(type) \
+	type OTG_ADD_DROP_PIXEL_DONE;\
+	type DSCCLK0_SRC_SEL;\
+	type DSCCLK1_SRC_SEL;\
+	type DSCCLK2_SRC_SEL;\
+	type DSCCLK3_SRC_SEL;
+
 struct dccg_shift {
 	DCCG_REG_FIELD_LIST(uint8_t)
 	DCCG3_REG_FIELD_LIST(uint8_t)
@@ -386,6 +393,7 @@ struct dccg_shift {
 	DCCG35_REG_FIELD_LIST(uint8_t)
 	DCCG401_REG_FIELD_LIST(uint8_t)
 	DCCG42_REG_FIELD_LIST(uint8_t)
+	DCCG60_REG_FIELD_LIST(uint8_t)
 };
 
 struct dccg_mask {
@@ -397,6 +405,7 @@ struct dccg_mask {
 	DCCG35_REG_FIELD_LIST(uint32_t)
 	DCCG401_REG_FIELD_LIST(uint32_t)
 	DCCG42_REG_FIELD_LIST(uint32_t)
+	DCCG60_REG_FIELD_LIST(uint32_t)
 };
 
 #define DCCG_REG_VARIABLE_LIST \
@@ -511,6 +520,7 @@ struct dccg_mask {
 struct dccg_registers {
 	DCCG_REG_VARIABLE_LIST;
 	uint32_t OTG_ADD_DROP_PIXEL_CNTL;
+	uint32_t DSCCLK_SRC_SEL;
 };
 
 struct dcn_dccg {
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
index ecb8493ec523..e52fb7248a88 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -1496,6 +1496,13 @@ static const struct clock_source_funcs dcn401_clk_src_funcs = {
 	.get_dp_dto_frequency_100hz = dcn401_get_dp_dto_frequency_100hz
 };
 
+static const struct clock_source_funcs dcn50_clk_src_funcs = {
+	.cs_power_down = dce110_clock_source_power_down,
+	.program_pix_clk = dcn401_program_pix_clk,
+	.get_pix_clk_dividers = dcn3_get_pix_clk_dividers,
+	.get_dp_dto_frequency_100hz = dcn401_get_dp_dto_frequency_100hz
+};
+
 /*****************************************/
 /* Constructor                           */
 /*****************************************/
@@ -1924,6 +1931,23 @@ bool dcn401_clk_src_construct(
 
 	return ret;
 }
+
+bool dcn50_clk_src_construct(
+	struct dce110_clk_src *clk_src,
+	struct dc_context *ctx,
+	struct dc_bios *bios,
+	enum clock_source_id id,
+	const struct dce110_clk_src_regs *regs,
+	const struct dce110_clk_src_shift *cs_shift,
+	const struct dce110_clk_src_mask *cs_mask)
+{
+	bool ret = dce112_clk_src_construct(clk_src, ctx, bios, id, regs, cs_shift, cs_mask);
+
+	clk_src->base.funcs = &dcn50_clk_src_funcs;
+
+	return ret;
+}
+
 bool dcn301_clk_src_construct(
 	struct dce110_clk_src *clk_src,
 	struct dc_context *ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h
index 55c96b4b7765..6eca94e99d96 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h
@@ -339,6 +339,15 @@ bool dcn401_clk_src_construct(
 	const struct dce110_clk_src_regs *regs,
 	const struct dce110_clk_src_shift *cs_shift,
 	const struct dce110_clk_src_mask *cs_mask);
+bool dcn50_clk_src_construct(
+	struct dce110_clk_src *clk_src,
+	struct dc_context *ctx,
+	struct dc_bios *bios,
+	enum clock_source_id id,
+	const struct dce110_clk_src_regs *regs,
+	const struct dce110_clk_src_shift *cs_shift,
+	const struct dce110_clk_src_mask *cs_mask);
+
 /* this table is use to find *1.001 and /1.001 pixel rates from non-precise pixel rate */
 struct pixel_rate_range_table_entry {
 	unsigned int range_min_khz;
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h
index eedbd5d2756e..a99879c58027 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h
@@ -75,12 +75,14 @@ struct dcn10_link_enc_aux_registers {
 	uint32_t AUX_DPHY_RX_CONTROL0;
 	uint32_t AUX_DPHY_TX_CONTROL;
 	uint32_t AUX_DPHY_RX_CONTROL1;
+	uint32_t DC_GPIO_DDC;
 };
 
 struct dcn10_link_enc_hpd_registers {
 	uint32_t DC_HPD_CONTROL;
 	uint32_t DC_HPD_INT_STATUS;
 	uint32_t DC_HPD_TOGGLE_FILT_CNTL;
+	uint32_t HPD_CTRL;
 };
 
 struct dcn10_link_enc_registers {
@@ -171,6 +173,8 @@ struct dcn10_link_enc_registers {
 	uint32_t DIO_LINKF_CNTL;
 	uint32_t DIO_CLK_CNTL;
 	uint32_t DIG_BE_CLK_CNTL;
+	uint32_t HDCP_I2C_CONTROL_0;
+	uint32_t HDCP_INT_CONTROL;
 };
 
 #define LE_SF(reg_name, field_name, post_fix)\
@@ -508,12 +512,23 @@ struct dcn10_link_enc_registers {
 	type SYMCLKF_G_HDCP_GATE_DIS;\
 	type SYMCLKG_G_HDCP_GATE_DIS
 
+#define DCN60_LINK_ENCODER_REG_FIELD_LIST(type) \
+	type HDCP_I2C_DISABLE;\
+	type HDCP_I2C_DDC_SELECT;\
+	type HDCP_I2C_XFER_REQ_MASK;\
+	type AUX_PAD1_MODE;\
+	type HPD1_Y_POL_INVERT;\
+	type HPD2_Y_POL_INVERT;\
+	type HPD3_Y_POL_INVERT;\
+	type HPD4_Y_POL_INVERT
+
 struct dcn10_link_enc_shift {
 	DCN_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
 	DCN20_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
 	DCN30_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
 	DCN31_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
 	DCN35_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
+	DCN60_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
 };
 
 struct dcn10_link_enc_mask {
@@ -522,6 +537,7 @@ struct dcn10_link_enc_mask {
 	DCN30_LINK_ENCODER_REG_FIELD_LIST(uint32_t);
 	DCN31_LINK_ENCODER_REG_FIELD_LIST(uint32_t);
 	DCN35_LINK_ENCODER_REG_FIELD_LIST(uint32_t);
+	DCN60_LINK_ENCODER_REG_FIELD_LIST(uint32_t);
 };
 
 struct dcn10_link_encoder {
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c
index 2aaf06d48771..dad4ef565168 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c
@@ -384,6 +384,20 @@ enum signal_type dcn401_get_dig_mode(
 	}
 }
 
+void dcn401_setup_ri_pj_check_in_sw_or_hw_mode(
+	struct link_encoder *enc,
+	unsigned char aux_or_ddc_instance,
+	bool enable_sw_mode)
+{
+	struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+
+	REG_UPDATE_2(HDCP_I2C_CONTROL_0,
+			HDCP_I2C_DISABLE, enable_sw_mode,
+			HDCP_I2C_DDC_SELECT, aux_or_ddc_instance);
+
+	REG_UPDATE(HDCP_INT_CONTROL, HDCP_I2C_XFER_REQ_MASK, enable_sw_mode);
+}
+
 static const struct link_encoder_funcs dcn401_link_enc_funcs = {
 	.read_state = link_enc2_read_state,
 	.validate_output_with_stream =
@@ -423,6 +437,7 @@ static const struct link_encoder_funcs dcn401_link_enc_funcs = {
 	.get_txffe = dpcs401_get_txffe,
 	.set_txffe = dpcs401_set_txffe,
 	.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
+	.setup_ri_pj_check_in_sw_or_hw_mode = dcn401_setup_ri_pj_check_in_sw_or_hw_mode,
 	.get_hpd_state = dcn10_get_hpd_state,
 	.program_hpd_filter = dcn10_program_hpd_filter,
 };
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h
index a40c479fada8..62f8f9098b53 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h
@@ -104,6 +104,11 @@
 	LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\
 	LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh)
 
+#define LINK_ENCODER_MASK_SH_LIST_DCN60_ON_DCN401(mask_sh) \
+	LE_SF(DIG0_HDCP_I2C_CONTROL_0, HDCP_I2C_DISABLE, mask_sh),\
+	LE_SF(DIG0_HDCP_I2C_CONTROL_0, HDCP_I2C_DDC_SELECT, mask_sh),\
+	LE_SF(DIG0_HDCP_INT_CONTROL, HDCP_I2C_XFER_REQ_MASK, mask_sh)
+
 void dcn401_link_encoder_construct(
 	struct dcn20_link_encoder *enc20,
 	const struct encoder_init_data *init_data,
@@ -147,4 +152,9 @@ enum signal_type dcn401_get_dig_mode(
 bool dcn401_is_dig_enabled(struct link_encoder *enc);
 
 enum signal_type dcn401_get_dig_mode(struct link_encoder *enc);
+
+void dcn401_setup_ri_pj_check_in_sw_or_hw_mode(
+	struct link_encoder *enc,
+	unsigned char aux_or_ddc_instance,
+	bool enable_sw_mode);
 #endif /* __DC_LINK_ENCODER__DCN401_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h
index f5252931ce35..c887fdcba049 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h
@@ -203,6 +203,14 @@ void dm_helpers_mccs_vcp_set(
 #define EXPORT_IF_KUNIT(symbol)
 #endif
 
+bool dm_helpers_submit_i2c_over_aux(
+	struct ddc_service *ddc,
+	uint32_t address,
+	uint8_t offset,
+	uint8_t *cmdBuffer,
+	uint32_t len,
+	bool read);
+
 bool dm_helpers_dp_handle_test_pattern_request(
 		struct dc_context *ctx,
 		const struct dc_link *link,
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c
index 47164fa150d9..1b0d55e2d7b0 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c
@@ -40,10 +40,10 @@ static void dml21_populate_pmo_options(struct dml2_pmo_options *pmo_options,
 	pmo_options->force_mandatory_uclk_pstate_support = config->pmo.force_mandatory_uclk_pstate_support;
 }
 
-static enum dml2_project_id dml21_dcn_revision_to_dml2_project_id(enum dce_version dcn_version)
+static enum dml2_project_id dml21_dcn_revision_to_dml2_project_id(const struct dc *in_dc)
 {
 	enum dml2_project_id project_id;
-	switch (dcn_version) {
+	switch (in_dc->ctx->dce_version) {
 	case DCN_VERSION_4_01:
 		project_id = dml2_project_dcn4x_stage2_auto_drr_svp;
 		break;
@@ -51,6 +51,9 @@ static enum dml2_project_id dml21_dcn_revision_to_dml2_project_id(enum dce_versi
 	case DCN_VERSION_4_2B:
 		project_id = dml2_project_dcn42;
 		break;
+	case DCN_VERSION_6_0:
+		project_id = dml2_project_dcn6x_soc_var_a;
+		break;
 	default:
 		project_id = dml2_project_invalid;
 		DC_ERR("unsupported dcn version for DML21!");
@@ -64,7 +67,7 @@ void dml21_populate_dml_init_params(struct dml2_initialize_instance_in_out *dml_
 		const struct dml2_configuration_options *config,
 		const struct dc *in_dc)
 {
-	dml_init->options.project_id = dml21_dcn_revision_to_dml2_project_id(in_dc->ctx->dce_version);
+	dml_init->options.project_id = dml21_dcn_revision_to_dml2_project_id(in_dc);
 
 	if (config->use_native_soc_bb_construction) {
 		in_dc->soc_and_ip_translator->translator_funcs->get_soc_bb(&dml_init->soc_bb, in_dc, config);
@@ -75,6 +78,9 @@ void dml21_populate_dml_init_params(struct dml2_initialize_instance_in_out *dml_
 	}
 
 	dml21_populate_pmo_options(&dml_init->options.pmo_options, in_dc, config);
+
+	if (in_dc->clk_mgr && in_dc->clk_mgr->bw_params)
+		dml_init->overrides.explicit_qos_model = in_dc->clk_mgr->bw_params->utm_qos_model;
 }
 
 static unsigned int calc_max_hardware_v_total(const struct dc_stream_state *stream)
@@ -528,7 +534,6 @@ static void populate_dml21_surface_config_from_plane_state(
 	switch (plane_state->tiling_info.gfxversion) {
 	case DcGfxVersion7:
 	case DcGfxVersion8:
-		break;
 	case DcGfxVersion9:
 	case DcGfxVersion10:
 	case DcGfxVersion11:
@@ -606,6 +611,36 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm
 	case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
 		plane->pixel_format = dml2_rgbe_alpha;
 		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P208:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P208:
+		plane->pixel_format = dml2_422_planar_8;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P210:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P210:
+		plane->pixel_format = dml2_422_planar_10;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P212:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P212:
+		plane->pixel_format = dml2_422_planar_12;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_YCrYCb:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_YCbYCr:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrYCbY:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbYCrY:
+		plane->pixel_format = dml2_422_packed_8;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCrYCb:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCbYCr:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CrYCbY:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CbYCrY:
+		plane->pixel_format = dml2_422_packed_10;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCrYCb:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCbYCr:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CrYCbY:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CbYCrY:
+		plane->pixel_format = dml2_422_packed_12;
+		break;
 	default:
 		plane->pixel_format = dml2_444_32;
 		break;
@@ -640,6 +675,8 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm
 			plane->composition.scaler_info.enabled = true;
 	}
 
+	plane->composition.scaler_info.upsp_enabled = (scaler_data->upsp != UPSP_BYPASS);
+
 	/* always_scale is only used for debug purposes not used in production but has to be
 	 * maintained for certain complainces. */
 	if (plane_state->ctx->dc->debug.always_scale == true) {
@@ -836,6 +873,9 @@ static enum dml2_uclk_pstate_change_strategy dml21_force_pstate_method_to_uclk_s
 	case dml2_force_pstate_method_subvp:
 		val = dml2_uclk_pstate_change_strategy_force_mall_svp;
 		break;
+	case dml2_force_pstate_method_alternate:
+		val = dml2_uclk_pstate_change_strategy_force_alternate;
+		break;
 	case dml2_force_pstate_method_auto:
 	default:
 		val = dml2_uclk_pstate_change_strategy_auto;
@@ -952,6 +992,9 @@ void dml21_copy_clocks_to_dc_state(struct dml2_context *in_ctx, struct dc_state
 	context->bw_ctx.bw.dcn.clk.socclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.socclk_khz;
 	context->bw_ctx.bw.dcn.clk.subvp_prefetch_dramclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.svp_prefetch_no_throttle.uclk_khz;
 	context->bw_ctx.bw.dcn.clk.subvp_prefetch_fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.svp_prefetch_no_throttle.fclk_khz;
+	context->bw_ctx.bw.dcn.clk.utm_latency_ub_index = 0; /* TODO - derive from qos model */
+	context->bw_ctx.bw.dcn.clk.utm_nominal_bandwidth_lb_Kbps = (unsigned int) in_ctx->v21.mode_programming.programming->qos_bound.bandwidth_lb.dcn5.non_urgent_bandwidth_kbps;
+	context->bw_ctx.bw.dcn.clk.utm_urgent_bandwidth_lb_Kbps = (unsigned int) in_ctx->v21.mode_programming.programming->qos_bound.bandwidth_lb.dcn5.urgent_bandwidth_kbps;
 	context->bw_ctx.bw.dcn.clk.stutter_efficiency.base_efficiency = (uint8_t)in_ctx->v21.mode_programming.programming->stutter.base_percent_efficiency;
 	context->bw_ctx.bw.dcn.clk.stutter_efficiency.low_power_efficiency = (uint8_t)in_ctx->v21.mode_programming.programming->stutter.low_power_percent_efficiency;
 	context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_efficiency = (uint8_t)in_ctx->v21.mode_programming.programming->informative.power_management.z8.stutter_efficiency;
@@ -1060,6 +1103,9 @@ void dml21_set_dc_p_state_type(
 		else
 			pipe_ctx->p_state_type = P_STATE_FPO;
 		break;
+	case dml2_pstate_method_alternate:
+		pipe_ctx->p_state_type = P_STATE_ALT;
+		break;
 	default:
 		pipe_ctx->p_state_type = P_STATE_UNKNOWN;
 		break;
@@ -1087,6 +1133,9 @@ void dml21_init_min_clocks_for_dc_state(struct dml2_context *in_ctx, struct dc_s
 	min_clocks->subvp_prefetch_dramclk_khz = 0;
 	min_clocks->subvp_prefetch_fclk_khz = 0;
 	min_clocks->phyclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.phyclk.clk_values_khz[lowest_dpm_state_index];
+	min_clocks->utm_latency_ub_index = 0; /* TODO - derive from qos model */
+	min_clocks->utm_nominal_bandwidth_lb_Kbps = 0;
+	min_clocks->utm_urgent_bandwidth_lb_Kbps = 0;
 	min_clocks->stutter_efficiency.base_efficiency = 1;
 	min_clocks->stutter_efficiency.low_power_efficiency = 1;
 	min_clocks->stutter_efficiency.z8_stutter_efficiency = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c
index 012dff4cf3fa..1ade48b8b621 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c
@@ -375,6 +375,130 @@ void dml21_handle_phantom_streams_planes(const struct dc *dc, struct dc_state *c
 		dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, dc->current_state);
 }
 
+static uint32_t calc_svp_size_64kb(uint32_t total_size_bytes)
+{
+	return (total_size_bytes + 0xFFFF) >> 16;
+}
+
+static unsigned int dml21_build_fams2_stream_programming_v3(const struct dc *dc,
+		struct dc_state *context,
+		struct dml2_context *dml_ctx)
+{
+	int dml_stream_idx, dc_stream_idx, dc_plane_idx, svp_idx;
+	unsigned int dc_pipe_idx;
+	unsigned int num_fams2_streams = 0;
+	unsigned int svp_size_64kb[2] = {0};
+	struct pipe_ctx *pipe;
+
+	for (dc_stream_idx = 0; dc_stream_idx < context->stream_count; dc_stream_idx++) {
+		enum fams2_stream_type type = 0;
+
+		union dmub_cmd_fams2_config *static_base_state = &context->bw_ctx.bw.dcn.fams2_stream_base_params[num_fams2_streams];
+		struct dmub_fams2_cmd_alternate_stream_static_state *alternate_static_state;
+
+		struct dc_stream_state *stream = context->streams[dc_stream_idx];
+
+		if (context->stream_status[dc_stream_idx].plane_count == 0 ||
+				dml_ctx->config.svp_pstate.callbacks.get_stream_subvp_type(context, stream) == SUBVP_PHANTOM) {
+			/* can ignore blanked or phantom streams */
+			continue;
+		}
+
+		dml_stream_idx = dml21_helper_find_dml_pipe_idx_by_stream_id(dml_ctx, stream->stream_id);
+		if (dml_stream_idx < 0) {
+			ASSERT(dml_stream_idx >= 0);
+			continue;
+		}
+
+		/* copy static state from PMO */
+		memcpy(static_base_state,
+				&dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_base_params,
+				sizeof(union dmub_cmd_fams2_config));
+
+		memcpy(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2[num_fams2_streams],
+				&dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params_v2,
+				sizeof(union dmub_fams2_stream_static_sub_state_v2));
+
+		type = static_base_state->stream_v1.base.type;
+
+		/* get information from context */
+		ASSERT(context->stream_status[dc_stream_idx].plane_count >= 0 &&
+				context->stream_status[dc_stream_idx].plane_count <= 0xFF);
+		ASSERT(context->stream_status[dc_stream_idx].primary_otg_inst >= 0 &&
+				context->stream_status[dc_stream_idx].primary_otg_inst <= 0xFF);
+		static_base_state->stream_v1.base.num_planes = (uint8_t)context->stream_status[dc_stream_idx].plane_count;
+		static_base_state->stream_v1.base.otg_inst = (uint8_t)context->stream_status[dc_stream_idx].primary_otg_inst;
+
+		/* populate pipe masks for planes */
+		for (dc_plane_idx = 0; dc_plane_idx < context->stream_status[dc_stream_idx].plane_count; dc_plane_idx++) {
+			for (dc_pipe_idx = 0; dc_pipe_idx < dc->res_pool->pipe_count; dc_pipe_idx++) {
+				if (context->res_ctx.pipe_ctx[dc_pipe_idx].stream &&
+						context->res_ctx.pipe_ctx[dc_pipe_idx].stream->stream_id == stream->stream_id &&
+						context->res_ctx.pipe_ctx[dc_pipe_idx].plane_state == context->stream_status[dc_stream_idx].plane_states[dc_plane_idx]) {
+					static_base_state->stream_v1.base.pipe_mask |= (1 << dc_pipe_idx);
+					static_base_state->stream_v1.base.plane_pipe_masks[dc_plane_idx] |= (1 << dc_pipe_idx);
+				}
+			}
+		}
+
+		/* get per method programming */
+		switch (type) {
+		case FAMS2_STREAM_TYPE_VBLANK:
+		case FAMS2_STREAM_TYPE_VACTIVE:
+		case FAMS2_STREAM_TYPE_DRR:
+			break;
+		case FAMS2_STREAM_TYPE_ALTERNATE:
+			alternate_static_state = &context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2[num_fams2_streams].alternate;
+
+			for (dc_plane_idx = 0; dc_plane_idx < context->stream_status[dc_stream_idx].plane_count; dc_plane_idx++) {
+				for (dc_pipe_idx = 0; dc_pipe_idx < dc->res_pool->pipe_count; dc_pipe_idx++) {
+					pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx];
+					if (pipe->plane_state != context->stream_status[dc_stream_idx].plane_states[dc_plane_idx])
+						continue;
+					// TODO: Mapping between plane_idx within stream_res and plane_idx within alternate_stream_static_state
+					// should be matching, but it's better to have an explicit map / check (future improvement)
+					ASSERT(pipe->plane_res.scl_data.viewport.height >= 0 && pipe->plane_res.scl_data.viewport.height <= 0xFFFF);
+					ASSERT(pipe->plane_res.scl_data.viewport.width >= 0 && pipe->plane_res.scl_data.viewport.width <= 0xFFFF);
+					ASSERT(pipe->plane_res.scl_data.viewport.x >= 0 && pipe->plane_res.scl_data.viewport.x <= 0xFFFF);
+					ASSERT(pipe->plane_res.scl_data.viewport.y >= 0 && pipe->plane_res.scl_data.viewport.y <= 0xFFFF);
+					alternate_static_state->pipe_viewports[dc_pipe_idx].luma.height = (uint16_t)pipe->plane_res.scl_data.viewport.height;
+					alternate_static_state->pipe_viewports[dc_pipe_idx].luma.width = (uint16_t)pipe->plane_res.scl_data.viewport.width;
+					alternate_static_state->pipe_viewports[dc_pipe_idx].luma.x = (uint16_t)pipe->plane_res.scl_data.viewport.x;
+					alternate_static_state->pipe_viewports[dc_pipe_idx].luma.y = (uint16_t)pipe->plane_res.scl_data.viewport.y;
+					if (alternate_static_state->config[dc_plane_idx].bits.is_multi_planar) {
+						ASSERT(pipe->plane_res.scl_data.viewport_c.height >= 0 && pipe->plane_res.scl_data.viewport_c.height <= 0xFFFF);
+						ASSERT(pipe->plane_res.scl_data.viewport_c.width >= 0 && pipe->plane_res.scl_data.viewport_c.width <= 0xFFFF);
+						ASSERT(pipe->plane_res.scl_data.viewport_c.x >= 0 && pipe->plane_res.scl_data.viewport_c.x <= 0xFFFF);
+						ASSERT(pipe->plane_res.scl_data.viewport_c.y >= 0 && pipe->plane_res.scl_data.viewport_c.y <= 0xFFFF);
+						alternate_static_state->pipe_viewports[dc_pipe_idx].chroma.height = (uint16_t)pipe->plane_res.scl_data.viewport_c.height;
+						alternate_static_state->pipe_viewports[dc_pipe_idx].chroma.width = (uint16_t)pipe->plane_res.scl_data.viewport_c.width;
+						alternate_static_state->pipe_viewports[dc_pipe_idx].chroma.x = (uint16_t)pipe->plane_res.scl_data.viewport_c.x;
+						alternate_static_state->pipe_viewports[dc_pipe_idx].chroma.y = (uint16_t)pipe->plane_res.scl_data.viewport_c.y;
+					}
+					for (svp_idx = 0; svp_idx < 2; svp_idx++) {
+						alternate_static_state->pipe_copy_addr_47_16[svp_idx][dc_pipe_idx] =
+								dml_ctx->config.alt_ch_cfg.region_base_addr_47_16[svp_idx] + svp_size_64kb[svp_idx];
+						svp_size_64kb[svp_idx] += calc_svp_size_64kb(alternate_static_state->pipe_copy_max_size[svp_idx][dc_plane_idx]);
+						if (alternate_static_state->config[dc_plane_idx].bits.is_multi_planar) {
+							alternate_static_state->pipe_copy_addr_47_16_c[svp_idx][dc_pipe_idx] =
+									dml_ctx->config.alt_ch_cfg.region_base_addr_47_16[svp_idx] + svp_size_64kb[svp_idx];
+							svp_size_64kb[svp_idx] += calc_svp_size_64kb(alternate_static_state->pipe_copy_max_size_c[svp_idx][dc_plane_idx]);
+						}
+					}
+				}
+			}
+			break;
+		case FAMS2_STREAM_TYPE_SUBVP:
+		default:
+			ASSERT(false);
+			break;
+		}
+
+		num_fams2_streams++;
+	}
+
+	return num_fams2_streams;
+}
 
 static unsigned int dml21_build_fams2_stream_programming_v2(const struct dc *dc,
 		struct dc_state *context,
@@ -509,7 +633,9 @@ void dml21_build_fams2_programming(const struct dc *dc,
 
 	if (dml_ctx->v21.mode_programming.programming->fams2_required ||
 			dml_ctx->v21.mode_programming.programming->legacy_pstate_info_for_dmu) {
-		if (dc->debug.fams_version.major == 2) {
+		if (dc->debug.fams_version.major == 3) {
+			num_fams2_streams = dml21_build_fams2_stream_programming_v3(dc, context, dml_ctx);
+		} else if (dc->debug.fams_version.major == 2) {
 			num_fams2_streams = dml21_build_fams2_stream_programming_v2(dc, context, dml_ctx);
 		}
 	}
@@ -525,6 +651,7 @@ void dml21_build_fams2_programming(const struct dc *dc,
 
 	context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching =
 			(context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable != 0);
+	context->bw_ctx.bw.dcn.clk.alt_ch_pstate_switch = dc_state_is_alt_in_use(dc, context);
 }
 
 bool dml21_is_plane1_enabled(enum dml2_source_format_class source_format)
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h
index 79dfba54344c..f402bb933f7d 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h
@@ -102,6 +102,7 @@ enum dml2_uclk_pstate_change_strategy {
 	dml2_uclk_pstate_change_strategy_force_drr = 3,
 	dml2_uclk_pstate_change_strategy_force_mall_svp = 4,
 	dml2_uclk_pstate_change_strategy_force_mall_full_frame = 5,
+	dml2_uclk_pstate_change_strategy_force_alternate = 6,
 };
 
 enum dml2_svp_mode_override {
@@ -474,6 +475,15 @@ struct dml2_display_cfg {
 				bool value;
 			} force_nom_det_size_kbytes;
 
+			struct {
+				bool enable; // So copy time can be forced to 0
+				unsigned int copy_time_us;
+			} force_alt_chan_copy_time;
+
+			struct {
+				bool enable; // So fw delay can be forced to 0
+				unsigned int fw_delay_us;
+			} force_alt_chan_fw_delay;
 			bool mode_support_check_disable;
 			bool mcache_admissibility_check_disable;
 			bool surface_viewport_size_check_disable;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h
index 672b96a3da74..b830e95b27c8 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h
@@ -117,6 +117,7 @@ struct dml2_soc_power_management_parameters {
 	double g6_temp_read_blackout_us[DML_MAX_CLK_TABLE_SIZE];
 	double type_b_dram_clk_change_blackout_us;
 	double type_b_ppt_blackout_us;
+	unsigned int alternate_dram_carveout_size_mb; // size per aperture - assumed same for both apertures for now
 };
 
 struct dml2_clk_table {
@@ -213,6 +214,7 @@ struct dml2_ip_capabilities {
 	unsigned int ppt_max_allow_delay_us;
 	unsigned int temp_read_max_allow_delay_us;
 	unsigned int dummy_pstate_max_allow_delay_us;
+	unsigned int vblank_nom_default_us;
 	/* FAMS2 delays */
 	struct {
 		unsigned int max_allow_delay_us;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h
index f00ca2983ff5..bf71f4e1a451 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h
@@ -20,6 +20,12 @@ enum dml2_project_id {
 	dml2_project_dcn4x_stage2,
 	dml2_project_dcn4x_stage2_auto_drr_svp,
 	dml2_project_dcn42,
+	dml2_project_dcn4x_utm,
+	dml2_project_dcn5x,
+	dml2_project_dcn5x_utm,
+	dml2_project_dcn6x_soc_var_a,
+	dml2_project_dcn6x_soc_var_b,
+	dml2_project_dcn6x = dml2_project_dcn6x_soc_var_b,
 };
 
 enum dml2_pstate_change_support {
@@ -72,6 +78,10 @@ struct dml2_pmo_options {
 	bool disable_dyn_odm_for_multi_stream;
 	bool disable_dyn_odm_for_stream_with_svp;
 	bool force_mandatory_uclk_pstate_support;
+	bool disable_alternate_memory_training;
+	bool force_optional_uclk_pstate_support;
+	bool force_optional_mcache_support;
+	bool force_optional_ppt_temp_read_admissibility;
 	struct dml2_pmo_pstate_strategy *override_strategy_lists[DML2_MAX_PLANES];
 	unsigned int num_override_strategies_per_list[DML2_MAX_PLANES];
 };
@@ -81,6 +91,7 @@ struct dml2_options {
 	struct dml2_pmo_options pmo_options;
 };
 
+struct utm_qos_mode;
 
 struct dml2_initialize_instance_in_out {
 	struct dml2_instance *dml2_instance;
@@ -91,6 +102,7 @@ struct dml2_initialize_instance_in_out {
 	struct {
 		void *explicit_ip_bb;
 		unsigned int explicit_ip_bb_size;
+		const struct utm_qos_model *explicit_qos_model;
 	} overrides;
 };
 
@@ -214,6 +226,7 @@ enum dml2_pstate_method {
 	dml2_pstate_method_reserved_fw_drr_clamped = 20,
 	dml2_pstate_method_fw_drr = 21,
 	dml2_pstate_method_reserved_fw_drr_var = 22,
+	dml2_pstate_method_alternate,
 	dml2_pstate_method_count
 };
 
@@ -369,6 +382,36 @@ struct dml2_mode_support_info {
 	bool dcfclk_support;
 }; // dml2_mode_support_info
 
+struct dml2_memory_path_latency {
+	union {
+		struct {
+			double urgent_ramp;
+			double t_trip;
+			double meta_trip_to_mem;
+			double max_req_latency_urg;
+			double avg_req_latency_urg;
+			double max_req_latency_non_urg;
+			double avg_req_latency_non_urg;
+			double df_response_time_us;
+		} dcn5;
+	};
+};
+
+struct dml2_memory_path_bandwidth {
+	union {
+		struct {
+			double urgent_bandwidth_kbps; // kbytes per sec
+			double non_urgent_bandwidth_kbps; // kbytes per sec
+		} dcn5;
+	};
+};
+
+struct dml2_qos_bound {
+	struct dml2_memory_path_latency latency_ub;
+	struct dml2_memory_path_bandwidth bandwidth_lb;
+	double lsdma_bandwidth_lb_kbps;
+};
+
 struct dml2_display_cfg_programming {
 	struct dml2_display_cfg display_config;
 
@@ -418,6 +461,8 @@ struct dml2_display_cfg_programming {
 		} dcn4x;
 	} min_clocks;
 
+	struct dml2_qos_bound qos_bound;
+	unsigned int min_sop_index;
 	bool uclk_pstate_supported;
 	bool fclk_pstate_supported;
 
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
index 09452f3e49db..72acf12e9251 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
@@ -13094,6 +13094,7 @@ void dml2_core_calcs_get_stream_fams2_programming(const struct dml2_core_interna
 			(uint16_t)stream_pstate_meta->method_subvp.common.allow_end_otg_vline;
 		base_programming->config.bits.clamp_vtotal_min = true;
 		break;
+	case dml2_pstate_method_alternate:
 	case dml2_pstate_method_reserved_hw:
 	case dml2_pstate_method_reserved_fw:
 	case dml2_pstate_method_reserved_fw_drr_clamped:
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c
index 9f1222f5a835..0800c667f204 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c
@@ -4,6 +4,12 @@
 
 #include "dml2_core_factory.h"
 #include "dml2_core_dcn4.h"
+#include "dml2_core_dcn5_funcs_initialize.h"
+#include "dml2_core_dcn5_funcs_mode_support.h"
+#include "dml2_core_dcn5_funcs_mode_programming.h"
+#include "dml2_core_dcn6_funcs_initialize.h"
+#include "dml2_core_dcn6_funcs_mode_support.h"
+#include "dml2_core_dcn6_funcs_mode_programming.h"
 #include "dml2_external_lib_deps.h"
 
 bool dml2_core_create(enum dml2_project_id project_id, struct dml2_core_instance *out)
@@ -36,6 +42,25 @@ bool dml2_core_create(enum dml2_project_id project_id, struct dml2_core_instance
 		out->calculate_mcache_allocation = &core_dcn4_calculate_mcache_allocation;
 		result = true;
 		break;
+	case dml2_project_dcn5x_utm:
+		out->initialize = &dml2_core_dcn5_funcs_initialize;
+		out->validate_solution = &dml2_core_dcn5_funcs_validate_solution;
+		out->populate_programming = &dml2_core_dcn5_funcs_populate_programming;
+		out->populate_informative = &core_dcn4_populate_informative;
+		out->calculate_mcache_allocation = &core_dcn4_calculate_mcache_allocation;
+		result = true;
+		break;
+	case dml2_project_dcn6x_soc_var_a:
+	case dml2_project_dcn6x_soc_var_b:
+		out->initialize = &dml2_core_dcn6_funcs_initialize;
+		out->validate_solution = &dml2_core_dcn6_funcs_validate_solution;
+		out->populate_programming = &dml2_core_dcn6_funcs_populate_programming;
+		out->populate_informative = &core_dcn4_populate_informative;
+		out->calculate_mcache_allocation = &core_dcn4_calculate_mcache_allocation;
+		result = true;
+		break;
+	case dml2_project_dcn4x_utm:
+	case dml2_project_dcn5x:
 	case dml2_project_invalid:
 	default:
 		break;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h
index b8af72392176..8a371bd1a7a5 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h
@@ -14,6 +14,7 @@
 #define __DML2_CALCS_MAX_VRATIO_PRE_OTO__ 4.0 //<brief max vratio for one-to-one prefetch bw scheduling
 #define __DML2_CALCS_MAX_VRATIO_PRE_EQU__ 6.0 //<brief max vratio for equalized prefetch bw scheduling
 #define __DML2_CALCS_MAX_VRATIO_PRE__ 8.0 //<brief max prefetch vratio register limit
+#define __DML2_CALCS_MAX_VSTARTUP__ 1023.0 // <brief max vstartup lines supported by hardware
 
 #define __DML2_CALCS_DPP_INVALID__ 0
 #define __DML2_CALCS_DCFCLK_FACTOR__ 1.15 //<brief fudge factor for min dcfclk calclation
@@ -51,6 +52,7 @@ struct dml2_core_ip_params {
 	unsigned int max_vscl_taps;
 	unsigned int odm_combine_support_mask;
 	unsigned int num_dsc;
+	unsigned int maximum_dsc_slices_per_pipe;
 	unsigned int maximum_dsc_bits_per_component;
 	unsigned int maximum_pixels_per_line_per_dsc_unit;
 	bool dsc422_native_support;
@@ -86,6 +88,7 @@ struct dml2_core_ip_params {
 	unsigned int subvp_swath_height_margin_lines;
 	unsigned int subvp_fw_processing_delay_us;
 	unsigned int subvp_pstate_allow_width_us;
+	unsigned int alt_chan_fw_delay_us; // FW delay value required in mode support calculation
 	// MRQ
 	bool dcn_mrq_present;
 	unsigned int zero_size_buffer_entries;
@@ -96,6 +99,11 @@ struct dml2_core_ip_params {
 
 	unsigned int dchub_arb_to_ret_delay; // num of dcfclk
 	unsigned int hostvm_mode;
+	unsigned int fams2_max_allow_delay_us;
+	unsigned int fams2_min_allow_width_us;
+	unsigned int ppt_max_allow_delay_us;
+	unsigned int temp_read_max_allow_delay_us;
+	bool use_legacy_dsc_delay_formula;
 };
 
 struct dml2_core_internal_DmlPipe {
@@ -335,6 +343,7 @@ struct dml2_core_internal_mode_support_info {
 	double non_urg_bandwidth_required[dml2_core_internal_soc_state_max][dml2_core_internal_bw_max]; // same as urg_bandwidth, except not scaled by urg burst factor
 	double non_urg_bandwidth_required_flip[dml2_core_internal_soc_state_max][dml2_core_internal_bw_max];
 	bool avg_bandwidth_support_ok[dml2_core_internal_soc_state_max][dml2_core_internal_bw_max];
+	struct dml2_memory_path_bandwidth bandwidth_upper_bound;
 	double max_urgent_latency_us;
 	double max_non_urgent_latency_us;
 	double avg_non_urgent_latency_us;
@@ -348,6 +357,7 @@ struct dml2_core_internal_mode_support_info {
 	struct dml2_core_internal_watermarks watermarks;
 	bool dcfclk_support;
 	bool qos_bandwidth_support;
+	bool alternate_channel_size_support;
 };
 
 struct dml2_core_internal_mode_support {
@@ -535,6 +545,7 @@ struct dml2_core_internal_mode_support {
 	double DesiredOutputBpp[DML2_MAX_PLANES];
 	double PixelClockBackEnd[DML2_MAX_PLANES];
 	unsigned int DSCDelay[DML2_MAX_PLANES];
+	bool use_legacy_dsc_delay_formula;
 	enum dml2_core_internal_output_type OutputType[DML2_MAX_PLANES];
 	enum dml2_core_internal_output_type_rate OutputRate[DML2_MAX_PLANES];
 	bool TotalAvailablePipesSupportNoDSC;
@@ -654,6 +665,42 @@ struct dml2_core_internal_mode_support {
 	unsigned int DSTXAfterScaler[DML2_MAX_PLANES];
 
 	enum dml2_pstate_method uclk_pstate_switch_modes[DML2_MAX_PLANES];
+	unsigned int svp0_max_bytes;
+	unsigned int svp1_max_bytes;
+	unsigned int svp0_max_bytes_per_dpp[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane
+	unsigned int svp0_max_bytes_per_dpp_c[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane
+	unsigned int svp1_max_bytes_per_dpp[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane
+	unsigned int svp1_max_bytes_per_dpp_c[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane
+	unsigned int svp0_dst_lines[DML2_MAX_PLANES]; // per stream
+	unsigned int svp1_dst_lines[DML2_MAX_PLANES]; // per stream
+	unsigned int svp_req_limit[DML2_MAX_PLANES]; // per stream, should be the same value in time between all streams max(2 swaths, dst_y_pre) over all planes
+	unsigned int nom_req_limit_alt[DML2_MAX_PLANES];
+	unsigned int min_lead_dst_lines[DML2_MAX_PLANES];
+	unsigned int total_swaths[DML2_MAX_PLANES];
+	unsigned int total_swaths_c[DML2_MAX_PLANES];
+	unsigned int prefetch_swaths[DML2_MAX_PLANES];
+	unsigned int prefetch_swaths_c[DML2_MAX_PLANES];
+	double prefetch_hdl_delta[DML2_MAX_PLANES]; // in dst
+	double recout_hdl_delta[DML2_MAX_PLANES]; // in dst
+	double prefetch_hdl_delta_c[DML2_MAX_PLANES]; // in dst
+	double recout_hdl_delta_c[DML2_MAX_PLANES]; // in dst
+	unsigned int max_prefetch_in_lines[DML2_MAX_PLANES]; // max prefetch time over all planes converted to lines for the given stream
+	double lsdma_bw_req_for_alt_kbps;
+
+	// Synchronized timing group assignement
+	unsigned int timing_group_id[DML2_MAX_PLANES]; // timing group id for the given plane
+	unsigned int timing_group_count;
+
+	bool fclk_pstate_required;
+	bool ppt_pstate_required;
+	bool temp_read_pstate_required;
+	// P-state schedule windows
+	double fclk_pstate_allow_start_us[DML2_MAX_PLANES];
+	double fclk_pstate_allow_end_us[DML2_MAX_PLANES];
+	double ppt_pstate_allow_start_us[DML2_MAX_PLANES];
+	double ppt_pstate_allow_end_us[DML2_MAX_PLANES];
+	double temp_read_pstate_allow_start_us[DML2_MAX_PLANES];
+	double temp_read_pstate_allow_end_us[DML2_MAX_PLANES];
 };
 
 /// @brief A mega structure that houses various info for model programming step.
@@ -705,6 +752,7 @@ struct dml2_core_internal_mode_program {
 	double PSCL_THROUGHPUT[DML2_MAX_PLANES];
 	double PSCL_THROUGHPUT_CHROMA[DML2_MAX_PLANES];
 	unsigned int DSCDelay[DML2_MAX_PLANES];
+	bool use_legacy_dsc_delay_formula;
 	double DPPCLKUsingSingleDPP[DML2_MAX_PLANES];
 
 	unsigned int Read256BlockHeightY[DML2_MAX_PLANES];
@@ -845,6 +893,26 @@ struct dml2_core_internal_mode_program {
 	double df_response_time_us;
 
 	enum dml2_pstate_method uclk_pstate_switch_modes[DML2_MAX_PLANES];
+	unsigned int svp0_max_bytes;
+	unsigned int svp1_max_bytes;
+	unsigned int svp0_max_bytes_per_dpp[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane
+	unsigned int svp0_max_bytes_per_dpp_c[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane
+	unsigned int svp1_max_bytes_per_dpp[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane
+	unsigned int svp1_max_bytes_per_dpp_c[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane
+	unsigned int svp0_dst_lines[DML2_MAX_PLANES]; // per stream
+	unsigned int svp1_dst_lines[DML2_MAX_PLANES]; // per stream
+	unsigned int min_lead_dst_lines[DML2_MAX_PLANES]; // per stream, should be max(nominal_req_limit, vstartup_to_vactive). Does not have to be maxed over all planes
+	unsigned int svp_req_limit[DML2_MAX_PLANES]; // per stream, should be the same value in time between all streams max(2 swaths, dst_y_pre) over all planes
+	unsigned int nom_req_limit_alt[DML2_MAX_PLANES]; // per stream
+	unsigned int total_swaths[DML2_MAX_PLANES];
+	unsigned int total_swaths_c[DML2_MAX_PLANES];
+	unsigned int prefetch_swaths[DML2_MAX_PLANES];
+	unsigned int prefetch_swaths_c[DML2_MAX_PLANES];
+	double prefetch_hdl_delta[DML2_MAX_PLANES]; // in dst
+	double recout_hdl_delta[DML2_MAX_PLANES]; // in dst
+	double prefetch_hdl_delta_c[DML2_MAX_PLANES]; // in dst
+	double recout_hdl_delta_c[DML2_MAX_PLANES]; // in dst
+	unsigned int max_prefetch_in_lines[DML2_MAX_PLANES]; // max prefetch time over all planes converted to lines for the given stream
 	// -------------------
 	// Output
 	// -------------------
@@ -1281,6 +1349,7 @@ struct dml2_core_calcs_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport_local
 	double ActiveClockChangeLatencyHidingY;
 	double ActiveClockChangeLatencyHidingC;
 	double ActiveClockChangeLatencyHiding;
+	double peak_vactive_p_vblank_latency_hiding_us;
 	unsigned int dst_y_pstate;
 	unsigned int src_y_pstate_l;
 	unsigned int src_y_pstate_c;
@@ -2180,6 +2249,90 @@ struct dml2_core_calcs_calculate_mcache_setting_params {
 	bool *lc_comb_mcache;
 };
 
+
+struct dml2_core_calcs_calculate_alternate_lead_lines {
+	/* input params */
+	const struct dml2_display_cfg *display_cfg;
+	unsigned int *VStartup;
+	double *VActiveLatencyHidingUs;
+
+	/* output params */
+	unsigned int *min_lead_dst_lines;
+};
+
+struct dml2_core_calcs_calculate_alternate_svp_lines {
+	/* input params */
+	const struct dml2_display_cfg *display_cfg;
+	unsigned int *SwathHeightY;
+	unsigned int *SwathHeightC;
+	unsigned int *DETBufferSizeY;
+	double *BytePerPixelInDETC;
+	double dram_blackout_us;
+
+	/* output params */
+	unsigned int *svp0_dst_lines;
+	unsigned int *svp1_dst_lines;
+	unsigned int *svp_req_limit;
+};
+
+struct dml2_core_calcs_calculate_alternate_params {
+	/* input params */
+	const struct dml2_display_cfg *display_cfg;
+	double *dst_y_prefetch;
+	unsigned int *SwathHeightY;
+	unsigned int *SwathHeightC;
+	unsigned int *SwathWidthY;
+	unsigned int *SwathWidthC;
+	unsigned int *DETBufferSizeY;
+	unsigned int *DETBufferSizeC;
+	unsigned int *BytePerPixelY;
+	unsigned int *BytePerPixelC;
+	double *BytePerPixelInDETY;
+	double *BytePerPixelInDETC;
+	unsigned int *Read256BlockWidthY;
+	unsigned int *Read256BlockHeightY;
+	unsigned int *Read256BlockWidthC;
+	unsigned int *Read256BlockHeightC;
+	unsigned int *MacroTileWidthY;
+	unsigned int *MacroTileWidthC;
+	unsigned int *VInitPrefillY;
+	unsigned int *VInitPrefillC;
+	double *VRatioPrefetchY;
+	double *VRatioPrefetchC;
+	unsigned int *NoOfDPP;
+	unsigned int max_num_dpp;
+	double dram_blackout_us;
+	double *VActiveLatencyHidingUs;
+	unsigned int *svp0_dst_lines;
+	unsigned int *svp1_dst_lines;
+	unsigned int *svp_req_limit;
+	double dcn_non_urgent_bandwidth_kbps;
+	unsigned int alt_chan_fw_delay_us;
+	double *dst_y_per_vm_vblank;
+	double *dst_y_per_row_vblank;
+	unsigned int *DSTYAfterScaler;
+	enum dml2_odm_mode *ODMMode;
+
+	/* output params */
+	unsigned int *svp0_max_bytes;
+	unsigned int *svp1_max_bytes;
+	unsigned int *svp0_max_bytes_per_dpp;
+	unsigned int *svp0_max_bytes_per_dpp_c;
+	unsigned int *svp1_max_bytes_per_dpp;
+	unsigned int *svp1_max_bytes_per_dpp_c;
+	unsigned int *nom_req_limit_alt;
+	unsigned int *min_lead_dst_lines;
+	unsigned int *total_swaths;
+	unsigned int *total_swaths_c;
+	unsigned int *prefetch_swaths;
+	unsigned int *prefetch_swaths_c;
+	double *prefetch_hdl_delta;
+	double *recout_hdl_delta;
+	double *prefetch_hdl_delta_c;
+	double *recout_hdl_delta_c;
+	unsigned int *max_prefetch_in_lines;
+	double *lsdma_bw_req_for_alt_kbps;
+};
 struct dml2_core_calcs_calculate_tdlut_setting_params {
 	// input params
 	double dispclk_mhz;
@@ -2307,6 +2460,9 @@ struct dml2_core_internal_scratch {
 	struct dml2_core_shared_CalculateMetaAndPTETimes_params CalculateMetaAndPTETimes_params;
 	struct dml2_core_calcs_calculate_peak_bandwidth_required_params calculate_peak_bandwidth_params;
 	struct dml2_core_calcs_calculate_bytes_to_fetch_required_to_hide_latency_params calculate_bytes_to_fetch_required_to_hide_latency_params;
+	struct dml2_core_calcs_calculate_alternate_params calculate_alternate_params;
+	struct dml2_core_calcs_calculate_alternate_svp_lines calculate_alternate_svp_lines;
+	struct dml2_core_calcs_calculate_alternate_lead_lines calculate_alternate_lead_lines;
 };
 
 //struct dml2_svp_mode_override;
@@ -2331,6 +2487,7 @@ struct dml2_core_calcs_mode_support_ex {
 	const struct dml2_display_cfg *in_display_cfg;
 	const struct dml2_mcg_min_clock_table *min_clk_table;
 	int min_clk_index;
+	const struct dml2_utm_soc_bb *utm_soc_bb;
 	//unsigned int in_state_index;
 	struct dml2_core_internal_mode_support_info *out_evaluation_info;
 	const enum dml2_pstate_method *uclk_pstate_switch_modes;
@@ -2344,6 +2501,9 @@ struct dml2_core_calcs_mode_programming_ex {
 	const struct dml2_mcg_min_clock_table *min_clk_table;
 	const struct core_display_cfg_support_info *cfg_support_info;
 	int min_clk_index;
+	const struct dml2_uclk_pstate_params *uclk_params;
+	const struct dml2_display_solution *solution;
+	const struct dml2_utm_soc_bb *utm_soc_bb;
 	struct dml2_display_cfg_programming *programming;
 };
 
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c
index be0517e10104..528ebadb87e1 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c
@@ -5,6 +5,7 @@
 #include "dml2_dpmm_factory.h"
 #include "dml2_dpmm_dcn4.h"
 #include "dml2_external_lib_deps.h"
+#include "dml2_dpmm_dcn5.h"
 
 static bool dummy_map_mode_to_soc_dpm(struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out *in_out)
 {
@@ -48,6 +49,17 @@ bool dml2_dpmm_create(enum dml2_project_id project_id, struct dml2_dpmm_instance
 		out->map_watermarks = &dpmm_dcn42_map_watermarks;
 		result = true;
 		break;
+	case dml2_project_dcn5x_utm:
+		out->map_mode_to_soc_dpm = &dpmm_dcn5_map_mode_to_soc_dpm;
+		result = true;
+		break;
+	case dml2_project_dcn6x_soc_var_a:
+	case dml2_project_dcn6x_soc_var_b:
+		/* dpmm is deprecated */
+		result = true;
+		break;
+	case dml2_project_dcn4x_utm:
+	case dml2_project_dcn5x:
 	case dml2_project_invalid:
 	default:
 		break;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c
index 270283332cc1..a1d63148b6e5 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c
@@ -36,6 +36,11 @@ bool dml2_mcg_create(enum dml2_project_id project_id, struct dml2_mcg_instance *
 		out->build_min_clock_table = &mcg_dcn42_build_min_clock_table;
 		result = true;
 		break;
+	case dml2_project_dcn4x_utm:
+	case dml2_project_dcn5x:
+	case dml2_project_dcn5x_utm:
+	case dml2_project_dcn6x_soc_var_a:
+	case dml2_project_dcn6x_soc_var_b:
 	case dml2_project_invalid:
 	default:
 		break;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c
index 8f481ef9316f..7ae02eccd598 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c
@@ -23,6 +23,11 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_1_display[] = {
 		.allow_state_increase = true,
 	},
 
+	// Even-Odd
+	{
+		.per_stream_pstate_method = { dml2_pstate_method_alternate, dml2_pstate_method_na, dml2_pstate_method_na, dml2_pstate_method_na },
+		.allow_state_increase = true,
+	},
 
 	// Then VBlank
 	{
@@ -54,6 +59,11 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_2_display[] = {
 		.allow_state_increase = true,
 	},
 
+	// Even-Odd
+	{
+		.per_stream_pstate_method = { dml2_pstate_method_alternate, dml2_pstate_method_alternate, dml2_pstate_method_na, dml2_pstate_method_na },
+		.allow_state_increase = true,
+	},
 
 	// Then VActive + VBlank
 	{
@@ -115,6 +125,11 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_3_display[] = {
 		.allow_state_increase = true,
 	},
 
+	// Even-Odd
+	{
+		.per_stream_pstate_method = { dml2_pstate_method_alternate, dml2_pstate_method_alternate, dml2_pstate_method_alternate, dml2_pstate_method_na },
+		.allow_state_increase = true,
+	},
 
 	// VActive + 1 VBlank
 	{
@@ -152,6 +167,11 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_4_display[] = {
 		.allow_state_increase = true,
 	},
 
+	// Even-Odd
+	{
+		.per_stream_pstate_method = { dml2_pstate_method_alternate, dml2_pstate_method_alternate, dml2_pstate_method_alternate, dml2_pstate_method_alternate },
+		.allow_state_increase = true,
+	},
 
 	// VActive + 1 VBlank
 	{
@@ -381,6 +401,7 @@ static enum dml2_pstate_method convert_strategy_to_drr_variant(const enum dml2_p
 	case dml2_pstate_method_reserved_fw:
 	case dml2_pstate_method_reserved_fw_drr_clamped:
 	case dml2_pstate_method_reserved_fw_drr_var:
+	case dml2_pstate_method_alternate:
 	case dml2_pstate_method_count:
 	case dml2_pstate_method_na:
 	default:
@@ -665,6 +686,7 @@ bool pmo_dcn4_fams2_initialize(struct dml2_pmo_initialize_in_out *in_out)
 	pmo->fams_params.v2.drr.refresh_rate_limit_min = 119;
 
 	pmo->options = in_out->options;
+	pmo->options->disable_alternate_memory_training = true;
 
 	/* generate permutations of p-state configs from base strategy list */
 	for (i = 0; i < PMO_DCN4_MAX_DISPLAYS; i++) {
@@ -1204,6 +1226,9 @@ enum dml2_pstate_method dcn4_uclk_pstate_strategy_override_to_pstate_method(cons
 	case dml2_uclk_pstate_change_strategy_force_mall_svp:
 		method = dml2_pstate_method_fw_svp;
 		break;
+	case dml2_uclk_pstate_change_strategy_force_alternate:
+		method = dml2_pstate_method_alternate;
+		break;
 	case dml2_uclk_pstate_change_strategy_force_mall_full_frame:
 	case dml2_uclk_pstate_change_strategy_auto:
 	default:
@@ -1233,6 +1258,9 @@ static enum dml2_uclk_pstate_change_strategy pstate_method_to_uclk_pstate_strate
 	case dml2_pstate_method_fw_drr:
 		override_strategy = dml2_uclk_pstate_change_strategy_force_drr;
 		break;
+	case dml2_pstate_method_alternate:
+		override_strategy = dml2_uclk_pstate_change_strategy_force_alternate;
+		break;
 	case dml2_pstate_method_reserved_hw:
 	case dml2_pstate_method_reserved_fw:
 	case dml2_pstate_method_reserved_fw_drr_clamped:
@@ -1291,6 +1319,7 @@ static struct dml2_pstate_per_method_common_meta *get_per_method_common_meta(
 		break;
 	case dml2_pstate_method_vblank:
 	case dml2_pstate_method_fw_vblank_drr:
+	case dml2_pstate_method_alternate:
 		stream_method_pstate_meta = &pmo->scratch.pmo_dcn4.stream_pstate_meta[stream_idx].method_vblank.common;
 		break;
 	case dml2_pstate_method_fw_svp:
@@ -1609,6 +1638,8 @@ static bool validate_pstate_support_strategy_cofunctionality(struct dml2_pmo_ins
 	unsigned int vactive_stream_mask = 0;
 	unsigned int vblank_count = 0;
 	unsigned int vblank_stream_mask = 0;
+	unsigned int alternate_count = 0;
+	unsigned int alternate_stream_mask = 0;
 
 	bool strategy_matches_forced_requirements = true;
 	bool strategy_matches_drr_requirements = true;
@@ -1640,6 +1671,9 @@ static bool validate_pstate_support_strategy_cofunctionality(struct dml2_pmo_ins
 			pstate_strategy->per_stream_pstate_method[stream_index] == dml2_pstate_method_fw_vblank_drr) {
 			vblank_count++;
 			set_bit_in_bitfield(&vblank_stream_mask, stream_index);
+		} else if (pstate_strategy->per_stream_pstate_method[stream_index] == dml2_pstate_method_alternate) {
+			alternate_count++;
+			set_bit_in_bitfield(&alternate_stream_mask, stream_index);
 		}
 	}
 
@@ -1658,6 +1692,8 @@ static bool validate_pstate_support_strategy_cofunctionality(struct dml2_pmo_ins
 	if (svp_count > 0 && (pmo->options->disable_svp || !all_timings_support_svp(pmo, display_cfg, svp_stream_mask)))
 		return false;
 
+	if (alternate_count > 0 && pmo->options->disable_alternate_memory_training)
+		return false;
 
 	return is_config_schedulable(pmo, display_cfg, pstate_strategy);
 }
@@ -1989,6 +2025,25 @@ static void reset_display_configuration(struct display_configuation_with_meta *d
 	}
 }
 
+static void setup_planes_for_alternate_by_mask(struct display_configuation_with_meta *display_config,
+	struct dml2_pmo_instance *pmo,
+	int plane_mask)
+{
+	(void)pmo;
+	unsigned int plane_index;
+	struct dml2_plane_parameters *plane;
+
+	for (plane_index = 0; plane_index < display_config->display_config.num_planes; plane_index++) {
+		if (is_bit_set_in_bitfield(plane_mask, plane_index)) {
+			plane = &display_config->display_config.plane_descriptors[plane_index];
+
+			// Setup DRR
+			plane->overrides.uclk_pstate_change_strategy = dml2_uclk_pstate_change_strategy_force_alternate;
+
+			display_config->stage3.pstate_switch_modes[plane_index] = dml2_pstate_method_alternate;
+		}
+	}
+}
 
 static void setup_planes_for_drr_by_mask(struct display_configuation_with_meta *display_config,
 	struct dml2_pmo_instance *pmo,
@@ -2168,6 +2223,8 @@ static bool setup_display_config(struct display_configuation_with_meta *display_
 		} else if (scratch->pmo_dcn4.pstate_strategy_candidates[strategy_index].per_stream_pstate_method[stream_index] == dml2_pstate_method_fw_drr) {
 			fams2_required = true;
 			setup_planes_for_drr_by_mask(display_config, pmo, scratch->pmo_dcn4.stream_plane_mask[stream_index]);
+		} else if (scratch->pmo_dcn4.pstate_strategy_candidates[strategy_index].per_stream_pstate_method[stream_index] == dml2_pstate_method_alternate) {
+			setup_planes_for_alternate_by_mask(display_config, pmo, scratch->pmo_dcn4.stream_plane_mask[stream_index]);
 		}
 	}
 
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c
index 21109a19f177..44438792931c 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c
@@ -7,6 +7,8 @@
 #include "dml2_pmo_dcn3.h"
 #include "dml2_pmo_dcn42.h"
 #include "dml2_external_lib_deps.h"
+#include "dml2_pmo_dcn5.h"
+#include "dml2_pmo_dcn6.h"
 
 static bool dummy_init_for_stutter(struct dml2_pmo_init_for_stutter_in_out *in_out)
 {
@@ -94,6 +96,38 @@ bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance *
 		out->optimize_for_stutter = pmo_dcn4_fams2_optimize_for_stutter;
 		result = true;
 		break;
+	case dml2_project_dcn5x_utm:
+		out->initialize = dml2_pmo_dcn5_initialize;
+		out->get_ordered_mandatory_stage_optimizers = dml2_pmo_dcn5_get_ordered_mandatory_stage_optimizers;
+		out->get_ordered_optional_stage_optimizers = dml2_pmo_dcn5_get_ordered_optional_stages_optimizers;
+		out->initialize_worksheet = dml2_pmo_dcn5_initialize_worksheet;
+		out->optional_sanity_check = dml2_pmo_dcn5_sanity_check;
+		out->convert_worksheet_to_solution = dml2_pmo_dcn5_convert_worksheet_to_solution;
+		out->clear_pre_validation_states = dml2_pmo_dcn5_clear_pre_validation_states;
+		result = true;
+		break;
+	case dml2_project_dcn6x_soc_var_a:
+		out->initialize = dml2_pmo_dcn6a_initialize;
+		out->get_ordered_mandatory_stage_optimizers = dml2_pmo_dcn6a_get_ordered_mandatory_stage_optimizers;
+		out->get_ordered_optional_stage_optimizers = dml2_pmo_dcn6a_get_ordered_optional_stages_optimizers;
+		out->initialize_worksheet = dml2_pmo_dcn5_initialize_worksheet;
+		out->optional_sanity_check = dml2_pmo_dcn5_sanity_check;
+		out->convert_worksheet_to_solution = dml2_pmo_dcn6_convert_worksheet_to_solution;
+		out->clear_pre_validation_states = dml2_pmo_dcn5_clear_pre_validation_states;
+		result = true;
+		break;
+	case dml2_project_dcn6x_soc_var_b:
+		out->initialize = dml2_pmo_dcn6b_initialize;
+		out->get_ordered_mandatory_stage_optimizers = dml2_pmo_dcn6b_get_ordered_mandatory_stage_optimizers;
+		out->get_ordered_optional_stage_optimizers = dml2_pmo_dcn6b_get_ordered_optional_stages_optimizers;
+		out->initialize_worksheet = dml2_pmo_dcn5_initialize_worksheet;
+		out->optional_sanity_check = dml2_pmo_dcn5_sanity_check;
+		out->convert_worksheet_to_solution = dml2_pmo_dcn6_convert_worksheet_to_solution;
+		out->clear_pre_validation_states = dml2_pmo_dcn5_clear_pre_validation_states;
+		result = true;
+		break;
+	case dml2_project_dcn4x_utm:
+	case dml2_project_dcn5x:
 	case dml2_project_invalid:
 	default:
 		break;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c
index 04860b6790df..aaca0a450f0e 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c
@@ -5,6 +5,7 @@
 #include "dml_top.h"
 #include "dml2_internal_shared_types.h"
 #include "dml2_top_soc15.h"
+#include "dml2_top_utm.h"
 
 unsigned int dml2_get_instance_size_bytes(void)
 {
@@ -19,6 +20,12 @@ bool dml2_initialize_instance(struct dml2_initialize_instance_in_out *in_out)
 	case dml2_project_dcn4x_stage2_auto_drr_svp:
 	case dml2_project_dcn42:
 		return dml2_top_soc15_initialize_instance(in_out);
+	case dml2_project_dcn5x_utm:
+	case dml2_project_dcn6x_soc_var_a:
+	case dml2_project_dcn6x_soc_var_b:
+		return dml2_top_utm_initialize_instance(in_out);
+	case dml2_project_dcn4x_utm:
+	case dml2_project_dcn5x:
 	case dml2_project_invalid:
 	default:
 		return false;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h
index 3ae817ea2aad..a18f067fe53f 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h
@@ -8,6 +8,9 @@
 #include "dml2_external_lib_deps.h"
 #include "dml_top_types.h"
 #include "dml2_core_shared_types.h"
+#include "bounding_boxes/utm_qos_model_dchub_v1.h"
+#include "bounding_boxes/utm_qos_model_dchub_v2.h"
+#include "bounding_boxes/utm_qos_model_dchub_v3.h"
 /*
 * DML2 MCG Types and Interfaces
 */
@@ -69,6 +72,153 @@ struct dml2_mcg_build_min_clock_table_params_in_out {
 	*/
 	struct dml2_mcg_min_clock_table *min_clk_table;
 };
+
+struct dml2_soc_operating_point {
+	unsigned int uclk_khz;
+	unsigned int fclk_khz;
+	unsigned int dcfclk_khz;
+	unsigned int socclk_khz;
+};
+
+struct dml2_sop_constraint {
+	union {
+		struct {
+			unsigned int min_sop_index;
+			struct dml2_memory_path_latency latency;
+			struct dml2_soc_operating_point clocks;
+			double min_available_urgent_bandwidth_KBps; // minimum guaranteed urgent bandwidth at active
+		} dcn5;
+	};
+};
+
+struct dml2_sop_table {
+	bool is_initialized;
+	const struct utm_qos_model *model;
+	uint32_t sop_min_available_urgent_bandwidths_KBps[MAX_UTM_SOP_COUNT];
+	uint32_t sop_optimal_dcfclks_khz[MAX_UTM_SOP_COUNT];
+	unsigned int (*get_highest_sop_index)(const struct dml2_sop_table *sop_table);
+	void (*get_sop_constraint_at_index)(const struct dml2_sop_table *sop_table, unsigned int index, struct dml2_sop_constraint *constraint);
+	bool (*is_bw_supported_at_index)(const struct dml2_sop_table *sop_table, const struct dml2_memory_path_bandwidth *bw, unsigned int index);
+	void (*get_max_sop)(const struct dml2_sop_table *sop_table, struct dml2_soc_operating_point *sop);
+	void (*get_min_sop)(const struct dml2_sop_table *sop_table, struct dml2_soc_operating_point *sop);
+};
+
+struct dml2_utm_soc_bb {
+	struct dml2_sop_table sop_table;
+	struct dml2_soc_power_management_parameters power_management_parameters;
+	struct dml2_soc_vmin_clock_limits vmin_limit;
+	struct dml2_dram_params dram_config;
+	struct utm_qos_model qos_model;
+	union {
+		struct utm_qos_model_dchub_v1 qos_model_dchub_v1;
+		struct utm_qos_model_dchub_v2 qos_model_dchub_v2;
+		struct utm_qos_model_dchub_v3 qos_model_dchub_v3;
+	};
+	double lower_bound_bandwidth_dchub;
+	double fraction_of_urgent_bandwidth_nominal_target;
+	double fraction_of_urgent_bandwidth_flip_target;
+	unsigned int dchub_refclk_mhz;
+	unsigned int max_outstanding_reqs;
+	unsigned long return_bus_width_bytes;
+	double phy_downspread_percent;
+	double dcn_downspread_percent;
+	double nominal_sdp_derate_percent;
+	double urgent_sdp_derate_percent;
+	double dispclk_dppclk_vco_speed_mhz;
+	bool no_dfs;
+	unsigned int mem_word_bytes;
+	unsigned int num_dcc_mcaches;
+	unsigned int mcache_size_bytes;
+	unsigned int mcache_line_size_bytes;
+	unsigned int writeback_base_latency_us;
+	unsigned int max_dispclk_khz;
+	unsigned int max_dppclk_khz;
+	unsigned int max_dscclk_khz;
+	unsigned int max_dtbclk_khz;
+	unsigned int max_phyclk_khz;
+	unsigned int max_phyclk_d18_khz;
+	unsigned int max_phyclk_d32_khz;
+	unsigned int min_socclk_khz;
+	unsigned int max_dcfclk_khz;
+	unsigned int min_dcfclk_khz;
+	/* TODO: remove once DML Core no longer depends on max SOP clocks */
+	unsigned int max_uclk_khz;
+	unsigned int max_fclk_khz;
+};
+
+struct dml2_clock_granularity_adjuster;
+struct dml2_cga_initialize_in_out {
+	struct dml2_clock_granularity_adjuster *adjuster;
+	const struct dml2_soc_bb *soc_bb;
+	const struct dml2_core_ip_params *ip;
+};
+
+struct dml2_clock_granularity_adjuster {
+	double dcn_downspread_percent;
+	double dispclk_dppclk_vco_speed_mhz;
+	double dispclk_ramp_margin_percent;
+	double max_dispclk_mhz;
+	void (*initialize)(const struct dml2_cga_initialize_in_out *in_out);
+	double (*adjust_dispclk_mhz)(const struct dml2_clock_granularity_adjuster *adjuster, double dispclk_mhz);
+	void (*adjust_dppclks_mhz)(const struct dml2_clock_granularity_adjuster *adjuster, unsigned int count,
+			const double *dppclks_mhz, double *adjusted_dppclks_mhz, double *adjusted_dpprefclk_mhz);
+	void (*adjust_dtbclks_mhz)(const struct dml2_clock_granularity_adjuster *adjuster, unsigned int count,
+			const double *dtbclks_mhz, double *adjusted_dtbclks_mhz, double *adjusted_dtbrefclk_mhz);
+	double (*adjust_dcfclk_deepsleep_mhz)(const struct dml2_clock_granularity_adjuster *adjuster,
+			double dcfclk_deepsleep_mhz);
+};
+
+#define DML2_STATUS_LIST(FORMAT) \
+	/* Generic */ \
+	FORMAT(DML2_STATUS_OK) \
+	FORMAT(DML2_STATUS_UNKNOWN) \
+	/* Validate */ \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_MODE_SUPPORT) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_MODE_SUPPORT_PREFETCH) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_MODE_SUPPORT_PREFETCH_URGENT) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_MODE_SUPPORT_QOS_BANDWIDTH) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_MODE_SUPPORT_DCFCLK) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_PREFETCH) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_MCACHE) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_PMO_SANITY_TOTAL_PIPE_USAGE) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_PMO_SANITY_ODM_DIVISIBILITY) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_PSTATE_SCHEDULE) \
+	FORMAT(DML2_STATUS_PSTATE_UNEXPECTED_PSTATE) \
+	FORMAT(DML2_STATUS_PSTATE_NOT_ADMISSIBLE) \
+	/* Optimize */ \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_MCACHE) \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_UCLK_PSTATE) \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_QOS) \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_VMIN) \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_STUTTER) \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_FCLK_PSTATE_UNSYNCHRONIZABLE_TIMINGS) \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_FCLK_PSTATE_INSUFFICENT_HIDING) \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_VMIN_DCFCLK) \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_EXCEED_MAX_ITERATION) \
+	/* Populate */ \
+	FORMAT(DML2_STATUS_POPULATE_FAIL_MIN_CLOCK_STATE) \
+	FORMAT(DML2_STATUS_POPULATE_FAIL_PROGRAMMING) \
+	FORMAT(DML2_STATUS_POPULATE_FAIL_PROGRAMMING_PREFETCH) \
+	FORMAT(DML2_STATUS_POPULATE_FAIL_PROGRAMMING_PREFETCH_URGENT) \
+	FORMAT(DML2_STATUS_POPULATE_FAIL_PROGRAMMING_FLIP_BANDWIDTH) \
+	FORMAT(DML2_STATUS_POPULATE_FAIL_PROGRAMMING_DCFCLK)
+
+#define ENUM_FORMAT(entry) entry,
+#define CASE_FORMAT(entry) case entry: return #entry;
+
+enum dml2_status {
+	DML2_STATUS_LIST(ENUM_FORMAT)
+};
+
+static inline const char *dml2_status_str(enum dml2_status status)
+{
+	switch (status) {
+		DML2_STATUS_LIST(CASE_FORMAT)
+	}
+
+	return "";
+}
+
 struct dml2_mcg_instance {
 	bool (*build_min_clock_table)(struct dml2_mcg_build_min_clock_table_params_in_out *in_out);
 };
@@ -85,6 +235,8 @@ struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out {
 	struct dml2_soc_bb *soc_bb;
 	struct dml2_mcg_min_clock_table *min_clk_table;
 	const struct display_configuation_with_meta *display_cfg;
+	const struct dml2_utm_soc_bb *utm_soc_bb;
+	const struct dml2_display_solution *solution;
 	struct {
 		bool perform_pseudo_map;
 		struct dml2_core_internal_soc_bb *soc_bb;
@@ -101,6 +253,7 @@ struct dml2_dpmm_map_watermarks_params_in_out {
 	* Input
 	*/
 	const struct display_configuation_with_meta *display_cfg;
+	const struct dml2_display_solution *solution;
 	const struct dml2_core_instance *core;
 
 	/*
@@ -131,6 +284,8 @@ struct dml2_core_initialize_in_out {
 	struct dml2_ip_capabilities *ip_caps;
 
 	struct dml2_mcg_min_clock_table *minimum_clock_table;
+	const struct dml2_utm_soc_bb *utm_soc_bb;
+	const struct dml2_clock_granularity_adjuster *clock_adjuster;
 
 	void *explicit_ip_bb;
 	unsigned int explicit_ip_bb_size;
@@ -169,6 +324,11 @@ struct core_stream_support_info {
 	int vblank_reserved_time_us;
 	int num_dsc_slices;
 	bool dsc_enable;
+	unsigned int alternate_svp0_dst_lines;
+	unsigned int alternate_svp1_dst_lines;
+	unsigned int max_vstartup_lines;
+	unsigned int max_dst_y_after_scaler;
+	unsigned int max_dst_y_prefetch;
 };
 
 struct core_display_cfg_support_info {
@@ -210,6 +370,9 @@ struct dml2_core_mode_support_result {
 
 		unsigned int uclk_pstate_supported;
 		unsigned int fclk_pstate_supported;
+		unsigned int alternate_total_bytes_copy_svp0;
+		unsigned int alternate_total_bytes_copy_svp1;
+		unsigned int lsdma_bw_req_for_alt_kbps;
 		struct dml2_core_internal_watermarks watermarks;
 	} global;
 
@@ -226,6 +389,7 @@ struct dml2_core_mode_support_result {
 	} per_plane[DML2_MAX_PLANES];
 
 	struct core_display_cfg_support_info cfg_support_info;
+	struct dml2_memory_path_bandwidth bandwidth_upper_bound;
 };
 
 struct dml2_optimization_stage1_state {
@@ -305,6 +469,11 @@ struct dml2_pstate_meta {
 		unsigned long phantom_vtotal;
 		struct dml2_pstate_per_method_common_meta common;
 	} method_subvp;
+	struct {
+		int programming_delay_otg_vlines; // DMCUB <-> PMFW delays + any DMCUB/PMFW programming delays required
+		int pmfw_throttle_delay_otg_vlines; // PMFW time it takes to throttle other clients + assert DF P-State allow
+		struct dml2_pstate_per_method_common_meta common;
+	} method_alternate;
 	struct {
 		int programming_delay_otg_vlines;
 		int stretched_vtotal;
@@ -379,6 +548,203 @@ struct dml2_pmo_pstate_strategy {
 	enum dml2_pstate_method per_stream_pstate_method[DML2_MAX_PLANES];
 	bool allow_state_increase;
 };
+
+struct dml2_validation_result {
+	bool is_mode_support_valid;
+	bool is_prefetch_valid;
+	struct dml2_core_mode_support_result mode_support;
+	bool is_mcache_allocation_valid;
+	struct dml2_mcache_surface_allocation mcache_allocations[DML2_MAX_PLANES];
+};
+
+struct dml2_optimization_change {
+	union {
+		struct {
+			bool sop_index				: 1; // bit 0
+			bool mpc_combine_overrides		: 1;
+			bool odm_combine_overrides		: 1;
+			bool reserved_vblank_time		: 1;
+			bool mcache_allocation			: 1;
+			bool uclk_pstate_method			: 1;
+			bool fclk_pstate_support		: 1;
+			bool stutter_support			: 1;
+			bool dcfclk_override			: 1; // bit 8
+			bool ppt_temp_read_pstate_support	: 1;
+			unsigned char reserved			: 6;
+		} bits;
+		unsigned short raw;
+	};
+};
+
+struct dml2_optimization_worksheet {
+	const struct dml2_display_cfg *orig_dispcfg;
+
+	unsigned int timing_group_ids[DML2_MAX_PLANES]; // per plane
+	unsigned int timing_group_count;
+
+	struct {
+		bool is_default_pipe_usage_attempted;
+		bool is_single_stream_odm_case;
+		bool per_plane_status[DML2_MAX_PLANES];
+		struct {
+			int pipe_vp_startx[DML2_MAX_DCN_PIPES];
+			int pipe_vp_endx[DML2_MAX_DCN_PIPES];
+		} plane0;
+		struct {
+			int pipe_vp_startx[DML2_MAX_DCN_PIPES];
+			int pipe_vp_endx[DML2_MAX_DCN_PIPES];
+		} plane1;
+	} mcache;
+
+	struct {
+		unsigned int stream_plane_mask[DML2_MAX_PLANES];
+
+		struct dml2_pstate_meta stream_pstate_meta[DML2_MAX_PLANES]; // per stream
+
+		// Meta-data for implicit SVP generation, indexed by stream index
+		struct dml2_implicit_svp_meta stream_svp_meta[DML2_MAX_PLANES];
+
+		struct dml2_pmo_pstate_strategy pstate_strategy_candidates[DML2_PMO_PSTATE_CANDIDATE_LIST_SIZE];
+		int num_pstate_candidates;
+		int cur_pstate_candidate;
+
+		// Initial value of reserved vblank time as pstate optimize may overwrite and clear current
+		long init_reserved_vblank_time_ns[DML2_MAX_PLANES];
+		unsigned int init_max_vactive_det_fill_delay_us[DML2_MAX_PLANES]; // per plane
+	} uclk_pstate;
+
+	struct {
+		bool is_initialized;
+		bool unoptimizable_streams[DML2_MAX_DCN_PIPES];
+		unsigned int init_odms_used[DML2_MAX_DCN_PIPES];
+	} vmin;
+
+	struct {
+		long init_reserved_vblank_time_ns[DML2_MAX_PLANES];
+		bool should_optimize_z8_stutter;
+		bool is_z8_stutter_attempted;
+		bool should_optimize_stutter;
+		bool is_stutter_attempted;
+	} stutter;
+
+	struct {
+		unsigned int passing_index;
+		unsigned int failing_index;
+		bool is_index0_tested;
+	} qos;
+
+	struct {
+		double max_available_bandwidth_kbps;
+	} dcfclk_vmin;
+
+	struct {
+		bool is_attempted;
+	} fclk_ppt_temp_read_pstate;
+
+	/*
+	 * unified structure for storing current optimization tuning variables. Please only store the final tuning knobs
+	 * we should see exactly what will be optimized in display solution at a quick glance.
+	 */
+	struct dml2_optimization_config {
+		struct  {
+			unsigned int min_sop_index;
+			unsigned int mpc_combine_overrides[DML2_MAX_PLANES]; // per plane
+			unsigned int odm_combine_overrides[DML2_MAX_PLANES]; // per stream
+			long reserved_vblank_time_ns[DML2_MAX_PLANES];
+			struct dml2_mcache_surface_allocation mcache_allocations[DML2_MAX_PLANES];
+
+			bool uclk_pstate_support;
+			enum dml2_pstate_method uclk_pstate_switch_modes[DML2_MAX_PLANES]; // per plane
+			int max_vactive_det_fill_delay_us[DML2_MAX_PLANES][dml2_pstate_type_count]; // per plane
+			// Meta-data for FAMS2
+			bool fams2_required;
+			bool legacy_pstate_info_for_dmu;
+			struct dml2_pstate_meta stream_pstate_meta[DML2_MAX_PLANES]; // per stream
+			bool fclk_pstate_support;
+			bool ppt_temp_read_support;
+			bool stutter_support_in_vblank;
+			bool z8_stutter_support_in_vblank;
+			bool enable_vmin_dcfclk;
+		} config;
+		/* changes that have not yet been validated */
+		struct dml2_optimization_change unvalidated_change;
+	} cur;
+
+	/* post validation */
+	struct dml2_validation_result validation_result;
+};
+
+struct dml2_display_solution {
+	const struct dml2_display_cfg *orig_dispcfg;
+
+	/* current display configuration */
+	struct dml2_display_cfg dispcfg;
+	unsigned int timing_group_ids[DML2_MAX_PLANES]; // per plane
+	unsigned int timing_group_count;
+
+	/* additional DML internally decided configurations */
+	struct dml2_sop_constraint sop_constraint;
+	struct dml2_mcache_surface_allocation mcache_allocations[DML2_MAX_PLANES];
+	struct dml2_uclk_pstate_params {
+		bool support;
+		/* Uclk pstate related*/
+		enum dml2_pstate_method pstate_switch_modes[DML2_MAX_PLANES];
+		// Meta-data for FAMS2
+		bool fams2_required;
+		bool legacy_pstate_info_for_dmu;
+		struct dml2_pstate_meta stream_pstate_meta[DML2_MAX_PLANES]; // per stream
+	} uclk_pstate_params;
+	bool fclk_pstate_support;
+	bool ppt_temp_read_support;
+	bool stutter_support_in_vblank;
+	bool z8_stutter_support_in_vblank;
+
+	/* pre-validation states */
+	struct dml2_optimization_change unvalidated_change;
+
+	/* post validation */
+	struct dml2_validation_result validation_result;
+};
+
+struct dml2_pmo_stage_optimizer {
+	const struct dml2_pmo_instance *pmo;
+	/*
+	 * to optimize stack memory usage, large local variables are pre-allocated in this heap memory. The scope of
+	 * func_locals is bounded by each optimizer's function defined in the union. To share states across an
+	 * optimizer's functions, define it in the dedicated optimizer state in optimization worksheet.
+	 */
+	union dml2_stage_optimizer_function_locals *func_locals;
+	/*
+	 * init interface builds the initial states associated with the current stage optimizer into the worksheet. It
+	 * is for state initialization only. It should not apply new optimization or cause changes to current validation
+	 * result. It is safe to assume that the worksheet passed in or exited from this interface is always validated.
+	 */
+	void (*init)(struct dml2_pmo_stage_optimizer *stage, struct dml2_optimization_worksheet *worksheet);
+	/*
+	 * optimize_next interface controls current optimization's stop conditions. When the interface returns false, it
+	 * means the stage optimizer no longer needs to attempt further optimization. The current worksheet should be
+	 * left unmodified. When the interface returns true, it means the stage optimizer applied new optimization to
+	 * the worksheet. DML top will need to validate and test permissibility again. The worksheet passed in is based
+	 * off the optimization decision from last attempt. It may or may not be validated or permissible. It is upto
+	 * DML top to keep track of the last valid permissible worksheet. This interface is also responsible to clear
+	 * corresponding valid bits in worksheet's validation result based on what optimization it gets applied. When
+	 * the valid bits are cleared, it will be revalidated by top. Otherwise, DML top will assume it is safe to skip
+	 * certain re-validations based on the remaining valid bits. Stage optimizers should clear only the necessary
+	 * valid bits based on the optimization applied to speed up the process.
+	 */
+	bool (*optimize_next)(struct dml2_pmo_stage_optimizer *stage, struct dml2_optimization_worksheet *worksheet);
+	/*
+	 * test_permissibility interface should only check against current optimizer policy specific
+	 * minimum requirements. Test permissibility result is orthogonal to validation result. It is
+	 * safe to assume the worksheet constant passed in is always validated. The interface checks if
+	 * the validated result fulfills the minimum requirements additionally imposed by current stage
+	 * optimizer in order to consider the current optimization as a potential candidate. Stage
+	 * optimizer may still attempt further optimization even if the current one is permissible.
+	 */
+	enum dml2_status (*test_permissibility)(struct dml2_pmo_stage_optimizer *stage,
+			const struct dml2_optimization_worksheet *worksheet);
+};
+
 struct dml2_core_mode_support_in_out {
 	/*
 	* Inputs
@@ -464,9 +830,27 @@ struct dml2_core_internal_state_intermediates {
 	unsigned int dummy;
 };
 
+struct dml2_core_calculate_mp_context {
+	const struct dml2_display_cfg *display_cfg;
+	const struct dml2_core_ip_params *ip;
+	const struct dml2_utm_soc_bb *soc_bb;
+	const struct dml2_core_internal_mode_support *ms;
+	struct dml2_core_calcs_mode_programming_locals *dummies;
+	struct dml2_core_internal_scratch *func_params;
+};
+struct dml2_core_calculate_ms_context {
+	const struct dml2_display_cfg *display_cfg;
+	const struct dml2_core_ip_params *ip;
+	const struct dml2_utm_soc_bb *soc_bb;
+	const struct dml2_clock_granularity_adjuster *clock_adjuster;
+	struct dml2_core_calcs_mode_support_locals *dummies;
+	struct dml2_core_internal_scratch *func_params;
+};
+
 struct dml2_core_mode_support_locals {
 	union {
 		struct dml2_core_calcs_mode_support_ex mode_support_ex_params;
+		struct dml2_core_calculate_ms_context calc_ms_ctx;
 	};
 	struct dml2_display_cfg svp_expanded_display_cfg;
 	struct dml2_calculate_mcache_allocation_in_out calc_mcache_allocation_params;
@@ -475,8 +859,10 @@ struct dml2_core_mode_support_locals {
 struct dml2_core_mode_programming_locals {
 	union {
 		struct dml2_core_calcs_mode_programming_ex mode_programming_ex_params;
+		struct dml2_core_calculate_mp_context calc_mp_ctx;
 	};
 	struct dml2_display_cfg svp_expanded_display_cfg;
+	struct dml2_validation_result temp_result;
 };
 
 struct dml2_core_scratch {
@@ -490,6 +876,8 @@ struct dml2_core_scratch {
 
 struct dml2_core_instance {
 	struct dml2_mcg_min_clock_table *minimum_clock_table;
+	const struct dml2_utm_soc_bb *utm_soc_bb;
+	const struct dml2_clock_granularity_adjuster *clock_adjuster;
 	struct dml2_core_internal_state_inputs inputs;
 	struct dml2_core_internal_state_intermediates intermediates;
 
@@ -497,6 +885,12 @@ struct dml2_core_instance {
 
 	bool (*initialize)(struct dml2_core_initialize_in_out *in_out);
 	bool (*mode_support)(struct dml2_core_mode_support_in_out *in_out);
+	enum dml2_status (*validate_solution)(struct dml2_core_instance *core,
+			const struct dml2_display_solution *solution,
+			struct dml2_validation_result *validation_result);
+	enum dml2_status (*populate_programming)(struct dml2_core_instance *core,
+			const struct dml2_display_solution *solution,
+			struct dml2_display_cfg_programming *programming);
 	bool (*mode_programming)(struct dml2_core_mode_programming_in_out *in_out);
 	bool (*populate_informative)(struct dml2_core_populate_informative_in_out *in_out);
 	bool (*calculate_mcache_allocation)(struct dml2_calculate_mcache_allocation_in_out *in_out);
@@ -520,6 +914,7 @@ struct dml2_pmo_initialize_in_out {
 	struct dml2_ip_capabilities *ip_caps;
 	struct dml2_pmo_options *options;
 	int mcg_clock_table_size;
+	const struct dml2_utm_soc_bb *utm_soc_bb;
 };
 
 struct dml2_pmo_optimize_dcc_mcache_in_out {
@@ -692,6 +1087,35 @@ struct dml2_pmo_scratch {
 			unsigned int sorted_group_gtl_period_index[DML2_MAX_PLANES];
 			double group_phase_offset[DML2_MAX_PLANES];
 		} pmo_dcn4;
+		struct {
+			union dml2_stage_optimizer_function_locals {
+				struct dml2_stage_optimizer_uclk_pstate_init_locals {
+					double allow_delay_us;
+					double blackout_us;
+					double watermark_us;
+
+					unsigned int stream_vactive_capability_mask;
+
+					struct dml2_pmo_pstate_strategy expanded_override_strategy_list[2 * 2 * 2 * 2];
+					unsigned int num_expanded_override_strategies;
+
+					/* mask of synchronized timings by stream index */
+					struct dml2_pmo_synchronized_timing_groups synchronized_timing_groups;
+
+					/* scheduling check locals */
+					struct dml2_scheduling_check_locals scheduling_check_locals;
+				} uclk_pstate_init;
+				struct dml2_stage_optimizer_fclk_ppt_temp_read_pstate_optimize_locals {
+					double pstate_blackout_us;
+					double pstate_watermark_us;
+					double pstate_allow_delay_us;
+
+					struct dml2_pstate_meta per_stream_pstate_meta[DML2_MAX_PLANES];
+					enum dml2_pstate_method per_stream_pstate_method[DML2_MAX_PLANES];
+					struct dml2_scheduling_check_locals scheduling_check_locals;
+				} fclk_ppt_temp_read_pstate_optimize;
+			} func_locals;
+		} pmo_dcn5;
 	};
 };
 
@@ -708,6 +1132,18 @@ struct dml2_pmo_init_data {
 	};
 };
 
+enum dml2_pmo_stage_index {
+	dml2_pmo_stage_index_start = 0,
+	dml2_pmo_stage_index_mcache = dml2_pmo_stage_index_start,
+	dml2_pmo_stage_index_uclk_pstate,
+	dml2_pmo_stage_index_qos,
+	dml2_pmo_stage_index_vmin,
+	dml2_pmo_stage_index_stutter,
+	dml2_pmo_stage_index_vmin_dcfclk,
+	dml2_pmo_stage_index_fclk_ppt_temp_read_pstate,
+	dml2_pmo_stage_index_max,
+};
+
 struct dml2_pmo_instance {
 	struct dml2_soc_bb *soc_bb;
 	struct dml2_ip_capabilities *ip_caps;
@@ -718,6 +1154,7 @@ struct dml2_pmo_instance {
 	int mpc_combine_limit;
 	int odm_combine_limit;
 	int mcg_clock_table_size;
+	const struct dml2_utm_soc_bb *utm_soc_bb;
 	union {
 		struct {
 			struct {
@@ -754,9 +1191,52 @@ struct dml2_pmo_instance {
 	bool (*test_for_stutter)(struct dml2_pmo_test_for_stutter_in_out *in_out);
 	bool (*optimize_for_stutter)(struct dml2_pmo_optimize_for_stutter_in_out *in_out);
 
+	/*
+	 * obtain a list of mandatory stage optimizers ordered by priority. Caller must perform stage optimization in
+	 * the same order.
+	 * return - stage optimizer count
+	 */
+	int (*get_ordered_mandatory_stage_optimizers)(struct dml2_pmo_instance *pmo,
+			struct dml2_pmo_stage_optimizer **optimers);
+	/*
+	 * obtain a list of option stage optimizers ordered by priority, Caller must perform stage optimization in the
+	 * same order. Caller must complete stage optimization for all mandatory stage optimizers before performing
+	 * optional stage optimization.
+	 * return - stage optimizer count
+	 */
+	int (*get_ordered_optional_stage_optimizers)(struct dml2_pmo_instance *pmo,
+			struct dml2_pmo_stage_optimizer **optimers);
+	/*
+	 * initialize an optimization worksheet based on the display config passed in.
+	 */
+	void (*initialize_worksheet)(struct dml2_pmo_instance *pmo,
+			const struct dml2_display_cfg *dispcfg,
+			struct dml2_optimization_worksheet *worksheet);
+	/*
+	 * convert an optimization worksheet to a display solution.
+	 */
+	void (*convert_worksheet_to_solution)(struct dml2_pmo_instance *pmo,
+			const struct dml2_optimization_worksheet *worksheet,
+			struct dml2_display_solution *solution);
+	/*
+	 * when validation is completed with an updated worksheet's validation result, PMO needs to reset pre validation
+	 * states stored in worksheet.
+	 */
+	void (*clear_pre_validation_states)(struct dml2_pmo_instance *pmo,
+			struct dml2_optimization_worksheet *worksheet);
+	/*
+	 * perform a mini validate solution to rule out common optimization config problems after optimize_next is
+	 * called. This interface is a performance optimization to avoid of performing expensive full validate solution
+	 * for common optimization problems. It also generalizes sanity check for all stage optimizers. So the concern
+	 * of sanity check optimization config is isolated out of each stage optimizer.
+	 */
+	enum dml2_status (*optional_sanity_check)(struct dml2_pmo_instance *pmo,
+			const struct dml2_optimization_worksheet *worksheet);
+
 
 	struct dml2_pmo_init_data init_data;
 	struct dml2_pmo_scratch scratch;
+	struct dml2_pmo_stage_optimizer stage_optimizers[dml2_pmo_stage_index_max];
 };
 
 /*
@@ -993,6 +1473,8 @@ struct dml2_instance {
 	struct dml2_ip_capabilities ip_caps;
 
 	struct dml2_mcg_min_clock_table min_clk_table;
+	struct dml2_utm_soc_bb utm_soc_bb;
+	struct dml2_clock_granularity_adjuster clock_adjuster;
 	struct dml2_pmo_options pmo_options;
 	struct dml2_top_funcs funcs;
 
@@ -1002,6 +1484,9 @@ struct dml2_instance {
 		struct dml2_top_mcache_validate_admissability_locals mcache_validate_admissability_locals;
 		struct dml2_check_mode_supported_locals check_mode_supported_locals;
 		struct dml2_build_mode_programming_locals build_mode_programming_locals;
+		struct dml2_optimization_worksheet worksheet;
+		struct dml2_optimization_worksheet worksheet_backup;
+		struct dml2_display_solution solution;
 	} scratch;
 
 	struct {
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h
index 2f2ae05dd59c..68ae013b026e 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h
@@ -55,6 +55,12 @@ struct dml2_soc_mall_info {
 	unsigned int mblk_height_8bpe_pixels;
 };
 
+struct dml2_soc_alt_ch_info {
+	unsigned int region_size_bytes[2];
+	/* bits 47:16 of the base address */
+	unsigned int region_base_addr_47_16[2];
+};
+
 // Output of DML2 for clock requirements
 struct dml2_dcn_clocks {
 	unsigned int dispclk_khz;
@@ -204,6 +210,7 @@ enum dml2_force_pstate_methods {
 	dml2_force_pstate_method_vblank,
 	dml2_force_pstate_method_drr,
 	dml2_force_pstate_method_subvp,
+	dml2_force_pstate_method_alternate,
 };
 
 struct dml2_configuration_options {
@@ -226,6 +233,7 @@ struct dml2_configuration_options {
 		struct dml2_dc_svp_callbacks callbacks;
 	} svp_pstate;
 	struct dml2_soc_mall_info mall_cfg;
+	struct dml2_soc_alt_ch_info alt_ch_cfg;
 	struct dml2_soc_bbox_overrides bbox_overrides;
 	unsigned int max_segments_per_hubp;
 	unsigned int det_segment_size;
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h
index debcf308cb3b..a57eb1cd77a6 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h
@@ -749,4 +749,45 @@ void dpp401_set_cursor_matrix(
 	enum dc_color_space color_space,
 	struct dc_csc_transform cursor_csc_color_matrix);
 
+enum dcn401_dscl_mode_sel dpp401_dscl_get_dscl_mode(
+	struct dpp *dpp_base,
+	const struct scaler_data *data,
+	bool dbg_always_scale);
+
+void dpp401_power_on_dscl(
+	struct dpp *dpp_base,
+	bool power_on);
+
+void dpp401_dscl_set_recout(
+	struct dcn401_dpp *dpp,
+	const struct rect *recout);
+
+enum lb_memory_config dpp401_dscl_find_lb_memory_config(
+	struct dcn401_dpp *dpp,
+	const struct scaler_data *scl_data);
+
+void dpp401_dscl_program_isharp(
+	struct dpp *dpp_base,
+	const struct scaler_data *scl_data,
+	bool program_isharp_1dlut,
+	bool *bs_coeffs_updated);
+
+void dpp401_dscl_set_isharp_filter(
+	struct dcn401_dpp *dpp,
+	const uint32_t *filter);
+
+void dpp401_dscl_set_scl_filter(
+	struct dcn401_dpp *dpp,
+	const struct scaler_data *scl_data,
+	bool chroma_coef_mode,
+	bool force_coeffs_update);
+
+void dpp401_dscl_disable_easf(
+	struct dpp *dpp_base,
+	const struct scaler_data *scl_data);
+
+void dpp401_dscl_program_easf(
+	struct dpp *dpp_base,
+	const struct scaler_data *scl_data);
+
 #endif /* __DCN401_DPP_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
index e0ee00c955bc..81f287c89562 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
@@ -112,7 +112,7 @@ static bool dpp401_dscl_is_420_format(enum dc_pixel_format format)
 		return false;
 }
 
-static enum dcn401_dscl_mode_sel dpp401_dscl_get_dscl_mode(
+enum dcn401_dscl_mode_sel dpp401_dscl_get_dscl_mode(
 		struct dpp *dpp_base,
 		const struct scaler_data *data,
 		bool dbg_always_scale)
@@ -146,7 +146,7 @@ static enum dcn401_dscl_mode_sel dpp401_dscl_get_dscl_mode(
 	return DCN401_DSCL_MODE_SCALING_420_YCBCR_ENABLE;
 }
 
-static void dpp401_power_on_dscl(
+void dpp401_power_on_dscl(
 	struct dpp *dpp_base,
 	bool power_on)
 {
@@ -273,7 +273,7 @@ static void dpp401_dscl_set_scaler_filter(
 
 }
 
-static void dpp401_dscl_set_scl_filter(
+void dpp401_dscl_set_scl_filter(
 		struct dcn401_dpp *dpp,
 		const struct scaler_data *scl_data,
 		bool chroma_coef_mode,
@@ -468,7 +468,7 @@ static bool dpp401_dscl_is_lb_conf_valid(int ceil_vratio, int num_partitions, in
 }
 
 /*find first match configuration which meets the min required lb size*/
-static enum lb_memory_config dpp401_dscl_find_lb_memory_config(struct dcn401_dpp *dpp,
+enum lb_memory_config dpp401_dscl_find_lb_memory_config(struct dcn401_dpp *dpp,
 		const struct scaler_data *scl_data)
 {
 	int num_part_y, num_part_c;
@@ -637,8 +637,8 @@ static void dpp401_dscl_set_manual_ratio_init(
  *
  * Note: This function only have effect if AutoCal is disabled.
  */
-static void dpp401_dscl_set_recout(struct dcn401_dpp *dpp,
-				 const struct rect *recout)
+void dpp401_dscl_set_recout(struct dcn401_dpp *dpp,
+	const struct rect *recout)
 {
 	REG_SET_2(RECOUT_START, 0,
 		  /* First pixel of RECOUT in the active OTG area */
@@ -881,7 +881,7 @@ static void dpp401_dscl_program_easf_h(struct dpp *dpp_base, const struct scaler
  * This is the primary function to program EASF
  *
  */
-static void dpp401_dscl_program_easf(struct dpp *dpp_base, const struct scaler_data *scl_data)
+void dpp401_dscl_program_easf(struct dpp *dpp_base, const struct scaler_data *scl_data)
 {
 	struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base);
 
@@ -910,7 +910,7 @@ static void dpp401_dscl_program_easf(struct dpp *dpp_base, const struct scaler_d
  * When we have 1:1 scaling, we need to disable EASF
  *
  */
-static void dpp401_dscl_disable_easf(struct dpp *dpp_base, const struct scaler_data *scl_data)
+void dpp401_dscl_disable_easf(struct dpp *dpp_base, const struct scaler_data *scl_data)
 {
 	struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base);
 
@@ -923,7 +923,7 @@ static void dpp401_dscl_disable_easf(struct dpp *dpp_base, const struct scaler_d
 			SCL_EASF_H_EN, scl_data->dscl_prog_data.easf_h_en);
 	PERF_TRACE();
 }
-static void dpp401_dscl_set_isharp_filter(
+void dpp401_dscl_set_isharp_filter(
 	struct dcn401_dpp *dpp, const uint32_t *filter)
 {
 	int level;
@@ -953,10 +953,10 @@ static void dpp401_dscl_set_isharp_filter(
  * This is the primary function to program isharp
  *
  */
-static void dpp401_dscl_program_isharp(struct dpp *dpp_base,
-		const struct scaler_data *scl_data,
-		bool program_isharp_1dlut,
-		bool *bs_coeffs_updated)
+void dpp401_dscl_program_isharp(struct dpp *dpp_base,
+	const struct scaler_data *scl_data,
+	bool program_isharp_1dlut,
+	bool *bs_coeffs_updated)
 {
 	struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base);
 	*bs_coeffs_updated = false;
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c
index f60e084068c8..eed86f5ae731 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c
@@ -35,10 +35,7 @@ static const uint32_t *get_hist_rgb_luma_coefs(enum dc_color_space color_space)
 	}
 }
 
-static void dpp42_dpp_cm_hist_control(
-	struct dpp *dpp_base,
-	struct cm_hist_control cntl,
-	enum dc_color_space color_space)
+void dpp42_dpp_cm_hist_control(struct dpp *dpp_base, struct cm_hist_control cntl, enum dc_color_space color_space)
 {
 	struct dcn42_dpp *dpp = TO_DCN42_DPP(dpp_base);
 
@@ -68,7 +65,7 @@ static void dpp42_dpp_cm_hist_control(
 	}
 }
 
-static bool dpp42_dpp_cm_hist_read(struct dpp *dpp_base, struct cm_hist *hist_out)
+bool dpp42_dpp_cm_hist_read(struct dpp *dpp_base, struct cm_hist *hist_out)
 {
 	struct dcn42_dpp *dpp = TO_DCN42_DPP(dpp_base);
 	uint32_t channel_mask = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h
index f4ee419eabf7..76e2ab10a3a0 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h
@@ -465,5 +465,11 @@ bool dpp42_construct(struct dcn42_dpp *dpp42,
 	const struct dcn42_dpp_shift *tf_shift,
 	const struct dcn42_dpp_mask *tf_mask);
 
+void dpp42_dpp_cm_hist_control(struct dpp *dpp_base,
+	struct cm_hist_control cntl,
+	enum dc_color_space color_space);
+
+bool dpp42_dpp_cm_hist_read(struct dpp *dpp_base,
+	struct cm_hist *hist_out);
 
 #endif /* __DCN42_DPP_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h b/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h
index 4a2bf81286d8..8de9a889886a 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h
+++ b/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h
@@ -125,6 +125,8 @@ struct ddc_registers {
 	uint32_t ddc_setup;
 	uint32_t phy_aux_cntl;
 	uint32_t dc_gpio_aux_ctrl_5;
+	uint32_t dc_i3cpad_control0;
+	uint32_t dc_i3cpad_control1;
 };
 
 struct ddc_sh_mask {
@@ -142,6 +144,19 @@ struct ddc_sh_mask {
 	//phy_aux_cntl
 	uint32_t AUX_PAD_RXSEL;
 	uint32_t DDC_PAD_I2CMODE;
+	//dc_i3cpad_control0
+	uint32_t DC_I3CPAD_DDCCLK_MASK;
+	uint32_t DC_I3CPAD_DDCDATA_MASK;
+	uint32_t DC_I3CPAD_PD_EN;
+	uint32_t DC_I3CPAD_CLK_A;
+	uint32_t DC_I3CPAD_DATA_A;
+	uint32_t DC_I3CPAD_CLK_EN;
+	uint32_t DC_I3CPAD_DATA_EN;
+	uint32_t DC_I3CPAD_CLK_Y;
+	uint32_t DC_I3CPAD_DATA_Y;
+	//dc_i3cpad_control1
+	uint32_t DC_I3CPAD_STR;
+	uint32_t DC_I3CPAD_RXSEL;
 };
 
 
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c
index a76884a069e8..b75bfea635fd 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c
@@ -248,3 +248,305 @@ struct hw_gpio_pin *dal_hw_ddc_get_pin(struct gpio *gpio)
 
 	return &hw_ddc->base.base;
 }
+
+static void store_registers_ddc_i3cpad(
+	struct hw_ddc *ddc)
+{
+	switch (ddc->base.base.id) {
+	case GPIO_ID_DDC_DATA:
+		REG_GET(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, &ddc->base.store.mask);
+		REG_GET(dc_i3cpad_control0, DC_I3CPAD_DATA_A, &ddc->base.store.a);
+		REG_GET(dc_i3cpad_control0, DC_I3CPAD_DATA_EN, &ddc->base.store.en);
+		break;
+	case GPIO_ID_DDC_CLOCK:
+		REG_GET(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, &ddc->base.store.mask);
+		REG_GET(dc_i3cpad_control0, DC_I3CPAD_CLK_A, &ddc->base.store.a);
+		REG_GET(dc_i3cpad_control0, DC_I3CPAD_CLK_EN, &ddc->base.store.en);
+		break;
+	default:
+		break;
+	}
+}
+
+static void restore_registers_ddc_i3cpad(
+	struct hw_ddc *ddc)
+{
+	switch (ddc->base.base.id) {
+	case GPIO_ID_DDC_DATA:
+		REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, ddc->base.store.mask);
+		REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_A, ddc->base.store.a);
+		REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_EN, ddc->base.store.en);
+		break;
+	case GPIO_ID_DDC_CLOCK:
+		REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, ddc->base.store.mask);
+		REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_A, ddc->base.store.a);
+		REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_EN, ddc->base.store.en);
+		break;
+	default:
+		break;
+	}
+}
+
+bool dal_hw_ddc_open_i3cpad(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode)
+{
+	struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
+
+	store_registers_ddc_i3cpad(ddc);
+
+	ptr->opened = (dal_hw_ddc_config_mode_i3cpad(ddc, mode) == GPIO_RESULT_OK);
+
+	return ptr->opened;
+}
+
+enum gpio_result dal_hw_ddc_get_value_i3cpad(
+	const struct hw_gpio_pin *ptr,
+	uint32_t *value)
+{
+	struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
+	enum gpio_result result = GPIO_RESULT_OK;
+
+	switch (ptr->mode) {
+	case GPIO_MODE_INPUT:
+	case GPIO_MODE_OUTPUT:
+	case GPIO_MODE_HARDWARE:
+	case GPIO_MODE_FAST_OUTPUT:
+		switch (ddc->base.base.id) {
+		case GPIO_ID_DDC_DATA:
+			REG_GET(dc_i3cpad_control0, DC_I3CPAD_DATA_Y, value);
+			break;
+		case GPIO_ID_DDC_CLOCK:
+			REG_GET(dc_i3cpad_control0, DC_I3CPAD_CLK_Y, value);
+			break;
+		default:
+			break;
+		}
+		break;
+	default:
+		result = GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+	return result;
+}
+
+enum gpio_result dal_hw_ddc_set_value_i3cpad(
+	const struct hw_gpio_pin *ptr,
+	uint32_t value)
+{
+	struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
+
+	switch (ptr->mode) {
+	case GPIO_MODE_OUTPUT:
+		switch (ddc->base.base.id) {
+		case GPIO_ID_DDC_DATA:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_A, value);
+			break;
+		case GPIO_ID_DDC_CLOCK:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_A, value);
+			break;
+		default:
+			break;
+		}
+		return GPIO_RESULT_OK;
+	case GPIO_MODE_FAST_OUTPUT:
+		/* We use (EN) to faster switch (used in DDC GPIO).
+		 * So (A) is grounded, output is driven by (EN = 0)
+		 * to pull the line down (output == 0) and (EN=1)
+		 * then output is tri-state */
+		switch (ddc->base.base.id) {
+		case GPIO_ID_DDC_DATA:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_EN, value);
+			break;
+		case GPIO_ID_DDC_CLOCK:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_EN, value);
+			break;
+		default:
+			break;
+		}
+		return GPIO_RESULT_OK;
+	default:
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+}
+
+enum gpio_result dal_hw_ddc_change_mode_i3cpad(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode)
+{
+	struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
+
+	return dal_hw_ddc_config_mode_i3cpad(ddc, mode);
+}
+
+enum gpio_result dal_hw_ddc_config_mode_i3cpad(
+	struct hw_ddc *ddc,
+	enum gpio_mode mode)
+{
+	ddc->base.base.mode = mode;
+
+	switch (mode) {
+	case GPIO_MODE_INPUT:
+		/* turn off output enable, act as input pin;
+		 * program the pin as GPIO, mask out signal driven by HW
+		 */
+		switch (ddc->base.base.id) {
+		case GPIO_ID_DDC_DATA:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_EN, 0);
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, 1);
+			break;
+		case GPIO_ID_DDC_CLOCK:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_EN, 0);
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, 1);
+			break;
+		default:
+			break;
+		}
+		return GPIO_RESULT_OK;
+
+	case GPIO_MODE_OUTPUT:
+		/* turn on output enable, act as output pin;
+		 * program the pin as GPIO, mask out signal driven by HW
+		 */
+		switch (ddc->base.base.id) {
+		case GPIO_ID_DDC_DATA:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_A, 0);
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, 1);
+			break;
+		case GPIO_ID_DDC_CLOCK:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_A, 0);
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, 1);
+			break;
+		default:
+			break;
+		}
+		return GPIO_RESULT_OK;
+
+	case GPIO_MODE_FAST_OUTPUT:
+		/* grounding the A register then use the EN register bit
+		 * will have faster effect on the rise time
+		 */
+		switch (ddc->base.base.id) {
+		case GPIO_ID_DDC_DATA:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_A, 0);
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, 1);
+			break;
+		case GPIO_ID_DDC_CLOCK:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_A, 0);
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, 1);
+			break;
+		default:
+			break;
+		}
+		return GPIO_RESULT_OK;
+
+	case GPIO_MODE_HARDWARE:
+		/* program the pin as tri-state, pin is driven by HW */
+		switch (ddc->base.base.id) {
+		case GPIO_ID_DDC_DATA:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, 0);
+			break;
+		case GPIO_ID_DDC_CLOCK:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, 0);
+			break;
+		default:
+			break;
+		}
+		return GPIO_RESULT_OK;
+
+	default:
+	case GPIO_MODE_INTERRUPT:
+	/* Interrupt mode supported only by HPD (IrqGpio) old pins. */
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+}
+
+static enum gpio_result dal_hw_ddc_set_config_i3cpad(
+	struct hw_gpio_pin *ptr,
+	const struct gpio_config_data *config_data)
+{
+	struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
+
+	switch (config_data->config.ddc.type) {
+	/* For ASICs with i3cpad module there is no dual pad mode for i3cpads */
+	case GPIO_DDC_CONFIG_TYPE_MODE_I2C:
+		/* Enable the RX for the PAD (it is disabled by default). */
+		REG_UPDATE(dc_i3cpad_control1, DC_I3CPAD_RXSEL, 0);
+		return GPIO_RESULT_OK;
+	case GPIO_DDC_CONFIG_TYPE_MODE_AUX:
+		return GPIO_RESULT_OK;
+
+	case GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT:
+		REG_UPDATE_3(ddc_setup,
+			DC_I2C_DDC1_ENABLE, 1,
+			DC_I2C_DDC1_EDID_DETECT_ENABLE, 1,
+			DC_I2C_DDC1_EDID_DETECT_MODE, 0);
+		return GPIO_RESULT_OK;
+
+	case GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT:
+		REG_UPDATE_3(ddc_setup,
+			DC_I2C_DDC1_ENABLE, 1,
+			DC_I2C_DDC1_EDID_DETECT_ENABLE, 1,
+			DC_I2C_DDC1_EDID_DETECT_MODE, 1);
+		return GPIO_RESULT_OK;
+
+	case GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING:
+		REG_UPDATE_2(ddc_setup,
+			DC_I2C_DDC1_ENABLE, 0,
+			DC_I2C_DDC1_EDID_DETECT_ENABLE, 0);
+		return GPIO_RESULT_OK;
+	}
+
+	BREAK_TO_DEBUGGER();
+	return GPIO_RESULT_NON_SPECIFIC_ERROR;
+}
+
+void dal_hw_ddc_close_i3cpad(
+	struct hw_gpio_pin *ptr)
+{
+	struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
+
+	restore_registers_ddc_i3cpad(ddc);
+
+	ptr->mode = GPIO_MODE_UNKNOWN;
+	ptr->opened = false;
+}
+
+static const struct hw_gpio_pin_funcs funcs_i3cpad = {
+	.destroy = dal_hw_ddc_destroy,
+	.open = dal_hw_ddc_open_i3cpad,
+	.get_value = dal_hw_ddc_get_value_i3cpad,
+	.set_value = dal_hw_ddc_set_value_i3cpad,
+	.set_config = dal_hw_ddc_set_config_i3cpad,
+	.change_mode = dal_hw_ddc_change_mode_i3cpad,
+	.close = dal_hw_ddc_close_i3cpad,
+};
+
+static void dal_hw_ddc_construct_i3cpad(
+	struct hw_ddc *ddc,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	dal_hw_gpio_construct(&ddc->base, id, en, ctx);
+	ddc->base.base.funcs = &funcs_i3cpad;
+}
+
+void dal_hw_ddc_init_i3cpad(
+	struct hw_ddc **hw_ddc,
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en)
+{
+	if (en > GPIO_DDC_LINE_MAX) {
+		ASSERT_CRITICAL(false);
+		*hw_ddc = NULL;
+	}
+
+	*hw_ddc = kzalloc(sizeof(struct hw_ddc), GFP_KERNEL);
+	if (!*hw_ddc) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	dal_hw_ddc_construct_i3cpad(*hw_ddc, id, en, ctx);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h
index cc30e65df431..ac2c87d30cf4 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h
@@ -46,4 +46,32 @@ void dal_hw_ddc_init(
 
 struct hw_gpio_pin *dal_hw_ddc_get_pin(struct gpio *gpio);
 
+void dal_hw_ddc_init_i3cpad(
+	struct hw_ddc **hw_ddc,
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en);
+
+bool dal_hw_ddc_open_i3cpad(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode);
+
+enum gpio_result dal_hw_ddc_get_value_i3cpad(
+	const struct hw_gpio_pin *ptr,
+	uint32_t *value);
+
+enum gpio_result dal_hw_ddc_set_value_i3cpad(
+	const struct hw_gpio_pin *ptr,
+	uint32_t value);
+
+enum gpio_result dal_hw_ddc_config_mode_i3cpad(
+	struct hw_ddc *ddc,
+	enum gpio_mode mode);
+
+enum gpio_result dal_hw_ddc_change_mode_i3cpad(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode);
+
+void dal_hw_ddc_close_i3cpad(
+	struct hw_gpio_pin *ptr);
 #endif
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c
index a907f7d0628b..3300dbc67f32 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c
@@ -55,6 +55,7 @@
 #include "dcn401/hw_factory_dcn401.h"
 #include "dcn42/hw_factory_dcn42.h"
 #include "dcn42b/hw_factory_dcn42b.h"
+#include "dcn60/hw_factory_dcn60.h"
 
 bool dal_hw_factory_init(
 	struct hw_factory *factory,
@@ -127,6 +128,9 @@ bool dal_hw_factory_init(
 	case DCN_VERSION_4_2B:
 		dal_hw_factory_dcn42b_init(factory);
 		return true;
+	case DCN_VERSION_6_0:
+		dal_hw_factory_dcn60_init(factory);
+		return true;
 	default:
 		ASSERT_CRITICAL(false);
 		return false;
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
index b58af86dee10..5a231f97aee3 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
@@ -55,6 +55,7 @@
 #include "dcn401/hw_translate_dcn401.h"
 #include "dcn42/hw_translate_dcn42.h"
 #include "dcn42b/hw_translate_dcn42b.h"
+#include "dcn60/hw_translate_dcn60.h"
 
 /*
  * This unit
@@ -128,6 +129,9 @@ bool dal_hw_translate_init(
 	case DCN_VERSION_4_2B:
 		dal_hw_translate_dcn42b_init(translate);
 		return true;
+	case DCN_VERSION_6_0:
+		dal_hw_translate_dcn60_init(translate);
+		return true;
 	default:
 		BREAK_TO_DEBUGGER();
 		return false;
diff --git a/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c b/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c
index 34fc9f56dbef..f3413d743107 100644
--- a/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c
+++ b/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c
@@ -177,6 +177,15 @@ static bool hdmi_14_process_transaction(
 	i2c_command.engine = I2C_COMMAND_ENGINE_HW;//only HW
 	i2c_command.speed = link->ddc->ctx->dc->caps.i2c_speed_in_khz;
 
+	if (link->force_to_use_aux)
+		result = dm_helpers_submit_i2c_over_aux(
+			link->ddc,
+			hdcp_i2c_addr_link_primary,
+			offset,
+			message_info->data,
+			message_info->length,
+			hdcp_cmd_is_read[message_info->msg_id]);
+	else
 	result = dm_helpers_submit_i2c(
 			link->ctx,
 			link,
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
index ff9a1ae29474..accb79c6dde5 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
@@ -201,6 +201,20 @@ struct dcn_hubbub_registers {
 	uint32_t DCHUBBUB_TIMEOUT_DETECTION_CTRL1;
 	uint32_t DCHUBBUB_TIMEOUT_DETECTION_CTRL2;
 	uint32_t DCHUBBUB_CTRL_STATUS;
+	uint32_t DCHUBBUB_ARB_BUFFER_FULLNESS_WATERMARK_A;
+	uint32_t DCHUBBUB_ARB_BUFFER_FULLNESS_WATERMARK_B;
+	uint32_t DCHUBBUB_PERFORMANCE_MEASUREMENT_CNTL;
+	uint32_t DCHUBBUB_PERFORMANCE_MEASUREMENT_CNTL2;
+	uint32_t DC_PERFMON5_PERFCOUNTER_CNTL;
+	uint32_t DC_PERFMON5_PERFCOUNTER_CNTL2;
+	uint32_t DC_PERFMON5_PERFCOUNTER_STATE;
+	uint32_t DC_PERFMON5_PERFMON_CNTL;
+	uint32_t DC_PERFMON5_PERFMON_CNTL2;
+	uint32_t DC_PERFMON5_PERFMON_CVALUE_INT_MISC;
+	uint32_t DC_PERFMON5_PERFMON_CVALUE_LOW;
+	uint32_t DC_PERFMON5_PERFMON_HI;
+	uint32_t DC_PERFMON5_PERFMON_LOW;
+	uint32_t FMON_CTRL;
 };
 
 #define HUBBUB_REG_FIELD_LIST_DCN32(type) \
@@ -443,6 +457,96 @@ struct dcn_hubbub_registers {
 
 #define HUBBUB_REG_FIELD_LIST_DCN4_2(type) \
 	type URGENT_ZERO_SIZE_REQ_EN
+
+#define HUBBUB_PERFMON_REG_FIELD_LIST(type) \
+		type DCHUBBUB_LATENCY_CNT_EN;\
+		type DCHUBBUB_DF_REQ_CMD_LATENCY_SEL;\
+		type ARB_LATENCY_PIPE_SEL;\
+		type ARB_LATENCY_REQ_TYPE_SEL;\
+		type ROB_FIFO_LEVEL;\
+		type REQ_UNIT_ID_MASK;\
+		type REQ_UNIT_ID_SEL;\
+		type DCHUBBUB_LATENCY_FRAME_WIN_EN;\
+		type DCHUBBUB_LATENCY_FRAME_WIN_SRC_SEL;\
+		type DCHUBBUB_LATENCY_FRAME_WIN_DUR;\
+		type LATENCY_SOURCE_SEL;\
+		type LATENCY_DEBUG_SEL;\
+		type UTM_FILTER_SEL;\
+		type ROB_MAX_FIFO_LEVEL;\
+		type ROB_MAX_FIFO_LEVEL_RESET;\
+		type PERFCOUNTER_EVENT_SEL;\
+		type PERFCOUNTER_CVALUE_SEL;\
+		type PERFCOUNTER_INC_MODE;\
+		type PERFCOUNTER_HW_CNTL_SEL;\
+		type PERFCOUNTER_RUNEN_MODE;\
+		type PERFCOUNTER_CNTOFF_START_DIS;\
+		type PERFCOUNTER_RESTART_EN;\
+		type PERFCOUNTER_INT_EN;\
+		type PERFCOUNTER_OFF_MASK;\
+		type PERFCOUNTER_ACTIVE;\
+		type PERFCOUNTER_CNTL_SEL;\
+		type PERFCOUNTER_COUNTED_VALUE_TYPE;\
+		type PERFCOUNTER_HW_STOP1_SEL;\
+		type PERFCOUNTER_HW_STOP2_SEL;\
+		type PERFCOUNTER_CNTOFF_SEL;\
+		type PERFCOUNTER_CNTL2_SEL;\
+		type PERFCOUNTER_CNT0_STATE;\
+		type PERFCOUNTER_STATE_SEL0;\
+		type PERFCOUNTER_CNT1_STATE;\
+		type PERFCOUNTER_STATE_SEL1;\
+		type PERFCOUNTER_CNT2_STATE;\
+		type PERFCOUNTER_STATE_SEL2;\
+		type PERFCOUNTER_CNT3_STATE;\
+		type PERFCOUNTER_STATE_SEL3;\
+		type PERFCOUNTER_CNT4_STATE;\
+		type PERFCOUNTER_STATE_SEL4;\
+		type PERFCOUNTER_CNT5_STATE;\
+		type PERFCOUNTER_STATE_SEL5;\
+		type PERFCOUNTER_CNT6_STATE;\
+		type PERFCOUNTER_STATE_SEL6;\
+		type PERFCOUNTER_CNT7_STATE;\
+		type PERFCOUNTER_STATE_SEL7;\
+		type PERFMON_STATE;\
+		type PERFMON_RPT_COUNT;\
+		type PERFMON_CNTOFF_AND_OR;\
+		type PERFMON_CNTOFF_INT_EN;\
+		type PERFMON_CNTOFF_INT_STATUS;\
+		type PERFMON_CNTOFF_INT_ACK;\
+		type PERFMON_CNTOFF_INT_TYPE;\
+		type PERFMON_CLK_ENABLE;\
+		type PERFMON_RUN_ENABLE_START_SEL;\
+		type PERFMON_RUN_ENABLE_STOP_SEL;\
+		type PERFCOUNTER_INT0_STATUS;\
+		type PERFCOUNTER_INT1_STATUS;\
+		type PERFCOUNTER_INT2_STATUS;\
+		type PERFCOUNTER_INT3_STATUS;\
+		type PERFCOUNTER_INT4_STATUS;\
+		type PERFCOUNTER_INT5_STATUS;\
+		type PERFCOUNTER_INT6_STATUS;\
+		type PERFCOUNTER_INT7_STATUS;\
+		type PERFCOUNTER_INT0_ACK;\
+		type PERFCOUNTER_INT1_ACK;\
+		type PERFCOUNTER_INT2_ACK;\
+		type PERFCOUNTER_INT3_ACK;\
+		type PERFCOUNTER_INT4_ACK;\
+		type PERFCOUNTER_INT5_ACK;\
+		type PERFCOUNTER_INT6_ACK;\
+		type PERFCOUNTER_INT7_ACK;\
+		type PERFMON_CVALUE_HI;\
+		type PERFMON_CVALUE_LOW;\
+		type PERFMON_HI;\
+		type PERFMON_READ_SEL;\
+		type PERFMON_LOW;\
+		type FMON_MODE;\
+		type DCHUBBUB_ARB_UTM_FORCE_URGENT;\
+		type DCHUBBUB_ARB_UTM_FORCE_BANDWIDTH_OVERHEAD;\
+		type DCHUBBUB_ARB_UTM_FORCE_ENABLE;\
+		type DCHUBBUB_ARB_DO_NOT_FORCE_URGENCY_DURING_PSTATE_CHANGE_REQUEST
+
+#define HUBBUB_REG_FIELD_LIST_DCN60(type) \
+		type DCHUBBUB_ARB_BUFFER_FULLNESS_WATERMARK_A;\
+		type DCHUBBUB_ARB_BUFFER_FULLNESS_WATERMARK_B
+
 struct dcn_hubbub_shift {
 	DCN_HUBBUB_REG_FIELD_LIST(uint8_t);
 	HUBBUB_STUTTER_REG_FIELD_LIST(uint8_t);
@@ -453,6 +557,8 @@ struct dcn_hubbub_shift {
 	HUBBUB_REG_FIELD_LIST_DCN4_01(uint8_t);
 	HUBBUB_REG_FIELD_LIST_DCN4_2(uint8_t);
 
+	HUBBUB_REG_FIELD_LIST_DCN60(uint8_t);
+	HUBBUB_PERFMON_REG_FIELD_LIST(uint8_t);
 };
 
 struct dcn_hubbub_mask {
@@ -465,6 +571,8 @@ struct dcn_hubbub_mask {
 	HUBBUB_REG_FIELD_LIST_DCN4_01(uint32_t);
 	HUBBUB_REG_FIELD_LIST_DCN4_2(uint8_t);
 
+	HUBBUB_REG_FIELD_LIST_DCN60(uint32_t);
+	HUBBUB_PERFMON_REG_FIELD_LIST(uint32_t);
 };
 
 struct dc;
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h
index 2595c6441f00..ea90dee05d5f 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h
@@ -182,6 +182,9 @@
 	uint32_t DCHUBP_ADDR_CONFIG;\
 	uint32_t HUBP_MALL_STATUS
 
+#define DCN60_HUBP_REG_VARIABLE_LIST \
+	uint32_t DCSURF_LEGACY_ADDR_CONFIG;\
+	uint32_t DST_Y_ALT_CH_DRQ_LIMIT
 #define DCN2_HUBP_REG_FIELD_VARIABLE_LIST(type) \
 	DCN_HUBP_REG_FIELD_BASE_LIST(type); \
 	type DMDATA_ADDRESS_HIGH;\
@@ -293,18 +296,44 @@
 	type HUBP_3DLUT_CROSSBAR_SEL_G;\
 	type HUBP_3DLUT_CROSSBAR_SEL_B;\
 	type HUBP_3DLUT_CROSSBAR_SEL_R
+#define DCN60_HUBP_REG_FIELD_VARIABLE_LIST(type) \
+	type COMPAT_LEVEL; \
+	type LEGACY_PIPE_INTERLEAVE;\
+	type ARRAY_MODE;\
+	type PIPE_CONFIG;\
+	type MICRO_TILE_MODE_NEW;\
+	type TILE_SPLIT; \
+	type BANK_WIDTH; \
+	type BANK_HEIGHT;\
+	type MACRO_TILE_ASPECT;\
+	type LEGACY_NUM_BANKS;\
+	type FORCE_URGENT_FLIP;\
+	type FORCE_URGENT_VM_PREFETCH;\
+	type URGENT_FORCE_VALUE;\
+	type URGENT_FORCE_EN;\
+	type FORCE_DISP_PREF_TO_VBLANK;\
+	type DST_Y_ALT_CH_DRQ_LIMIT;\
+	type FORCE_CURSOR_TO_DISP_PREF
+/*
+	type HUBP_3DLUT_CROSSBAR_SEL_B;\
+	type HUBP_3DLUT_CROSSBAR_SEL_G;\
+	type HUBP_3DLUT_CROSSBAR_SEL_R;
+*/
 struct dcn_hubp2_registers {
 	DCN401_HUBP_REG_COMMON_VARIABLE_LIST;
+	DCN60_HUBP_REG_VARIABLE_LIST;
 };
 
 struct dcn_hubp2_shift {
 	DCN401_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t);
 	DCN42_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t);
+	DCN60_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t);
 };
 
 struct dcn_hubp2_mask {
 	DCN401_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t);
 	DCN42_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t);
+	DCN60_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t);
 };
 
 struct dcn20_hubp {
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h
index dc8feca578c5..2cc4e7516a5d 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h
@@ -702,6 +702,7 @@ struct dce_hwseq_registers {
 	uint32_t DOMAIN25_PG_STATUS;
 	uint32_t DOMAIN26_PG_CONFIG;
 	uint32_t DOMAIN26_PG_STATUS;
+	uint32_t HDCP_INTERRUPT_DEST;
 };
  /* set field name */
 #define HWS_SF(blk_name, reg_name, field_name, post_fix)\
@@ -1254,6 +1255,12 @@ struct dce_hwseq_registers {
 	type DOMAIN26_POWER_GATE; \
 	type DOMAIN26_PGFSM_PWR_STATUS;
 
+#define HWSEQ_DCN60_REG_FIELD_LIST(type) \
+	type DOUT_IHC_HDCP0_I2C_XFER_REQ_INTERRUPT_DEST; \
+	type DOUT_IHC_HDCP1_I2C_XFER_REQ_INTERRUPT_DEST; \
+	type DOUT_IHC_HDCP2_I2C_XFER_REQ_INTERRUPT_DEST; \
+	type DOUT_IHC_HDCP3_I2C_XFER_REQ_INTERRUPT_DEST;
+
 struct dce_hwseq_shift {
 	HWSEQ_REG_FIELD_LIST(uint8_t)
 	HWSEQ_DCN_REG_FIELD_LIST(uint8_t)
@@ -1263,6 +1270,7 @@ struct dce_hwseq_shift {
 	HWSEQ_DCN35_REG_FIELD_LIST(uint8_t)
 	HWSEQ_DCN401_REG_FIELD_LIST(uint8_t)
 	HWSEQ_DCN42_REG_FIELD_LIST(uint8_t)
+	HWSEQ_DCN60_REG_FIELD_LIST(uint8_t)
 };
 
 struct dce_hwseq_mask {
@@ -1274,6 +1282,7 @@ struct dce_hwseq_mask {
 	HWSEQ_DCN35_REG_FIELD_LIST(uint32_t)
 	HWSEQ_DCN401_REG_FIELD_LIST(uint32_t)
 	HWSEQ_DCN42_REG_FIELD_LIST(uint32_t)
+	HWSEQ_DCN60_REG_FIELD_LIST(uint32_t)
 };
 
 
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
index f91ce2b4b1bf..5fcf30b448a5 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
@@ -3487,6 +3487,17 @@ void dce110_enable_tmds_link_output(struct dc_link *link,
 			signal,
 			pixel_clock);
 	link->phy_state.symclk_state = SYMCLK_ON_TX_ON;
+
+	// For dongle Type 2 with no I2C support on board, setup sw mode of Ri/Pj check with proper aux instance
+	if (link->force_to_use_aux) {
+		if (link->link_enc && link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode)
+			link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode(link->link_enc,
+				link->aux_hw_inst, true);
+	} else
+		// For HDMI setup hw mode of Ri/Pj check with proper ddc pin instance
+		if (link->link_enc && link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode)
+			link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode(link->link_enc,
+				link->ddc_hw_inst, false);
 }
 
 static void dce110_enable_analog_link_output(
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
index 22c7535fd9c4..097e4ac2df05 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
@@ -524,7 +524,7 @@ static void dcn10_log_color_state(struct dc *dc,
 	DTN_INFO("DPP Color Caps: input_lut_shared:%d  icsc:%d"
 		 "  dgam_ram:%d  dgam_rom: srgb:%d,bt2020:%d,gamma2_2:%d,pq:%d,hlg:%d"
 		 "  post_csc:%d  gamcor:%d  dgam_rom_for_yuv:%d  3d_lut:%d"
-		 "  blnd_lut:%d  oscs:%d\n\n",
+		 "  upsp_pre_scaler:%d  blnd_lut:%d  oscs:%d\n\n",
 		 dc->caps.color.dpp.input_lut_shared,
 		 dc->caps.color.dpp.icsc,
 		 dc->caps.color.dpp.dgam_ram,
@@ -537,6 +537,7 @@ static void dcn10_log_color_state(struct dc *dc,
 		 dc->caps.color.dpp.gamma_corr,
 		 dc->caps.color.dpp.dgam_rom_for_yuv,
 		 dc->caps.color.dpp.hw_3d_lut,
+		 dc->caps.color.dpp.upsp_pre_scaler,
 		 dc->caps.color.dpp.ogam_ram,
 		 dc->caps.color.dpp.ocsc);
 
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
index 98778d5e114e..16bb6f678567 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
@@ -148,7 +148,7 @@ void dcn20_log_color_state(struct dc *dc,
 	DTN_INFO("DPP Color Caps: input_lut_shared:%d  icsc:%d"
 		 "  dgam_ram:%d  dgam_rom: srgb:%d,bt2020:%d,gamma2_2:%d,pq:%d,hlg:%d"
 		 "  post_csc:%d  gamcor:%d  dgam_rom_for_yuv:%d  3d_lut:%d"
-		 "  blnd_lut:%d  oscs:%d\n\n",
+		 "  upsp_pre_scaler:%d  blnd_lut:%d  oscs:%d\n\n",
 		 dc->caps.color.dpp.input_lut_shared,
 		 dc->caps.color.dpp.icsc,
 		 dc->caps.color.dpp.dgam_ram,
@@ -161,6 +161,7 @@ void dcn20_log_color_state(struct dc *dc,
 		 dc->caps.color.dpp.gamma_corr,
 		 dc->caps.color.dpp.dgam_rom_for_yuv,
 		 dc->caps.color.dpp.hw_3d_lut,
+		 dc->caps.color.dpp.upsp_pre_scaler,
 		 dc->caps.color.dpp.ogam_ram,
 		 dc->caps.color.dpp.ocsc);
 
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
index 59184e146fc9..cb163902e12e 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
@@ -157,7 +157,7 @@ void dcn30_log_color_state(struct dc *dc,
 	DTN_INFO("DPP Color Caps: input_lut_shared:%d  icsc:%d"
 		 "  dgam_ram:%d  dgam_rom: srgb:%d,bt2020:%d,gamma2_2:%d,pq:%d,hlg:%d"
 		 "  post_csc:%d  gamcor:%d  dgam_rom_for_yuv:%d  3d_lut:%d"
-		 "  blnd_lut:%d  oscs:%d\n\n",
+		 "  upsp_pre_scaler:%d  blnd_lut:%d  oscs:%d\n\n",
 		 dc->caps.color.dpp.input_lut_shared,
 		 dc->caps.color.dpp.icsc,
 		 dc->caps.color.dpp.dgam_ram,
@@ -170,6 +170,7 @@ void dcn30_log_color_state(struct dc *dc,
 		 dc->caps.color.dpp.gamma_corr,
 		 dc->caps.color.dpp.dgam_rom_for_yuv,
 		 dc->caps.color.dpp.hw_3d_lut,
+		 dc->caps.color.dpp.upsp_pre_scaler,
 		 dc->caps.color.dpp.ogam_ram,
 		 dc->caps.color.dpp.ocsc);
 
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
index c5f6eb482f07..51fd2b3fe106 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
@@ -544,7 +544,10 @@ bool dcn32_set_input_transfer_func(struct dc *dc,
 	if (plane_state->in_transfer_func.type == TF_TYPE_PREDEFINED)
 		tf = plane_state->in_transfer_func.tf;
 
-	dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf);
+	if (dpp_base->funcs->dpp_set_pregam_state)
+		dpp_base->funcs->dpp_set_pregam_state(dpp_base, tf, plane_state->scaling_linearity);
+	else
+		dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf);
 
 	if (plane_state->in_transfer_func.type == TF_TYPE_HWPWL)
 		params = &plane_state->in_transfer_func.pwl;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
index f14c39a643da..08f1f307657c 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
@@ -48,6 +48,7 @@
 #include "dpcd_defs.h"
 #include "dce/dmub_outbox.h"
 #include "link_service.h"
+#include "dce/dmub_hw_lock_mgr.h"
 #include "dcn10/dcn10_hwseq.h"
 #include "inc/link_enc_cfg.h"
 #include "dcn30/dcn30_vpg.h"
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index fa9a5d8065d3..b89010a88b44 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -348,6 +348,11 @@ void dcn401_init_hw(struct dc *dc)
 					dal_gpio_destroy_ddc(&ddc_pin);
 				}
 			}
+		//Setup corresponding HDCP XFER DEST interrupt to go to DMUCB
+		dc_dmub_srv_ihc_set_dig_hdcp_interrupt_dest(
+			dc->ctx->dmub_srv,
+			link->eng_id,
+			true);
 		}
 	}
 
@@ -1099,6 +1104,12 @@ void dcn401_disable_link_output(struct dc_link *link,
 		dmcu->funcs->lock_phy(dmcu);
 
 	if (dc_is_tmds_signal(signal) && link->phy_state.symclk_ref_cnts.otg > 0) {
+		// Disable interrupt, setup default hw mode of Ri/Pj check with proper aux instance
+		if (link->force_to_use_aux) {
+			if (link->link_enc && link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode)
+				link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode(link->link_enc,
+					link->aux_hw_inst, false);
+		}
 		disable_link_output_symclk_on_tx_off(link, DP_UNKNOWN_ENCODING);
 		link->phy_state.symclk_state = SYMCLK_ON_TX_OFF;
 	} else {
@@ -2609,6 +2620,16 @@ void dcn401_program_front_end_for_ctx(
 
 	if (resource_is_pipe_topology_changed(dc->current_state, context))
 		resource_log_pipe_topology_update(dc, context);
+	if (dc->debug.enable_block_sequence_programming) {
+		hwss_build_full_sequence(dc,
+			context->block_sequence,
+			&(context->block_sequence_steps),
+			context, false);
+		hwss_execute_sequence(dc,
+			context->block_sequence,
+			context->block_sequence_steps);
+		return;
+	}
 
 	if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
 		for (i = 0; i < dc->res_pool->pipe_count; i++) {
@@ -2770,6 +2791,17 @@ void dcn401_post_unlock_program_front_end(
 	struct dce_hwseq *hwseq = dc->hwseq;
 	unsigned int i;
 
+	if (dc->debug.enable_block_sequence_programming) {
+		hwss_build_post_unlock_full_sequence(dc,
+			context->block_sequence,
+			&(context->block_sequence_steps),
+			context);
+		hwss_execute_sequence(dc,
+			context->block_sequence,
+			context->block_sequence_steps);
+		return;
+	}
+
 	for (i = 0; i < dc->res_pool->pipe_count; i++)
 		if (resource_is_pipe_type(&dc->current_state->res_ctx.pipe_ctx[i], OPP_HEAD) &&
 			!resource_is_pipe_type(&context->res_ctx.pipe_ctx[i], OPP_HEAD))
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
index 4549c435501a..c4296b8390f2 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -145,6 +145,9 @@ struct set_output_transfer_func_params {
 	bool is_top_pipe;
 	const struct dc_stream_state *stream;
 };
+struct program_upsp_params {
+	struct pipe_ctx *pipe_ctx;
+};
 
 struct update_visual_confirm_params {
 	struct dc *dc;
@@ -1030,6 +1033,7 @@ union block_sequence_params {
 	struct setup_dpp_params setup_dpp_params;
 	struct program_bias_and_scale_params program_bias_and_scale_params;
 	struct set_output_transfer_func_params set_output_transfer_func_params;
+	struct program_upsp_params program_upsp_params;
 	struct update_visual_confirm_params update_visual_confirm_params;
 	struct power_on_mpc_mem_pwr_params power_on_mpc_mem_pwr_params;
 	struct set_output_csc_params set_output_csc_params;
@@ -1207,6 +1211,7 @@ enum block_sequence_func {
 	DPP_PROGRAM_BIAS_AND_SCALE,
 	DPP_SET_OUTPUT_TRANSFER_FUNC,
 	DPP_SET_HDR_MULTIPLIER,
+	DPP_PROGRAM_UPSP,
 	MPC_UPDATE_VISUAL_CONFIRM,
 	MPC_POWER_ON_MPC_MEM_PWR,
 	MPC_SET_OUTPUT_CSC,
@@ -1783,6 +1788,16 @@ void hwss_build_fast_sequence(struct dc *dc,
 		struct dc_stream_status *stream_status,
 		struct dc_state *context);
 
+void hwss_build_full_sequence(struct dc *dc,
+	struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE],
+	unsigned int *num_steps,
+	struct dc_state *context, bool program_phantom_pipe);
+
+void hwss_build_post_unlock_full_sequence(struct dc *dc,
+	struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE],
+	unsigned int *num_steps,
+	struct dc_state *context);
+
 void hwss_wait_for_all_blank_complete(struct dc *dc,
 		struct dc_state *context);
 
@@ -1806,6 +1821,8 @@ void hwss_setup_dpp(union block_sequence_params *params);
 
 void hwss_program_bias_and_scale(union block_sequence_params *params);
 
+void hwss_program_upsp(union block_sequence_params *params);
+
 void hwss_power_on_mpc_mem_pwr(union block_sequence_params *params);
 
 void hwss_set_output_csc(union block_sequence_params *params);
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 e87f9fd60bcb..b18d607fb222 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -447,6 +447,7 @@ enum p_state_switch_method {
 	P_STATE_SUB_VP,
 	P_STATE_DRR_SUB_VP,
 	P_STATE_V_BLANK_SUB_VP,
+	P_STATE_ALT,
 };
 
 struct dsc_padding_params {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
index 23c9798936c2..d735eb1e7f43 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
@@ -293,6 +293,27 @@ enum dentist_divider_range {
 	CLK_SF(CLK5_CLK2_DS_CNTL, CLK2_ALLOW_DS, mask_sh), \
 	CLK_SF(CLK5_CLK3_DS_CNTL, CLK3_ALLOW_DS, mask_sh)
 
+#define CLK_REG_LIST_DCN60()	  \
+	CLK_SR_DCN60(CLK8_CLK_TICK_CNT_CONFIG_REG,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK0_CURRENT_CNT,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK1_CURRENT_CNT,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK2_CURRENT_CNT,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK3_CURRENT_CNT,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK4_CURRENT_CNT,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK0_BYPASS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK1_BYPASS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK2_BYPASS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK3_BYPASS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK4_BYPASS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK0_DS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK1_DS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK2_DS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK3_DS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK4_DS_CNTL,  CLK08, 0)
+
+#define CLK_COMMON_MASK_SH_LIST_DCN60(mask_sh) \
+	CLK_COMMON_MASK_SH_LIST_DCN42(mask_sh)
+
 #define CLK_REG_FIELD_LIST(type) \
 	type DPREFCLK_SRC_SEL; \
 	type DENTIST_DPREFCLK_WDIVIDER; \
@@ -406,6 +427,7 @@ struct clk_mgr_registers {
 	uint32_t CLK6_spll_field_8;
 	CLK42_REG_LIST(8, uint32_t)
 	CLK42_REG_LIST(5, uint32_t)
+	uint32_t CLK8_CLK0_ALLOW_DS;
 };
 
 struct clk_mgr_shift {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/cursor_reg_cache.h b/drivers/gpu/drm/amd/display/dc/inc/hw/cursor_reg_cache.h
index 7ce2f417f86a..3932a4f766e2 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/cursor_reg_cache.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/cursor_reg_cache.h
@@ -59,7 +59,8 @@ struct cursor_attribute_cache_hubp {
 		struct {
 			uint32_t              dst_y_offset: 8;
 			uint32_t          chunk_hdl_adjust: 2;
-			uint32_t                  reserved: 22;
+			uint32_t force_cursor_to_disp_pref: 1;
+			uint32_t                  reserved: 21;
 		} bits;
 		uint32_t raw;
 	} settings;
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
index 39215ecb480e..b31b144d2e8f 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
@@ -375,6 +375,13 @@ struct dpp_funcs {
 	bool (*dpp_cm_hist_read)(
 		struct dpp *dpp_base,
 		struct cm_hist *cm_hist);
+	void (*dpp_set_pregam_state)(
+			struct dpp *dpp_base,
+			enum dc_transfer_func_predefined tr,
+			enum dc_scaling_linearity scaling);
+	void (*dpp_program_upsp)(
+			struct dpp *dpp_base,
+			const struct dscl_prog_data *dscl_prog_data);
 };
 
 
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
index e7727ed3300c..70545df981ef 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
@@ -52,6 +52,7 @@ struct encoder_init_data {
 	enum engine_id analog_engine;
 	struct dc_context *ctx;
 	enum transmitter transmitter;
+	bool hpd_active_high;
 };
 
 struct encoder_feature_support {
@@ -106,6 +107,7 @@ struct link_encoder {
 	enum hpd_source_id hpd_source;
 	bool usbc_combo_phy;
 	uint8_t txffe_state;
+	bool hpd_active_high;
 };
 
 struct link_enc_state {
@@ -242,6 +244,10 @@ struct link_encoder_funcs {
 		uint8_t digmode);
 	bool (*get_hpd_state)(struct link_encoder *enc);
 	bool (*program_hpd_filter)(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms);
+
+	void (*setup_ri_pj_check_in_sw_or_hw_mode)(struct link_encoder *link_enc,
+		unsigned char aux_or_ddc_instance,
+		bool ri_pj_sw_mode);
 };
 
 /*
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
index 30990355985d..d67373ec8e36 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
@@ -164,6 +164,7 @@ struct scaler_data {
 	struct line_buffer_params lb_params;
 	// Below struct holds the scaler values to program hw registers
 	struct dscl_prog_data dscl_prog_data;
+	enum upsp_mode upsp;
 };
 
 struct transform_funcs {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h
index d3171e70e07c..8e21aaac06b3 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/resource.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h
@@ -123,6 +123,8 @@ void resource_build_test_pattern_params(
 		struct resource_context *res_ctx,
 		struct pipe_ctx *pipe_ctx);
 
+enum upsp_mode resource_is_upsp_required(enum surface_pixel_format format);
+
 bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx);
 
 enum dc_status resource_build_scaling_params_for_context(
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
index 4f18b668340c..22ad6a743038 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
@@ -336,6 +336,34 @@ static void query_dp_dual_mode_adaptor(
 	sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK;
 
 	/* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/
+	if (link->force_to_use_aux) {
+
+		if (!dm_helpers_submit_i2c_over_aux(
+			ddc,
+			DP_HDMI_DONGLE_ADDRESS,
+			0,
+			type2_dongle_buf,
+			sizeof(type2_dongle_buf),
+			true)) {
+
+			/* Use same approach as below with native i2c - HDMI dongles can sometimes fail here without retrying*/
+			while (retry_count > 0) {
+				if (dm_helpers_submit_i2c_over_aux(
+					ddc,
+					DP_HDMI_DONGLE_ADDRESS,
+					0,
+					type2_dongle_buf,
+					sizeof(type2_dongle_buf),
+					true))
+					break;
+				retry_count--;
+			}
+			/* In case I2C over Aux no response, it is interpreted as DISPLAY_DONGLE_NONE */
+			if (retry_count == 0) {
+				return;
+			}
+		}
+	} else {
 	if (!i2c_read(
 		ddc,
 		DP_HDMI_DONGLE_ADDRESS,
@@ -360,6 +388,7 @@ static void query_dp_dual_mode_adaptor(
 			return;
 		}
 	}
+	}
 
 	/* Check if Type 2 dongle.*/
 	if (type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_ID] == DP_ADAPTOR_TYPE2_ID)
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
index 67ce8d95bbd6..89265b083935 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
@@ -577,6 +577,10 @@ static bool construct_phy(struct dc_link *link,
 		link->is_internal_display = (disp_connect_caps_info.INTERNAL_DISPLAY != 0);
 		DC_LOG_DC("BIOS object table - is_internal_display: %d", link->is_internal_display);
 		link->no_ddc_pin = disp_connect_caps_info.NO_DDC_PIN != 0;
+		//reworked DP port on N-1 board, for testing on N-1, to be removed when IFWI ready
+		if (link->dc->config.dp_connector_no_native_i2c &&
+			(link->link_id.enum_id == link->dc->config.link_index_with_no_ddc))
+			link->no_ddc_pin = true;
 		link->force_to_use_aux = link->dc->config.dp_connector_no_native_i2c
 				&& link->no_ddc_pin;
 	}
@@ -642,6 +646,7 @@ static bool construct_phy(struct dc_link *link,
 			link->hpd_src = hpd_info.hpd_int_gpio_uid - 1;
 			link->irq_source_hpd =  DC_IRQ_SOURCE_HPD1 + link->hpd_src;
 			enc_init_data.hpd_source = link->hpd_src;
+			enc_init_data.hpd_active_high = (hpd_info.hpd_active == 0) ? true : false;
 			DC_LOG_DC("BIOS object table - hpd_int_gpio_uid id: %d", hpd_info.hpd_int_gpio_uid);
 		} else {
 			ASSERT(0);
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
index f9d5a2441e38..6123b10977bf 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
@@ -423,6 +423,14 @@ int link_aux_transfer_raw(struct ddc_service *ddc,
 		struct aux_payload *payload,
 		enum aux_return_code_type *operation_result)
 {
+	if (ddc->ctx->dc->config.dp_connector_no_native_i2c && ddc->link->no_ddc_pin) {
+		/* Check whether aux to be processed via dmub or dcn directly */
+		if (ddc->ctx->dc->debug.enable_dmub_aux_for_legacy_ddc) {
+			return dce_aux_transfer_dmub_raw(ddc, payload, operation_result);
+		} else {
+			return dce_aux_transfer_raw_without_ddc_pin(ddc, payload, operation_result);
+		}
+	}
 	return dce_aux_transfer_raw(ddc, payload, operation_result);
 }
 
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
index 2afdfc113675..75ec3b701d81 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
@@ -144,6 +144,11 @@ void hdmi_frl_retrieve_link_cap(struct dc_link *link, struct dc_sink *sink)
 
 	if (link->link_enc->features.flags.bits.IS_FRL_12G_CAPABLE)
 		encoder_link_rate = HDMI_FRL_LINK_RATE_12GBPS;
+	if (link->link_enc->features.flags.bits.IS_FRL_16G_CAPABLE)
+		encoder_link_rate = HDMI_FRL_LINK_RATE_16GBPS;
+
+	if (link->link_enc->features.flags.bits.IS_FRL_20G_CAPABLE)
+		encoder_link_rate = HDMI_FRL_LINK_RATE_20GBPS;
 
 	if (link->dc->debug.max_frl_rate != 0 && encoder_link_rate > link->dc->debug.max_frl_rate)
 		encoder_link_rate = link->dc->debug.max_frl_rate;
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c
index a3431ec2f058..4370d64259e7 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c
@@ -40,8 +40,8 @@
  * results in the parameters.
  */
 
-static bool optc42_get_crc(struct timing_generator *optc, uint8_t idx,
-		   uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
+bool optc42_get_crc(struct timing_generator *optc, uint8_t idx,
+	uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
 {
 	uint32_t field = 0;
 	struct optc *optc1 = DCN10TG_FROM_TG(optc);
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h
index d652358eea22..758cddd9e64f 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h
@@ -395,4 +395,6 @@ void optc42_clear_optc_underflow(struct timing_generator *optc);
 bool optc42_is_optc_underflow_occurred(struct timing_generator *optc);
 bool optc42_disable_crtc(struct timing_generator *optc);
 void optc42_lock_doublebuffer_enable(struct timing_generator *optc);
+bool optc42_get_crc(struct timing_generator *optc, uint8_t idx,
+	uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb);
 #endif /* __DC_OPTC_DCN42_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c
index db1b6a1b92e8..37974c45b44a 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c
@@ -1419,6 +1419,7 @@ static bool dcn10_resource_construct(
 	dc->caps.color.dpp.post_csc = 0;
 	dc->caps.color.dpp.gamma_corr = 0;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 1;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 0;
 	dc->caps.color.dpp.ogam_ram = 1; // RGAM on DCN1
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
index 95abc4c38eae..996fce26941f 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
@@ -2502,6 +2502,7 @@ static bool dcn20_resource_construct(
 	dc->caps.color.dpp.post_csc = 0;
 	dc->caps.color.dpp.gamma_corr = 0;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 1;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c
index 02b7dc07ad53..765c63513a31 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c
@@ -1165,6 +1165,7 @@ static bool dcn201_resource_construct(
 	dc->caps.color.dpp.post_csc = 0;
 	dc->caps.color.dpp.gamma_corr = 0;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 1;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
index b653f951e104..4095a850ebc6 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
@@ -1478,6 +1478,7 @@ static bool dcn21_resource_construct(
 	dc->caps.color.dpp.post_csc = 0;
 	dc->caps.color.dpp.gamma_corr = 0;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 1;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
index 40fc66e64c1b..f09bbb932150 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
@@ -2496,6 +2496,7 @@ static bool dcn30_resource_construct(
 	dc->caps.color.dpp.post_csc = 1;
 	dc->caps.color.dpp.gamma_corr = 1;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 0;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c
index 551565ae9ef2..29113f518c53 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c
@@ -1497,6 +1497,7 @@ static bool dcn301_resource_construct(
 	dc->caps.color.dpp.post_csc = 1;
 	dc->caps.color.dpp.gamma_corr = 1;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 0;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
index 2574e706631d..d6b036e3933e 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
@@ -1397,6 +1397,7 @@ static bool dcn302_resource_construct(
 	dc->caps.color.dpp.post_csc = 1;
 	dc->caps.color.dpp.gamma_corr = 1;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 0;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
index 8b24628e3e14..c8598ba23dd0 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
@@ -1341,6 +1341,7 @@ static bool dcn303_resource_construct(
 	dc->caps.color.dpp.post_csc = 1;
 	dc->caps.color.dpp.gamma_corr = 1;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 0;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
index 372e05487847..5f08fb136b14 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
@@ -2032,6 +2032,7 @@ static bool dcn314_resource_construct(
 	dc->caps.color.dpp.post_csc = 1;
 	dc->caps.color.dpp.gamma_corr = 1;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 0;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
index 6e112ef0a49a..7c78f8ba40ef 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
@@ -2076,6 +2076,7 @@ static bool dcn315_resource_construct(
 	dc->caps.color.dpp.post_csc = 1;
 	dc->caps.color.dpp.gamma_corr = 1;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 0;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
index cd9d2087d14e..a20ff9f0c3f8 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
@@ -2428,6 +2428,7 @@ static bool dcn32_resource_construct(
 	dc->caps.color.dpp.post_csc = 1;
 	dc->caps.color.dpp.gamma_corr = 1;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 0;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 0;
 	dc->caps.color.dpp.ogam_ram = 0;  // no OGAM in DPP since DCN1
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
index ff9c1379896e..105fba8ff171 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
@@ -1919,6 +1919,7 @@ static bool dcn321_resource_construct(
 	dc->caps.color.dpp.post_csc = 1;
 	dc->caps.color.dpp.gamma_corr = 1;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 0;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 0;
 	dc->caps.color.dpp.ogam_ram = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
index 1b9b6eb8b322..a92e0dc5ad6a 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
@@ -2058,6 +2058,7 @@ static bool dcn35_resource_construct(
 	dc->caps.color.dpp.post_csc = 1;
 	dc->caps.color.dpp.gamma_corr = 1;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 0;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 0;
 	dc->caps.color.dpp.ogam_ram = 0;  // no OGAM in DPP since DCN1
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
index 2268ced16969..68a2169da0c1 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
@@ -2031,6 +2031,7 @@ static bool dcn351_resource_construct(
 	dc->caps.color.dpp.post_csc = 1;
 	dc->caps.color.dpp.gamma_corr = 1;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 0;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 0;
 	dc->caps.color.dpp.ogam_ram = 0;  // no OGAM in DPP since DCN1
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c
index b1323e76801e..ba04e8b9b569 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c
@@ -2028,6 +2028,7 @@ static bool dcn36_resource_construct(
 	dc->caps.color.dpp.post_csc = 1;
 	dc->caps.color.dpp.gamma_corr = 1;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 0;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 0;
 	dc->caps.color.dpp.ogam_ram = 0;  // no OGAM in DPP since DCN1
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
index 181cb7135dfb..fff84f9ce816 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
@@ -305,19 +305,21 @@ static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5];
 
 static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5];
 
-#define link_regs_init(id, phyid)\
-	LE_DCN401_REG_LIST_RI(id)
+#define link_regs_init(id, phyid) \
+	LE_DCN401_REG_LIST_RI(id), \
+	LE_DCN60_REG_LIST_RI(id)
 
 static struct dcn10_link_enc_registers link_enc_regs[4];
 
 
 static const struct dcn10_link_enc_shift le_shift = {
-	LINK_ENCODER_MASK_SH_LIST_DCN401(__SHIFT)
+	LINK_ENCODER_MASK_SH_LIST_DCN401(__SHIFT), \
+	LINK_ENCODER_MASK_SH_LIST_DCN60_ON_DCN401(__SHIFT)
 };
 
-
 static const struct dcn10_link_enc_mask le_mask = {
-	LINK_ENCODER_MASK_SH_LIST_DCN401(_MASK)
+	LINK_ENCODER_MASK_SH_LIST_DCN401(_MASK), \
+	LINK_ENCODER_MASK_SH_LIST_DCN60_ON_DCN401(_MASK)
 };
 
 
@@ -602,8 +604,12 @@ static const struct dccg_mask dccg_mask = {
 
 static struct dce_hwseq_registers hwseq_reg;
 
-#define hwseq_reg_init()\
-	HWSEQ_DCN401_REG_LIST()
+#define HWSEQ_DCN60_REG_LIST() \
+	SR(HDCP_INTERRUPT_DEST)
+
+#define hwseq_reg_init() \
+	HWSEQ_DCN401_REG_LIST(), \
+	HWSEQ_DCN60_REG_LIST()
 
 #define HWSEQ_DCN401_MASK_SH_LIST(mask_sh)\
 	HWSEQ_DCN_MASK_SH_LIST(mask_sh), \
@@ -651,12 +657,20 @@ static struct dce_hwseq_registers hwseq_reg;
 	HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \
 	HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh)
 
+#define HWSEQ_DCN60_MASK_SH_LIST(mask_sh) \
+	HWS_SF(, HDCP_INTERRUPT_DEST, DOUT_IHC_HDCP0_I2C_XFER_REQ_INTERRUPT_DEST, mask_sh), \
+	HWS_SF(, HDCP_INTERRUPT_DEST, DOUT_IHC_HDCP1_I2C_XFER_REQ_INTERRUPT_DEST, mask_sh), \
+	HWS_SF(, HDCP_INTERRUPT_DEST, DOUT_IHC_HDCP2_I2C_XFER_REQ_INTERRUPT_DEST, mask_sh), \
+	HWS_SF(, HDCP_INTERRUPT_DEST, DOUT_IHC_HDCP3_I2C_XFER_REQ_INTERRUPT_DEST, mask_sh)
+
 static const struct dce_hwseq_shift hwseq_shift = {
-		HWSEQ_DCN401_MASK_SH_LIST(__SHIFT)
+		HWSEQ_DCN401_MASK_SH_LIST(__SHIFT), \
+		HWSEQ_DCN60_MASK_SH_LIST(__SHIFT)
 };
 
 static const struct dce_hwseq_mask hwseq_mask = {
-		HWSEQ_DCN401_MASK_SH_LIST(_MASK)
+		HWSEQ_DCN401_MASK_SH_LIST(_MASK), \
+		HWSEQ_DCN60_MASK_SH_LIST(_MASK)
 };
 
 #define vmid_regs_init(id)\
@@ -2111,6 +2125,7 @@ static bool dcn401_resource_construct(
 	dc->caps.color.dpp.post_csc = 1;
 	dc->caps.color.dpp.gamma_corr = 1;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 0;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 0;
 	dc->caps.color.dpp.ogam_ram = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
index 42a0986d6fe2..8e3473f86490 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
@@ -236,6 +236,10 @@ int dcn401_get_power_profile(const struct dc_state *context);
 	SRI_ARR(DIG_BE_CLK_CNTL, DIG, id),\
 	SR_ARR(DIO_CLK_CNTL, id)
 
+#define LE_DCN60_REG_LIST_RI(id)                                             \
+	SRI_ARR(HDCP_I2C_CONTROL_0, DIG, id),                                    \
+	SRI_ARR(HDCP_INT_CONTROL, DIG, id)
+
 /* DPP */
 #define DPP_REG_LIST_DCN401_COMMON_RI(id)                                    \
 	SRI_ARR(CM_DEALPHA, CM, id), SRI_ARR(CM_MEM_PWR_STATUS, CM, id),         \
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
index dba1b69137f9..7507994f12d8 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
@@ -2066,6 +2066,7 @@ static bool dcn42_resource_construct(
 	dc->caps.color.dpp.post_csc = 1;
 	dc->caps.color.dpp.gamma_corr = 1;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 0;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 0;
 	dc->caps.color.dpp.ogam_ram = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c
index 1e3ee25732fa..3821846aa2d0 100644
--- a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c
+++ b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c
@@ -6,6 +6,7 @@
 #include "soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.h"
 #include "soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.h"
 #include "soc_and_ip_translator/dcn42b/dcn42b_soc_and_ip_translator.h"
+#include "soc_and_ip_translator/dcn60/dcn60_soc_and_ip_translator.h"
 
 static void dc_construct_soc_and_ip_translator(struct soc_and_ip_translator *soc_and_ip_translator,
 		enum dce_version dc_version)
@@ -20,6 +21,9 @@ static void dc_construct_soc_and_ip_translator(struct soc_and_ip_translator *soc
 	case DCN_VERSION_4_2B:
 		dcn42b_construct_soc_and_ip_translator(soc_and_ip_translator);
 		break;
+	case DCN_VERSION_6_0:
+		dcn60_construct_soc_and_ip_translator(soc_and_ip_translator);
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
index 94d4b40ee16a..d8a18cd97811 100644
--- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
@@ -122,6 +122,8 @@ enum dmub_asic {
 	DMUB_ASIC_DCN401,
 	DMUB_ASIC_DCN42,
 	DMUB_ASIC_DCN42B,
+	DMUB_ASIC_DCN60,
+
 	DMUB_ASIC_MAX,
 };
 
@@ -318,6 +320,8 @@ struct dmub_srv_fb_info {
 struct dmub_soc_fb_info {
 	uint64_t fb_base;
 	uint64_t fb_offset;
+	uint32_t alt_channel_region_size[2];
+	uint64_t alt_channel_region_base[2]; /* mc address */
 };
 
 /*
@@ -608,6 +612,7 @@ struct dmub_srv {
 	struct dmub_srv_dcn35_regs *regs_dcn35;
 	const struct dmub_srv_dcn401_regs *regs_dcn401;
 	struct dmub_srv_dcn42_regs *regs_dcn42;
+    const struct dmub_srv_dcn60_regs *regs_dcn60;
 	struct dmub_srv_base_funcs funcs;
 	struct dmub_srv_hw_funcs hw_funcs;
 	struct dmub_srv_inbox inbox1;
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
index e7879bd81f83..44aefa3608ec 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -910,6 +910,41 @@ struct dmub_cursor_offload_pipe_data_dcn401_v1 {
 	uint32_t reserved2[3];
 };
 
+/**
+ * struct dmub_cursor_offload_pipe_data_dcn60_v1 - DCN60 per pipe data.
+ */
+struct dmub_cursor_offload_pipe_data_dcn60_v1 {
+	uint32_t CURSOR0_0_CURSOR_SURFACE_ADDRESS;
+	uint32_t CURSOR0_0_CURSOR_SURFACE_ADDRESS_HIGH;
+	uint32_t CURSOR0_0_CURSOR_SIZE__CURSOR_WIDTH : 16;
+	uint32_t CURSOR0_0_CURSOR_SIZE__CURSOR_HEIGHT : 16;
+	uint32_t CURSOR0_0_CURSOR_POSITION__CURSOR_X_POSITION : 16;
+	uint32_t CURSOR0_0_CURSOR_POSITION__CURSOR_Y_POSITION : 16;
+	uint32_t CURSOR0_0_CURSOR_HOT_SPOT__CURSOR_HOT_SPOT_X : 16;
+	uint32_t CURSOR0_0_CURSOR_HOT_SPOT__CURSOR_HOT_SPOT_Y : 16;
+	uint32_t CURSOR0_0_CURSOR_DST_OFFSET__CURSOR_DST_X_OFFSET : 13;
+	uint32_t CURSOR0_0_CURSOR_CONTROL__CURSOR_ENABLE : 1;
+	uint32_t CURSOR0_0_CURSOR_CONTROL__CURSOR_MODE : 3;
+	uint32_t CURSOR0_0_CURSOR_CONTROL__CURSOR_2X_MAGNIFY : 1;
+	uint32_t CURSOR0_0_CURSOR_CONTROL__CURSOR_PITCH : 2;
+	uint32_t CURSOR0_0_CURSOR_CONTROL__CURSOR_LINES_PER_CHUNK : 5;
+	uint32_t reserved0[4];
+	uint32_t CM_CUR0_CURSOR0_CONTROL__CUR0_ENABLE : 1;
+	uint32_t CM_CUR0_CURSOR0_CONTROL__CUR0_MODE : 3;
+	uint32_t CM_CUR0_CURSOR0_CONTROL__CUR0_EXPANSION_MODE : 1;
+	uint32_t CM_CUR0_CURSOR0_CONTROL__CUR0_ROM_EN : 1;
+	uint32_t CM_CUR0_CURSOR0_COLOR0__CUR0_COLOR0 : 24;
+	uint32_t CM_CUR0_CURSOR0_COLOR1__CUR0_COLOR1 : 24;
+	uint32_t CM_CUR0_CURSOR0_FP_SCALE_BIAS_G_Y__CUR0_FP_BIAS_G_Y : 16;
+	uint32_t CM_CUR0_CURSOR0_FP_SCALE_BIAS_G_Y__CUR0_FP_SCALE_G_Y, : 16;
+	uint32_t CM_CUR0_CURSOR0_FP_SCALE_BIAS_RB_CRCB__CUR0_FP_BIAS_RB_CRCB : 16;
+	uint32_t CM_CUR0_CURSOR0_FP_SCALE_BIAS_RB_CRCB__CUR0_FP_SCALE_RB_CRCB : 16;
+	uint32_t reserved1[4];
+	uint32_t HUBPREQ0_CURSOR_SETTINGS__CURSOR0_DST_Y_OFFSET : 8;
+	uint32_t HUBPREQ0_CURSOR_SETTINGS__CURSOR0_CHUNK_HDL_ADJUST : 8;
+	uint32_t HUBPREQ0_CURSOR_SETTINGS__FORCE_CURSOR_TO_DISP_PREF : 1;
+	uint32_t reserved2[3];
+};
 /**
  * struct dmub_cursor_offload_pipe_data_v1 - Per pipe data for cursor offload.
  */
@@ -917,6 +952,7 @@ struct dmub_cursor_offload_pipe_data_v1 {
 	union {
 		struct dmub_cursor_offload_pipe_data_dcn30_v1 dcn30; /**< DCN30 cursor data. */
 		struct dmub_cursor_offload_pipe_data_dcn401_v1 dcn401; /**< DCN401 cursor data. */
+		struct dmub_cursor_offload_pipe_data_dcn60_v1 dcn60; /**< DCN60 cursor data. */
 		uint8_t payload[96]; /**< Guarantees the cursor pipe data size per-pipe. */
 	};
 };
@@ -2465,6 +2501,7 @@ enum fams2_stream_type {
 	FAMS2_STREAM_TYPE_VACTIVE = 2,
 	FAMS2_STREAM_TYPE_DRR = 3,
 	FAMS2_STREAM_TYPE_SUBVP = 4,
+	FAMS2_STREAM_TYPE_ALTERNATE = 5,
 };
 
 struct dmub_rect16 {
@@ -2489,6 +2526,140 @@ struct dmub_rect16 {
 	uint16_t height;
 };
 
+struct plane_pipe_rect {
+	struct dmub_rect16 luma;
+	struct dmub_rect16 chroma;
+};
+
+/**
+ * Structure to hold the LSDMA source / dest copy parameters.
+ * Each field is an array of [2][4]:
+ * [2] - Instance 0 is the copy for current frame, instance 1 is the copy for next frame (instance 1 potentially unused if no next)
+ * [4] - One instance per pipe
+ */
+
+struct lsdma_outputs {
+	uint16_t src_x[2][4]; // src x position for the copy. Array of [2][4] for curr vs. next and each pipe
+	uint16_t src_y[2][4]; // src y position for the copy
+	uint16_t dst_x[2][4]; // dst x position for the copy (can change for curr vs. next)
+	uint16_t dst_y[2][4]; // dst y position for the copy (can change for curr vs. next)
+	uint16_t width[2][4]; // src and dst width for the copy (src and dst must match)
+	uint16_t height[2][4]; // src and dst height for the copy (src and dst must match)
+	uint16_t dst_pitch[4]; // dst pitch for the copy (same for curr and next)
+};
+
+struct dmub_fams2_alternate_stream_dynamic_state {
+	uint64_t earliest_init_tick; // track earliest possible init tick for calculating is_tick_in_allow
+	uint32_t otg_frame_pending_clear[3]; // In this context pending means prefetch has never been completed for this frame yet
+	uint8_t flip_pending_clear_order[3];
+	uint8_t num_pending_flips;
+	uint32_t prefetch_start_line_x1000[3]; // can compute from existing params, but store because we use this multiple times
+	uint16_t prefetch_end_line[3]; // can compute from existing params, but store because we use this multiple times
+	uint16_t recout_y[3];
+	uint8_t flip_pending[3];
+	uint8_t copy_from_earliest[3];
+	uint16_t lsdma_bandwidth_mbps;
+	uint16_t vstartup_line;
+	uint16_t vready_line;
+	uint8_t cursor_size[3]; //  Cursor array per plane for now - if we assume a single cursor, then we don't need an array
+	uint8_t pad; // to maintain alignment for below fields - re-arrange structure once all fields are finalized
+	/* outputs: */
+	uint16_t subvp_start_line_a[3];
+	uint16_t subvp_height_a[3];
+	uint16_t subvp_next_start_line_a[3];
+	uint16_t subvp_next_height_a[3];
+	uint16_t subvp_start_line_b[3];
+	uint16_t subvp_height_b[3];
+	uint16_t subvp_next_start_line_b[3];
+	uint16_t subvp_next_height_b[3];
+	uint16_t subvp_c_start_line_a[3];
+	uint16_t subvp_c_height_a[3];
+	uint16_t subvp_c_next_start_line_a[3];
+	uint16_t subvp_c_next_height_a[3];
+	uint16_t subvp_c_start_line_b[3];
+	uint16_t subvp_c_height_b[3];
+	uint16_t subvp_c_next_start_line_b[3];
+	uint16_t subvp_c_next_height_b[3];
+	uint8_t subvp_position[3];
+	uint8_t pad1[1]; // to maintain alignment for below fields - re-arrange structure once all fields are finalized
+	uint32_t program_go_line;
+	uint32_t program_go_frame_count;
+	uint16_t svp0_start_dst_line;
+	uint16_t svp0_end_dst_line;
+	uint16_t svp1_start_dst_line;
+	uint16_t svp1_end_dst_line;
+	struct lsdma_outputs lsdma[2]; // [2] - instance per SVP0 and SVP1
+	struct lsdma_outputs lsdma_c[2]; // [2] - instance per SVP0 and SVP1
+};
+struct dmub_fams2_cmd_alternate_stream_static_state {
+	uint32_t total_bytes_to_copy;
+	uint16_t svp0_dst_lines; // per stream
+	uint16_t svp1_dst_lines; // per stream
+	uint16_t min_lead_dst_lines; // per stream, should be max(nominal_req_limit, vstartup_to_vactive). Does not have to be maxed over all planes
+	uint16_t svp_req_limit; // per stream, should be the same value in time between all streams max(2 swaths, dst_y_pre) over all planes
+	uint16_t fw_delays;
+	uint16_t vstartup_start;
+	uint16_t rec_height[3];
+	uint16_t viewport_start[3];
+	uint16_t viewport_size[3]; // for now size will be the number of lines perpendicular to scan direction (height for 0 / 180, width for 90 and 270)
+	uint16_t viewport_start_c[3];
+	uint16_t viewport_size_c[3];
+	uint16_t surface_pitch[3];
+	uint16_t surface_pitch_c[3];
+	uint16_t surface_height[3];
+	uint16_t surface_height_c[3];
+	uint8_t element_size[3];
+	uint8_t element_size_c[3];
+	uint8_t swizzle_mode[3]; // TODO: Add mapping, should be value used in LSDMA command
+	uint8_t vready_offset_lines; // vready offset from vstartup in lines (rounded up, as the actual offset may be a fraction of a line)
+	uint16_t dst_y_prefetch_x1000[3];
+	uint16_t total_swaths[3];
+	uint16_t total_swaths_c[3];
+	uint8_t prefetch_swaths[3];
+	uint8_t prefetch_swaths_c[3];
+	uint8_t swath_height[3];
+	uint8_t swath_height_c[3];
+	uint16_t block_256b_width[3];
+	uint16_t block_256b_height[3];
+	uint16_t block_256b_width_c[3];
+	uint16_t block_256b_height_c[3];
+	uint16_t macro_tile_width[3];
+	uint16_t macro_tile_width_c[3];
+	union {
+		struct {
+			uint8_t is_multi_planar : 1;
+			uint8_t is_yuv420 : 1;
+			uint8_t prefetch_relative_vblank : 1;
+			uint8_t vertical_access : 1; // vertical_access = 1 means 90 or 270 rotation
+			uint8_t access_direction : 1; // access_direction = 1 means bigger to smaller coordinations (e.g., scan from 2160 to 0 as opposed to regular 0 to 2160)
+			uint8_t dcc : 1;
+			uint8_t tmz : 1; // TODO: Need to assign outside of DML (DML not aware of TMZ)
+		} bits;
+		uint8_t all;
+	} config[3];
+	uint8_t max_cursor_size;
+	uint16_t pre_hdl_delta_x1000[3];
+	uint16_t pre_hdl_delta_c_x1000[3];
+	uint16_t rec_hdl_delta_x1000[3];
+	uint16_t rec_hdl_delta_c_x1000[3];
+	uint16_t dst_y_per_vm_vblank_x1000[3];
+	uint16_t dst_y_per_row_vblank_x1000[3];
+	uint16_t dst_y_after_scaler[3];
+	uint16_t vinit_prefill[3];
+	uint16_t vinit_prefill_c[3];
+	uint16_t vratio_x1000[3];
+	uint16_t vratio_c_x1000[3];
+	struct plane_pipe_rect pipe_viewports[4];
+	/* TODO - remove these deprecated vars */
+	uint32_t pipe_copy_offset[2][4]; // [2] - SVP0/1, [4] - 4 pipes
+	uint32_t pipe_copy_offset_c[2][4];
+	/* bits 47:16 of the surface address */
+	uint32_t pipe_copy_addr_47_16[2][4]; // [2] - SVP0/1, [4] - 4 pipes
+	uint32_t pipe_copy_addr_47_16_c[2][4];
+	uint32_t pipe_copy_max_size[2][4];
+	uint32_t pipe_copy_max_size_c[2][4];
+};
+
 /* static stream state */
 struct dmub_fams2_legacy_stream_static_state {
 	uint8_t vactive_det_fill_delay_otg_vlines;
@@ -2567,6 +2738,7 @@ union dmub_fams2_cmd_stream_static_sub_state {
 
 union dmub_fams2_stream_static_sub_state_v2 {
 	COMMON_STREAM_STATIC_SUB_STATE
+	struct dmub_fams2_cmd_alternate_stream_static_state alternate;
 }; //v2
 
 struct dmub_fams2_stream_static_state {
@@ -2660,7 +2832,8 @@ union dmub_fams2_global_feature_config {
 		uint32_t enable_visual_confirm: 1;
 		uint32_t allow_delay_check_mode: 2;
 		uint32_t legacy_method_no_fams2 : 1;
-		uint32_t reserved : 23;
+		uint32_t alternate_channel_workaround : 1;
+		uint32_t reserved: 22;
 	} bits;
 	uint32_t all;
 };
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
index 5a1a2276c432..204375f1eff8 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
@@ -42,6 +42,7 @@
 #include "dmub_dcn401.h"
 #include "dmub_dcn42.h"
 #include "dmub_dcn42b.h"
+#include "dmub_dcn60.h"
 #include "os_types.h"
 /*
  * Note: the DMUB service is standalone. No additional headers should be
@@ -528,6 +529,57 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
 		funcs->enable_reg_inbox0_rsp_int = dmub_dcn401_enable_reg_inbox0_rsp_int;
 		funcs->enable_reg_outbox0_rdy_int = dmub_dcn401_enable_reg_outbox0_rdy_int;
 		break;
+	case DMUB_ASIC_DCN60:
+		dmub->regs_dcn60 = &dmub_srv_dcn60_regs;
+		funcs->configure_dmub_in_system_memory = dmub_dcn60_configure_dmub_in_system_memory;
+		funcs->send_inbox0_cmd = dmub_dcn60_send_inbox0_cmd;
+		funcs->clear_inbox0_ack_register = dmub_dcn60_clear_inbox0_ack_register;
+		funcs->read_inbox0_ack_register = dmub_dcn60_read_inbox0_ack_register;
+		funcs->reset = dmub_dcn60_reset;
+		funcs->reset_release = dmub_dcn60_reset_release;
+		funcs->backdoor_load = dmub_dcn60_backdoor_load;
+		funcs->backdoor_load_zfb_mode = dmub_dcn60_backdoor_load_zfb_mode;
+		funcs->setup_windows = dmub_dcn60_setup_windows;
+		funcs->setup_mailbox = dmub_dcn60_setup_mailbox;
+		funcs->get_inbox1_wptr = dmub_dcn60_get_inbox1_wptr;
+		funcs->get_inbox1_rptr = dmub_dcn60_get_inbox1_rptr;
+		funcs->set_inbox1_wptr = dmub_dcn60_set_inbox1_wptr;
+		funcs->setup_out_mailbox = dmub_dcn60_setup_out_mailbox;
+		funcs->get_outbox1_wptr = dmub_dcn60_get_outbox1_wptr;
+		funcs->set_outbox1_rptr = dmub_dcn60_set_outbox1_rptr;
+		funcs->is_supported = dmub_dcn60_is_supported;
+		funcs->is_hw_init = dmub_dcn60_is_hw_init;
+		funcs->set_gpint = dmub_dcn60_set_gpint;
+		funcs->is_gpint_acked = dmub_dcn60_is_gpint_acked;
+		funcs->get_gpint_response = dmub_dcn60_get_gpint_response;
+		funcs->get_gpint_dataout = dmub_dcn60_get_gpint_dataout;
+		funcs->get_fw_status = dmub_dcn60_get_fw_boot_status;
+		funcs->enable_dmub_boot_options = dmub_dcn60_enable_dmub_boot_options;
+		funcs->skip_dmub_panel_power_sequence = dmub_dcn60_skip_dmub_panel_power_sequence;
+		//outbox0 call stacks
+		funcs->setup_outbox0 = dmub_dcn60_setup_outbox0;
+		funcs->get_outbox0_wptr = dmub_dcn60_get_outbox0_wptr;
+		funcs->set_outbox0_rptr = dmub_dcn60_set_outbox0_rptr;
+
+		funcs->get_current_time = dmub_dcn60_get_current_time;
+		funcs->get_diagnostic_data = dmub_dcn60_get_diagnostic_data;
+
+		funcs->send_reg_inbox0_cmd_msg = dmub_dcn60_send_reg_inbox0_cmd_msg;
+		funcs->read_reg_inbox0_rsp_int_status = dmub_dcn60_read_reg_inbox0_rsp_int_status;
+		funcs->read_reg_inbox0_cmd_rsp = dmub_dcn60_read_reg_inbox0_cmd_rsp;
+		funcs->write_reg_inbox0_rsp_int_ack = dmub_dcn60_write_reg_inbox0_rsp_int_ack;
+		funcs->clear_reg_inbox0_rsp_int_ack = dmub_dcn60_clear_reg_inbox0_rsp_int_ack;
+		funcs->enable_reg_inbox0_rsp_int = dmub_dcn60_enable_reg_inbox0_rsp_int;
+		default_inbox_type = DMUB_CMD_INTERFACE_FB; // still default to FB for now
+
+		funcs->write_reg_outbox0_rdy_int_ack = dmub_dcn60_write_reg_outbox0_rdy_int_ack;
+		funcs->read_reg_outbox0_msg = dmub_dcn60_read_reg_outbox0_msg;
+		funcs->write_reg_outbox0_rsp = dmub_dcn60_write_reg_outbox0_rsp;
+		funcs->read_reg_outbox0_rdy_int_status = dmub_dcn60_read_reg_outbox0_rdy_int_status;
+		funcs->read_reg_outbox0_rsp_int_status = dmub_dcn60_read_reg_outbox0_rsp_int_status;
+		funcs->enable_reg_inbox0_rsp_int = dmub_dcn60_enable_reg_inbox0_rsp_int;
+		funcs->enable_reg_outbox0_rdy_int = dmub_dcn60_enable_reg_outbox0_rdy_int;
+		break;
 	default:
 		return false;
 	}
diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h
index ca77d29ebacc..7ed785be8473 100644
--- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h
+++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h
@@ -266,6 +266,24 @@ enum {
 #define ASICREV_IS_DCN36(eChipRev) ((eChipRev) >= 0x50 && (eChipRev) < 0xC0)
 
 #define AMDGPU_FAMILY_GC_12_0_0         152 /* GC 12.0.0 */
+#define AMDGPU_FAMILY_GC_13_0_1         153 /*We may need an update if we find DCN5 and DCN6
+											do not share the same GFX version*/
+enum {
+	DCN6_VARIANT0_A0        = 0x1,
+	DCN6_VARIANT1_A0        = DCN6_VARIANT0_A0,
+	DCN6_VARIANT2_A0        = 0x10,
+	DCN6_VARIANT2_B0        = 0x11,
+	DCN6_VARIANT3_A0        = 0x20,
+	DCN6_VARIANT3_UPPER     = 0x2F,
+	DCN6_UNKNOWN		= 0xFF
+};
+
+#define ASICREV_IS_DCN6_VARIANT0(eChipRev)        (eChipRev < DCN6_VARIANT2_A0)
+#define ASICREV_IS_DCN6_VARIANT1(eChipRev)        ASICREV_IS_DCN_VARIANT0(eChipRev)
+#define ASICREV_IS_DCN6_VARIANT2(eChipRev)        (eChipRev >= DCN6_VARIANT2_A0 && eChipRev < DCN6_VARIANT3_A0)
+#define ASICREV_IS_DCN6_VARIANT2_A0(eChipRev)     (eChipRev >= DCN6_VARIANT2_A0 && eChipRev < DCN6_VARIANT2_B0)
+#define ASICREV_IS_DCN6_VARIANT2_B0(eChipRev)     (eChipRev >= DCN6_VARIANT2_B0 && eChipRev < DCN6_VARIANT3_A0)
+#define ASICREV_IS_DCN6_VARIANT3(eChipRev)        (eChipRev >= DCN6_VARIANT3_A0 && eChipRev <= DCN6_VARIANT3_UPPER)
 
 enum {
 	GC_12_0_0_A0 = 0x50,
-- 
2.34.1