From f70575805708cabdedea7498aaa3f710fde4d920 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 31 Jan 2024 03:29:01 +0000
Subject: [PATCH] add lvds1024*800

---
 kernel/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c |  808 ++++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 478 insertions(+), 330 deletions(-)

diff --git a/kernel/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/kernel/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
index eab007e..9dd41ea 100644
--- a/kernel/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+++ b/kernel/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
@@ -23,6 +23,8 @@
  *
  */
 
+#include <linux/slab.h>
+
 #include "dm_services.h"
 
 #include "ObjectID.h"
@@ -109,7 +111,7 @@
 
 #define DATA_TABLES(table) (bp->master_data_tbl->listOfdatatables.table)
 
-static void destruct(struct bios_parser *bp)
+static void bios_parser2_destruct(struct bios_parser *bp)
 {
 	kfree(bp->base.bios_local_image);
 	kfree(bp->base.integrated_info);
@@ -124,7 +126,7 @@
 		return;
 	}
 
-	destruct(bp);
+	bios_parser2_destruct(bp);
 
 	kfree(bp);
 	*dcb = NULL;
@@ -166,21 +168,6 @@
 	return count;
 }
 
-static struct graphics_object_id bios_parser_get_encoder_id(
-	struct dc_bios *dcb,
-	uint32_t i)
-{
-	struct bios_parser *bp = BP_FROM_DCB(dcb);
-	struct graphics_object_id object_id = dal_graphics_object_id_init(
-		0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
-
-	if (bp->object_info_tbl.v1_4->number_of_path > i)
-		object_id = object_id_from_bios_object_id(
-		bp->object_info_tbl.v1_4->display_path[i].encoderobjid);
-
-	return object_id;
-}
-
 static struct graphics_object_id bios_parser_get_connector_id(
 	struct dc_bios *dcb,
 	uint8_t i)
@@ -203,26 +190,6 @@
 
 	return object_id;
 }
-
-
-/*  TODO:  GetNumberOfSrc*/
-
-static uint32_t bios_parser_get_dst_number(struct dc_bios *dcb,
-	struct graphics_object_id id)
-{
-	/* connector has 1 Dest, encoder has 0 Dest */
-	switch (id.type) {
-	case OBJECT_TYPE_ENCODER:
-		return 0;
-	case OBJECT_TYPE_CONNECTOR:
-		return 1;
-	default:
-		return 0;
-	}
-}
-
-/*  removed getSrcObjList, getDestObjList*/
-
 
 static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
 	struct graphics_object_id object_id, uint32_t index,
@@ -283,52 +250,10 @@
 	return bp_result;
 }
 
-static enum bp_result bios_parser_get_dst_obj(struct dc_bios *dcb,
-	struct graphics_object_id object_id, uint32_t index,
-	struct graphics_object_id *dest_object_id)
-{
-	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};
-	struct object_info_table *tbl = &bp->object_info_tbl;
-
-	if (!dest_object_id)
-		return BP_RESULT_BADINPUT;
-
-	switch (object_id.type) {
-	case OBJECT_TYPE_ENCODER:
-		/* TODO: since num of src must be less than 2.
-		 * 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) {
-				*dest_object_id =
-					object_id_from_bios_object_id(
-				tbl->v1_4->display_path[i].display_objid);
-				/* break; */
-			}
-		}
-		bp_result = BP_RESULT_OK;
-		break;
-	default:
-		break;
-	}
-
-	return bp_result;
-}
-
-
 /* from graphics_object_id, find display path which includes the object_id */
 static struct atom_display_object_path_v2 *get_bios_object(
-	struct bios_parser *bp,
-	struct graphics_object_id id)
+		struct bios_parser *bp,
+		struct graphics_object_id id)
 {
 	unsigned int i;
 	struct graphics_object_id obj_id = {0};
@@ -337,28 +262,25 @@
 	case OBJECT_TYPE_ENCODER:
 		for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) {
 			obj_id = object_id_from_bios_object_id(
-			bp->object_info_tbl.v1_4->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_4->display_path[i];
+					bp->object_info_tbl.v1_4->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_4->display_path[i];
 		}
+		fallthrough;
 	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_4->number_of_path; i++) {
 			obj_id = object_id_from_bios_object_id(
-			bp->object_info_tbl.v1_4->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_4->display_path[i];
+					bp->object_info_tbl.v1_4->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_4->display_path[i];
 		}
+		fallthrough;
 	default:
 		return NULL;
 	}
@@ -372,10 +294,20 @@
 	struct atom_display_object_path_v2 *object;
 	struct atom_common_record_header *header;
 	struct atom_i2c_record *record;
+	struct atom_i2c_record dummy_record = {0};
 	struct bios_parser *bp = BP_FROM_DCB(dcb);
 
 	if (!info)
 		return BP_RESULT_BADINPUT;
