[PATCH 11/43] drm/amd/display: Add dependant changes for DCN32/321

Alex Deucher alexander.deucher at amd.com
Wed May 25 16:19:09 UTC 2022


From: Aurabindo Pillai <aurabindo.pillai at amd.com>

[Why&How]
This patch adds necessary changes needed in DC files outside DCN32/321
specific tree

v2: squash in updates (Alex)

Signed-off-by: Aurabindo Pillai <aurabindo.pillai at amd.com>
Acked-by: Alex Deucher <alexander.deucher at amd.com>
Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
---
 drivers/gpu/drm/amd/display/dc/Makefile       |   2 +
 .../drm/amd/display/dc/bios/bios_parser2.c    | 949 ++++++++++++++----
 .../dc/bios/bios_parser_types_internal2.h     |   1 +
 .../display/dc/bios/command_table_helper2.c   |   2 +
 .../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c  |   2 +-
 drivers/gpu/drm/amd/display/dc/core/dc.c      |  14 +-
 .../gpu/drm/amd/display/dc/core/dc_resource.c |  20 +-
 drivers/gpu/drm/amd/display/dc/dc.h           |  19 +
 .../gpu/drm/amd/display/dc/dc_bios_types.h    |   5 +
 drivers/gpu/drm/amd/display/dc/dc_hw_types.h  |   1 +
 drivers/gpu/drm/amd/display/dc/dc_stream.h    |  21 +
 drivers/gpu/drm/amd/display/dc/dce/dce_abm.h  |  45 +
 .../drm/amd/display/dc/dce/dce_clock_source.h |  15 +
 .../drm/amd/display/dc/dcn10/dcn10_hubbub.h   |  33 +
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c |   5 -
 .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.h |   2 +
 .../display/dc/dcn10/dcn10_stream_encoder.h   |  28 +-
 .../gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h |  34 +-
 .../gpu/drm/amd/display/dc/dcn20/dcn20_hubp.h |  25 +-
 .../drm/amd/display/dc/dcn20/dcn20_hwseq.c    |  32 +-
 .../dc/dcn30/dcn30_dio_stream_encoder.c       |  16 +-
 .../dc/dcn30/dcn30_dio_stream_encoder.h       |  35 +
 .../gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c  |   8 +-
 .../gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h  |  16 +
 .../gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c  |  14 +-
 .../gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h  | 147 +++
 .../gpu/drm/amd/display/dc/dcn30/dcn30_optc.h |   9 +
 .../gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c |  73 +-
 .../gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h |  14 +-
 .../gpu/drm/amd/display/dc/dcn31/dcn31_optc.c |  22 +-
 .../gpu/drm/amd/display/dc/dcn31/dcn31_optc.h |   6 +-
 .../dc/dcn32/dcn32_dio_stream_encoder.c       |  36 +-
 .../dc/dcn32/dcn32_dio_stream_encoder.h       |  15 +-
 .../drm/amd/display/dc/dcn32/dcn32_hwseq.c    |   4 +-
 .../gpu/drm/amd/display/dc/dcn32/dcn32_optc.c |  36 +-
 .../drm/amd/display/dc/dcn32/dcn32_resource.c |   2 +-
 .../drm/amd/display/dc/dml/dcn20/dcn20_fpu.c  |  59 +-
 .../gpu/drm/amd/display/dc/inc/core_types.h   |  10 +
 drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h  |   9 +-
 .../gpu/drm/amd/display/dc/inc/hw/dchubbub.h  |   3 +
 drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h  |   7 +
 .../gpu/drm/amd/display/dc/inc/hw/mem_input.h |   2 +
 .../amd/display/dc/inc/hw/stream_encoder.h    |   4 +
 .../amd/display/dc/inc/hw/timing_generator.h  |  10 +-
 .../gpu/drm/amd/display/dc/inc/hw_sequencer.h |   2 +
 .../amd/display/dc/inc/hw_sequencer_private.h |   5 +
 drivers/gpu/drm/amd/display/dc/inc/resource.h |   7 +
 .../amd/display/include/bios_parser_types.h   |  10 +
 48 files changed, 1529 insertions(+), 307 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile
index b4eca0236435..4de8e1871711 100644
--- a/drivers/gpu/drm/amd/display/dc/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/Makefile
@@ -38,6 +38,8 @@ DC_LIBS += dcn303
 DC_LIBS += dcn31
 DC_LIBS += dcn315
 DC_LIBS += dcn316
+DC_LIBS += dcn32
+DC_LIBS += dcn321
 endif
 
 DC_LIBS += dce120
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
index 23a3b640f0ee..bbc0a5769e88 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
@@ -165,9 +165,21 @@ static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)
 	unsigned int count = 0;
 	unsigned int i;
 
-	for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) {
-		if (bp->object_info_tbl.v1_4->display_path[i].encoderobjid != 0)
-			count++;
+	switch (bp->object_info_tbl.revision.minor) {
+	default:
+	case 4:
+		for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++)
+			if (bp->object_info_tbl.v1_4->display_path[i].encoderobjid != 0)
+				count++;
+
+		break;
+
+	case 5:
+		for (i = 0; i < bp->object_info_tbl.v1_5->number_of_path; i++)
+			if (bp->object_info_tbl.v1_5->display_path[i].encoderobjid != 0)
+				count++;
+
+		break;
 	}
 	return count;
 }