+
+	if (id.type == OBJECT_TYPE_GENERIC) {
+		dummy_record.i2c_id = id.id;
+
+		if (get_gpio_i2c_info(bp, &dummy_record, info) == BP_RESULT_OK)
+			return BP_RESULT_OK;
+		else
+			return BP_RESULT_NORECORD;
+	}
 
 	object = get_bios_object(bp, id);
 
@@ -419,6 +351,8 @@
 	struct atom_gpio_pin_lut_v2_1 *header;
 	uint32_t count = 0;
 	unsigned int table_index = 0;
+	bool find_valid = false;
+	struct atom_gpio_pin_assignment *pin;
 
 	if (!info)
 		return BP_RESULT_BADINPUT;
@@ -446,32 +380,24 @@
 			- sizeof(struct atom_common_table_header))
 				/ sizeof(struct atom_gpio_pin_assignment);
 
-	table_index = record->i2c_id  & I2C_HW_LANE_MUX;
+	pin = (struct atom_gpio_pin_assignment *) header->gpio_pin;
 
-	if (count < table_index) {
-		bool find_valid = false;
-
-		for (table_index = 0; table_index < count; table_index++) {
-			if (((record->i2c_id & I2C_HW_CAP) == (
-			header->gpio_pin[table_index].gpio_id &
-							I2C_HW_CAP)) &&
-			((record->i2c_id & I2C_HW_ENGINE_ID_MASK)  ==
-			(header->gpio_pin[table_index].gpio_id &
-						I2C_HW_ENGINE_ID_MASK)) &&
-			((record->i2c_id & I2C_HW_LANE_MUX) ==
-			(header->gpio_pin[table_index].gpio_id &
-							I2C_HW_LANE_MUX))) {
-				/* still valid */
-				find_valid = true;
-				break;
-			}
+	for (table_index = 0; table_index < count; table_index++) {
+		if (((record->i2c_id & I2C_HW_CAP) 				== (pin->gpio_id & I2C_HW_CAP)) &&
+		    ((record->i2c_id & I2C_HW_ENGINE_ID_MASK)	== (pin->gpio_id & I2C_HW_ENGINE_ID_MASK)) &&
+		    ((record->i2c_id & I2C_HW_LANE_MUX) 		== (pin->gpio_id & I2C_HW_LANE_MUX))) {
+			/* still valid */
+			find_valid = true;
+			break;
 		}
-		/* If we don't find the entry that we are looking for then
-		 *  we will return BP_Result_BadBiosTable.
-		 */
-		if (find_valid == false)
-			return BP_RESULT_BADBIOSTABLE;
+		pin = (struct atom_gpio_pin_assignment *)((uint8_t *)pin + sizeof(struct atom_gpio_pin_assignment));
 	}
+
+	/* If we don't find the entry that we are looking for then
+	 *  we will return BP_Result_BadBiosTable.
+	 */
+	if (find_valid == false)
+		return BP_RESULT_BADBIOSTABLE;
 
 	/* get the GPIO_I2C_INFO */
 	info->i2c_hw_assist = (record->i2c_id & I2C_HW_CAP) ? true : false;
@@ -480,106 +406,10 @@
 	info->i2c_slave_address = record->i2c_slave_addr;
 
 	/* TODO: check how to get register offset for en, Y, etc. */
-	info->gpio_info.clk_a_register_index =
-			le16_to_cpu(
-			header->gpio_pin[table_index].data_a_reg_index);
-	info->gpio_info.clk_a_shift =
-			header->gpio_pin[table_index].gpio_bitshift;
+	info->gpio_info.clk_a_register_index = le16_to_cpu(pin->data_a_reg_index);
+	info->gpio_info.clk_a_shift = pin->gpio_bitshift;
 
 	return BP_RESULT_OK;
-}
-
-static enum bp_result get_voltage_ddc_info_v4(
-	uint8_t *i2c_line,
-	uint32_t index,
-	struct atom_common_table_header *header,
-	uint8_t *address)
-{
-	enum bp_result result = BP_RESULT_NORECORD;
-	struct atom_voltage_objects_info_v4_1 *info =
-		(struct atom_voltage_objects_info_v4_1 *) address;
-
-	uint8_t *voltage_current_object =
-		(uint8_t *) (&(info->voltage_object[0]));
-
-	while ((address + le16_to_cpu(header->structuresize)) >
-						voltage_current_object) {
-		struct atom_i2c_voltage_object_v4 *object =
-			(struct atom_i2c_voltage_object_v4 *)
-						voltage_current_object;
-
-		if (object->header.voltage_mode ==
-			ATOM_INIT_VOLTAGE_REGULATOR) {
-			if (object->header.voltage_type == index) {
-				*i2c_line = object->i2c_id ^ 0x90;
-				result = BP_RESULT_OK;
-				break;
-			}
-		}
-
-		voltage_current_object +=
-				le16_to_cpu(object->header.object_size);
-	}
-	return result;
-}
-
-static enum bp_result bios_parser_get_thermal_ddc_info(
-	struct dc_bios *dcb,
-	uint32_t i2c_channel_id,
-	struct graphics_object_i2c_info *info)
-{
-	struct bios_parser *bp = BP_FROM_DCB(dcb);
-	struct i2c_id_config_access *config;
-	struct atom_i2c_record record;
-
-	if (!info)
-		return BP_RESULT_BADINPUT;
-
-	config = (struct i2c_id_config_access *) &i2c_channel_id;
-
-	record.i2c_id = config->bfHW_Capable;
-	record.i2c_id |= config->bfI2C_LineMux;
-	record.i2c_id |= config->bfHW_EngineID;
-
-	return get_gpio_i2c_info(bp, &record, info);
-}
-
-static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb,
-	uint32_t index,
-	struct graphics_object_i2c_info *info)
-{
-	uint8_t i2c_line = 0;
-	enum bp_result result = BP_RESULT_NORECORD;
-	uint8_t *voltage_info_address;
-	struct atom_common_table_header *header;
-	struct atom_data_revision revision = {0};
-	struct bios_parser *bp = BP_FROM_DCB(dcb);
-
-	if (!DATA_TABLES(voltageobject_info))
-		return result;
-
-	voltage_info_address = bios_get_image(&bp->base,
-			DATA_TABLES(voltageobject_info),
-			sizeof(struct atom_common_table_header));
-
-	header = (struct atom_common_table_header *) voltage_info_address;
-
-	get_atom_data_table_revision(header, &revision);
-
-	switch (revision.major) {
-	case 4:
-		if (revision.minor != 1)
-			break;
-		result = get_voltage_ddc_info_v4(&i2c_line, index, header,
-			voltage_info_address);
-		break;
-	}
-
-	if (result == BP_RESULT_OK)
-		result = bios_parser_get_thermal_ddc_info(dcb,
-			i2c_line, info);
-
-	return result;
 }
 
 static enum bp_result bios_parser_get_hpd_info(
@@ -813,6 +643,7 @@
 {
 	enum bp_result result = BP_RESULT_OK;
 	struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL;
+	struct atom_smu_info_v3_3 *smu_info = NULL;
 
 	if (!ss_info)
 		return BP_RESULT_BADINPUT;
@@ -824,6 +655,7 @@
 							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;
@@ -862,6 +694,19 @@
 		 * copy it into dce_info
 		 */
 		result = BP_RESULT_UNSUPPORTED;
+		break;
+	case AS_SIGNAL_TYPE_XGMI:
+		smu_info =  GET_IMAGE(struct atom_smu_info_v3_3,
+				      DATA_TABLES(smu_info));
+		if (!smu_info)
+			return BP_RESULT_BADBIOSTABLE;
+
+		ss_info->spread_spectrum_percentage =
+				smu_info->waflclk_ss_percentage;
+		ss_info->spread_spectrum_range =
+				smu_info->gpuclk_ss_rate_10hz * 10;
+		if (smu_info->waflclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
+			ss_info->type.CENTER_MODE = true;
 		break;
 	default:
 		result = BP_RESULT_UNSUPPORTED;
@@ -984,6 +829,7 @@
 		case 1:
 			return get_ss_info_v4_1(bp, signal, index, ss_info);
 		case 2:
+		case 3:
 			return get_ss_info_v4_2(bp, signal, index, ss_info);
 		default:
 			break;
@@ -996,9 +842,76 @@
 	return result;
 }
 
-static enum bp_result get_embedded_panel_info_v2_1(
+static enum bp_result get_soc_bb_info_v4_4(
 	struct bios_parser *bp,
-	struct embedded_panel_info *info)
+	struct bp_soc_bb_info *soc_bb_info)
+{
+	enum bp_result result = BP_RESULT_OK;
+	struct atom_display_controller_info_v4_4 *disp_cntl_tbl = NULL;
+
+	if (!soc_bb_info)
+		return BP_RESULT_BADINPUT;
+
+	if (!DATA_TABLES(dce_info))
+		return BP_RESULT_BADBIOSTABLE;
+
+	if (!DATA_TABLES(smu_info))
+		return BP_RESULT_BADBIOSTABLE;
+
+	disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_4,
+							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)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	enum bp_result result = BP_RESULT_UNSUPPORTED;
+	struct atom_common_table_header *header;
+	struct atom_data_revision tbl_revision;
+
+	if (!soc_bb_info) /* check for bad input */
+		return BP_RESULT_BADINPUT;
+
+	if (!DATA_TABLES(dce_info))
+		return BP_RESULT_UNSUPPORTED;
+
+	header = GET_IMAGE(struct atom_common_table_header,
+						DATA_TABLES(dce_info));
+	get_atom_data_table_revision(header, &tbl_revision);
+
+	switch (tbl_revision.major) {
+	case 4:
+		switch (tbl_revision.minor) {
+		case 1:
+		case 2:
+		case 3:
+			break;
+		case 4:
+			result = get_soc_bb_info_v4_4(bp, soc_bb_info);
+		default:
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return result;
+}
+
+static enum bp_result get_embedded_panel_info_v2_1(
+		struct bios_parser *bp,
+		struct embedded_panel_info *info)
 {
 	struct lcd_info_v2_1 *lvds;
 
@@ -1021,91 +934,77 @@
 	memset(info, 0, sizeof(struct embedded_panel_info));
 
 	/* We need to convert from 10KHz units into KHz units */
-	info->lcd_timing.pixel_clk =
-			le16_to_cpu(lvds->lcd_timing.pixclk) * 10;
+	info->lcd_timing.pixel_clk = le16_to_cpu(lvds->lcd_timing.pixclk) * 10;
 	/* usHActive does not include borders, according to VBIOS team */
-	info->lcd_timing.horizontal_addressable =
-			le16_to_cpu(lvds->lcd_timing.h_active);
+	info->lcd_timing.horizontal_addressable = le16_to_cpu(lvds->lcd_timing.h_active);
 	/* usHBlanking_Time includes borders, so we should really be
 	 * subtractingborders duing this translation, but LVDS generally
 	 * doesn't have borders, so we should be okay leaving this as is for
 	 * now.  May need to revisit if we ever have LVDS with borders
 	 */
-	info->lcd_timing.horizontal_blanking_time =
-		le16_to_cpu(lvds->lcd_timing.h_blanking_time);
+	info->lcd_timing.horizontal_blanking_time = le16_to_cpu(lvds->lcd_timing.h_blanking_time);
 	/* usVActive does not include borders, according to VBIOS team*/
-	info->lcd_timing.vertical_addressable =
-		le16_to_cpu(lvds->lcd_timing.v_active);
+	info->lcd_timing.vertical_addressable = le16_to_cpu(lvds->lcd_timing.v_active);
 	/* usVBlanking_Time includes borders, so we should really be
 	 * subtracting borders duing this translation, but LVDS generally
 	 * doesn't have borders, so we should be okay leaving this as is for
 	 * now. May need to revisit if we ever have LVDS with borders
 	 */
-	info->lcd_timing.vertical_blanking_time =
-		le16_to_cpu(lvds->lcd_timing.v_blanking_time);
-	info->lcd_timing.horizontal_sync_offset =
-		le16_to_cpu(lvds->lcd_timing.h_sync_offset);
-	info->lcd_timing.horizontal_sync_width =
-		le16_to_cpu(lvds->lcd_timing.h_sync_width);
-	info->lcd_timing.vertical_sync_offset =
-		le16_to_cpu(lvds->lcd_timing.v_sync_offset);
-	info->lcd_timing.vertical_sync_width =
-		le16_to_cpu(lvds->lcd_timing.v_syncwidth);
+	info->lcd_timing.vertical_blanking_time = le16_to_cpu(lvds->lcd_timing.v_blanking_time);
+	info->lcd_timing.horizontal_sync_offset = le16_to_cpu(lvds->lcd_timing.h_sync_offset);
+	info->lcd_timing.horizontal_sync_width = le16_to_cpu(lvds->lcd_timing.h_sync_width);
+	info->lcd_timing.vertical_sync_offset = le16_to_cpu(lvds->lcd_timing.v_sync_offset);
+	info->lcd_timing.vertical_sync_width = le16_to_cpu(lvds->lcd_timing.v_syncwidth);
 	info->lcd_timing.horizontal_border = lvds->lcd_timing.h_border;
 	info->lcd_timing.vertical_border = lvds->lcd_timing.v_border;
 
 	/* not provided by VBIOS */
 	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 0;
 
-	info->lcd_timing.misc_info.H_SYNC_POLARITY =
-		~(uint32_t)
-		(lvds->lcd_timing.miscinfo & ATOM_HSYNC_POLARITY);
-	info->lcd_timing.misc_info.V_SYNC_POLARITY =
-		~(uint32_t)
-		(lvds->lcd_timing.miscinfo & ATOM_VSYNC_POLARITY);
+	info->lcd_timing.misc_info.H_SYNC_POLARITY = ~(uint32_t) (lvds->lcd_timing.miscinfo
+			& ATOM_HSYNC_POLARITY);
+	info->lcd_timing.misc_info.V_SYNC_POLARITY = ~(uint32_t) (lvds->lcd_timing.miscinfo
+			& ATOM_VSYNC_POLARITY);
 
 	/* not provided by VBIOS */
 	info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0;
 
-	info->lcd_timing.misc_info.H_REPLICATION_BY2 =
-		!!(lvds->lcd_timing.miscinfo & ATOM_H_REPLICATIONBY2);
-	info->lcd_timing.misc_info.V_REPLICATION_BY2 =
-		!!(lvds->lcd_timing.miscinfo & ATOM_V_REPLICATIONBY2);
-	info->lcd_timing.misc_info.COMPOSITE_SYNC =
-		!!(lvds->lcd_timing.miscinfo & ATOM_COMPOSITESYNC);
-	info->lcd_timing.misc_info.INTERLACE =
-		!!(lvds->lcd_timing.miscinfo & ATOM_INTERLACE);
+	info->lcd_timing.misc_info.H_REPLICATION_BY2 = !!(lvds->lcd_timing.miscinfo
+			& ATOM_H_REPLICATIONBY2);
+	info->lcd_timing.misc_info.V_REPLICATION_BY2 = !!(lvds->lcd_timing.miscinfo
+			& ATOM_V_REPLICATIONBY2);
+	info->lcd_timing.misc_info.COMPOSITE_SYNC = !!(lvds->lcd_timing.miscinfo
+			& ATOM_COMPOSITESYNC);
+	info->lcd_timing.misc_info.INTERLACE = !!(lvds->lcd_timing.miscinfo & ATOM_INTERLACE);
 
 	/* not provided by VBIOS*/
 	info->lcd_timing.misc_info.DOUBLE_CLOCK = 0;
 	/* not provided by VBIOS*/
 	info->ss_id = 0;
 
-	info->realtek_eDPToLVDS =
-			!!(lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID);
+	info->realtek_eDPToLVDS = !!(lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID);
 
 	return BP_RESULT_OK;
 }
 
 static enum bp_result bios_parser_get_embedded_panel_info(
-	struct dc_bios *dcb,
-	struct embedded_panel_info *info)
+		struct dc_bios *dcb,
+		struct embedded_panel_info *info)
 {
-	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	struct bios_parser
+	*bp = BP_FROM_DCB(dcb);
 	struct atom_common_table_header *header;
 	struct atom_data_revision tbl_revision;
 
 	if (!DATA_TABLES(lcd_info))
 		return BP_RESULT_FAILURE;
 
-	header = GET_IMAGE(struct atom_common_table_header,
-					DATA_TABLES(lcd_info));
+	header = GET_IMAGE(struct atom_common_table_header, DATA_TABLES(lcd_info));
 
 	if (!header)
 		return BP_RESULT_BADBIOSTABLE;
 
 	get_atom_data_table_revision(header, &tbl_revision);
-
 
 	switch (tbl_revision.major) {
 	case 2:
@@ -1156,7 +1055,7 @@
 		break;
 	default:
 		break;
-	};
+	}
 
 	/* Unidentified device ID, return empty support mask. */
 	return 0;
@@ -1172,12 +1071,6 @@
 
 	return (le16_to_cpu(bp->object_info_tbl.v1_4->supporteddevices) &
 								mask) != 0;
-}
-
-static void bios_parser_post_init(
-	struct dc_bios *dcb)
-{
-	/* TODO for OPM module. Need implement later */
 }
 
 static uint32_t bios_parser_get_ss_entry_number(
@@ -1238,17 +1131,6 @@
 	return bp->cmd_tbl.set_dce_clock(bp, bp_params);
 }
 
-static unsigned int bios_parser_get_smu_clock_info(
-	struct dc_bios *dcb)
-{
-	struct bios_parser *bp = BP_FROM_DCB(dcb);
-
-	if (!bp->cmd_tbl.get_smu_clock_info)
-		return BP_RESULT_FAILURE;
-
-	return bp->cmd_tbl.get_smu_clock_info(bp, 0);
-}
-
 static enum bp_result bios_parser_program_crtc_timing(
 	struct dc_bios *dcb,
 	struct bp_hw_crtc_timing_parameters *bp_params)
@@ -1274,18 +1156,6 @@
 	return bp->cmd_tbl.enable_crtc(bp, id, enable);
 }
 