@@ -182,16 +194,34 @@ static struct graphics_object_id bios_parser_get_connector_id(
 	struct object_info_table *tbl = &bp->object_info_tbl;
 	struct display_object_info_table_v1_4 *v1_4 = tbl->v1_4;
 
-	if (v1_4->number_of_path > i) {
-		/* If display_objid is generic object id,  the encoderObj
-		 * /extencoderobjId should be 0
-		 */
-		if (v1_4->display_path[i].encoderobjid != 0 &&
-				v1_4->display_path[i].display_objid != 0)
-			object_id = object_id_from_bios_object_id(
+	struct display_object_info_table_v1_5 *v1_5 = tbl->v1_5;
+
+	switch (bp->object_info_tbl.revision.minor) {
+	default:
+	case 4:
+		if (v1_4->number_of_path > i) {
+			/* If display_objid is generic object id,  the encoderObj
+			 * /extencoderobjId should be 0
+			 */
+			if (v1_4->display_path[i].encoderobjid != 0 &&
+			    v1_4->display_path[i].display_objid != 0)
+				object_id = object_id_from_bios_object_id(
 					v1_4->display_path[i].display_objid);
-	}
+		}
+		break;
 
+	case 5:
+		if (v1_5->number_of_path > i) {
+			/* If display_objid is generic object id,  the encoderObjId
+		 * should be 0
+		 */
+			if (v1_5->display_path[i].encoderobjid != 0 &&
+			    v1_5->display_path[i].display_objid != 0)
+				object_id = object_id_from_bios_object_id(
+					v1_5->display_path[i].display_objid);
+		}
+		break;
+	}
 	return object_id;
 }
 
@@ -201,8 +231,8 @@ static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
 {
 	struct bios_parser *bp = BP_FROM_DCB(dcb);
 	unsigned int i;
-	enum bp_result  bp_result = BP_RESULT_BADINPUT;
-	struct graphics_object_id obj_id = {0};
+	enum bp_result bp_result = BP_RESULT_BADINPUT;
+	struct graphics_object_id obj_id = { 0 };
 	struct object_info_table *tbl = &bp->object_info_tbl;
 
 	if (!src_object_id)
@@ -217,37 +247,84 @@ static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
 		 * If found in for loop, should break.
 		 * DAL2 implementation may be changed too
 		 */
-		for (i = 0; i < tbl->v1_4->number_of_path; i++) {
-			obj_id = object_id_from_bios_object_id(
-			tbl->v1_4->display_path[i].encoderobjid);
-			if (object_id.type == obj_id.type &&
-					object_id.id == obj_id.id &&
-						object_id.enum_id ==
-							obj_id.enum_id) {
-				*src_object_id =
-				object_id_from_bios_object_id(0x1100);
-				/* break; */
+		switch (bp->object_info_tbl.revision.minor) {
+		default:
+		case 4:
+			for (i = 0; i < tbl->v1_4->number_of_path; i++) {
+				obj_id = object_id_from_bios_object_id(
+					tbl->v1_4->display_path[i].encoderobjid);
+				if (object_id.type == obj_id.type &&
+				    object_id.id == obj_id.id &&
+				    object_id.enum_id == obj_id.enum_id) {
+					*src_object_id =
+						object_id_from_bios_object_id(
+							0x1100);
+					/* break; */
+				}
+			}
+			bp_result = BP_RESULT_OK;
+			break;
+
+		case 5:
+			for (i = 0; i < tbl->v1_5->number_of_path; i++) {
+				obj_id = object_id_from_bios_object_id(
+					tbl->v1_5->display_path[i].encoderobjid);
+				if (object_id.type == obj_id.type &&
+				    object_id.id == obj_id.id &&
+				    object_id.enum_id == obj_id.enum_id) {
+					*src_object_id =
+						object_id_from_bios_object_id(
+							0x1100);
+					/* break; */
+				}
 			}
+			bp_result = BP_RESULT_OK;
+			break;
 		}
-		bp_result = BP_RESULT_OK;
 		break;
 	case OBJECT_TYPE_CONNECTOR:
-		for (i = 0; i < tbl->v1_4->number_of_path; i++) {
-			obj_id = object_id_from_bios_object_id(
-				tbl->v1_4->display_path[i].display_objid);
-
-			if (object_id.type == obj_id.type &&
-				object_id.id == obj_id.id &&
-					object_id.enum_id == obj_id.enum_id) {
-				*src_object_id =
-				object_id_from_bios_object_id(
-				tbl->v1_4->display_path[i].encoderobjid);
-				/* break; */
+		switch (bp->object_info_tbl.revision.minor) {
+		default:
+		case 4:
+			for (i = 0; i < tbl->v1_4->number_of_path; i++) {
+				obj_id = object_id_from_bios_object_id(
+					tbl->v1_4->display_path[i]
+						.display_objid);
+
+				if (object_id.type == obj_id.type &&
+				    object_id.id == obj_id.id &&
+				    object_id.enum_id == obj_id.enum_id) {
+					*src_object_id =
+						object_id_from_bios_object_id(
+							tbl->v1_4
+								->display_path[i]
+								.encoderobjid);
+					/* break; */
+				}
 			}
+			bp_result = BP_RESULT_OK;
+			break;
 		}
 		bp_result = BP_RESULT_OK;
 		break;
+		case 5:
+			for (i = 0; i < tbl->v1_5->number_of_path; i++) {
+				obj_id = object_id_from_bios_object_id(
+								       tbl->v1_5->display_path[i].display_objid);
+
+				if (object_id.type == obj_id.type &&
+				    object_id.id == obj_id.id &&
+				    object_id.enum_id == obj_id.enum_id) {
+					*src_object_id = object_id_from_bios_object_id(
+										       tbl->v1_5->display_path[i].encoderobjid);
+					/* break; */
+				}
+			}
+		bp_result = BP_RESULT_OK;
+		break;
+
 	default:
+		bp_result = BP_RESULT_OK;
 		break;
 	}
 
@@ -290,12 +367,55 @@ static struct atom_display_object_path_v2 *get_bios_object(
 	}
 }
 
+/* from graphics_object_id, find display path which includes the object_id */
+static struct atom_display_object_path_v3 *get_bios_object_from_path_v3(
+	struct bios_parser *bp,
+	struct graphics_object_id id)
+{
+	unsigned int i;
+	struct graphics_object_id obj_id = {0};
+
+	switch (id.type) {
+	case OBJECT_TYPE_ENCODER:
+		for (i = 0; i < bp->object_info_tbl.v1_5->number_of_path; i++) {
+			obj_id = object_id_from_bios_object_id(
+					bp->object_info_tbl.v1_5->display_path[i].encoderobjid);
+			if (id.type == obj_id.type && id.id == obj_id.id
+					&& id.enum_id == obj_id.enum_id)
+				return &bp->object_info_tbl.v1_5->display_path[i];
+		}
+        break;
+
+	case OBJECT_TYPE_CONNECTOR:
+	case OBJECT_TYPE_GENERIC:
+		/* Both Generic and Connector Object ID
+		 * will be stored on display_objid
+		 */
+		for (i = 0; i < bp->object_info_tbl.v1_5->number_of_path; i++) {
+			obj_id = object_id_from_bios_object_id(
+					bp->object_info_tbl.v1_5->display_path[i].display_objid);
+			if (id.type == obj_id.type && id.id == obj_id.id
+					&& id.enum_id == obj_id.enum_id)
+				return &bp->object_info_tbl.v1_5->display_path[i];
+		}
+        break;
+
+	default:
+		return NULL;
+	}
+
+    return NULL;
+}
+
 static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
 	struct graphics_object_id id,
 	struct graphics_object_i2c_info *info)
 {
 	uint32_t offset;
 	struct atom_display_object_path_v2 *object;
+
+	struct atom_display_object_path_v3 *object_path_v3;
+
 	struct atom_common_record_header *header;
 	struct atom_i2c_record *record;
 	struct atom_i2c_record dummy_record = {0};
@@ -313,12 +433,25 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
 			return BP_RESULT_NORECORD;
 	}
 
-	object = get_bios_object(bp, id);
+	switch (bp->object_info_tbl.revision.minor) {
+	    case 4:
+	    default:
+	        object = get_bios_object(bp, id);
 
-	if (!object)
-		return BP_RESULT_BADINPUT;
+	        if (!object)
+				return BP_RESULT_BADINPUT;
 
-	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+	        offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+	        break;
+	    case 5:
+		object_path_v3 = get_bios_object_from_path_v3(bp, id);
+
+		if (!object_path_v3)
+			return BP_RESULT_BADINPUT;
+
+		offset = object_path_v3->disp_recordoffset + bp->object_info_tbl_offset;
+		break;
+	}
 
 	for (;;) {
 		header = GET_IMAGE(struct atom_common_record_header, offset);
@@ -421,6 +554,41 @@ static enum bp_result get_gpio_i2c_info(
 	return BP_RESULT_OK;
 }
 
+static struct atom_hpd_int_record *get_hpd_record_for_path_v3(
+	struct bios_parser *bp,
+	struct atom_display_object_path_v3 *object)
+{
+	struct atom_common_record_header *header;
+	uint32_t offset;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object */
+		return NULL;
+	}
+
+	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(struct atom_common_record_header, offset);
+
+		if (!header)
+			return NULL;
+
+		if (header->record_type == ATOM_RECORD_END_TYPE ||
+			!header->record_size)
+			break;
+
+		if (header->record_type == ATOM_HPD_INT_RECORD_TYPE
+			&& sizeof(struct atom_hpd_int_record) <=
+							header->record_size)
+			return (struct atom_hpd_int_record *) header;
+
+		offset += header->record_size;
+	}
+
+	return NULL;
+}
+
 static enum bp_result bios_parser_get_hpd_info(
 	struct dc_bios *dcb,
 	struct graphics_object_id id,
@@ -428,17 +596,32 @@ static enum bp_result bios_parser_get_hpd_info(
 {
 	struct bios_parser *bp = BP_FROM_DCB(dcb);
 	struct atom_display_object_path_v2 *object;
+	struct atom_display_object_path_v3 *object_path_v3;
 	struct atom_hpd_int_record *record = NULL;
 
 	if (!info)
 		return BP_RESULT_BADINPUT;
 
-	object = get_bios_object(bp, id);
+	switch (bp->object_info_tbl.revision.minor) {
+	    case 4:
+	    default:
+	        object = get_bios_object(bp, id);
 
-	if (!object)
-		return BP_RESULT_BADINPUT;
+			if (!object)
+				return BP_RESULT_BADINPUT;
+
+	        record = get_hpd_record(bp, object);
+
+	        break;
+	    case 5:
+		object_path_v3 = get_bios_object_from_path_v3(bp, id);
 
-	record = get_hpd_record(bp, object);
+		if (!object_path_v3)
+			return BP_RESULT_BADINPUT;
+
+		record = get_hpd_record_for_path_v3(bp, object_path_v3);
+		break;
+	}
 
 	if (record != NULL) {
 		info->hpd_int_gpio_uid = record->pin_id;
@@ -526,25 +709,9 @@ static enum bp_result bios_parser_get_gpio_pin_info(
 		return BP_RESULT_UNSUPPORTED;
 
 	/* Temporary hard code gpio pin info */
-#if defined(FOR_SIMNOW_BOOT)
-	{
-		struct  atom_gpio_pin_assignment  gpio_pin[8] = {
-				{0x5db5, 0, 0, 1, 0},
-				{0x5db5, 8, 8, 2, 0},
-				{0x5db5, 0x10, 0x10, 3, 0},
-				{0x5db5, 0x18, 0x14, 4, 0},
-				{0x5db5, 0x1A, 0x18, 5, 0},
-				{0x5db5, 0x1C, 0x1C, 6, 0},
-		};
-
-		count = 6;
-		memmove(header->gpio_pin, gpio_pin, sizeof(gpio_pin));
-	}
-#else
 	count = (le16_to_cpu(header->table_header.structuresize)
 			- sizeof(struct atom_common_table_header))
 				/ sizeof(struct atom_gpio_pin_assignment);
-#endif
 	for (i = 0; i < count; ++i) {
 		if (header->gpio_pin[i].gpio_id != gpio_id)
 			continue;
@@ -633,19 +800,37 @@ static enum bp_result bios_parser_get_device_tag(
 	struct bios_parser *bp = BP_FROM_DCB(dcb);
 	struct atom_display_object_path_v2 *object;
 
+	struct atom_display_object_path_v3 *object_path_v3;
+
+
 	if (!info)
 		return BP_RESULT_BADINPUT;
 
-	/* getBiosObject will return MXM object */
-	object = get_bios_object(bp, connector_object_id);
+	switch (bp->object_info_tbl.revision.minor) {
+	    case 4:
+	    default:
+	        /* getBiosObject will return MXM object */
+	        object = get_bios_object(bp, connector_object_id);
 
-	if (!object) {
-		BREAK_TO_DEBUGGER(); /* Invalid object id */
-		return BP_RESULT_BADINPUT;
-	}
+			if (!object) {
+				BREAK_TO_DEBUGGER(); /* Invalid object id */
+				return BP_RESULT_BADINPUT;
+			}
 
-	info->acpi_device = 0; /* BIOS no longer provides this */
-	info->dev_id = device_type_from_device_id(object->device_tag);
+	        info->acpi_device = 0; /* BIOS no longer provides this */
+	        info->dev_id = device_type_from_device_id(object->device_tag);
+	        break;
+	    case 5:
+		object_path_v3 = get_bios_object_from_path_v3(bp, connector_object_id);
+
+		if (!object_path_v3) {
+			BREAK_TO_DEBUGGER(); /* Invalid object id */
+			return BP_RESULT_BADINPUT;
+		}
+		info->acpi_device = 0; /* BIOS no longer provides this */
+		info->dev_id = device_type_from_device_id(object_path_v3->device_tag);
+		break;
+	}
 
 	return BP_RESULT_OK;
 }
@@ -803,6 +988,71 @@ static enum bp_result get_ss_info_v4_2(
 	return result;
 }
 
+static enum bp_result get_ss_info_v4_5(
+	struct bios_parser *bp,
+	uint32_t id,
+	uint32_t index,
+	struct spread_spectrum_info *ss_info)
+{
+	enum bp_result result = BP_RESULT_OK;
+	struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
+
+	if (!ss_info)
+		return BP_RESULT_BADINPUT;
+
+	if (!DATA_TABLES(dce_info))
+		return BP_RESULT_BADBIOSTABLE;
+
+	disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_5,
+							DATA_TABLES(dce_info));
+	if (!disp_cntl_tbl)
+		return BP_RESULT_BADBIOSTABLE;
+
+	ss_info->type.STEP_AND_DELAY_INFO = false;
+	ss_info->spread_percentage_divider = 1000;
+	/* BIOS no longer uses target clock.  Always enable for now */
+	ss_info->target_clock_range = 0xffffffff;
+
+	switch (id) {
+	case AS_SIGNAL_TYPE_DVI:
+		ss_info->spread_spectrum_percentage =
+				disp_cntl_tbl->dvi_ss_percentage;
+		ss_info->spread_spectrum_range =
+				disp_cntl_tbl->dvi_ss_rate_10hz * 10;
+		if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
+			ss_info->type.CENTER_MODE = true;
+		break;
+	case AS_SIGNAL_TYPE_HDMI:
+		ss_info->spread_spectrum_percentage =
+				disp_cntl_tbl->hdmi_ss_percentage;
+		ss_info->spread_spectrum_range =
+				disp_cntl_tbl->hdmi_ss_rate_10hz * 10;
+		if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
+			ss_info->type.CENTER_MODE = true;
+		break;
+	case AS_SIGNAL_TYPE_DISPLAY_PORT:
+		ss_info->spread_spectrum_percentage =
+				disp_cntl_tbl->dp_ss_percentage;
+		ss_info->spread_spectrum_range =
+				disp_cntl_tbl->dp_ss_rate_10hz * 10;
+		if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
+			ss_info->type.CENTER_MODE = true;
+		break;
+	case AS_SIGNAL_TYPE_GPU_PLL:
+		/* atom_smu_info_v4_0 does not have fields for SS for SMU Display PLL anymore.
+		 * SMU Display PLL supposed to be without spread.
+		 * Better place for it would be in atom_display_controller_info_v4_5 table.
+		 */
+		result = BP_RESULT_UNSUPPORTED;
+		break;
+	default:
+		result = BP_RESULT_UNSUPPORTED;
+		break;
+	}
+
+	return result;
+}
+
 /**
  * bios_parser_get_spread_spectrum_info
  * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or
@@ -847,6 +1097,9 @@ static enum bp_result bios_parser_get_spread_spectrum_info(
 		case 3:
 		case 4:
 			return get_ss_info_v4_2(bp, signal, index, ss_info);
+		case 5:
+			return get_ss_info_v4_5(bp, signal, index, ss_info);
+
 		default:
 			ASSERT(0);
 			break;
@@ -887,6 +1140,31 @@ static enum bp_result get_soc_bb_info_v4_4(
 	return result;
 }
 
+static enum bp_result get_soc_bb_info_v4_5(
+	struct bios_parser *bp,
+	struct bp_soc_bb_info *soc_bb_info)
+{
+	enum bp_result result = BP_RESULT_OK;
+	struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
+
+	if (!soc_bb_info)
+		return BP_RESULT_BADINPUT;
+
+	if (!DATA_TABLES(dce_info))
+		return BP_RESULT_BADBIOSTABLE;
+
+	disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_5,
+							DATA_TABLES(dce_info));
+	if (!disp_cntl_tbl)
+		return BP_RESULT_BADBIOSTABLE;
+
+	soc_bb_info->dram_clock_change_latency_100ns = disp_cntl_tbl->max_mclk_chg_lat;
+	soc_bb_info->dram_sr_enter_exit_latency_100ns = disp_cntl_tbl->max_sr_enter_exit_lat;
+	soc_bb_info->dram_sr_exit_latency_100ns = disp_cntl_tbl->max_sr_exit_lat;
+
+	return result;
+}
+
 static enum bp_result bios_parser_get_soc_bb_info(
 	struct dc_bios *dcb,
 	struct bp_soc_bb_info *soc_bb_info)
@@ -916,6 +1194,9 @@ static enum bp_result bios_parser_get_soc_bb_info(
 		case 4:
 			result = get_soc_bb_info_v4_4(bp, soc_bb_info);
 			break;
+		case 5:
+			result = get_soc_bb_info_v4_5(bp, soc_bb_info);
+			break;
 		default:
 			break;
 		}
@@ -1023,6 +1304,30 @@ static enum bp_result get_disp_caps_v4_4(
 	return result;
 }
 
+static enum bp_result get_disp_caps_v4_5(
+	struct bios_parser *bp,
+	uint8_t *dce_caps)
+{
+	enum bp_result result = BP_RESULT_OK;
+	struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
+
+	if (!dce_caps)
+		return BP_RESULT_BADINPUT;
+
+	if (!DATA_TABLES(dce_info))
+		return BP_RESULT_BADBIOSTABLE;
+
+	disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_5,
+							DATA_TABLES(dce_info));
+
+	if (!disp_cntl_tbl)
+		return BP_RESULT_BADBIOSTABLE;
+
+	*dce_caps = disp_cntl_tbl->display_caps;
+
+	return result;
+}
+
 static enum bp_result bios_parser_get_lttpr_interop(
 	struct dc_bios *dcb,
 	uint8_t *dce_caps)
@@ -1057,6 +1362,11 @@ static enum bp_result bios_parser_get_lttpr_interop(
 			result = get_disp_caps_v4_4(bp, dce_caps);
 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
 			break;
+		case 5:
+			result = get_disp_caps_v4_5(bp, dce_caps);
+			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
+			break;
+
 		default:
 			break;
 		}
@@ -1102,6 +1412,10 @@ static enum bp_result bios_parser_get_lttpr_caps(
 			result = get_disp_caps_v4_4(bp, dce_caps);
 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
 			break;
+		case 5:
+			result = get_disp_caps_v4_5(bp, dce_caps);
+			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
+
 		default:
 			break;
 		}
@@ -1218,7 +1532,6 @@ static enum bp_result bios_parser_get_embedded_panel_info(
 		default:
 			break;
 		}
-		break;
 	default:
 		break;
 	}
@@ -1274,8 +1587,17 @@ static bool bios_parser_is_device_id_supported(
 
 	uint32_t mask = get_support_mask_for_device_id(id);
 
-	return (le16_to_cpu(bp->object_info_tbl.v1_4->supporteddevices) &
-								mask) != 0;
+	switch (bp->object_info_tbl.revision.minor) {
+	    case 4:
+	    default:
+	        return (le16_to_cpu(bp->object_info_tbl.v1_4->supporteddevices) & mask) != 0;
+			break;
+	    case 5:
+			return (le16_to_cpu(bp->object_info_tbl.v1_5->supporteddevices) & mask) != 0;
+			break;
+	}
+
+    return false;
 }
 
 static uint32_t bios_parser_get_ss_entry_number(
@@ -1408,12 +1730,21 @@ static void bios_parser_set_scratch_critical_state(
 	bios_set_scratch_critical_state(dcb, state);
 }
 
+struct atom_dig_transmitter_info_header_v5_3 {
+    struct atom_common_table_header table_header;
+    uint16_t dpphy_hdmi_settings_offset;
+    uint16_t dpphy_dvi_settings_offset;
+    uint16_t dpphy_dp_setting_table_offset;
+    uint16_t uniphy_xbar_settings_v2_table_offset;
+    uint16_t dpphy_internal_reg_overide_offset;
+};
+
 static enum bp_result bios_parser_get_firmware_info(
 	struct dc_bios *dcb,
 	struct dc_firmware_info *info)
 {
 	struct bios_parser *bp = BP_FROM_DCB(dcb);
-	enum bp_result result = BP_RESULT_BADBIOSTABLE;
+	static enum bp_result result = BP_RESULT_BADBIOSTABLE;
 	struct atom_common_table_header *header;
 
 	struct atom_data_revision revision;
@@ -1590,6 +1921,11 @@ static enum bp_result get_firmware_info_v3_4(
 	struct atom_data_revision revision;
 	struct atom_display_controller_info_v4_1 *dce_info_v4_1 = NULL;
 	struct atom_display_controller_info_v4_4 *dce_info_v4_4 = NULL;
+
+	struct atom_smu_info_v3_5 *smu_info_v3_5 = NULL;
+	struct atom_display_controller_info_v4_5 *dce_info_v4_5 = NULL;
+	struct atom_smu_info_v4_0 *smu_info_v4_0 = NULL;
+
 	if (!info)
 		return BP_RESULT_BADINPUT;
 
@@ -1609,6 +1945,22 @@ static enum bp_result get_firmware_info_v3_4(
 	switch (revision.major) {
 	case 4:
 		switch (revision.minor) {
+		case 5:
+			dce_info_v4_5 = GET_IMAGE(struct atom_display_controller_info_v4_5,
+							DATA_TABLES(dce_info));
+
+			if (!dce_info_v4_5)
+				return BP_RESULT_BADBIOSTABLE;
+
+			 /* 100MHz expected */
+			info->pll_info.crystal_frequency = dce_info_v4_5->dce_refclk_10khz * 10;
+			info->dp_phy_ref_clk             = dce_info_v4_5->dpphy_refclk_10khz * 10;
+			 /* 50MHz expected */
+			info->i2c_engine_ref_clk         = dce_info_v4_5->i2c_engine_refclk_10khz * 10;
+
+			/* For DCN32/321 Display PLL VCO Frequency from dce_info_v4_5 may not be reliable */
+			break;
+
 		case 4:
 			dce_info_v4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,
 							DATA_TABLES(dce_info));
@@ -1650,6 +2002,45 @@ static enum bp_result get_firmware_info_v3_4(
 					DATA_TABLES(smu_info));
 	get_atom_data_table_revision(header, &revision);
 
+	switch (revision.major) {
+	case 3:
+		switch (revision.minor) {
+		case 5:
+			smu_info_v3_5 = GET_IMAGE(struct atom_smu_info_v3_5,
+							DATA_TABLES(smu_info));
+
+			if (!smu_info_v3_5)
+				return BP_RESULT_BADBIOSTABLE;
+
+			info->default_engine_clk = smu_info_v3_5->bootup_dcefclk_10khz * 10;
+			break;
+
+		default:
+			break;
+		}
+		break;
+
+	case 4:
+		switch (revision.minor) {
+		case 0:
+			smu_info_v4_0 = GET_IMAGE(struct atom_smu_info_v4_0,
+							DATA_TABLES(smu_info));
+
+			if (!smu_info_v4_0)
+				return BP_RESULT_BADBIOSTABLE;
+
+			/* For DCN32/321 bootup DCFCLK from smu_info_v4_0 may not be reliable */
+			break;
+
+		default:
+			break;
+		}
+		break;
+
+	default:
+		break;
+	}
+
 	 // We need to convert from 10KHz units into KHz units.
 	info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
 
@@ -1675,6 +2066,12 @@ static enum bp_result bios_parser_get_encoder_cap_info(
 	if (!info)
 		return BP_RESULT_BADINPUT;
 
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+	/* encoder cap record not available in v1_5 */
+	if (bp->object_info_tbl.revision.minor == 5)
+		return BP_RESULT_NORECORD;
+#endif
+
 	object = get_bios_object(bp, object_id);
 
 	if (!object)
@@ -1781,6 +2178,42 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
 	return NULL;
 }
 
+static struct atom_connector_caps_record *get_connector_caps_record(
+	struct bios_parser *bp,
+	struct atom_display_object_path_v3 *object)
+{
+	struct atom_common_record_header *header;
+	uint32_t offset;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object */
+		return NULL;
+	}
+
+	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(struct atom_common_record_header, offset);
+
+		if (!header)
+			return NULL;
+
+		offset += header->record_size;
+
+		if (header->record_type == ATOM_RECORD_END_TYPE ||
+				!header->record_size)
+			break;
+
+		if (header->record_type != ATOM_CONNECTOR_CAP_RECORD_TYPE)
+			continue;
+
+		if (sizeof(struct atom_connector_caps_record) <= header->record_size)
+			return (struct atom_connector_caps_record *)header;
+	}
+
+	return NULL;
+}
+
 static enum bp_result bios_parser_get_disp_connector_caps_info(
 	struct dc_bios *dcb,
 	struct graphics_object_id object_id,
@@ -1788,25 +2221,116 @@ static enum bp_result bios_parser_get_disp_connector_caps_info(
 {
 	struct bios_parser *bp = BP_FROM_DCB(dcb);
 	struct atom_display_object_path_v2 *object;
+
+	struct atom_display_object_path_v3 *object_path_v3;
+	struct atom_connector_caps_record *record_path_v3;
+
 	struct atom_disp_connector_caps_record *record = NULL;
 
 	if (!info)
 		return BP_RESULT_BADINPUT;
 
-	object = get_bios_object(bp, object_id);
+	switch (bp->object_info_tbl.revision.minor) {
+	    case 4:
+	    default:
+		    object = get_bios_object(bp, object_id);
 
-	if (!object)
+		    if (!object)
+			    return BP_RESULT_BADINPUT;
+
+		    record = get_disp_connector_caps_record(bp, object);
+		    if (!record)
+			    return BP_RESULT_NORECORD;
+
+		    info->INTERNAL_DISPLAY =
+			    (record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY) ? 1 : 0;
+		    info->INTERNAL_DISPLAY_BL =
+			    (record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL) ? 1 : 0;
+		    break;
+	    case 5:
+		object_path_v3 = get_bios_object_from_path_v3(bp, object_id);
+
+		if (!object_path_v3)
+			return BP_RESULT_BADINPUT;
+
+		record_path_v3 = get_connector_caps_record(bp, object_path_v3);
+		if (!record_path_v3)
+			return BP_RESULT_NORECORD;
+
+		info->INTERNAL_DISPLAY = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY)
+									? 1 : 0;
+		info->INTERNAL_DISPLAY_BL = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL)
+										? 1 : 0;
+		break;
+	}
+
+	return BP_RESULT_OK;
+}
+
+static struct atom_connector_speed_record *get_connector_speed_cap_record(
+	struct bios_parser *bp,
+	struct atom_display_object_path_v3 *object)
+{
+	struct atom_common_record_header *header;
+	uint32_t offset;
+
+	if (!object) {
+		BREAK_TO_DEBUGGER(); /* Invalid object */
+		return NULL;
+	}
+
+	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+
+	for (;;) {
+		header = GET_IMAGE(struct atom_common_record_header, offset);
+
+		if (!header)
+			return NULL;
+
+		offset += header->record_size;
+
+		if (header->record_type == ATOM_RECORD_END_TYPE ||
+				!header->record_size)
+			break;
+
+		if (header->record_type != ATOM_CONNECTOR_SPEED_UPTO)
+			continue;
+
+		if (sizeof(struct atom_connector_speed_record) <= header->record_size)
+			return (struct atom_connector_speed_record *)header;
+	}
+
+	return NULL;
+}
+
+static enum bp_result bios_parser_get_connector_speed_cap_info(
+	struct dc_bios *dcb,
+	struct graphics_object_id object_id,
+	struct bp_connector_speed_cap_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	struct atom_display_object_path_v3 *object_path_v3;
+	//struct atom_connector_speed_record *record = NULL;
+	struct atom_connector_speed_record *record;
+
+	if (!info)
+		return BP_RESULT_BADINPUT;
+
+	object_path_v3 = get_bios_object_from_path_v3(bp, object_id);
+
+	if (!object_path_v3)
 		return BP_RESULT_BADINPUT;
 
-	record = get_disp_connector_caps_record(bp, object);
+	record = get_connector_speed_cap_record(bp, object_path_v3);
 	if (!record)
 		return BP_RESULT_NORECORD;
 
-	info->INTERNAL_DISPLAY = (record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY)
-									? 1 : 0;
-	info->INTERNAL_DISPLAY_BL = (record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL)
-											? 1 : 0;
-
+	info->DP_HBR2_EN = (record->connector_max_speed >= 5400) ? 1 : 0;
+	info->DP_HBR3_EN = (record->connector_max_speed >= 8100) ? 1 : 0;
+	info->HDMI_6GB_EN = (record->connector_max_speed >= 5940) ? 1 : 0;
+	info->DP_UHBR10_EN = (record->connector_max_speed >= 10000) ? 1 : 0;
+	info->DP_UHBR13_5_EN = (record->connector_max_speed >= 13500) ? 1 : 0;
+	info->DP_UHBR20_EN = (record->connector_max_speed >= 20000) ? 1 : 0;
 	return BP_RESULT_OK;
 }
 
@@ -1815,7 +2339,7 @@ static enum bp_result get_vram_info_v23(
 	struct dc_vram_info *info)
 {
 	struct atom_vram_info_header_v2_3 *info_v23;
-	enum bp_result result = BP_RESULT_OK;
+	static enum bp_result result = BP_RESULT_OK;
 
 	info_v23 = GET_IMAGE(struct atom_vram_info_header_v2_3,
 						DATA_TABLES(vram_info));
@@ -1834,7 +2358,7 @@ static enum bp_result get_vram_info_v24(
 	struct dc_vram_info *info)
 {
 	struct atom_vram_info_header_v2_4 *info_v24;
-	enum bp_result result = BP_RESULT_OK;
+	static enum bp_result result = BP_RESULT_OK;
 
 	info_v24 = GET_IMAGE(struct atom_vram_info_header_v2_4,
 						DATA_TABLES(vram_info));
@@ -1853,7 +2377,7 @@ static enum bp_result get_vram_info_v25(
 	struct dc_vram_info *info)
 {
 	struct atom_vram_info_header_v2_5 *info_v25;
-	enum bp_result result = BP_RESULT_OK;
+	static enum bp_result result = BP_RESULT_OK;
 
 	info_v25 = GET_IMAGE(struct atom_vram_info_header_v2_5,
 						DATA_TABLES(vram_info));
@@ -1878,7 +2402,7 @@ static enum bp_result get_vram_info_v25(
  * integrated_info *info - [out] store and output integrated info
  *
  * @return
- * enum bp_result - BP_RESULT_OK if information is available,
+ * static enum bp_result - BP_RESULT_OK if information is available,
  *                  BP_RESULT_BADBIOSTABLE otherwise.
  */
 static enum bp_result get_integrated_info_v11(
@@ -2369,17 +2893,19 @@ static enum bp_result get_integrated_info_v2_2(
  * integrated_info *info - [out] store and output integrated info
  *
  * @return
- * enum bp_result - BP_RESULT_OK if information is available,
+ * static enum bp_result - BP_RESULT_OK if information is available,
  *                  BP_RESULT_BADBIOSTABLE otherwise.
  */
 static enum bp_result construct_integrated_info(
 	struct bios_parser *bp,
 	struct integrated_info *info)
 {
-	enum bp_result result = BP_RESULT_BADBIOSTABLE;
+	static enum bp_result result = BP_RESULT_BADBIOSTABLE;
 
 	struct atom_common_table_header *header;
 	struct atom_data_revision revision;
+
+	struct clock_voltage_caps temp = {0, 0};
 	uint32_t i;
 	uint32_t j;
 
@@ -2427,8 +2953,10 @@ static enum bp_result construct_integrated_info(
 				info->disp_clk_voltage[j-1].max_supported_clk
 				) {
 				/* swap j and j - 1*/
-				swap(info->disp_clk_voltage[j - 1],
-				     info->disp_clk_voltage[j]);
+				temp = info->disp_clk_voltage[j-1];
+				info->disp_clk_voltage[j-1] =
+					info->disp_clk_voltage[j];
+				info->disp_clk_voltage[j] = temp;
 			}
 		}
 	}
@@ -2441,7 +2969,7 @@ static enum bp_result bios_parser_get_vram_info(
 		struct dc_vram_info *info)
 {
 	struct bios_parser *bp = BP_FROM_DCB(dcb);
-	enum bp_result result = BP_RESULT_BADBIOSTABLE;
+	static enum bp_result result = BP_RESULT_BADBIOSTABLE;
 	struct atom_common_table_header *header;
 	struct atom_data_revision revision;
 
@@ -2507,7 +3035,7 @@ static enum bp_result update_slot_layout_info(
 	struct atom_display_object_path_v2 *object;
 	struct atom_bracket_layout_record *record;
 	struct atom_common_record_header *record_header;
-	enum bp_result result;
+	static enum bp_result result;
 	struct bios_parser *bp;
 	struct object_info_table *tbl;
 	struct display_object_info_table_v1_4 *v1_4;
@@ -2613,6 +3141,104 @@ static enum bp_result update_slot_layout_info(
 	return result;
 }
 
+static enum bp_result update_slot_layout_info_v2(
+	struct dc_bios *dcb,
+	unsigned int i,
+	struct slot_layout_info *slot_layout_info)
+{
+	unsigned int record_offset;
+	struct atom_display_object_path_v3 *object;
+	struct atom_bracket_layout_record_v2 *record;
+	struct atom_common_record_header *record_header;
+	static enum bp_result result;
+	struct bios_parser *bp;
+	struct object_info_table *tbl;
+	struct display_object_info_table_v1_5 *v1_5;
+	struct graphics_object_id connector_id;
+
+	record = NULL;
+	record_header = NULL;
+	result = BP_RESULT_NORECORD;
+
+	bp = BP_FROM_DCB(dcb);
+	tbl = &bp->object_info_tbl;
+	v1_5 = tbl->v1_5;
+
+	object = &v1_5->display_path[i];
+	record_offset = (unsigned int)
+		(object->disp_recordoffset) +
+		(unsigned int)(bp->object_info_tbl_offset);
+
+	for (;;) {
+
+		record_header = (struct atom_common_record_header *)
+			GET_IMAGE(struct atom_common_record_header,
+			record_offset);
+		if (record_header == NULL) {
+			result = BP_RESULT_BADBIOSTABLE;
+			break;
+		}
+
+		/* the end of the list */
+		if (record_header->record_type == ATOM_RECORD_END_TYPE ||
+			record_header->record_size == 0)	{
+			break;
+		}
+
+		if (record_header->record_type ==
+			ATOM_BRACKET_LAYOUT_V2_RECORD_TYPE &&
+			sizeof(struct atom_bracket_layout_record_v2)
+			<= record_header->record_size) {
+			record = (struct atom_bracket_layout_record_v2 *)
+				(record_header);
+			result = BP_RESULT_OK;
+			break;
+		}
+
+		record_offset += record_header->record_size;
+	}
+
+	/* return if the record not found */
+	if (result != BP_RESULT_OK)
+		return result;
+
+	/* get slot sizes */
+	connector_id = object_id_from_bios_object_id(object->display_objid);
+
+	slot_layout_info->length = record->bracketlen;
+	slot_layout_info->width = record->bracketwidth;
+	slot_layout_info->num_of_connectors = v1_5->number_of_path;
+	slot_layout_info->connectors[i].position = record->conn_num;
+	slot_layout_info->connectors[i].connector_id = connector_id;
+
+	switch (connector_id.id) {
+	case CONNECTOR_ID_SINGLE_LINK_DVID:
+	case CONNECTOR_ID_DUAL_LINK_DVID:
+		slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_DVI_D;
+		slot_layout_info->connectors[i].length = CONNECTOR_SIZE_DVI;
+		break;
+
+	case CONNECTOR_ID_HDMI_TYPE_A:
+		slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_HDMI;
+		slot_layout_info->connectors[i].length = CONNECTOR_SIZE_HDMI;
+		break;
+
+	case CONNECTOR_ID_DISPLAY_PORT:
+		if (record->mini_type == MINI_TYPE_NORMAL) {
+			slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_DP;
+			slot_layout_info->connectors[i].length = CONNECTOR_SIZE_DP;
+		} else {
+			slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_MINI_DP;
+			slot_layout_info->connectors[i].length = CONNECTOR_SIZE_MINI_DP;
+		}
+		break;
+
+	default:
+		slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_UNKNOWN;
+		slot_layout_info->connectors[i].length = CONNECTOR_SIZE_UNKNOWN;
+	}
+	return result;
+}
 
 static enum bp_result get_bracket_layout_record(
 	struct dc_bios *dcb,
@@ -2621,9 +3247,10 @@ static enum bp_result get_bracket_layout_record(
 {
 	unsigned int i;
 	struct bios_parser *bp = BP_FROM_DCB(dcb);
-	enum bp_result result;
+	static enum bp_result result;
 	struct object_info_table *tbl;
 	struct display_object_info_table_v1_4 *v1_4;
+    struct display_object_info_table_v1_5 *v1_5;
 
 	if (slot_layout_info == NULL) {
 		DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");
@@ -2633,14 +3260,21 @@ static enum bp_result get_bracket_layout_record(
 	v1_4 = tbl->v1_4;
 
 	result = BP_RESULT_NORECORD;
-	for (i = 0; i < v1_4->number_of_path; ++i)	{
-
-		if (bracket_layout_id ==
-			v1_4->display_path[i].display_objid) {
-			result = update_slot_layout_info(dcb, i,
-				slot_layout_info);
+	switch (bp->object_info_tbl.revision.minor) {
+		case 4:
+		default:
+			for (i = 0; i < v1_4->number_of_path; ++i)	{
+				if (bracket_layout_id ==
+					v1_4->display_path[i].display_objid) {
+					result = update_slot_layout_info(dcb, i, slot_layout_info);
+					break;
+				}
+			}
+		    break;
+		case 5:
+			for (i = 0; i < v1_5->number_of_path; ++i)
+				result = update_slot_layout_info_v2(dcb, i, slot_layout_info);
 			break;
-		}
 	}
 	return result;
 }
@@ -2650,7 +3284,10 @@ static enum bp_result bios_get_board_layout_info(
 	struct board_layout_info *board_layout_info)
 {
 	unsigned int i;
-	enum bp_result record_result;
+
+	struct bios_parser *bp;
+
+	static enum bp_result record_result;
 
 	const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {
 		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1,
@@ -2658,6 +3295,9 @@ static enum bp_result bios_get_board_layout_info(
 		0, 0
 	};
 
+
+	bp = BP_FROM_DCB(dcb);
+
 	if (board_layout_info == NULL) {
 		DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");
 		return BP_RESULT_BADINPUT;
@@ -2692,99 +3332,6 @@ static uint16_t bios_parser_pack_data_tables(
 	struct dc_bios *dcb,
 	void *dst)
 {
-#ifdef PACK_BIOS_DATA
-	struct bios_parser *bp = BP_FROM_DCB(dcb);
-	struct atom_rom_header_v2_2 *rom_header = NULL;
-	struct atom_rom_header_v2_2 *packed_rom_header = NULL;
-	struct atom_common_table_header *data_tbl_header = NULL;
-	struct atom_master_list_of_data_tables_v2_1 *data_tbl_list = NULL;
-	struct atom_master_data_table_v2_1 *packed_master_data_tbl = NULL;
-	struct atom_data_revision tbl_rev = {0};
-	uint16_t *rom_header_offset = NULL;
-	const uint8_t *bios = bp->base.bios;
-	uint8_t *bios_dst = (uint8_t *)dst;
-	uint16_t packed_rom_header_offset;
-	uint16_t packed_masterdatatable_offset;
-	uint16_t packed_data_tbl_offset;
-	uint16_t data_tbl_offset;
-	unsigned int i;
-
-	rom_header_offset =
-		GET_IMAGE(uint16_t, OFFSET_TO_ATOM_ROM_HEADER_POINTER);
-
-	if (!rom_header_offset)
-		return 0;
-
-	rom_header = GET_IMAGE(struct atom_rom_header_v2_2, *rom_header_offset);
-
-	if (!rom_header)
-		return 0;
-
-	get_atom_data_table_revision(&rom_header->table_header, &tbl_rev);
-	if (!(tbl_rev.major >= 2 && tbl_rev.minor >= 2))
-		return 0;
-
-	get_atom_data_table_revision(&bp->master_data_tbl->table_header, &tbl_rev);
-	if (!(tbl_rev.major >= 2 && tbl_rev.minor >= 1))
-		return 0;
-
-	packed_rom_header_offset =
-		OFFSET_TO_ATOM_ROM_HEADER_POINTER + sizeof(*rom_header_offset);
-
-	packed_masterdatatable_offset =
-		packed_rom_header_offset + rom_header->table_header.structuresize;
-
-	packed_data_tbl_offset =
-		packed_masterdatatable_offset +
-		bp->master_data_tbl->table_header.structuresize;
-
-	packed_rom_header =
-		(struct atom_rom_header_v2_2 *)(bios_dst + packed_rom_header_offset);
-
-	packed_master_data_tbl =
-		(struct atom_master_data_table_v2_1 *)(bios_dst +
-		packed_masterdatatable_offset);
-
-	memcpy(bios_dst, bios, OFFSET_TO_ATOM_ROM_HEADER_POINTER);
-
-	*((uint16_t *)(bios_dst + OFFSET_TO_ATOM_ROM_HEADER_POINTER)) =
-		packed_rom_header_offset;
-
-	memcpy(bios_dst + packed_rom_header_offset, rom_header,
-		rom_header->table_header.structuresize);
-
-	packed_rom_header->masterdatatable_offset = packed_masterdatatable_offset;
-
-	memcpy(&packed_master_data_tbl->table_header,
-		&bp->master_data_tbl->table_header,
-		sizeof(bp->master_data_tbl->table_header));
-
-	data_tbl_list = &bp->master_data_tbl->listOfdatatables;
-
-	/* Each data table offset in data table list is 2 bytes,
-	 * we can use that to iterate through listOfdatatables
-	 * without knowing the name of each member.
-	 */
-	for (i = 0; i < sizeof(*data_tbl_list)/sizeof(uint16_t); i++) {
-		data_tbl_offset = *((uint16_t *)data_tbl_list + i);
-
-		if (data_tbl_offset) {
-			data_tbl_header =
-				(struct atom_common_table_header *)(bios + data_tbl_offset);
-
-			memcpy(bios_dst + packed_data_tbl_offset, data_tbl_header,
-				data_tbl_header->structuresize);
-
-			*((uint16_t *)&packed_master_data_tbl->listOfdatatables + i) =
-				packed_data_tbl_offset;
-
-			packed_data_tbl_offset += data_tbl_header->structuresize;
-		} else {
-			*((uint16_t *)&packed_master_data_tbl->listOfdatatables + i) = 0;
-		}
-	}
-	return packed_data_tbl_offset;
-#endif
 	// TODO: There is data bytes alignment issue, disable it for now.
 	return 0;
 }
@@ -2814,6 +3361,13 @@ static struct atom_dc_golden_table_v1 *bios_get_golden_table(
 			dc_golden_offset = DATA_TABLES(dce_info) + disp_cntl_tbl_4_4->dc_golden_table_offset;
 			*dc_golden_table_ver = disp_cntl_tbl_4_4->dc_golden_table_ver;
 			break;
+		case 5:
+		default:
+			/* For atom_display_controller_info_v4_5 there is no need to get golden table from
+			 * dc_golden_table_offset as all these fields previously in golden table used for AUX
+			 * pre-charge settings are now available directly in atom_display_controller_info_v4_5.
+			 */
+			break;
 		}
 		break;
 	}
@@ -2916,6 +3470,7 @@ static const struct dc_vbios_funcs vbios_funcs = {
 	.bios_parser_destroy = firmware_parser_destroy,
 
 	.get_board_layout_info = bios_get_board_layout_info,
+	/* TODO: use this fn in hw init?*/
 	.pack_data_tables = bios_parser_pack_data_tables,
 
 	.get_atom_dc_golden_table = bios_get_atom_dc_golden_table,
@@ -2929,6 +3484,8 @@ static const struct dc_vbios_funcs vbios_funcs = {
 	.get_lttpr_caps = bios_parser_get_lttpr_caps,
 
 	.get_lttpr_interop = bios_parser_get_lttpr_interop,
+
+	.get_connector_speed_cap_info = bios_parser_get_connector_speed_cap_info,
 };
 
 static bool bios_parser2_construct(
@@ -3002,6 +3559,16 @@ static bool bios_parser2_construct(
 			return false;
 
 		bp->object_info_tbl.v1_4 = tbl_v1_4;
+	} else if (bp->object_info_tbl.revision.major == 1
+		&& bp->object_info_tbl.revision.minor == 5) {
+		struct display_object_info_table_v1_5 *tbl_v1_5;
+
+		tbl_v1_5 = GET_IMAGE(struct display_object_info_table_v1_5,
+			bp->object_info_tbl_offset);
+		if (!tbl_v1_5)
+			return false;
+
+		bp->object_info_tbl.v1_5 = tbl_v1_5;
 	} else {
 		ASSERT(0);
 		return false;
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h
index bf1f5c86e65c..41d02d473082 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h
@@ -40,6 +40,7 @@ struct object_info_table {
 	struct atom_data_revision revision;
 	union {
 		struct display_object_info_table_v1_4 *v1_4;
+		struct display_object_info_table_v1_5 *v1_5;
 	};
 };
 
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c
index f3792286f571..f22593bcb862 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c
@@ -77,6 +77,8 @@ bool dal_bios_parser_init_cmd_tbl_helper2(
 	case DCN_VERSION_3_1:
 	case DCN_VERSION_3_15:
 	case DCN_VERSION_3_16:
+	case DCN_VERSION_3_2:
+	case DCN_VERSION_3_21:
 		*h = dal_cmd_tbl_helper_dce112_get_table2();
 		return true;
 
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 e803e59abd56..d145dcbca778 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
@@ -328,8 +328,8 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
 	    dcn32_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
 	    return &clk_mgr->base;
 	    break;
-#endif
 	}
+#endif
 	default:
 		ASSERT(0); /* Unknown Asic */
 		break;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index f14449401188..e3e3b2791632 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -3054,11 +3054,15 @@ static void commit_planes_for_stream(struct dc *dc,
 
 	}
 
-	if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) {
-		dc->hwss.interdependent_update_lock(dc, context, false);
-	} else {
-		dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
-	}
+#ifdef CONFIG_DRM_AMD_DC_DCN
+		if (update_type != UPDATE_TYPE_FAST)
+			if (dc->hwss.commit_subvp_config)
+				dc->hwss.commit_subvp_config(dc, context);
+#endif
+		if (should_lock_all_pipes && dc->hwss.interdependent_update_lock)
+			dc->hwss.interdependent_update_lock(dc, context, false);
+		else
+			dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false);
 
 	if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed)
 		if (top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) {
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 6774dd8bb53e..b087452e4590 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -67,6 +67,8 @@
 #include "dcn31/dcn31_resource.h"
 #include "dcn315/dcn315_resource.h"
 #include "dcn316/dcn316_resource.h"
+#include "../dcn32/dcn32_resource.h"
+#include "../dcn321/dcn321_resource.h"
 
 #define DC_LOGGER_INIT(logger)
 
@@ -162,7 +164,11 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
 		if (ASICREV_IS_GC_10_3_7(asic_id.hw_internal_rev))
 			dc_version = DCN_VERSION_3_16;
 		break;
-
+	case AMDGPU_FAMILY_GC_11_0_0:
+		dc_version = DCN_VERSION_3_2;
+		if (ASICREV_IS_GC_11_0_2(asic_id.hw_internal_rev))
+			dc_version = DCN_VERSION_3_21;
+		break;
 	default:
 		dc_version = DCE_VERSION_UNKNOWN;
 		break;
@@ -258,6 +264,12 @@ struct resource_pool *dc_create_resource_pool(struct dc  *dc,
 	case DCN_VERSION_3_16:
 		res_pool = dcn316_create_resource_pool(init_data, dc);
 		break;
+	case DCN_VERSION_3_2:
+		res_pool = dcn32_create_resource_pool(init_data, dc);
+		break;
+	case DCN_VERSION_3_21:
+		res_pool = dcn321_create_resource_pool(init_data, dc);
+		break;
 #endif
 	default:
 		break;
@@ -1982,6 +1994,11 @@ enum dc_status dc_remove_stream_from_ctx(
 				dc->res_pool,
 			del_pipe->stream_res.stream_enc,
 			false);
+	/* Release link encoder from stream in new dc_state. */
+	if (dc->res_pool->funcs->link_enc_unassign)
+		dc->res_pool->funcs->link_enc_unassign(new_ctx, del_pipe->stream);
+
+#if defined(CONFIG_DRM_AMD_DC_DCN)
 	if (is_dp_128b_132b_signal(del_pipe)) {
 		update_hpo_dp_stream_engine_usage(
 			&new_ctx->res_ctx, dc->res_pool,
@@ -1989,6 +2006,7 @@ enum dc_status dc_remove_stream_from_ctx(
 			false);
 		remove_hpo_dp_link_enc_from_ctx(&new_ctx->res_ctx, del_pipe, del_pipe->stream);
 	}
+#endif
 
 	if (del_pipe->stream_res.audio)
 		update_audio_usage(
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 2eabcdef8903..b6decdf820fa 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -162,6 +162,10 @@ struct dc_color_caps {
 	struct mpc_color_caps mpc;
 };
 
+struct dc_dmub_caps {
+    bool psr;
+};
+
 struct dc_caps {
 	uint32_t max_streams;
 	uint32_t max_links;
@@ -196,12 +200,22 @@ struct dc_caps {
 	unsigned int cursor_cache_size;
 	struct dc_plane_cap planes[MAX_PLANES];
 	struct dc_color_caps color;
+	struct dc_dmub_caps dmub_caps;
 	bool dp_hpo;
 	bool hdmi_frl_pcon_support;
 	bool edp_dsc_support;
 	bool vbios_lttpr_aware;
 	bool vbios_lttpr_enable;
 	uint32_t max_otg_num;
+#ifdef CONFIG_DRM_AMD_DC_DCN
+	uint32_t max_cab_allocation_bytes;
+	uint32_t cache_line_size;
+	uint32_t cache_num_ways;
+	uint16_t subvp_fw_processing_delay_us;
+	uint16_t subvp_prefetch_end_to_mall_start_us;
+	uint16_t subvp_pstate_allow_width_us;
+	uint16_t subvp_vertical_int_margin_us;
+#endif
 };
 
 struct dc_bug_wa {
@@ -425,6 +439,8 @@ struct dc_clocks {
 	 */
 	bool prev_p_state_change_support;
 	bool fclk_prev_p_state_change_support;
+	int num_ways;
+	int prev_num_ways;
 	enum dtm_pstate dtm_level;
 	int max_supported_dppclk_khz;
 	int max_supported_dispclk_khz;
@@ -719,6 +735,9 @@ struct dc_debug_options {
 	bool enable_z9_disable_interface;
 	bool enable_sw_cntl_psr;
 	union dpia_debug_options dpia_debug;
+	bool force_disable_subvp;
+	bool force_subvp_mclk_switch;
+	bool force_usr_allow;
 	bool apply_vendor_specific_lttpr_wa;
 	bool extended_blank_optimization;
 	union aux_wake_wa_options aux_wake_wa;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h
index 67abda44eb1f..260ac4458870 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h
@@ -156,6 +156,11 @@ struct dc_vbios_funcs {
 	enum bp_result (*get_lttpr_interop)(
 			struct dc_bios *dcb,
 			uint8_t *dce_caps);
+
+	enum bp_result (*get_connector_speed_cap_info)(
+		struct dc_bios *bios,
+		struct graphics_object_id object_id,
+		struct bp_connector_speed_cap_info *info);
 };
 
 struct bios_registers {
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 aa7e3a07191d..d75416dc9fae 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -780,6 +780,7 @@ struct dc_crtc_timing {
 	uint32_t v_sync_width;
 
 	uint32_t pix_clk_100hz;
+	uint32_t min_refresh_in_uhz;
 
 	uint32_t vic;
 	uint32_t hdmi_vic;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index 58941f4defb3..772b4a61f166 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -145,6 +145,24 @@ struct test_pattern {
 	unsigned int cust_pattern_size;
 };
 
+#ifdef CONFIG_DRM_AMD_DC_DCN
+#define SUBVP_DRR_MARGIN_US 500 // 500us for DRR margin (SubVP + DRR)
+
+enum mall_stream_type {
+	SUBVP_NONE, // subvp not in use
+	SUBVP_MAIN, // subvp in use, this stream is main stream
+	SUBVP_PHANTOM, // subvp in use, this stream is a phantom stream
+};
+
+struct mall_stream_config {
+	/* MALL stream config to indicate if the stream is phantom or not.
+	 * We will use a phantom stream to indicate that the pipe is phantom.
+	 */
+	enum mall_stream_type type;
+	struct dc_stream_state *paired_stream;	// master / slave stream
+};
+#endif
+
 struct dc_stream_state {
 	// sink is deprecated, new code should not reference
 	// this pointer
@@ -255,6 +273,9 @@ struct dc_stream_state {
 
 	bool has_non_synchronizable_pclk;
 	bool vblank_synchronized;
+#ifdef CONFIG_DRM_AMD_DC_DCN
+	struct mall_stream_config mall_stream_config;
+#endif
 };
 
 #define ABM_LEVEL_IMMEDIATE_DISABLE 255
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h
index b699d1b2ba83..e6c06325742a 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h
@@ -128,6 +128,21 @@
 	SRI(DC_ABM1_ACE_THRES_12, ABM, id), \
 	NBIO_SR(BIOS_SCRATCH_2)
 
+#define ABM_DCN32_REG_LIST(id)\
+	SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \
+	SRI(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \
+	SRI(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \
+	SRI(DC_ABM1_HG_MISC_CTRL, ABM, id), \
+	SRI(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \
+	SRI(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \
+	SRI(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \
+	SRI(BL1_PWM_USER_LEVEL, ABM, id), \
+	SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \
+	SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \
+	SRI(DC_ABM1_ACE_OFFSET_SLOPE_0, ABM, id), \
+	SRI(DC_ABM1_ACE_THRES_12, ABM, id), \
+	NBIO_SR(BIOS_SCRATCH_2)
+
 #define ABM_SF(reg_name, field_name, post_fix)\
 	.field_name = reg_name ## __ ## field_name ## post_fix
 
@@ -203,6 +218,36 @@
 
 #define ABM_MASK_SH_LIST_DCN30(mask_sh) ABM_MASK_SH_LIST_DCN10(mask_sh)
 
+#define ABM_MASK_SH_LIST_DCN32(mask_sh) \
+	ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
+			ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \
+	ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
+			ABM1_HG_VMAX_SEL, mask_sh), \
+	ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
+			ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \
+	ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
+			ABM1_IPCSC_COEFF_SEL_R, mask_sh), \
+	ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
+			ABM1_IPCSC_COEFF_SEL_G, mask_sh), \
+	ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
+			ABM1_IPCSC_COEFF_SEL_B, mask_sh), \
+	ABM_SF(ABM0_BL1_PWM_CURRENT_ABM_LEVEL, \
+			BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \
+	ABM_SF(ABM0_BL1_PWM_TARGET_ABM_LEVEL, \
+			BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \
+	ABM_SF(ABM0_BL1_PWM_USER_LEVEL, \
+			BL1_PWM_USER_LEVEL, mask_sh), \
+	ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \
+			ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \
+	ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \
+			ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \
+	ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
+			ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
+	ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
+			ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
+	ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
+			ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh)
+
 #define ABM_REG_FIELD_LIST(type) \
 	type ABM1_HG_NUM_OF_BINS_SEL; \
 	type ABM1_HG_VMAX_SEL; \
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 9eec3524335f..e0c390fcc12c 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
@@ -164,6 +164,10 @@
 	CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\
 	CS_SF(OTG0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE, mask_sh)
 
+#define CS_COMMON_MASK_SH_LIST_DCN3_2(mask_sh)\
+	CS_COMMON_MASK_SH_LIST_DCN2_0(mask_sh),\
+	CS_SF(OTG0_PIXEL_RATE_CNTL, PIPE0_DTO_SRC_SEL, mask_sh)
+
 #define CS_COMMON_REG_LIST_DCN1_0(index, pllid) \
 		SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\
 		SRII(PHASE, DP_DTO, 0),\
@@ -197,12 +201,23 @@
 	type DP_DTO0_MODULO; \
 	type DP_DTO0_ENABLE;
 
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+#define CS_REG_FIELD_LIST_DCN32(type) \
+	type PIPE0_DTO_SRC_SEL;
+#endif
+
 struct dce110_clk_src_shift {
 	CS_REG_FIELD_LIST(uint8_t)
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+	CS_REG_FIELD_LIST_DCN32(uint8_t)
+#endif
 };
 
 struct dce110_clk_src_mask{
 	CS_REG_FIELD_LIST(uint32_t)
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+	CS_REG_FIELD_LIST_DCN32(uint32_t)
+#endif
 };
 
 struct dce110_clk_src_regs {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
index 39485bdeb90e..e48fd044f572 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
@@ -158,8 +158,39 @@ struct dcn_hubbub_registers {
 	uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C;
 	uint32_t DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D;
 	uint32_t DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D;
+	uint32_t DCHUBBUB_ARB_USR_RETRAINING_CNTL;
+	uint32_t DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A;
+	uint32_t DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B;
+	uint32_t DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C;
+	uint32_t DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D;
+	uint32_t DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A;
+	uint32_t DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B;
+	uint32_t DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C;
+	uint32_t DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D;
+	uint32_t DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A;
+	uint32_t DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B;
+	uint32_t DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C;
+	uint32_t DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D;
 };
 
+#define HUBBUB_REG_FIELD_LIST_DCN32(type) \
+		type DCHUBBUB_ARB_ALLOW_USR_RETRAINING_FORCE_VALUE;\
+		type DCHUBBUB_ARB_ALLOW_USR_RETRAINING_FORCE_ENABLE;\
+		type DCHUBBUB_ARB_DO_NOT_FORCE_ALLOW_USR_RETRAINING_DURING_PSTATE_CHANGE_REQUEST;\
+		type DCHUBBUB_ARB_DO_NOT_FORCE_ALLOW_USR_RETRAINING_DURING_PRE_CSTATE;\
+		type DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A;\
+		type DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B;\
+		type DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C;\
+		type DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D;\
+		type DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A;\
+		type DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B;\
+		type DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C;\
+		type DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D;\
+		type DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A;\
+		type DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B;\
+		type DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C;\
+		type DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D
+
 /* set field name */
 #define HUBBUB_SF(reg_name, field_name, post_fix)\
 	.field_name = reg_name ## __ ## field_name ## post_fix
@@ -337,6 +368,7 @@ struct dcn_hubbub_shift {
 	HUBBUB_STUTTER_REG_FIELD_LIST(uint8_t);
 	HUBBUB_HVM_REG_FIELD_LIST(uint8_t);
 	HUBBUB_RET_REG_FIELD_LIST(uint8_t);
+	HUBBUB_REG_FIELD_LIST_DCN32(uint8_t);
 };
 
 struct dcn_hubbub_mask {
@@ -344,6 +376,7 @@ struct dcn_hubbub_mask {
 	HUBBUB_STUTTER_REG_FIELD_LIST(uint32_t);
 	HUBBUB_HVM_REG_FIELD_LIST(uint32_t);
 	HUBBUB_RET_REG_FIELD_LIST(uint32_t);
+	HUBBUB_REG_FIELD_LIST_DCN32(uint32_t);
 };
 
 struct dc;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index e3a62873c0e7..1cb206dc8352 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -1375,11 +1375,6 @@ void dcn10_init_pipes(struct dc *dc, struct dc_state *context)
 		pipe_ctx->stream_res.tg = NULL;
 		pipe_ctx->plane_res.hubp = NULL;
 
-		if (tg->funcs->is_tg_enabled(tg)) {
-			if (tg->funcs->init_odm)
-				tg->funcs->init_odm(tg);
-		}
-
 		tg->funcs->tg_init(tg);
 	}
 
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
index c50c29984d51..df155cc2bfea 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
@@ -514,6 +514,7 @@ struct dcn_optc_registers {
 	type DIG_UPDATE_POSITION_X;\
 	type DIG_UPDATE_POSITION_Y;\
 	type OTG_H_TIMING_DIV_MODE;\
+	type OTG_H_TIMING_DIV_MODE_MANUAL;\
 	type OTG_DRR_TIMING_DBUF_UPDATE_MODE;\
 	type OTG_CRC_DSC_MODE;\
 	type OTG_CRC_DATA_STREAM_COMBINE_MODE;\
@@ -553,6 +554,7 @@ struct optc {
 	int vupdate_offset;
 	int vupdate_width;
 	int vready_offset;
+	struct dc_crtc_timing orginal_patched_timing;
 	enum signal_type signal;
 };
 
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h
index 293595a33982..fa6ff540e8f2 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h
@@ -73,6 +73,7 @@
 	SRI(HDMI_ACR_48_1, DIG, id),\
 	SRI(DP_DB_CNTL, DP, id), \
 	SRI(DP_MSA_MISC, DP, id), \
+	SRI(DP_MSA_VBID_MISC, DP, id), \
 	SRI(DP_MSA_COLORIMETRY, DP, id), \
 	SRI(DP_MSA_TIMING_PARAM1, DP, id), \
 	SRI(DP_MSA_TIMING_PARAM2, DP, id), \
@@ -186,6 +187,7 @@ struct dcn10_stream_enc_registers {
 	uint32_t HDMI_GENERIC_PACKET_CONTROL9;
 	uint32_t HDMI_GENERIC_PACKET_CONTROL10;
 	uint32_t DIG_CLOCK_PATTERN;
+	uint32_t DIG_FIFO_CTRL0;
 };
 
 
@@ -338,7 +340,8 @@ struct dcn10_stream_enc_registers {
 	SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh)
 
 #define SE_COMMON_MASK_SH_LIST_SOC(mask_sh)\
-	SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh)
+	SE_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh),\
+	SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh)
 
 #define SE_COMMON_MASK_SH_LIST_DCN10(mask_sh)\
 	SE_COMMON_MASK_SH_LIST_SOC(mask_sh),\
@@ -567,16 +570,39 @@ struct dcn10_stream_enc_registers {
 	type DP_SEC_GSP11_ENABLE;\
 	type DP_SEC_GSP11_LINE_NUM
 
+#define SE_REG_FIELD_LIST_DCN3_2(type) \
+	type DIG_SYMCLK_FE_ON;\
+	type DIG_FIFO_READ_START_LEVEL;\
+	type DIG_FIFO_ENABLE;\
+	type DIG_FIFO_RESET;\
+	type DIG_FIFO_RESET_DONE
+
+/* TODO: fix this */
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
+#define DIG0_HDMI_VBI_PACKET_CONTROL__HDMI_ACP_SEND__SHIFT 0xc
+#define DIG0_HDMI_VBI_PACKET_CONTROL__HDMI_ACP_SEND_MASK 0x00001000L
+#endif
+
 struct dcn10_stream_encoder_shift {
 	SE_REG_FIELD_LIST_DCN1_0(uint8_t);
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
+	uint8_t HDMI_ACP_SEND;
+#endif
 	SE_REG_FIELD_LIST_DCN2_0(uint8_t);
 	SE_REG_FIELD_LIST_DCN3_0(uint8_t);
+	SE_REG_FIELD_LIST_DCN3_2(uint8_t);
+
 };
 
 struct dcn10_stream_encoder_mask {
 	SE_REG_FIELD_LIST_DCN1_0(uint32_t);
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
+	uint32_t HDMI_ACP_SEND;
+#endif
 	SE_REG_FIELD_LIST_DCN2_0(uint32_t);
 	SE_REG_FIELD_LIST_DCN3_0(uint32_t);
+	SE_REG_FIELD_LIST_DCN3_2(uint32_t);
+
 };
 
 struct dcn10_stream_encoder {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h
index b3c9a9724efd..2b9d3e63191b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h
@@ -133,6 +133,8 @@
 	type OTG_DROP_PIXEL[MAX_PIPES];
 
 #define DCCG3_REG_FIELD_LIST(type) \
+	type HDMICHARCLK0_EN;\
+	type HDMICHARCLK0_SRC_SEL;\
 	type PHYASYMCLK_FORCE_EN;\
 	type PHYASYMCLK_FORCE_SRC_SEL;\
 	type PHYBSYMCLK_FORCE_EN;\
@@ -203,16 +205,45 @@
 	type PHYDSYMCLK_GATE_DISABLE; \
 	type PHYESYMCLK_GATE_DISABLE;
 
+#define DCCG32_REG_FIELD_LIST(type) \
+	type DPSTREAMCLK0_EN;\
+	type DPSTREAMCLK1_EN;\
+	type DPSTREAMCLK2_EN;\
+	type DPSTREAMCLK3_EN;\
+	type DPSTREAMCLK0_SRC_SEL;\
+	type DPSTREAMCLK1_SRC_SEL;\
+	type DPSTREAMCLK2_SRC_SEL;\
+	type DPSTREAMCLK3_SRC_SEL;\
+	type HDMISTREAMCLK0_EN;\
+	type OTG0_PIXEL_RATE_DIVK1;\
+	type OTG0_PIXEL_RATE_DIVK2;\
+	type OTG1_PIXEL_RATE_DIVK1;\
+	type OTG1_PIXEL_RATE_DIVK2;\
+	type OTG2_PIXEL_RATE_DIVK1;\
+	type OTG2_PIXEL_RATE_DIVK2;\
+	type OTG3_PIXEL_RATE_DIVK1;\
+	type OTG3_PIXEL_RATE_DIVK2;\
+	type DTBCLK_P0_SRC_SEL;\
+	type DTBCLK_P0_EN;\
+	type DTBCLK_P1_SRC_SEL;\
+	type DTBCLK_P1_EN;\
+	type DTBCLK_P2_SRC_SEL;\
+	type DTBCLK_P2_EN;\
+	type DTBCLK_P3_SRC_SEL;\
+	type DTBCLK_P3_EN;
+
 struct dccg_shift {
 	DCCG_REG_FIELD_LIST(uint8_t)
 	DCCG3_REG_FIELD_LIST(uint8_t)
 	DCCG31_REG_FIELD_LIST(uint8_t)
+	DCCG32_REG_FIELD_LIST(uint8_t)
 };
 
 struct dccg_mask {
 	DCCG_REG_FIELD_LIST(uint32_t)
 	DCCG3_REG_FIELD_LIST(uint32_t)
 	DCCG31_REG_FIELD_LIST(uint32_t)
+	DCCG32_REG_FIELD_LIST(uint32_t)
 };
 
 struct dccg_registers {
@@ -247,7 +278,8 @@ struct dccg_registers {
 	uint32_t DCCG_GATE_DISABLE_CNTL3;
 	uint32_t HDMISTREAMCLK0_DTO_PARAM;
 	uint32_t DCCG_GATE_DISABLE_CNTL4;
-
+	uint32_t OTG_PIXEL_RATE_DIV;
+	uint32_t DTBCLK_P_CNTL;
 };
 
 struct dcn_dccg {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.h
index 9204c3ef323b..efa2adf4f83d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.h
@@ -161,6 +161,12 @@
 	DCN21_HUBP_REG_COMMON_VARIABLE_LIST;\
 	uint32_t DCN_DMDATA_VM_CNTL
 
+#define DCN32_HUBP_REG_COMMON_VARIABLE_LIST \
+	DCN30_HUBP_REG_COMMON_VARIABLE_LIST;\
+	uint32_t DCHUBP_MALL_CONFIG;\
+	uint32_t DCHUBP_VMPG_CONFIG;\
+	uint32_t UCLK_PSTATE_FORCE
+
 #define DCN2_HUBP_REG_FIELD_VARIABLE_LIST(type) \
 	DCN_HUBP_REG_FIELD_BASE_LIST(type); \
 	type DMDATA_ADDRESS_HIGH;\
@@ -222,16 +228,29 @@
 	type CURSOR_REQ_MODE;\
 	type HUBP_SOFT_RESET
 
+#define DCN32_HUBP_REG_FIELD_VARIABLE_LIST(type) \
+	DCN31_HUBP_REG_FIELD_VARIABLE_LIST(type);\
+	type USE_MALL_SEL; \
+	type USE_MALL_FOR_CURSOR;\
+	type VMPG_SIZE; \
+	type PTE_BUFFER_MODE; \
+	type BIGK_FRAGMENT_SIZE; \
+	type FORCE_ONE_ROW_FOR_FRAME; \
+	type DATA_UCLK_PSTATE_FORCE_EN; \
+	type DATA_UCLK_PSTATE_FORCE_VALUE; \
+	type CURSOR_UCLK_PSTATE_FORCE_EN; \
+	type CURSOR_UCLK_PSTATE_FORCE_VALUE
+
 struct dcn_hubp2_registers {
-	DCN30_HUBP_REG_COMMON_VARIABLE_LIST;
+	DCN32_HUBP_REG_COMMON_VARIABLE_LIST;
 };
 
 struct dcn_hubp2_shift {
-	DCN31_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t);
+	DCN32_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t);
 };
 
 struct dcn_hubp2_mask {
-	DCN31_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t);
+	DCN32_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t);
 };
 
 struct dcn20_hubp {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index ec6aa8d8b251..d00a27893ab0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -768,6 +768,10 @@ enum dc_status dcn20_enable_stream_timing(
 	/* TODO enable stream if timing changed */
 	/* TODO unblank stream if DP */
 
+	if (pipe_ctx->stream && pipe_ctx->stream->mall_stream_config.type == SUBVP_PHANTOM) {
+		if (pipe_ctx->stream_res.tg && pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable)
+			pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable(pipe_ctx->stream_res.tg);
+	}
 	return DC_OK;
 }
 
@@ -1247,6 +1251,16 @@ void dcn20_pipe_control_lock(
 					lock,
 					&hw_locks,
 					&inst_flags);
+	} else if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
+		union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
+		hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
+		hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
+		hw_lock_cmd.bits.lock_pipe = 1;
+		hw_lock_cmd.bits.otg_inst = pipe->stream_res.tg->inst;
+		hw_lock_cmd.bits.lock = lock;
+		if (!lock)
+			hw_lock_cmd.bits.should_release = 1;
+		dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd);
 	} else if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) {
 		if (lock)
 			pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg);
@@ -1564,10 +1578,12 @@ static void dcn20_update_dchubp_dpp(
 		plane_state->update_flags.bits.addr_update)
 		hws->funcs.update_plane_addr(dc, pipe_ctx);
 
-
-
 	if (pipe_ctx->update_flags.bits.enable)
 		hubp->funcs->set_blank(hubp, false);
+	/* If the stream paired with this plane is phantom, the plane is also phantom */
+	if (pipe_ctx->stream && pipe_ctx->stream->mall_stream_config.type == SUBVP_PHANTOM
+			&& hubp->funcs->phantom_hubp_post_enable)
+		hubp->funcs->phantom_hubp_post_enable(hubp);
 }
 
 
@@ -1578,6 +1594,7 @@ static void dcn20_program_pipe(
 {
 	struct dce_hwseq *hws = dc->hwseq;
 	/* Only need to unblank on top pipe */
+
 	if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->stream->update_flags.bits.abm_level)
 			&& !pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe)
 		hws->funcs.blank_pixel_data(dc, pipe_ctx, !pipe_ctx->plane_state->visible);
@@ -1585,7 +1602,6 @@ static void dcn20_program_pipe(
 	/* Only update TG on top pipe */
 	if (pipe_ctx->update_flags.bits.global_sync && !pipe_ctx->top_pipe
 			&& !pipe_ctx->prev_odm_pipe) {
-
 		pipe_ctx->stream_res.tg->funcs->program_global_sync(
 				pipe_ctx->stream_res.tg,
 				pipe_ctx->pipe_dlg_param.vready_offset,
@@ -1593,7 +1609,12 @@ static void dcn20_program_pipe(
 				pipe_ctx->pipe_dlg_param.vupdate_offset,
 				pipe_ctx->pipe_dlg_param.vupdate_width);
 
-		pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
+		if (pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) {
+			pipe_ctx->stream_res.tg->funcs->wait_for_state(
+				pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK);
+			pipe_ctx->stream_res.tg->funcs->wait_for_state(
+				pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
+		}
 
 		pipe_ctx->stream_res.tg->funcs->set_vtg_params(
 				pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, true);
@@ -1749,6 +1770,8 @@ void dcn20_program_front_end_for_ctx(
 			pipe->plane_res.hubp->funcs->hubp_wait_pipe_read_start(pipe->plane_res.hubp);
 		}
 	}
+	if (hws->funcs.program_mall_pipe_config)
+		hws->funcs.program_mall_pipe_config(dc, context);
 }
 
 void dcn20_post_unlock_program_front_end(
@@ -2409,6 +2432,7 @@ void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
 			NULL,
 			hubp->inst,
 			mpcc_id);
+
 	dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
 
 	ASSERT(new_mpcc != NULL);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c
index a04ca4a98392..b683ad817106 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c
@@ -195,7 +195,7 @@ static void enc3_update_hdmi_info_packet(
 	}
 }
 
-static void enc3_stream_encoder_update_hdmi_info_packets(
+void enc3_stream_encoder_update_hdmi_info_packets(
 	struct stream_encoder *enc,
 	const struct encoder_info_frame *info_frame)
 {
@@ -214,7 +214,7 @@ static void enc3_stream_encoder_update_hdmi_info_packets(
 	enc3_update_hdmi_info_packet(enc1, 4, &info_frame->hdrsmd);
 }
 
-static void enc3_stream_encoder_stop_hdmi_info_packets(
+void enc3_stream_encoder_stop_hdmi_info_packets(
 	struct stream_encoder *enc)
 {
 	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
@@ -318,7 +318,7 @@ static void enc3_dp_set_dsc_config(struct stream_encoder *enc,
 }
 
 
-static void enc3_dp_set_dsc_pps_info_packet(struct stream_encoder *enc,
+void enc3_dp_set_dsc_pps_info_packet(struct stream_encoder *enc,
 					bool enable,
 					uint8_t *dsc_packed_pps,
 					bool immediate_update)
@@ -404,7 +404,7 @@ static void enc3_read_state(struct stream_encoder *enc, struct enc_state *s)
 	}
 }
 
-static void enc3_stream_encoder_update_dp_info_packets(
+void enc3_stream_encoder_update_dp_info_packets(
 	struct stream_encoder *enc,
 	const struct encoder_info_frame *info_frame)
 {
@@ -652,7 +652,7 @@ static void enc3_stream_encoder_hdmi_set_stream_attribute(
 	REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0);
 }
 
-static void enc3_audio_mute_control(
+void enc3_audio_mute_control(
 	struct stream_encoder *enc,
 	bool mute)
 {
@@ -660,7 +660,7 @@ static void enc3_audio_mute_control(
 	enc->afmt->funcs->audio_mute_control(enc->afmt, mute);
 }
 
-static void enc3_se_dp_audio_setup(
+void enc3_se_dp_audio_setup(
 	struct stream_encoder *enc,
 	unsigned int az_inst,
 	struct audio_info *info)
@@ -691,7 +691,7 @@ static void enc3_se_setup_dp_audio(
 	enc->afmt->funcs->setup_dp_audio(enc->afmt);
 }
 
-static void enc3_se_dp_audio_enable(
+void enc3_se_dp_audio_enable(
 	struct stream_encoder *enc)
 {
 	enc1_se_enable_audio_clock(enc, true);
@@ -757,7 +757,7 @@ static void enc3_se_setup_hdmi_audio(
 	 */
 }
 
-static void enc3_se_hdmi_audio_setup(
+void enc3_se_hdmi_audio_setup(
 	struct stream_encoder *enc,
 	unsigned int az_inst,
 	struct audio_info *info,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h
index 42140e73c3b2..d2207b35f15f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h
@@ -287,4 +287,39 @@ void dcn30_dio_stream_encoder_construct(
 	const struct dcn10_stream_encoder_shift *se_shift,
 	const struct dcn10_stream_encoder_mask *se_mask);
 
+void enc3_stream_encoder_update_hdmi_info_packets(
+	struct stream_encoder *enc,
+	const struct encoder_info_frame *info_frame);
+
+void enc3_stream_encoder_stop_hdmi_info_packets(
+	struct stream_encoder *enc);
+
+void enc3_stream_encoder_update_dp_info_packets(
+	struct stream_encoder *enc,
+	const struct encoder_info_frame *info_frame);
+
+void enc3_audio_mute_control(
+	struct stream_encoder *enc,
+	bool mute);
+
+void enc3_se_dp_audio_setup(
+	struct stream_encoder *enc,
+	unsigned int az_inst,
+	struct audio_info *info);
+
+void enc3_se_dp_audio_enable(
+	struct stream_encoder *enc);
+
+void enc3_se_hdmi_audio_setup(
+	struct stream_encoder *enc,
+	unsigned int az_inst,
+	struct audio_info *info,
+	struct audio_crtc_info *audio_crtc_info);
+
+void enc3_dp_set_dsc_pps_info_packet(
+	struct stream_encoder *enc,
+	bool enable,
+	uint8_t *dsc_packed_pps,
+    bool immediate_update);
+
 #endif /* __DC_DIO_STREAM_ENCODER_DCN30_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c
index ab3918c0a15b..9cca59bf2ae0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c
@@ -41,9 +41,9 @@
 	dpp->tf_shift->field_name, dpp->tf_mask->field_name
 
 
-static void dpp30_read_state(struct dpp *dpp_base, struct dcn_dpp_state *s)
+void dpp30_read_state(struct dpp *dpp_base, struct dcn_dpp_state *s)
 {
-	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
+	struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
 
 	REG_GET(DPP_CONTROL,
 			DPP_CLOCK_ENABLE, &s->is_enabled);
@@ -167,7 +167,7 @@ void dpp3_set_pre_degam(struct dpp *dpp_base, enum dc_transfer_func_predefined t
 			PRE_DEGAM_SELECT, degamma_lut_selection);
 }
 
-static void dpp3_cnv_setup (
+void dpp3_cnv_setup (
 		struct dpp *dpp_base,
 		enum surface_pixel_format format,
 		enum expansion_mode mode,
@@ -372,7 +372,7 @@ void dpp3_set_cursor_attributes(
 }
 
 
-static bool dpp3_get_optimal_number_of_taps(
+bool dpp3_get_optimal_number_of_taps(
 		struct dpp *dpp,
 		struct scaler_data *scl_data,
 		const struct scaling_taps *in_taps)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h
index ac644ae6b9f2..6263408d71fc 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h
@@ -588,6 +588,22 @@ void dpp3_program_CM_dealpha(
 		struct dpp *dpp_base,
 		uint32_t enable, uint32_t additive_blending);
 
+void dpp30_read_state(struct dpp *dpp_base,
+		struct dcn_dpp_state *s);
+
+bool dpp3_get_optimal_number_of_taps(
+		struct dpp *dpp,
+		struct scaler_data *scl_data,
+		const struct scaling_taps *in_taps);
+
+void dpp3_cnv_setup (
+		struct dpp *dpp_base,
+		enum surface_pixel_format format,
+		enum expansion_mode mode,
+		struct dc_csc_transform input_csc_color_matrix,
+		enum dc_color_space input_color_space,
+		struct cnv_alpha_2bit_lut *alpha_2bit_lut);
+
 void dpp3_program_CM_bias(
 		struct dpp *dpp_base,
 		struct CM_bias_params *bias_params);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c
index 0ce0d6165f43..1981a71b961b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c
@@ -44,7 +44,7 @@
 #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
 
 
-static bool mpc3_is_dwb_idle(
+bool mpc3_is_dwb_idle(
 	struct mpc *mpc,
 	int dwb_id)
 {
@@ -59,7 +59,7 @@ static bool mpc3_is_dwb_idle(
 		return false;
 }
 
-static void mpc3_set_dwb_mux(
+void mpc3_set_dwb_mux(
 	struct mpc *mpc,
 	int dwb_id,
 	int mpcc_id)
@@ -70,7 +70,7 @@ static void mpc3_set_dwb_mux(
 		MPC_DWB0_MUX, mpcc_id);
 }
 
-static void mpc3_disable_dwb_mux(
+void mpc3_disable_dwb_mux(
 	struct mpc *mpc,
 	int dwb_id)
 {
@@ -80,7 +80,7 @@ static void mpc3_disable_dwb_mux(
 		MPC_DWB0_MUX, 0xf);
 }
 
-static void mpc3_set_out_rate_control(
+void mpc3_set_out_rate_control(
 	struct mpc *mpc,
 	int opp_id,
 	bool enable,
@@ -99,7 +99,7 @@ static void mpc3_set_out_rate_control(
 			MPC_OUT_FLOW_CONTROL_COUNT, flow_control->flow_ctrl_cnt1);
 }
 
-static enum dc_lut_mode mpc3_get_ogam_current(struct mpc *mpc, int mpcc_id)
+enum dc_lut_mode mpc3_get_ogam_current(struct mpc *mpc, int mpcc_id)
 {
 	/*Contrary to DCN2 and DCN1 wherein a single status register field holds this info;
 	 *in DCN3/3AG, we need to read two separate fields to retrieve the same info
@@ -137,7 +137,7 @@ static enum dc_lut_mode mpc3_get_ogam_current(struct mpc *mpc, int mpcc_id)
 		return mode;
 }
 
-static void mpc3_power_on_ogam_lut(
+void mpc3_power_on_ogam_lut(
 		struct mpc *mpc, int mpcc_id,
 		bool power_on)
 {
@@ -1035,7 +1035,7 @@ static void mpc3_set3dlut_ram10(
 }
 
 
-static void mpc3_init_mpcc(struct mpcc *mpcc, int mpcc_inst)
+void mpc3_init_mpcc(struct mpcc *mpcc, int mpcc_inst)
 {
 	mpcc->mpcc_id = mpcc_inst;
 	mpcc->dpp_id = 0xf;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h
index 34b9cedbd012..a4d8f77d43bc 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h
@@ -282,6 +282,73 @@
 	uint32_t MPCC_OGAM_RAMB_START_BASE_CNTL_R[MAX_MPCC]; \
 	uint32_t MPC_OUT_CSC_COEF_FORMAT
 
+#define MPC_REG_VARIABLE_LIST_DCN32 \
+	uint32_t MPCC_MCM_SHAPER_CONTROL[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_OFFSET_R[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_OFFSET_G[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_OFFSET_B[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_SCALE_R[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_SCALE_G_B[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_LUT_INDEX[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_LUT_DATA[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_START_CNTL_B[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_START_CNTL_G[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_START_CNTL_R[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_END_CNTL_B[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_END_CNTL_G[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_END_CNTL_R[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_0_1[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_2_3[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_4_5[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_6_7[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_8_9[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_10_11[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_12_13[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_14_15[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_16_17[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_18_19[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_20_21[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_22_23[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_24_25[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_26_27[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_28_29[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_30_31[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMA_REGION_32_33[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_START_CNTL_B[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_START_CNTL_G[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_START_CNTL_R[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_END_CNTL_B[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_END_CNTL_G[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_END_CNTL_R[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_0_1[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_2_3[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_4_5[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_6_7[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_8_9[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_10_11[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_12_13[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_14_15[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_16_17[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_18_19[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_20_21[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_22_23[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_24_25[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_26_27[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_28_29[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_30_31[MAX_MPCC]; \
+	uint32_t MPCC_MCM_SHAPER_RAMB_REGION_32_33[MAX_MPCC]; \
+	uint32_t MPCC_MCM_3DLUT_MODE[MAX_MPCC]; \
+	uint32_t MPCC_MCM_3DLUT_INDEX[MAX_MPCC]; \
+	uint32_t MPCC_MCM_3DLUT_DATA[MAX_MPCC]; \
+	uint32_t MPCC_MCM_3DLUT_DATA_30BIT[MAX_MPCC]; \
+	uint32_t MPCC_MCM_3DLUT_READ_WRITE_CONTROL[MAX_MPCC]; \
+	uint32_t MPCC_MCM_3DLUT_OUT_NORM_FACTOR[MAX_MPCC]; \
+	uint32_t MPCC_MCM_3DLUT_OUT_OFFSET_R[MAX_MPCC]; \
+	uint32_t MPCC_MCM_3DLUT_OUT_OFFSET_G[MAX_MPCC]; \
+	uint32_t MPCC_MCM_3DLUT_OUT_OFFSET_B[MAX_MPCC]; \
+	uint32_t MPCC_MCM_MEM_PWR_CTRL[MAX_MPCC]
+
 #define MPC_COMMON_MASK_SH_LIST_DCN3_0(mask_sh) \
 	MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh),\
 	SF(MPCC0_MPCC_CONTROL, MPCC_BG_BPC, mask_sh),\
@@ -580,6 +647,53 @@
 	type MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS;\
 	type MPC_RMU_SHAPER_MODE_CURRENT
 
+#define MPC_REG_FIELD_LIST_DCN32(type) \
+	type MPCC_MCM_SHAPER_MEM_PWR_FORCE;\
+	type MPCC_MCM_SHAPER_MEM_PWR_DIS;\
+	type MPCC_MCM_SHAPER_MEM_LOW_PWR_MODE;\
+	type MPCC_MCM_3DLUT_MEM_PWR_FORCE;\
+	type MPCC_MCM_3DLUT_MEM_PWR_DIS;\
+	type MPCC_MCM_3DLUT_MEM_LOW_PWR_MODE;\
+	type MPCC_MCM_1DLUT_MEM_PWR_FORCE;\
+	type MPCC_MCM_1DLUT_MEM_PWR_DIS;\
+	type MPCC_MCM_1DLUT_MEM_LOW_PWR_MODE;\
+	type MPCC_MCM_SHAPER_MEM_PWR_STATE;\
+	type MPCC_MCM_3DLUT_MEM_PWR_STATE;\
+	type MPCC_MCM_1DLUT_MEM_PWR_STATE;\
+	type MPCC_MCM_3DLUT_MODE; \
+	type MPCC_MCM_3DLUT_SIZE; \
+	type MPCC_MCM_3DLUT_MODE_CURRENT; \
+	type MPCC_MCM_3DLUT_WRITE_EN_MASK;\
+	type MPCC_MCM_3DLUT_RAM_SEL;\
+	type MPCC_MCM_3DLUT_30BIT_EN;\
+	type MPCC_MCM_3DLUT_CONFIG_STATUS;\
+	type MPCC_MCM_3DLUT_READ_SEL;\
+	type MPCC_MCM_3DLUT_INDEX;\
+	type MPCC_MCM_3DLUT_DATA0;\
+	type MPCC_MCM_3DLUT_DATA1;\
+	type MPCC_MCM_3DLUT_DATA_30BIT;\
+	type MPCC_MCM_SHAPER_LUT_MODE;\
+	type MPCC_MCM_SHAPER_MODE_CURRENT;\
+	type MPCC_MCM_SHAPER_OFFSET_R;\
+	type MPCC_MCM_SHAPER_OFFSET_G;\
+	type MPCC_MCM_SHAPER_OFFSET_B;\
+	type MPCC_MCM_SHAPER_SCALE_R;\
+	type MPCC_MCM_SHAPER_SCALE_G;\
+	type MPCC_MCM_SHAPER_SCALE_B;\
+	type MPCC_MCM_SHAPER_LUT_INDEX;\
+	type MPCC_MCM_SHAPER_LUT_DATA;\
+	type MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK;\
+	type MPCC_MCM_SHAPER_LUT_WRITE_SEL;\
+	type MPCC_MCM_SHAPER_CONFIG_STATUS;\
+	type MPCC_MCM_SHAPER_RAMA_EXP_REGION_START_B;\
+	type MPCC_MCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B;\
+	type MPCC_MCM_SHAPER_RAMA_EXP_REGION_END_B;\
+	type MPCC_MCM_SHAPER_RAMA_EXP_REGION_END_BASE_B;\
+	type MPCC_MCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET;\
+	type MPCC_MCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS;\
+	type MPCC_MCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET;\
+	type MPCC_MCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS
+
 #define MPC_COMMON_MASK_SH_LIST_DCN303(mask_sh) \
 	MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh),\
 	SF(MPCC0_MPCC_CONTROL, MPCC_BG_BPC, mask_sh),\
@@ -758,14 +872,17 @@
 
 struct dcn30_mpc_registers {
 	MPC_REG_VARIABLE_LIST_DCN3_0;
+	MPC_REG_VARIABLE_LIST_DCN32;
 };
 
 struct dcn30_mpc_shift {
 	MPC_REG_FIELD_LIST_DCN3_0(uint8_t);
+	MPC_REG_FIELD_LIST_DCN32(uint8_t);
 };
 
 struct dcn30_mpc_mask {
 	MPC_REG_FIELD_LIST_DCN3_0(uint32_t);
+	MPC_REG_FIELD_LIST_DCN32(uint32_t);
 };
 
 struct dcn30_mpc {
@@ -841,4 +958,34 @@ void mpc3_set_rmu_mux(
 	int rmu_idx,
 	int value);
 
+void mpc3_set_dwb_mux(
+	struct mpc *mpc,
+	int dwb_id,
+	int mpcc_id);
+
+void mpc3_disable_dwb_mux(
+	struct mpc *mpc,
+	int dwb_id);
+
+bool mpc3_is_dwb_idle(
+	struct mpc *mpc,
+	int dwb_id);
+
+void mpc3_set_out_rate_control(
+	struct mpc *mpc,
+	int opp_id,
+	bool enable,
+	bool rate_2x_mode,
+	struct mpc_dwb_flow_control *flow_control);
+
+void mpc3_power_on_ogam_lut(
+	struct mpc *mpc, int mpcc_id,
+	bool power_on);
+
+void mpc3_init_mpcc(struct mpcc *mpcc, int mpcc_inst);
+
+enum dc_lut_mode mpc3_get_ogam_current(
+	struct mpc *mpc,
+	int mpcc_id);
+
 #endif
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
index 97f11ef6e9f0..33bd12f5dc17 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
@@ -28,6 +28,7 @@
 
 #include "dcn20/dcn20_optc.h"
 
+#define V_TOTAL_REGS_DCN30_SRI(inst)
 
 #define OPTC_COMMON_REG_LIST_DCN3_BASE(inst) \
 	SRI(OTG_VSTARTUP_PARAM, OTG, inst),\
@@ -55,6 +56,7 @@
 	SRI(OTG_V_TOTAL_MAX, OTG, inst),\
 	SRI(OTG_V_TOTAL_MIN, OTG, inst),\
 	SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\
+	V_TOTAL_REGS_DCN30_SRI(inst)\
 	SRI(OTG_TRIGA_CNTL, OTG, inst),\
 	SRI(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\
 	SRI(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\
@@ -80,6 +82,7 @@
 	SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\
 	SRI(OTG_GSL_CONTROL, OTG, inst),\
 	SRI(OTG_CRC_CNTL, OTG, inst),\
+	SRI(OTG_CRC_CNTL2, OTG, inst),\
 	SRI(OTG_CRC0_DATA_RG, OTG, inst),\
 	SRI(OTG_CRC0_DATA_B, OTG, inst),\
 	SRI(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst),\
@@ -108,6 +111,7 @@
 	SRI(OPTC_MEMORY_CONFIG, ODM, inst),\
 	SR(DWB_SOURCE_SELECT)
 
+#define DCN30_VTOTAL_REGS_SF(mask_sh)
 
 #define OPTC_COMMON_MASK_SH_LIST_DCN3_BASE(mask_sh)\
 	SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\
@@ -161,6 +165,7 @@
 	SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\
 	SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MIN_EN, mask_sh),\
 	SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\
+	DCN30_VTOTAL_REGS_SF(mask_sh)\
 	SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\
 	SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\
 	SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\
@@ -219,6 +224,10 @@
 	SF(OTG0_OTG_CRC_CNTL, OTG_CRC_CONT_EN, mask_sh),\
 	SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\
 	SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\
+	SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\
+	SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\
+	SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\
+	SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\
 	SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\
 	SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\
 	SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c
index 287a1066b547..20f11fb8f5a6 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c
@@ -158,10 +158,9 @@ static void dccg31_disable_dpstreamclk(struct dccg *dccg, int otg_inst)
 	}
 }
 
-void dccg31_set_dpstreamclk(
-		struct dccg *dccg,
-		enum hdmistreamclk_source src,
-		int otg_inst)
+void dccg31_set_dpstreamclk(struct dccg *dccg,
+			    enum streamclk_source src,
+			    int otg_inst)
 {
 	if (src == REFCLK)
 		dccg31_disable_dpstreamclk(dccg, otg_inst);
@@ -513,12 +512,13 @@ void dccg31_set_physymclk(
 /* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */
 static void dccg31_set_dtbclk_dto(
 		struct dccg *dccg,
-		int dtbclk_inst,
-		int req_dtbclk_khz,
+		int otg_inst,
+		int pixclk_khz,
 		int num_odm_segments,
 		const struct dc_crtc_timing *timing)
 {
 	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+	int req_dtbclk_khz = pixclk_khz;
 	uint32_t dtbdto_div;
 
 	/* Mode	                DTBDTO Rate       DTBCLK_DTO<x>_DIV Register
@@ -531,13 +531,13 @@ static void dccg31_set_dtbclk_dto(
 	 */
 	if (num_odm_segments == 4) {
 		dtbdto_div = 2;
-		req_dtbclk_khz = req_dtbclk_khz / 4;
+		req_dtbclk_khz = pixclk_khz / 4;
 	} else if ((num_odm_segments == 2) ||
 			(timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) ||
 			(timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
 					&& !timing->dsc_cfg.ycbcr422_simple)) {
 		dtbdto_div = 4;
-		req_dtbclk_khz = req_dtbclk_khz / 2;
+		req_dtbclk_khz = pixclk_khz / 2;
 	} else
 		dtbdto_div = 8;
 
@@ -549,37 +549,37 @@ static void dccg31_set_dtbclk_dto(
 		phase = div_u64((((unsigned long long)modulo * req_dtbclk_khz) + dccg->ref_dtbclk_khz - 1),
 			dccg->ref_dtbclk_khz);
 
-		REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst],
-				DTBCLK_DTO_DIV[dtbclk_inst], dtbdto_div);
+		REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
+				DTBCLK_DTO_DIV[otg_inst], dtbdto_div);
 
-		REG_WRITE(DTBCLK_DTO_MODULO[dtbclk_inst], modulo);
-		REG_WRITE(DTBCLK_DTO_PHASE[dtbclk_inst], phase);
+		REG_WRITE(DTBCLK_DTO_MODULO[otg_inst], modulo);
+		REG_WRITE(DTBCLK_DTO_PHASE[otg_inst], phase);
 
-		REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst],
-				DTBCLK_DTO_ENABLE[dtbclk_inst], 1);
+		REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
+				DTBCLK_DTO_ENABLE[otg_inst], 1);
 
-		REG_WAIT(OTG_PIXEL_RATE_CNTL[dtbclk_inst],
-				DTBCLKDTO_ENABLE_STATUS[dtbclk_inst], 1,
+		REG_WAIT(OTG_PIXEL_RATE_CNTL[otg_inst],
+				DTBCLKDTO_ENABLE_STATUS[otg_inst], 1,
 				1, 100);
 
 		/* The recommended programming sequence to enable DTBCLK DTO to generate
 		 * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
 		 * be set only after DTO is enabled
 		 */
-		REG_UPDATE(OTG_PIXEL_RATE_CNTL[dtbclk_inst],
-				PIPE_DTO_SRC_SEL[dtbclk_inst], 1);
+		REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
+				PIPE_DTO_SRC_SEL[otg_inst], 1);
 
-		dccg->dtbclk_khz[dtbclk_inst] = req_dtbclk_khz;
+		dccg->dtbclk_khz[otg_inst] = req_dtbclk_khz;
 	} else {
-		REG_UPDATE_3(OTG_PIXEL_RATE_CNTL[dtbclk_inst],
-				DTBCLK_DTO_ENABLE[dtbclk_inst], 0,
-				PIPE_DTO_SRC_SEL[dtbclk_inst], 0,
-				DTBCLK_DTO_DIV[dtbclk_inst], dtbdto_div);
+		REG_UPDATE_3(OTG_PIXEL_RATE_CNTL[otg_inst],
+				DTBCLK_DTO_ENABLE[otg_inst], 0,
+				PIPE_DTO_SRC_SEL[otg_inst], 0,
+				DTBCLK_DTO_DIV[otg_inst], dtbdto_div);
 
-		REG_WRITE(DTBCLK_DTO_MODULO[dtbclk_inst], 0);
-		REG_WRITE(DTBCLK_DTO_PHASE[dtbclk_inst], 0);
+		REG_WRITE(DTBCLK_DTO_MODULO[otg_inst], 0);
+		REG_WRITE(DTBCLK_DTO_PHASE[otg_inst], 0);
 
-		dccg->dtbclk_khz[dtbclk_inst] = 0;
+		dccg->dtbclk_khz[otg_inst] = 0;
 	}
 }
 
@@ -673,6 +673,24 @@ void dccg31_init(struct dccg *dccg)
 	}
 }
 
+void dccg31_otg_add_pixel(struct dccg *dccg,
+		uint32_t otg_inst)
+{
+	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+	REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
+			OTG_ADD_PIXEL[otg_inst], 1);
+}
+
+void dccg31_otg_drop_pixel(struct dccg *dccg,
+		uint32_t otg_inst)
+{
+	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+	REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],
+			OTG_DROP_PIXEL[otg_inst], 1);
+}
+
 static const struct dccg_funcs dccg31_funcs = {
 	.update_dpp_dto = dccg31_update_dpp_dto,
 	.get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
@@ -685,6 +703,9 @@ static const struct dccg_funcs dccg31_funcs = {
 	.set_physymclk = dccg31_set_physymclk,
 	.set_dtbclk_dto = dccg31_set_dtbclk_dto,
 	.set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
+	.set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
+	.otg_add_pixel = dccg31_otg_add_pixel,
+	.otg_drop_pixel = dccg31_otg_drop_pixel,
 	.set_dispclk_change_mode = dccg31_set_dispclk_change_mode,
 	.disable_dsc = dccg31_disable_dscclk,
 	.enable_dsc = dccg31_enable_dscclk,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h
index 269cabbea72a..f31cced5f441 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h
@@ -28,10 +28,6 @@
 
 #include "dcn30/dcn30_dccg.h"
 
-#define DCCG_SFII(block, reg_name, field_prefix, field_name, inst, post_fix)\
-	.field_prefix ## _ ## field_name[inst] = block ## inst ## _ ## reg_name ## __ ## field_prefix ## inst ## _ ## field_name ## post_fix
-
-
 #define DCCG_REG_LIST_DCN31() \
 	SR(DPPCLK_DTO_CTRL),\
 	DCCG_SRII(DTO_PARAM, DPPCLK, 0),\
@@ -124,6 +120,10 @@
 	DCCG_SFII(OTG, PIXEL_RATE_CNTL, DTBCLK_DTO, DIV, 1, mask_sh),\
 	DCCG_SFII(OTG, PIXEL_RATE_CNTL, DTBCLK_DTO, DIV, 2, mask_sh),\
 	DCCG_SFII(OTG, PIXEL_RATE_CNTL, DTBCLK_DTO, DIV, 3, mask_sh),\
+	DCCG_SFII(OTG, PIXEL_RATE_CNTL, OTG, ADD_PIXEL, 0, mask_sh),\
+	DCCG_SFII(OTG, PIXEL_RATE_CNTL, OTG, ADD_PIXEL, 1, mask_sh),\
+	DCCG_SFII(OTG, PIXEL_RATE_CNTL, OTG, ADD_PIXEL, 2, mask_sh),\
+	DCCG_SFII(OTG, PIXEL_RATE_CNTL, OTG, ADD_PIXEL, 3, mask_sh),\
 	DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\
 	DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\
 	DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE, mask_sh), \
@@ -163,7 +163,7 @@ void dccg31_init(struct dccg *dccg);
 
 void dccg31_set_dpstreamclk(
 		struct dccg *dccg,
-		enum hdmistreamclk_source src,
+		enum streamclk_source src,
 		int otg_inst);
 
 void dccg31_enable_symclk32_se(
@@ -194,8 +194,4 @@ void dccg31_set_audio_dtbclk_dto(
 		struct dccg *dccg,
 		uint32_t req_audio_dtbclk_khz);
 
-void dccg31_set_hdmistreamclk(
-		struct dccg *dccg,
-		enum hdmistreamclk_source src);
-
 #endif //__DCN31_DCCG_H__
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c
index c51f7dca94f8..96fac715a77b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c
@@ -213,26 +213,6 @@ void optc31_set_drr(
 	}
 }
 
-void optc3_init_odm(struct timing_generator *optc)
-{
-	struct optc *optc1 = DCN10TG_FROM_TG(optc);
-
-	REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0,
-			OPTC_NUM_OF_INPUT_SEGMENT, 0,
-			OPTC_SEG0_SRC_SEL, optc->inst,
-			OPTC_SEG1_SRC_SEL, 0xf,
-			OPTC_SEG2_SRC_SEL, 0xf,
-			OPTC_SEG3_SRC_SEL, 0xf
-			);
-
-	REG_SET(OTG_H_TIMING_CNTL, 0,
-			OTG_H_TIMING_DIV_MODE, 0);
-
-	REG_SET(OPTC_MEMORY_CONFIG, 0,
-			OPTC_MEM_SEL, 0);
-	optc1->opp_count = 1;
-}
-
 static struct timing_generator_funcs dcn31_tg_funcs = {
 		.validate_timing = optc1_validate_timing,
 		.program_timing = optc1_program_timing,
@@ -266,6 +246,7 @@ static struct timing_generator_funcs dcn31_tg_funcs = {
 		.lock_doublebuffer_disable = optc3_lock_doublebuffer_disable,
 		.enable_optc_clock = optc1_enable_optc_clock,
 		.set_drr = optc31_set_drr,
+		.get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal,
 		.set_vtotal_min_max = optc1_set_vtotal_min_max,
 		.set_static_screen_control = optc1_set_static_screen_control,
 		.program_stereo = optc1_program_stereo,
@@ -292,7 +273,6 @@ static struct timing_generator_funcs dcn31_tg_funcs = {
 		.program_manual_trigger = optc2_program_manual_trigger,
 		.setup_manual_trigger = optc2_setup_manual_trigger,
 		.get_hw_timing = optc1_get_hw_timing,
-		.init_odm = optc3_init_odm,
 };
 
 void dcn31_timing_generator_init(struct optc *optc1)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h
index 9e881f2ce74b..3706e6f7880e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h
@@ -98,7 +98,8 @@
 	SRI(OPTC_WIDTH_CONTROL, ODM, inst),\
 	SRI(OPTC_MEMORY_CONFIG, ODM, inst),\
 	SRI(OTG_CRC_CNTL2, OTG, inst),\
-	SR(DWB_SOURCE_SELECT)
+	SR(DWB_SOURCE_SELECT),\
+	SRI(OTG_DRR_CONTROL, OTG, inst)
 
 #define OPTC_COMMON_MASK_SH_LIST_DCN3_1(mask_sh)\
 	SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\
@@ -252,7 +253,8 @@
 	SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\
 	SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\
 	SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\
-	SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh)
+	SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\
+	SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh)
 
 void dcn31_timing_generator_init(struct optc *optc1);
 
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c
index 62532da94913..4d7588f2ee79 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c
@@ -211,8 +211,10 @@ static void enc32_stream_encoder_hdmi_set_stream_attribute(
 		HDMI_GC_SEND, 1,
 		HDMI_NULL_SEND, 1);
 
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
 	/* Disable Audio Content Protection packet transmission */
 	REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0);
+#endif
 
 	/* following belongs to audio */
 	/* Enable Audio InfoFrame packet transmission. */
@@ -301,6 +303,21 @@ static void enc32_stream_encoder_dp_unblank(
 
 	REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0);
 
+	/* DIG Resync FIFO now needs to be explicitly enabled
+	 */
+	// TODO: Confirm if we need to wait for DIG_SYMCLK_FE_ON
+	REG_WAIT(DIG_FE_CNTL, DIG_SYMCLK_FE_ON, 1, 10, 5000);
+
+	REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 1);
+
+	REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 1, 10, 5000);
+
+	REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 0);
+
+	REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 0, 10, 5000);
+
+	REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 1);
+
 	/* wait 100us for DIG/DP logic to prime
 	 * (i.e. a few video lines)
 	 */
@@ -354,6 +371,23 @@ static void enc32_read_state(struct stream_encoder *enc, struct enc_state *s)
 	}
 }
 
+static void enc32_stream_encoder_reset_fifo(struct stream_encoder *enc)
+{
+	struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+	uint32_t fifo_enabled;
+
+	REG_GET(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, &fifo_enabled);
+
+	if (fifo_enabled == 0) {
+		/* reset DIG resync FIFO */
+		REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 1);
+		/* TODO: fix timeout when wait for DIG_FIFO_RESET_DONE */
+		//REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 1, 1, 100);
+		udelay(1);
+		REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_RESET, 0);
+		REG_WAIT(DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, 0, 1, 100);
+	}
+}
 
 static const struct stream_encoder_funcs dcn32_str_enc_funcs = {
 	.dp_set_odm_combine =
@@ -375,7 +409,7 @@ static const struct stream_encoder_funcs dcn32_str_enc_funcs = {
 	.stop_dp_info_packets =
 		enc1_stream_encoder_stop_dp_info_packets,
 	.reset_fifo =
-		enc1_stream_encoder_reset_fifo,
+		enc32_stream_encoder_reset_fifo,
 	.dp_blank =
 		enc1_stream_encoder_dp_blank,
 	.dp_unblank =
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.h
index 7241080b1553..77da0a13525b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.h
@@ -89,7 +89,8 @@
 	SRI(DP_SEC_METADATA_TRANSMISSION, DP, id), \
 	SRI(HDMI_METADATA_PACKET_CONTROL, DIG, id), \
 	SRI(DIG_FE_CNTL, DIG, id), \
-	SRI(DIG_CLOCK_PATTERN, DIG, id)
+	SRI(DIG_CLOCK_PATTERN, DIG, id), \
+	SRI(DIG_FIFO_CTRL0, DIG, id)
 
 
 #define SE_COMMON_MASK_SH_LIST_DCN32_BASE(mask_sh)\
@@ -233,12 +234,22 @@
 	SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\
 	SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh),\
 	SE_SF(DIG0_DIG_FE_CNTL, DOLBY_VISION_EN, mask_sh),\
+	SE_SF(DIG0_DIG_FE_CNTL, DIG_SYMCLK_FE_ON, mask_sh),\
 	SE_SF(DP0_DP_SEC_FRAMING4, DP_SST_SDP_SPLITTING, mask_sh),\
-	SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh)
+	SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\
+	SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, mask_sh),\
+	SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, mask_sh),\
+	SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET, mask_sh),\
+	SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, mask_sh)
 
+#if defined(CONFIG_DRM_AMD_DC_HDCP)
 #define SE_COMMON_MASK_SH_LIST_DCN32(mask_sh)\
 	SE_COMMON_MASK_SH_LIST_DCN32_BASE(mask_sh),\
 	SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh)
+#else
+#define SE_COMMON_MASK_SH_LIST_DCN32(mask_sh)\
+	SE_COMMON_MASK_SH_LIST_DCN32_BASE(mask_sh)
+#endif
 
 void dcn32_dio_stream_encoder_construct(
 	struct dcn10_stream_encoder *enc1,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
index d0a222f1a09c..40afd33ffec6 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
@@ -649,7 +649,7 @@ void dcn32_init_hw(struct dc *dc)
 	 * Otherwise, if taking control is not possible, we need to power
 	 * everything down.
 	 */
-	if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) {
+	if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.seamless_boot_edp_requested) {
 		hws->funcs.init_pipes(dc, dc->current_state);
 		if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
 			dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
@@ -661,7 +661,7 @@ void dcn32_init_hw(struct dc *dc)
 	 * To avoid this, power down hardware on boot
 	 * if DIG is turned on and seamless boot not enabled
 	 */
-	if (dc->config.power_down_display_on_boot) {
+	if (dc->config.seamless_boot_edp_requested) {
 		struct dc_link *edp_links[MAX_NUM_EDP];
 		struct dc_link *edp_link;
 
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c
index f1ed25e972f2..88275ea4193c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c
@@ -91,10 +91,18 @@ static void optc32_set_odm_combine(struct timing_generator *optc, int *opp_id, i
 	REG_UPDATE(OPTC_WIDTH_CONTROL,
 			OPTC_SEGMENT_WIDTH, mpcc_hactive);
 
-	REG_SET(OTG_H_TIMING_CNTL, 0, OTG_H_TIMING_DIV_MODE, opp_cnt - 1);
+	REG_UPDATE(OTG_H_TIMING_CNTL,
+			OTG_H_TIMING_DIV_MODE, opp_cnt - 1);
 	optc1->opp_count = opp_cnt;
 }
 
+static void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode)
+{
+	struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+	REG_UPDATE(OTG_H_TIMING_CNTL,
+			OTG_H_TIMING_DIV_MODE_MANUAL, manual_mode ? 1 : 0);
+}
 /**
  * Enable CRTC
  * Enable CRTC - call ASIC Control Object to enable Timing generator.
@@ -157,6 +165,29 @@ void optc32_phantom_crtc_post_enable(struct timing_generator *optc)
 	REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, 1, 100000);
 }
 
+static void optc32_set_odm_bypass(struct timing_generator *optc,
+		const struct dc_crtc_timing *dc_crtc_timing)
+{
+	struct optc *optc1 = DCN10TG_FROM_TG(optc);
+	enum h_timing_div_mode h_div = H_TIMING_NO_DIV;
+
+	REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0,
+			OPTC_NUM_OF_INPUT_SEGMENT, 0,
+			OPTC_SEG0_SRC_SEL, optc->inst,
+			OPTC_SEG1_SRC_SEL, 0xf,
+			OPTC_SEG2_SRC_SEL, 0xf,
+			OPTC_SEG3_SRC_SEL, 0xf
+			);
+
+	h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing);
+	REG_UPDATE(OTG_H_TIMING_CNTL,
+			OTG_H_TIMING_DIV_MODE, h_div);
+
+	REG_SET(OPTC_MEMORY_CONFIG, 0,
+			OPTC_MEM_SEL, 0);
+	optc1->opp_count = 1;
+}
+
 
 static struct timing_generator_funcs dcn32_tg_funcs = {
 		.validate_timing = optc1_validate_timing,
@@ -206,8 +237,9 @@ static struct timing_generator_funcs dcn32_tg_funcs = {
 		.set_dsc_config = optc3_set_dsc_config,
 		.get_dsc_status = optc2_get_dsc_status,
 		.set_dwb_source = NULL,
-		.set_odm_bypass = optc3_set_odm_bypass,
+		.set_odm_bypass = optc32_set_odm_bypass,
 		.set_odm_combine = optc32_set_odm_combine,
+		.set_h_timing_div_manual_mode = optc32_set_h_timing_div_manual_mode,
 		.get_optc_source = optc2_get_optc_source,
 		.set_out_mux = optc3_set_out_mux,
 		.set_drr_trigger_window = optc3_set_drr_trigger_window,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
index 17a287bc89ce..7ac6428aae52 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
@@ -77,7 +77,7 @@
 
 #include "dcn/dcn_3_2_0_offset.h"
 #include "dcn/dcn_3_2_0_sh_mask.h"
-#include "dcn/nbio_4_3_0_offset.h"
+#include "nbio/nbio_4_3_0_offset.h"
 
 #include "reg_helper.h"
 #include "dce/dmub_abm.h"
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
index f79dd40f8d81..8d4c74b0fc90 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
@@ -811,9 +811,14 @@ void dcn20_calculate_dlg_params(
 		pipes[pipe_idx].pipe.dest.vupdate_offset = get_vupdate_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
 		pipes[pipe_idx].pipe.dest.vupdate_width = get_vupdate_width(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
 		pipes[pipe_idx].pipe.dest.vready_offset = get_vready_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
-		context->res_ctx.pipe_ctx[i].det_buffer_size_kb = context->bw_ctx.dml.ip.det_buffer_size_kbytes;
-		context->res_ctx.pipe_ctx[i].unbounded_req = pipes[pipe_idx].pipe.src.unbounded_req_mode;
-
+		if (context->res_ctx.pipe_ctx[i].stream->mall_stream_config.type == SUBVP_PHANTOM) {
+			// Phantom pipe requires that DET_SIZE = 0 and no unbounded requests
+			context->res_ctx.pipe_ctx[i].det_buffer_size_kb = 0;
+			context->res_ctx.pipe_ctx[i].unbounded_req = false;
+		} else {
+			context->res_ctx.pipe_ctx[i].det_buffer_size_kb = context->bw_ctx.dml.ip.det_buffer_size_kbytes;
+			context->res_ctx.pipe_ctx[i].unbounded_req = pipes[pipe_idx].pipe.src.unbounded_req_mode;
+		}
 		if (context->bw_ctx.bw.dcn.clk.dppclk_khz < pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
 			context->bw_ctx.bw.dcn.clk.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
 		context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz =
@@ -1013,6 +1018,31 @@ int dcn20_populate_dml_pipes_from_context(
 			pipes[pipe_cnt].pipe.dest.pixel_rate_mhz *= 2;
 		pipes[pipe_cnt].pipe.dest.otg_inst = res_ctx->pipe_ctx[i].stream_res.tg->inst;
 		pipes[pipe_cnt].dout.dp_lanes = 4;
+		if (res_ctx->pipe_ctx[i].stream->link) {
+			switch (res_ctx->pipe_ctx[i].stream->link->cur_link_settings.link_rate) {
+			case LINK_RATE_HIGH:
+				pipes[pipe_cnt].dout.dp_rate = dm_dp_rate_hbr;
+				break;
+			case LINK_RATE_HIGH2:
+				pipes[pipe_cnt].dout.dp_rate = dm_dp_rate_hbr2;
+				break;
+			case LINK_RATE_HIGH3:
+				pipes[pipe_cnt].dout.dp_rate = dm_dp_rate_hbr3;
+				break;
+			case LINK_RATE_UHBR10:
+				pipes[pipe_cnt].dout.dp_rate = dm_dp_rate_uhbr10;
+				break;
+			case LINK_RATE_UHBR13_5:
+				pipes[pipe_cnt].dout.dp_rate = dm_dp_rate_uhbr13p5;
+				break;
+			case LINK_RATE_UHBR20:
+				pipes[pipe_cnt].dout.dp_rate = dm_dp_rate_uhbr20;
+				break;
+			default:
+				pipes[pipe_cnt].dout.dp_rate = dm_dp_rate_na;
+				break;
+			}
+		}
 		pipes[pipe_cnt].dout.is_virtual = 0;
 		pipes[pipe_cnt].pipe.dest.vtotal_min = res_ctx->pipe_ctx[i].stream->adjust.v_total_min;
 		pipes[pipe_cnt].pipe.dest.vtotal_max = res_ctx->pipe_ctx[i].stream->adjust.v_total_max;
@@ -1070,6 +1100,7 @@ int dcn20_populate_dml_pipes_from_context(
 			pipes[pipe_cnt].dout.is_virtual = 1;
 			pipes[pipe_cnt].dout.output_type = dm_dp;
 			pipes[pipe_cnt].dout.dp_lanes = 4;
+			pipes[pipe_cnt].dout.dp_rate = dm_dp_rate_hbr2;
 		}
 
 		switch (res_ctx->pipe_ctx[i].stream->timing.display_color_depth) {
@@ -1138,7 +1169,8 @@ int dcn20_populate_dml_pipes_from_context(
 		 * bw calculations due to cursor on/off
 		 */
 		if (res_ctx->pipe_ctx[i].plane_state &&
-				res_ctx->pipe_ctx[i].plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
+				(res_ctx->pipe_ctx[i].plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE ||
+				 res_ctx->pipe_ctx[i].stream->mall_stream_config.type == SUBVP_PHANTOM))
 			pipes[pipe_cnt].pipe.src.num_cursors = 0;
 		else
 			pipes[pipe_cnt].pipe.src.num_cursors = dc->dml.ip.number_of_cursors;
@@ -1149,6 +1181,7 @@ int dcn20_populate_dml_pipes_from_context(
 		if (!res_ctx->pipe_ctx[i].plane_state) {
 			pipes[pipe_cnt].pipe.src.is_hsplit = pipes[pipe_cnt].pipe.dest.odm_combine != dm_odm_combine_mode_disabled;
 			pipes[pipe_cnt].pipe.src.source_scan = dm_horz;
+			pipes[pipe_cnt].pipe.src.source_rotation = dm_rotation_0;
 			pipes[pipe_cnt].pipe.src.sw_mode = dm_sw_4kb_s;
 			pipes[pipe_cnt].pipe.src.macro_tile_size = dm_64k_tile;
 			pipes[pipe_cnt].pipe.src.viewport_width = timing->h_addressable;
@@ -1201,8 +1234,26 @@ int dcn20_populate_dml_pipes_from_context(
 
 			pipes[pipe_cnt].pipe.src.source_scan = pln->rotation == ROTATION_ANGLE_90
 					|| pln->rotation == ROTATION_ANGLE_270 ? dm_vert : dm_horz;
+			switch (pln->rotation) {
+			case ROTATION_ANGLE_0:
+				pipes[pipe_cnt].pipe.src.source_rotation = dm_rotation_0;
+				break;
+			case ROTATION_ANGLE_90:
+				pipes[pipe_cnt].pipe.src.source_rotation = dm_rotation_90;
+				break;
+			case ROTATION_ANGLE_180:
+				pipes[pipe_cnt].pipe.src.source_rotation = dm_rotation_180;
+				break;
+			case ROTATION_ANGLE_270:
+				pipes[pipe_cnt].pipe.src.source_rotation = dm_rotation_270;
+				break;
+			default:
+				break;
+			}
 			pipes[pipe_cnt].pipe.src.viewport_y_y = scl->viewport.y;
 			pipes[pipe_cnt].pipe.src.viewport_y_c = scl->viewport_c.y;
+			pipes[pipe_cnt].pipe.src.viewport_x_y = scl->viewport.x;
+			pipes[pipe_cnt].pipe.src.viewport_x_c = scl->viewport_c.x;
 			pipes[pipe_cnt].pipe.src.viewport_width = scl->viewport.width;
 			pipes[pipe_cnt].pipe.src.viewport_width_c = scl->viewport_c.width;
 			pipes[pipe_cnt].pipe.src.viewport_height = scl->viewport.height;
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 555d4d9e1454..0317af5bb8ca 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -195,6 +195,16 @@ struct resource_funcs {
 	enum dc_status (*add_dsc_to_stream_resource)(
 			struct dc *dc, struct dc_state *state,
 			struct dc_stream_state *stream);
+
+	void (*add_phantom_pipes)(
+            struct dc *dc,
+            struct dc_state *context,
+            display_e2e_pipe_params_st *pipes,
+			unsigned int pipe_cnt,
+            unsigned int index);
+	void (*remove_phantom_pipes)(
+            struct dc *dc,
+            struct dc_state *context);
 };
 
 struct audio_support{
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
index b2fa4de47734..5cc6d1fb887d 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
@@ -45,9 +45,10 @@ enum physymclk_clock_source {
 	PHYSYMCLK_FORCE_SRC_PHYD32CLK, // Select phyd32clk as the source of clock which is output to PHY through DCIO.
 };
 
-enum hdmistreamclk_source {
+enum streamclk_source {
 	REFCLK,                   // Selects REFCLK as source for hdmistreamclk.
 	DTBCLK0,                  // Selects DTBCLK0 as source for hdmistreamclk.
+	DPREFCLK,                 // Selects DPREFCLK as source for hdmistreamclk
 };
 
 enum dentist_dispclk_change_mode {
@@ -82,7 +83,7 @@ struct dccg_funcs {
 
 	void (*set_dpstreamclk)(
 			struct dccg *dccg,
-			enum hdmistreamclk_source src,
+			enum streamclk_source src,
 			int otg_inst);
 
 	void (*enable_symclk32_se)(
@@ -111,8 +112,8 @@ struct dccg_funcs {
 
 	void (*set_dtbclk_dto)(
 			struct dccg *dccg,
-			int dtbclk_inst,
-			int req_dtbclk_khz,
+			int otg_inst,
+			int pixclk_khz,
 			int num_odm_segments,
 			const struct dc_crtc_timing *timing);
 
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
index 9195dec294c2..e7571c6f5ead 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
@@ -47,6 +47,8 @@ struct dcn_hubbub_wm_set {
 	uint32_t sr_enter;
 	uint32_t sr_exit;
 	uint32_t dram_clk_chanage;
+	uint32_t usr_retrain;
+	uint32_t fclk_pstate_change;
 };
 
 struct dcn_hubbub_wm {
@@ -168,6 +170,7 @@ struct hubbub_funcs {
 	void (*program_det_size)(struct hubbub *hubbub, int hubp_inst, unsigned det_buffer_size_in_kbyte);
 	void (*program_compbuf_size)(struct hubbub *hubbub, unsigned compbuf_size_kb, bool safe_to_increase);
 	void (*init_crb)(struct hubbub *hubbub);
+	void (*force_usr_retraining_allow)(struct hubbub *hubbub, bool allow);
 };
 
 struct hubbub {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
index ad69d78c4ac3..b2cdb6bfc9b8 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
@@ -140,6 +140,9 @@ struct hubp_funcs {
 
 	void (*set_blank)(struct hubp *hubp, bool blank);
 	void (*set_blank_regs)(struct hubp *hubp, bool blank);
+#ifdef CONFIG_DRM_AMD_DC_DCN
+	void (*phantom_hubp_post_enable)(struct hubp *hubp);
+#endif
 	void (*set_hubp_blank_en)(struct hubp *hubp, bool blank);
 
 	void (*set_cursor_attributes)(
@@ -193,6 +196,10 @@ struct hubp_funcs {
 	bool (*hubp_in_blank)(struct hubp *hubp);
 	void (*hubp_soft_reset)(struct hubp *hubp, bool reset);
 
+	void (*hubp_update_force_pstate_disallow)(struct hubp *hubp, bool allow);
+	void (*hubp_update_mall_sel)(struct hubp *hubp, uint32_t mall_sel);
+	void (*hubp_prepare_subvp_buffering)(struct hubp *hubp, bool enable);
+
 	void (*hubp_set_flip_int)(struct hubp *hubp);
 
 	void (*program_extended_blank)(struct hubp *hubp,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h
index 8798cfa11a4d..b72fb314d804 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h
@@ -37,6 +37,7 @@ struct cstate_pstate_watermarks_st {
 	uint32_t cstate_enter_plus_exit_z8_ns;
 	uint32_t cstate_enter_plus_exit_ns;
 	uint32_t pstate_change_ns;
+	uint32_t fclk_pstate_change_ns;
 };
 
 struct dcn_watermarks {
@@ -46,6 +47,7 @@ struct dcn_watermarks {
 	uint32_t frac_urg_bw_flip;
 	int32_t urgent_latency_ns;
 	struct cstate_pstate_watermarks_st cstate_pstate;
+	uint32_t usr_retraining_ns;
 };
 
 struct dcn_watermark_set {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
index 678c2065e5e8..36ec56524afd 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
@@ -164,6 +164,10 @@ struct stream_encoder_funcs {
 	void (*stop_dp_info_packets)(
 		struct stream_encoder *enc);
 
+	void (*reset_fifo)(
+		struct stream_encoder *enc
+	);
+
 	void (*dp_blank)(
 		struct dc_link *link,
 		struct stream_encoder *enc);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
index 554d2e33bd7f..a89b2230cd2c 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
@@ -174,6 +174,9 @@ struct timing_generator_funcs {
 
 	bool (*enable_crtc)(struct timing_generator *tg);
 	bool (*disable_crtc)(struct timing_generator *tg);
+#ifdef CONFIG_DRM_AMD_DC_DCN
+	void (*phantom_crtc_post_enable)(struct timing_generator *tg);
+#endif
 	bool (*immediate_disable_crtc)(struct timing_generator *tg);
 	bool (*is_counter_moving)(struct timing_generator *tg);
 	void (*get_position)(struct timing_generator *tg,
@@ -293,6 +296,7 @@ struct timing_generator_funcs {
 	void (*set_odm_bypass)(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing);
 	void (*set_odm_combine)(struct timing_generator *optc, int *opp_id, int opp_cnt,
 			struct dc_crtc_timing *timing);
+	void (*set_h_timing_div_manual_mode)(struct timing_generator *optc, bool manual_mode);
 	void (*set_gsl)(struct timing_generator *optc, const struct gsl_params *params);
 	void (*set_gsl_source_select)(struct timing_generator *optc,
 			int group_idx,
@@ -310,8 +314,10 @@ struct timing_generator_funcs {
 			uint32_t slave_pixel_clock_100Hz,
 			uint8_t master_clock_divider,
 			uint8_t slave_clock_divider);
-
-	void (*init_odm)(struct timing_generator *tg);
+	bool (*validate_vmin_vmax)(struct timing_generator *optc,
+			int vmin, int vmax);
+	bool (*validate_vtotal_change_limit)(struct timing_generator *optc,
+			uint32_t vtotal_change_limit);
 };
 
 #endif
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
index 05053f3b4ab7..eb616a4ed508 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
@@ -244,6 +244,8 @@ struct hw_sequencer_funcs {
 			struct pipe_ctx *pipe_ctx,
 			struct tg_color *color,
 			int mpcc_id);
+
+	void (*commit_subvp_config)(struct dc *dc, struct dc_state *context);
 };
 
 void color_space_to_black_color(
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
index 8c2f190c4712..5a0648784872 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h
@@ -143,6 +143,11 @@ struct hwseq_private_funcs {
 	void (*PLAT_58856_wa)(struct dc_state *context,
 			struct pipe_ctx *pipe_ctx);
 	void (*setup_hpo_hw_control)(const struct dce_hwseq *hws, bool enable);
+#ifdef CONFIG_DRM_AMD_DC_DCN
+	void (*program_mall_pipe_config)(struct dc *dc, struct dc_state *context);
+	void (*subvp_update_force_pstate)(struct dc *dc, struct dc_state *context);
+	void (*update_mall_sel)(struct dc *dc, struct dc_state *context);
+#endif
 };
 
 struct dce_hwseq {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h
index 2369f38ed06f..58158764adc0 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/resource.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h
@@ -205,6 +205,13 @@ bool get_temp_dp_link_res(struct dc_link *link,
 		struct link_resource *link_res,
 		struct dc_link_settings *link_settings);
 
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+struct hpo_dp_link_encoder *resource_get_hpo_dp_link_enc_for_det_lt(
+		const struct resource_context *res_ctx,
+		const struct resource_pool *pool,
+		const struct dc_link *link);
+#endif
+
 void reset_syncd_pipes_from_disabled_pipes(struct dc *dc,
 	struct dc_state *context);
 
diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h
index cf4027cc3f4c..83058bcbb2e8 100644
--- a/drivers/gpu/drm/amd/display/include/bios_parser_types.h
+++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h
@@ -335,4 +335,14 @@ struct bp_soc_bb_info {
 	uint32_t dram_sr_enter_exit_latency_100ns;
 };
 
+struct bp_connector_speed_cap_info {
+	uint32_t DP_HBR2_EN:1;
+	uint32_t DP_HBR3_EN:1;
+	uint32_t HDMI_6GB_EN:1;
+	uint32_t DP_UHBR10_EN:1;
+	uint32_t DP_UHBR13_5_EN:1;
+	uint32_t DP_UHBR20_EN:1;
+	uint32_t RESERVED:29;
+};
+
 #endif /*__DAL_BIOS_PARSER_TYPES_H__ */
-- 
2.35.3



More information about the amd-gfx mailing list