-static enum bp_result bios_parser_crtc_source_select(
-	struct dc_bios *dcb,
-	struct bp_crtc_source_select *bp_params)
-{
-	struct bios_parser *bp = BP_FROM_DCB(dcb);
-
-	if (!bp->cmd_tbl.select_crtc_source)
-		return BP_RESULT_FAILURE;
-
-	return bp->cmd_tbl.select_crtc_source(bp, bp_params);
-}
-
 static enum bp_result bios_parser_enable_disp_power_gating(
 	struct dc_bios *dcb,
 	enum controller_id controller_id,
@@ -1300,18 +1170,23 @@
 		action);
 }
 
+static enum bp_result bios_parser_enable_lvtma_control(
+	struct dc_bios *dcb,
+	uint8_t uc_pwr_on)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+	if (!bp->cmd_tbl.enable_lvtma_control)
+		return BP_RESULT_FAILURE;
+
+	return bp->cmd_tbl.enable_lvtma_control(bp, uc_pwr_on);
+}
+
 static bool bios_parser_is_accelerated_mode(
 	struct dc_bios *dcb)
 {
 	return bios_is_accelerated_mode(dcb);
 }
-
-static uint32_t bios_parser_get_vga_enabled_displays(
-	struct dc_bios *bios)
-{
-	return bios_get_vga_enabled_displays(bios);
-}
-
 
 /**
  * bios_parser_set_scratch_critical_state
@@ -1353,6 +1228,9 @@
 				result = get_firmware_info_v3_2(bp, info);
 				break;
 			case 3:
+#ifdef CONFIG_DRM_AMD_DC_DCN3_0
+			case 4:
+#endif
 				result = get_firmware_info_v3_2(bp, info);
 				break;
 			default:
@@ -1410,6 +1288,8 @@
 		info->smu_gpu_pll_output_freq =
 				bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;
 	}
+
+	info->oem_i2c_present = false;
 
 	return BP_RESULT_OK;
 }
@@ -1489,6 +1369,13 @@
 					bp->cmd_tbl.get_smu_clock_info(bp, SMU11_SYSPLL3_0_ID) * 10;
 	}
 
+	if (firmware_info->board_i2c_feature_id == 0x2) {
+		info->oem_i2c_present = true;
+		info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;
+	} else {
+		info->oem_i2c_present = false;
+	}
+
 	return BP_RESULT_OK;
 }
 
@@ -1521,6 +1408,8 @@
 			ATOM_ENCODER_CAP_RECORD_HBR3_EN) ? 1 : 0;
 	info->HDMI_6GB_EN = (record->encodercaps &
 			ATOM_ENCODER_CAP_RECORD_HDMI6Gbps_EN) ? 1 : 0;
+	info->DP_IS_USB_C = (record->encodercaps &
+			ATOM_ENCODER_CAP_RECORD_USB_C_TYPE) ? 1 : 0;
 
 	return BP_RESULT_OK;
 }
@@ -1561,6 +1450,63 @@
 	}
 
 	return NULL;
+}
+
+static enum bp_result get_vram_info_v23(
+	struct bios_parser *bp,
+	struct dc_vram_info *info)
+{
+	struct atom_vram_info_header_v2_3 *info_v23;
+	enum bp_result result = BP_RESULT_OK;
+
+	info_v23 = GET_IMAGE(struct atom_vram_info_header_v2_3,
+						DATA_TABLES(vram_info));
+
+	if (info_v23 == NULL)
+		return BP_RESULT_BADBIOSTABLE;
+
+	info->num_chans = info_v23->vram_module[0].channel_num;
+	info->dram_channel_width_bytes = (1 << info_v23->vram_module[0].channel_width) / 8;
+
+	return result;
+}
+
+static enum bp_result get_vram_info_v24(
+	struct bios_parser *bp,
+	struct dc_vram_info *info)
+{
+	struct atom_vram_info_header_v2_4 *info_v24;
+	enum bp_result result = BP_RESULT_OK;
+
+	info_v24 = GET_IMAGE(struct atom_vram_info_header_v2_4,
+						DATA_TABLES(vram_info));
+
+	if (info_v24 == NULL)
+		return BP_RESULT_BADBIOSTABLE;
+
+	info->num_chans = info_v24->vram_module[0].channel_num;
+	info->dram_channel_width_bytes = (1 << info_v24->vram_module[0].channel_width) / 8;
+
+	return result;
+}
+
+static enum bp_result get_vram_info_v25(
+	struct bios_parser *bp,
+	struct dc_vram_info *info)
+{
+	struct atom_vram_info_header_v2_5 *info_v25;
+	enum bp_result result = BP_RESULT_OK;
+
+	info_v25 = GET_IMAGE(struct atom_vram_info_header_v2_5,
+						DATA_TABLES(vram_info));
+
+	if (info_v25 == NULL)
+		return BP_RESULT_BADBIOSTABLE;
+
+	info->num_chans = info_v25->vram_module[0].channel_num;
+	info->dram_channel_width_bytes = (1 << info_v25->vram_module[0].channel_width) / 8;
+
+	return result;
 }
 
 /*
@@ -1606,6 +1552,8 @@
 	info->ma_channel_number = info_v11->umachannelnumber;
 	info->lvds_ss_percentage =
 	le16_to_cpu(info_v11->lvds_ss_percentage);
+	info->dp_ss_control =
+	le16_to_cpu(info_v11->reserved1);
 	info->lvds_sspread_rate_in_10hz =
 	le16_to_cpu(info_v11->lvds_ss_rate_10hz);
 	info->hdmi_ss_percentage =
@@ -1813,8 +1761,6 @@
 
 	struct atom_common_table_header *header;
 	struct atom_data_revision revision;
-
-	struct clock_voltage_caps temp = {0, 0};
 	uint32_t i;
 	uint32_t j;
 
@@ -1827,6 +1773,7 @@
 		/* Don't need to check major revision as they are all 1 */
 		switch (revision.minor) {
 		case 11:
+		case 12:
 			result = get_integrated_info_v11(bp, info);
 			break;
 		default:
@@ -1844,14 +1791,52 @@
 				info->disp_clk_voltage[j-1].max_supported_clk
 				) {
 				/* swap j and j - 1*/
-				temp = info->disp_clk_voltage[j-1];
-				info->disp_clk_voltage[j-1] =
-					info->disp_clk_voltage[j];
-				info->disp_clk_voltage[j] = temp;
+				swap(info->disp_clk_voltage[j - 1],
+				     info->disp_clk_voltage[j]);
 			}
 		}
 	}
 
+	return result;
+}
+
+static enum bp_result bios_parser_get_vram_info(
+		struct dc_bios *dcb,
+		struct dc_vram_info *info)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	enum bp_result result = BP_RESULT_BADBIOSTABLE;
+	struct atom_common_table_header *header;
+	struct atom_data_revision revision;
+
+	if (info && DATA_TABLES(vram_info)) {
+		header = GET_IMAGE(struct atom_common_table_header,
+					DATA_TABLES(vram_info));
+
+		get_atom_data_table_revision(header, &revision);
+
+		switch (revision.major) {
+		case 2:
+			switch (revision.minor) {
+			case 3:
+				result = get_vram_info_v23(bp, info);
+				break;
+			case 4:
+				result = get_vram_info_v24(bp, info);
+				break;
+			case 5:
+				result = get_vram_info_v25(bp, info);
+				break;
+			default:
+				break;
+			}
+			break;
+
+		default:
+			return result;
+		}
+
+	}
 	return result;
 }
 
@@ -2029,7 +2014,6 @@
 	struct board_layout_info *board_layout_info)
 {
 	unsigned int i;
-	struct bios_parser *bp;
 	enum bp_result record_result;
 
 	const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {
@@ -2038,7 +2022,6 @@
 		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;
@@ -2068,30 +2051,199 @@
 	return BP_RESULT_OK;
 }
 
+
+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;
+}
+
+static struct atom_dc_golden_table_v1 *bios_get_golden_table(
+		struct bios_parser *bp,
+		uint32_t rev_major,
+		uint32_t rev_minor,
+		uint16_t *dc_golden_table_ver)
+{
+	struct atom_display_controller_info_v4_4 *disp_cntl_tbl_4_4 = NULL;
+	uint32_t dc_golden_offset = 0;
+	*dc_golden_table_ver = 0;
+
+	if (!DATA_TABLES(dce_info))
+		return NULL;
+
+	/* ver.4.4 or higher */
+	switch (rev_major) {
+	case 4:
+		switch (rev_minor) {
+		case 4:
+			disp_cntl_tbl_4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,
+									DATA_TABLES(dce_info));
+			if (!disp_cntl_tbl_4_4)
+				return NULL;
+			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;
+		}
+		break;
+	}
+
+	if (!dc_golden_offset)
+		return NULL;
+
+	if (*dc_golden_table_ver != 1)
+		return NULL;
+
+	return GET_IMAGE(struct atom_dc_golden_table_v1,
+			dc_golden_offset);
+}
+
+static enum bp_result bios_get_atom_dc_golden_table(
+	struct dc_bios *dcb)
+{
+	struct bios_parser *bp = BP_FROM_DCB(dcb);
+	enum bp_result result = BP_RESULT_OK;
+	struct atom_dc_golden_table_v1 *atom_dc_golden_table = NULL;
+	struct atom_common_table_header *header;
+	struct atom_data_revision tbl_revision;
+	uint16_t dc_golden_table_ver = 0;
+
+	header = GET_IMAGE(struct atom_common_table_header,
+							DATA_TABLES(dce_info));
+	if (!header)
+		return BP_RESULT_UNSUPPORTED;
+
+	get_atom_data_table_revision(header, &tbl_revision);
+
+	atom_dc_golden_table = bios_get_golden_table(bp,
+			tbl_revision.major,
+			tbl_revision.minor,
+			&dc_golden_table_ver);
+
+	if (!atom_dc_golden_table)
+		return BP_RESULT_UNSUPPORTED;
+
+	dcb->golden_table.dc_golden_table_ver = dc_golden_table_ver;
+	dcb->golden_table.aux_dphy_rx_control0_val = atom_dc_golden_table->aux_dphy_rx_control0_val;
+	dcb->golden_table.aux_dphy_rx_control1_val = atom_dc_golden_table->aux_dphy_rx_control1_val;
+	dcb->golden_table.aux_dphy_tx_control_val = atom_dc_golden_table->aux_dphy_tx_control_val;
+	dcb->golden_table.dc_gpio_aux_ctrl_0_val = atom_dc_golden_table->dc_gpio_aux_ctrl_0_val;
+	dcb->golden_table.dc_gpio_aux_ctrl_1_val = atom_dc_golden_table->dc_gpio_aux_ctrl_1_val;
+	dcb->golden_table.dc_gpio_aux_ctrl_2_val = atom_dc_golden_table->dc_gpio_aux_ctrl_2_val;
+	dcb->golden_table.dc_gpio_aux_ctrl_3_val = atom_dc_golden_table->dc_gpio_aux_ctrl_3_val;
+	dcb->golden_table.dc_gpio_aux_ctrl_4_val = atom_dc_golden_table->dc_gpio_aux_ctrl_4_val;
+	dcb->golden_table.dc_gpio_aux_ctrl_5_val = atom_dc_golden_table->dc_gpio_aux_ctrl_5_val;
+
+	return result;
+}
+
+
 static const struct dc_vbios_funcs vbios_funcs = {
 	.get_connectors_number = bios_parser_get_connectors_number,
 
-	.get_encoder_id = bios_parser_get_encoder_id,
-
 	.get_connector_id = bios_parser_get_connector_id,
-
-	.get_dst_number = bios_parser_get_dst_number,
 
 	.get_src_obj = bios_parser_get_src_obj,
 
-	.get_dst_obj = bios_parser_get_dst_obj,
-
 	.get_i2c_info = bios_parser_get_i2c_info,
-
-	.get_voltage_ddc_info = bios_parser_get_voltage_ddc_info,
-
-	.get_thermal_ddc_info = bios_parser_get_thermal_ddc_info,
 
 	.get_hpd_info = bios_parser_get_hpd_info,
 
 	.get_device_tag = bios_parser_get_device_tag,
-
-	.get_firmware_info = bios_parser_get_firmware_info,
 
 	.get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
 
@@ -2105,10 +2257,7 @@
 
 	.is_device_id_supported = bios_parser_is_device_id_supported,
 
-
-
 	.is_accelerated_mode = bios_parser_is_accelerated_mode,
-	.get_vga_enabled_displays = bios_parser_get_vga_enabled_displays,
 
 	.set_scratch_critical_state = bios_parser_set_scratch_critical_state,
 
@@ -2126,24 +2275,21 @@
 
 	.program_crtc_timing = bios_parser_program_crtc_timing,
 
-	/* .blank_crtc = bios_parser_blank_crtc, */
-
-	.crtc_source_select = bios_parser_crtc_source_select,
-
-	/* .external_encoder_control = bios_parser_external_encoder_control, */
-
 	.enable_disp_power_gating = bios_parser_enable_disp_power_gating,
-
-	.post_init = bios_parser_post_init,
 
 	.bios_parser_destroy = firmware_parser_destroy,
 
-	.get_smu_clock_info = bios_parser_get_smu_clock_info,
-
 	.get_board_layout_info = bios_get_board_layout_info,
+	.pack_data_tables = bios_parser_pack_data_tables,
+
+	.get_atom_dc_golden_table = bios_get_atom_dc_golden_table,
+
+	.enable_lvtma_control = bios_parser_enable_lvtma_control,
+
+	.get_soc_bb_info = bios_parser_get_soc_bb_info,
 };
 
-static bool bios_parser_construct(
+static bool bios_parser2_construct(
 	struct bios_parser *bp,
 	struct bp_init_data *init,
 	enum dce_version dce_version)
@@ -2221,6 +2367,8 @@
 	dal_bios_parser_init_cmd_tbl_helper2(&bp->cmd_helper, dce_version);
 
 	bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);
+	bp->base.fw_info_valid = bios_parser_get_firmware_info(&bp->base, &bp->base.fw_info) == BP_RESULT_OK;
+	bios_parser_get_vram_info(&bp->base, &bp->base.vram_info);
 
 	return true;
 }
@@ -2235,7 +2383,7 @@
 	if (!bp)
 		return NULL;
 
-	if (bios_parser_construct(bp, init, dce_version))
+	if (bios_parser2_construct(bp, init, dce_version))
 		return &bp->base;
 
 	kfree(bp);

--
Gitblit v1.6.2