aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c')
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c1147
1 files changed, 1081 insertions, 66 deletions
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 6aa2e56dfb67..23a3b640f0ee 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
@@ -99,6 +99,10 @@ static enum bp_result get_firmware_info_v3_2(
struct bios_parser *bp,
struct dc_firmware_info *info);
+static enum bp_result get_firmware_info_v3_4(
+ struct bios_parser *bp,
+ struct dc_firmware_info *info);
+
static struct atom_hpd_int_record *get_hpd_record(struct bios_parser *bp,
struct atom_display_object_path_v2 *object);
@@ -111,7 +115,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record(
#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);
@@ -126,7 +130,7 @@ static void firmware_parser_destroy(struct dc_bios **dcb)
return;
}
- destruct(bp);
+ bios_parser2_destruct(bp);
kfree(bp);
*dcb = NULL;
@@ -267,7 +271,7 @@ static struct atom_display_object_path_v2 *get_bios_object(
&& id.enum_id == obj_id.enum_id)
return &bp->object_info_tbl.v1_4->display_path[i];
}
- /* fall through */
+ fallthrough;
case OBJECT_TYPE_CONNECTOR:
case OBJECT_TYPE_GENERIC:
/* Both Generic and Connector Object ID
@@ -280,7 +284,7 @@ static struct atom_display_object_path_v2 *get_bios_object(
&& id.enum_id == obj_id.enum_id)
return &bp->object_info_tbl.v1_4->display_path[i];
}
- /* fall through */
+ fallthrough;
default:
return NULL;
}
@@ -294,11 +298,21 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
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);
if (!object)
@@ -341,6 +355,7 @@ static enum bp_result get_gpio_i2c_info(
struct atom_gpio_pin_lut_v2_1 *header;
uint32_t count = 0;
unsigned int table_index = 0;
+ bool find_valid = false;
if (!info)
return BP_RESULT_BADINPUT;
@@ -368,33 +383,28 @@ static enum bp_result get_gpio_i2c_info(
- sizeof(struct atom_common_table_header))
/ sizeof(struct atom_gpio_pin_assignment);
- table_index = record->i2c_id & I2C_HW_LANE_MUX;
-
- 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) == (
+ 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;
}
- /* 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;
}
+ /* 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;
info->i2c_line = record->i2c_id & I2C_HW_LANE_MUX;
@@ -479,10 +489,11 @@ static struct atom_hpd_int_record *get_hpd_record(
* bios_parser_get_gpio_pin_info
* Get GpioPin information of input gpio id
*
- * @param gpio_id, GPIO ID
- * @param info, GpioPin information structure
- * @return Bios parser result code
- * @note
+ * @dcb: pointer to the DC BIOS
+ * @gpio_id: GPIO ID
+ * @info: GpioPin information structure
+ * return: Bios parser result code
+ * note:
* to get the GPIO PIN INFO, we need:
* 1. get the GPIO_ID from other object table, see GetHPDInfo()
* 2. in DATA_TABLE.GPIO_Pin_LUT, search all records,
@@ -570,6 +581,11 @@ static struct device_id device_type_from_device_id(uint16_t device_id)
result_device_id.enum_id = 1;
break;
+ case ATOM_DISPLAY_LCD2_SUPPORT:
+ result_device_id.device_type = DEVICE_TYPE_LCD;
+ result_device_id.enum_id = 2;
+ break;
+
case ATOM_DISPLAY_DFP1_SUPPORT:
result_device_id.device_type = DEVICE_TYPE_DFP;
result_device_id.enum_id = 1;
@@ -795,11 +811,11 @@ static enum bp_result get_ss_info_v4_2(
* ver 3.1,
* there is only one entry for each signal /ss id. However, there is
* no planning of supporting multiple spread Sprectum entry for EverGreen
- * @param [in] this
- * @param [in] signal, ASSignalType to be converted to info index
- * @param [in] index, number of entries that match the converted info index
- * @param [out] ss_info, sprectrum information structure,
- * @return Bios parser result code
+ * @dcb: pointer to the DC BIOS
+ * @signal: ASSignalType to be converted to info index
+ * @index: number of entries that match the converted info index
+ * @ss_info: sprectrum information structure,
+ * return: Bios parser result code
*/
static enum bp_result bios_parser_get_spread_spectrum_info(
struct dc_bios *dcb,
@@ -828,8 +844,11 @@ static enum bp_result bios_parser_get_spread_spectrum_info(
case 1:
return get_ss_info_v4_1(bp, signal, index, ss_info);
case 2:
+ case 3:
+ case 4:
return get_ss_info_v4_2(bp, signal, index, ss_info);
default:
+ ASSERT(0);
break;
}
break;
@@ -840,6 +859,260 @@ static enum bp_result bios_parser_get_spread_spectrum_info(
return result;
}
+static enum bp_result get_soc_bb_info_v4_4(
+ 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_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);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+static enum bp_result get_disp_caps_v4_1(
+ struct bios_parser *bp,
+ uint8_t *dce_caps)
+{
+ enum bp_result result = BP_RESULT_OK;
+ struct atom_display_controller_info_v4_1 *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_1,
+ 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 get_disp_caps_v4_2(
+ struct bios_parser *bp,
+ uint8_t *dce_caps)
+{
+ enum bp_result result = BP_RESULT_OK;
+ struct atom_display_controller_info_v4_2 *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_2,
+ 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 get_disp_caps_v4_3(
+ struct bios_parser *bp,
+ uint8_t *dce_caps)
+{
+ enum bp_result result = BP_RESULT_OK;
+ struct atom_display_controller_info_v4_3 *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_3,
+ 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 get_disp_caps_v4_4(
+ struct bios_parser *bp,
+ uint8_t *dce_caps)
+{
+ enum bp_result result = BP_RESULT_OK;
+ struct atom_display_controller_info_v4_4 *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_4,
+ 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)
+{
+ 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 (!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:
+ result = get_disp_caps_v4_1(bp, dce_caps);
+ *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
+ break;
+ case 2:
+ result = get_disp_caps_v4_2(bp, dce_caps);
+ *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
+ break;
+ case 3:
+ result = get_disp_caps_v4_3(bp, dce_caps);
+ *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
+ break;
+ case 4:
+ result = get_disp_caps_v4_4(bp, dce_caps);
+ *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+static enum bp_result bios_parser_get_lttpr_caps(
+ struct dc_bios *dcb,
+ uint8_t *dce_caps)
+{
+ 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 (!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:
+ result = get_disp_caps_v4_1(bp, dce_caps);
+ *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
+ break;
+ case 2:
+ result = get_disp_caps_v4_2(bp, dce_caps);
+ *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
+ break;
+ case 3:
+ result = get_disp_caps_v4_3(bp, dce_caps);
+ *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
+ break;
+ case 4:
+ result = get_disp_caps_v4_4(bp, dce_caps);
+ *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
+ break;
+ 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)
@@ -945,6 +1218,7 @@ static enum bp_result bios_parser_get_embedded_panel_info(
default:
break;
}
+ break;
default:
break;
}
@@ -986,7 +1260,7 @@ static uint32_t get_support_mask_for_device_id(struct device_id device_id)
break;
default:
break;
- };
+ }
/* Unidentified device ID, return empty support mask. */
return 0;
@@ -1101,6 +1375,19 @@ static enum bp_result bios_parser_enable_disp_power_gating(
action);
}
+static enum bp_result bios_parser_enable_lvtma_control(
+ struct dc_bios *dcb,
+ uint8_t uc_pwr_on,
+ uint8_t panel_instance)
+{
+ 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, panel_instance);
+}
+
static bool bios_parser_is_accelerated_mode(
struct dc_bios *dcb)
{
@@ -1108,13 +1395,11 @@ static bool bios_parser_is_accelerated_mode(
}
/**
- * bios_parser_set_scratch_critical_state
- *
- * @brief
- * update critical state bit in VBIOS scratch register
+ * bios_parser_set_scratch_critical_state - update critical state bit
+ * in VBIOS scratch register
*
- * @param
- * bool - to set or reset state
+ * @dcb: pointer to the DC BIO
+ * @state: set or reset state
*/
static void bios_parser_set_scratch_critical_state(
struct dc_bios *dcb,
@@ -1144,10 +1429,11 @@ static enum bp_result bios_parser_get_firmware_info(
result = get_firmware_info_v3_1(bp, info);
break;
case 2:
- result = get_firmware_info_v3_2(bp, info);
- break;
case 3:
result = get_firmware_info_v3_2(bp, info);
+ break;
+ case 4:
+ result = get_firmware_info_v3_4(bp, info);
break;
default:
break;
@@ -1205,6 +1491,8 @@ static enum bp_result get_firmware_info_v3_1(
bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;
}
+ info->oem_i2c_present = false;
+
return BP_RESULT_OK;
}
@@ -1283,6 +1571,95 @@ static enum bp_result get_firmware_info_v3_2(
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;
+}
+
+static enum bp_result get_firmware_info_v3_4(
+ struct bios_parser *bp,
+ struct dc_firmware_info *info)
+{
+ struct atom_firmware_info_v3_4 *firmware_info;
+ struct atom_common_table_header *header;
+ 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;
+ if (!info)
+ return BP_RESULT_BADINPUT;
+
+ firmware_info = GET_IMAGE(struct atom_firmware_info_v3_4,
+ DATA_TABLES(firmwareinfo));
+
+ if (!firmware_info)
+ return BP_RESULT_BADBIOSTABLE;
+
+ memset(info, 0, sizeof(*info));
+
+ header = GET_IMAGE(struct atom_common_table_header,
+ DATA_TABLES(dce_info));
+
+ get_atom_data_table_revision(header, &revision);
+
+ switch (revision.major) {
+ case 4:
+ switch (revision.minor) {
+ case 4:
+ dce_info_v4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,
+ DATA_TABLES(dce_info));
+
+ if (!dce_info_v4_4)
+ return BP_RESULT_BADBIOSTABLE;
+
+ /* 100MHz expected */
+ info->pll_info.crystal_frequency = dce_info_v4_4->dce_refclk_10khz * 10;
+ info->dp_phy_ref_clk = dce_info_v4_4->dpphy_refclk_10khz * 10;
+ /* 50MHz expected */
+ info->i2c_engine_ref_clk = dce_info_v4_4->i2c_engine_refclk_10khz * 10;
+
+ /* Get SMU Display PLL VCO Frequency in KHz*/
+ info->smu_gpu_pll_output_freq = dce_info_v4_4->dispclk_pll_vco_freq * 10;
+ break;
+
+ default:
+ /* should not come here, keep as backup, as was before */
+ dce_info_v4_1 = GET_IMAGE(struct atom_display_controller_info_v4_1,
+ DATA_TABLES(dce_info));
+
+ if (!dce_info_v4_1)
+ return BP_RESULT_BADBIOSTABLE;
+
+ info->pll_info.crystal_frequency = dce_info_v4_1->dce_refclk_10khz * 10;
+ info->dp_phy_ref_clk = dce_info_v4_1->dpphy_refclk_10khz * 10;
+ info->i2c_engine_ref_clk = dce_info_v4_1->i2c_engine_refclk_10khz * 10;
+ break;
+ }
+ break;
+
+ default:
+ ASSERT(0);
+ break;
+ }
+
+ header = GET_IMAGE(struct atom_common_table_header,
+ DATA_TABLES(smu_info));
+ get_atom_data_table_revision(header, &revision);
+
+ // We need to convert from 10KHz units into KHz units.
+ info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 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;
}
@@ -1315,6 +1692,14 @@ static enum bp_result bios_parser_get_encoder_cap_info(
ATOM_ENCODER_CAP_RECORD_HBR3_EN) ? 1 : 0;
info->HDMI_6GB_EN = (record->encodercaps &
ATOM_ENCODER_CAP_RECORD_HDMI6Gbps_EN) ? 1 : 0;
+ info->IS_DP2_CAPABLE = (record->encodercaps &
+ ATOM_ENCODER_CAP_RECORD_DP2) ? 1 : 0;
+ info->DP_UHBR10_EN = (record->encodercaps &
+ ATOM_ENCODER_CAP_RECORD_UHBR10_EN) ? 1 : 0;
+ info->DP_UHBR13_5_EN = (record->encodercaps &
+ ATOM_ENCODER_CAP_RECORD_UHBR13_5_EN) ? 1 : 0;
+ info->DP_UHBR20_EN = (record->encodercaps &
+ ATOM_ENCODER_CAP_RECORD_UHBR20_EN) ? 1 : 0;
info->DP_IS_USB_C = (record->encodercaps &
ATOM_ENCODER_CAP_RECORD_USB_C_TYPE) ? 1 : 0;
@@ -1359,6 +1744,129 @@ static struct atom_encoder_caps_record *get_encoder_cap_record(
return NULL;
}
+static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
+ struct bios_parser *bp,
+ struct atom_display_object_path_v2 *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 == LAST_RECORD_TYPE ||
+ !header->record_size)
+ break;
+
+ if (header->record_type != ATOM_DISP_CONNECTOR_CAPS_RECORD_TYPE)
+ continue;
+
+ if (sizeof(struct atom_disp_connector_caps_record) <=
+ header->record_size)
+ return (struct atom_disp_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,
+ struct bp_disp_connector_caps_info *info)
+{
+ struct bios_parser *bp = BP_FROM_DCB(dcb);
+ struct atom_display_object_path_v2 *object;
+ struct atom_disp_connector_caps_record *record = NULL;
+
+ if (!info)
+ return BP_RESULT_BADINPUT;
+
+ object = get_bios_object(bp, object_id);
+
+ 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;
+
+ return BP_RESULT_OK;
+}
+
+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;
+}
+
/*
* get_integrated_info_v11
*
@@ -1402,10 +1910,8 @@ static enum bp_result get_integrated_info_v11(
info->ma_channel_number = info_v11->umachannelnumber;
info->lvds_ss_percentage =
le16_to_cpu(info_v11->lvds_ss_percentage);
-#ifdef CONFIG_DRM_AMD_DC_DCN2_0
info->dp_ss_control =
le16_to_cpu(info_v11->reserved1);
-#endif
info->lvds_sspread_rate_in_10hz =
le16_to_cpu(info_v11->lvds_ss_rate_10hz);
info->hdmi_ss_percentage =
@@ -1590,6 +2096,267 @@ static enum bp_result get_integrated_info_v11(
return BP_RESULT_OK;
}
+static enum bp_result get_integrated_info_v2_1(
+ struct bios_parser *bp,
+ struct integrated_info *info)
+{
+ struct atom_integrated_system_info_v2_1 *info_v2_1;
+ uint32_t i;
+
+ info_v2_1 = GET_IMAGE(struct atom_integrated_system_info_v2_1,
+ DATA_TABLES(integratedsysteminfo));
+
+ if (info_v2_1 == NULL)
+ return BP_RESULT_BADBIOSTABLE;
+
+ info->gpu_cap_info =
+ le32_to_cpu(info_v2_1->gpucapinfo);
+ /*
+ * system_config: Bit[0] = 0 : PCIE power gating disabled
+ * = 1 : PCIE power gating enabled
+ * Bit[1] = 0 : DDR-PLL shut down disabled
+ * = 1 : DDR-PLL shut down enabled
+ * Bit[2] = 0 : DDR-PLL power down disabled
+ * = 1 : DDR-PLL power down enabled
+ */
+ info->system_config = le32_to_cpu(info_v2_1->system_config);
+ info->cpu_cap_info = le32_to_cpu(info_v2_1->cpucapinfo);
+ info->memory_type = info_v2_1->memorytype;
+ info->ma_channel_number = info_v2_1->umachannelnumber;
+ info->dp_ss_control =
+ le16_to_cpu(info_v2_1->reserved1);
+
+ for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
+ info->ext_disp_conn_info.gu_id[i] =
+ info_v2_1->extdispconninfo.guid[i];
+ }
+
+ for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
+ info->ext_disp_conn_info.path[i].device_connector_id =
+ object_id_from_bios_object_id(
+ le16_to_cpu(info_v2_1->extdispconninfo.path[i].connectorobjid));
+
+ info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
+ object_id_from_bios_object_id(
+ le16_to_cpu(
+ info_v2_1->extdispconninfo.path[i].ext_encoder_objid));
+
+ info->ext_disp_conn_info.path[i].device_tag =
+ le16_to_cpu(
+ info_v2_1->extdispconninfo.path[i].device_tag);
+ info->ext_disp_conn_info.path[i].device_acpi_enum =
+ le16_to_cpu(
+ info_v2_1->extdispconninfo.path[i].device_acpi_enum);
+ info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
+ info_v2_1->extdispconninfo.path[i].auxddclut_index;
+ info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
+ info_v2_1->extdispconninfo.path[i].hpdlut_index;
+ info->ext_disp_conn_info.path[i].channel_mapping.raw =
+ info_v2_1->extdispconninfo.path[i].channelmapping;
+ info->ext_disp_conn_info.path[i].caps =
+ le16_to_cpu(info_v2_1->extdispconninfo.path[i].caps);
+ }
+
+ info->ext_disp_conn_info.checksum =
+ info_v2_1->extdispconninfo.checksum;
+ info->dp0_ext_hdmi_slv_addr = info_v2_1->dp0_retimer_set.HdmiSlvAddr;
+ info->dp0_ext_hdmi_reg_num = info_v2_1->dp0_retimer_set.HdmiRegNum;
+ for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
+ info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
+ info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
+ info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
+ info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
+ }
+ info->dp0_ext_hdmi_6g_reg_num = info_v2_1->dp0_retimer_set.Hdmi6GRegNum;
+ for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
+ info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
+ info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
+ info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
+ info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
+ }
+ info->dp1_ext_hdmi_slv_addr = info_v2_1->dp1_retimer_set.HdmiSlvAddr;
+ info->dp1_ext_hdmi_reg_num = info_v2_1->dp1_retimer_set.HdmiRegNum;
+ for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
+ info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
+ info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
+ info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
+ info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
+ }
+ info->dp1_ext_hdmi_6g_reg_num = info_v2_1->dp1_retimer_set.Hdmi6GRegNum;
+ for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
+ info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
+ info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
+ info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
+ info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
+ }
+ info->dp2_ext_hdmi_slv_addr = info_v2_1->dp2_retimer_set.HdmiSlvAddr;
+ info->dp2_ext_hdmi_reg_num = info_v2_1->dp2_retimer_set.HdmiRegNum;
+ for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
+ info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
+ info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
+ info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
+ info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
+ }
+ info->dp2_ext_hdmi_6g_reg_num = info_v2_1->dp2_retimer_set.Hdmi6GRegNum;
+ for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
+ info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
+ info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
+ info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
+ info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
+ }
+ info->dp3_ext_hdmi_slv_addr = info_v2_1->dp3_retimer_set.HdmiSlvAddr;
+ info->dp3_ext_hdmi_reg_num = info_v2_1->dp3_retimer_set.HdmiRegNum;
+ for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
+ info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
+ info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
+ info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
+ info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
+ }
+ info->dp3_ext_hdmi_6g_reg_num = info_v2_1->dp3_retimer_set.Hdmi6GRegNum;
+ for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
+ info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
+ info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
+ info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
+ info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
+ }
+
+ info->edp1_info.edp_backlight_pwm_hz =
+ le16_to_cpu(info_v2_1->edp1_info.edp_backlight_pwm_hz);
+ info->edp1_info.edp_ss_percentage =
+ le16_to_cpu(info_v2_1->edp1_info.edp_ss_percentage);
+ info->edp1_info.edp_ss_rate_10hz =
+ le16_to_cpu(info_v2_1->edp1_info.edp_ss_rate_10hz);
+ info->edp1_info.edp_pwr_on_off_delay =
+ info_v2_1->edp1_info.edp_pwr_on_off_delay;
+ info->edp1_info.edp_pwr_on_vary_bl_to_blon =
+ info_v2_1->edp1_info.edp_pwr_on_vary_bl_to_blon;
+ info->edp1_info.edp_pwr_down_bloff_to_vary_bloff =
+ info_v2_1->edp1_info.edp_pwr_down_bloff_to_vary_bloff;
+ info->edp1_info.edp_panel_bpc =
+ info_v2_1->edp1_info.edp_panel_bpc;
+ info->edp1_info.edp_bootup_bl_level = info_v2_1->edp1_info.edp_bootup_bl_level;
+
+ info->edp2_info.edp_backlight_pwm_hz =
+ le16_to_cpu(info_v2_1->edp2_info.edp_backlight_pwm_hz);
+ info->edp2_info.edp_ss_percentage =
+ le16_to_cpu(info_v2_1->edp2_info.edp_ss_percentage);
+ info->edp2_info.edp_ss_rate_10hz =
+ le16_to_cpu(info_v2_1->edp2_info.edp_ss_rate_10hz);
+ info->edp2_info.edp_pwr_on_off_delay =
+ info_v2_1->edp2_info.edp_pwr_on_off_delay;
+ info->edp2_info.edp_pwr_on_vary_bl_to_blon =
+ info_v2_1->edp2_info.edp_pwr_on_vary_bl_to_blon;
+ info->edp2_info.edp_pwr_down_bloff_to_vary_bloff =
+ info_v2_1->edp2_info.edp_pwr_down_bloff_to_vary_bloff;
+ info->edp2_info.edp_panel_bpc =
+ info_v2_1->edp2_info.edp_panel_bpc;
+ info->edp2_info.edp_bootup_bl_level =
+ info_v2_1->edp2_info.edp_bootup_bl_level;
+
+ return BP_RESULT_OK;
+}
+
+static enum bp_result get_integrated_info_v2_2(
+ struct bios_parser *bp,
+ struct integrated_info *info)
+{
+ struct atom_integrated_system_info_v2_2 *info_v2_2;
+ uint32_t i;
+
+ info_v2_2 = GET_IMAGE(struct atom_integrated_system_info_v2_2,
+ DATA_TABLES(integratedsysteminfo));
+
+ if (info_v2_2 == NULL)
+ return BP_RESULT_BADBIOSTABLE;
+
+ info->gpu_cap_info =
+ le32_to_cpu(info_v2_2->gpucapinfo);
+ /*
+ * system_config: Bit[0] = 0 : PCIE power gating disabled
+ * = 1 : PCIE power gating enabled
+ * Bit[1] = 0 : DDR-PLL shut down disabled
+ * = 1 : DDR-PLL shut down enabled
+ * Bit[2] = 0 : DDR-PLL power down disabled
+ * = 1 : DDR-PLL power down enabled
+ */
+ info->system_config = le32_to_cpu(info_v2_2->system_config);
+ info->cpu_cap_info = le32_to_cpu(info_v2_2->cpucapinfo);
+ info->memory_type = info_v2_2->memorytype;
+ info->ma_channel_number = info_v2_2->umachannelnumber;
+ info->dp_ss_control =
+ le16_to_cpu(info_v2_2->reserved1);
+
+ for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
+ info->ext_disp_conn_info.gu_id[i] =
+ info_v2_2->extdispconninfo.guid[i];
+ }
+
+ for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
+ info->ext_disp_conn_info.path[i].device_connector_id =
+ object_id_from_bios_object_id(
+ le16_to_cpu(info_v2_2->extdispconninfo.path[i].connectorobjid));
+
+ info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
+ object_id_from_bios_object_id(
+ le16_to_cpu(
+ info_v2_2->extdispconninfo.path[i].ext_encoder_objid));
+
+ info->ext_disp_conn_info.path[i].device_tag =
+ le16_to_cpu(
+ info_v2_2->extdispconninfo.path[i].device_tag);
+ info->ext_disp_conn_info.path[i].device_acpi_enum =
+ le16_to_cpu(
+ info_v2_2->extdispconninfo.path[i].device_acpi_enum);
+ info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
+ info_v2_2->extdispconninfo.path[i].auxddclut_index;
+ info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
+ info_v2_2->extdispconninfo.path[i].hpdlut_index;
+ info->ext_disp_conn_info.path[i].channel_mapping.raw =
+ info_v2_2->extdispconninfo.path[i].channelmapping;
+ info->ext_disp_conn_info.path[i].caps =
+ le16_to_cpu(info_v2_2->extdispconninfo.path[i].caps);
+ }
+
+ info->ext_disp_conn_info.checksum =
+ info_v2_2->extdispconninfo.checksum;
+ info->ext_disp_conn_info.fixdpvoltageswing =
+ info_v2_2->extdispconninfo.fixdpvoltageswing;
+
+ info->edp1_info.edp_backlight_pwm_hz =
+ le16_to_cpu(info_v2_2->edp1_info.edp_backlight_pwm_hz);
+ info->edp1_info.edp_ss_percentage =
+ le16_to_cpu(info_v2_2->edp1_info.edp_ss_percentage);
+ info->edp1_info.edp_ss_rate_10hz =
+ le16_to_cpu(info_v2_2->edp1_info.edp_ss_rate_10hz);
+ info->edp1_info.edp_pwr_on_off_delay =
+ info_v2_2->edp1_info.edp_pwr_on_off_delay;
+ info->edp1_info.edp_pwr_on_vary_bl_to_blon =
+ info_v2_2->edp1_info.edp_pwr_on_vary_bl_to_blon;
+ info->edp1_info.edp_pwr_down_bloff_to_vary_bloff =
+ info_v2_2->edp1_info.edp_pwr_down_bloff_to_vary_bloff;
+ info->edp1_info.edp_panel_bpc =
+ info_v2_2->edp1_info.edp_panel_bpc;
+ info->edp1_info.edp_bootup_bl_level =
+
+ info->edp2_info.edp_backlight_pwm_hz =
+ le16_to_cpu(info_v2_2->edp2_info.edp_backlight_pwm_hz);
+ info->edp2_info.edp_ss_percentage =
+ le16_to_cpu(info_v2_2->edp2_info.edp_ss_percentage);
+ info->edp2_info.edp_ss_rate_10hz =
+ le16_to_cpu(info_v2_2->edp2_info.edp_ss_rate_10hz);
+ info->edp2_info.edp_pwr_on_off_delay =
+ info_v2_2->edp2_info.edp_pwr_on_off_delay;
+ info->edp2_info.edp_pwr_on_vary_bl_to_blon =
+ info_v2_2->edp2_info.edp_pwr_on_vary_bl_to_blon;
+ info->edp2_info.edp_pwr_down_bloff_to_vary_bloff =
+ info_v2_2->edp2_info.edp_pwr_down_bloff_to_vary_bloff;
+ info->edp2_info.edp_panel_bpc =
+ info_v2_2->edp2_info.edp_panel_bpc;
+ info->edp2_info.edp_bootup_bl_level =
+ info_v2_2->edp2_info.edp_bootup_bl_level;
+
+ return BP_RESULT_OK;
+}
/*
* construct_integrated_info
@@ -1613,8 +2380,6 @@ static enum bp_result construct_integrated_info(
struct atom_common_table_header *header;
struct atom_data_revision revision;
-
- struct clock_voltage_caps temp = {0, 0};
uint32_t i;
uint32_t j;
@@ -1624,10 +2389,28 @@ static enum bp_result construct_integrated_info(
get_atom_data_table_revision(header, &revision);
- /* Don't need to check major revision as they are all 1 */
- switch (revision.minor) {
- case 11:
- result = get_integrated_info_v11(bp, info);
+ switch (revision.major) {
+ case 1:
+ switch (revision.minor) {
+ case 11:
+ case 12:
+ result = get_integrated_info_v11(bp, info);
+ break;
+ default:
+ return result;
+ }
+ break;
+ case 2:
+ switch (revision.minor) {
+ case 1:
+ result = get_integrated_info_v2_1(bp, info);
+ break;
+ case 2:
+ result = get_integrated_info_v2_2(bp, info);
+ break;
+ default:
+ return result;
+ }
break;
default:
return result;
@@ -1644,10 +2427,8 @@ static enum bp_result construct_integrated_info(
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]);
}
}
}
@@ -1655,6 +2436,46 @@ static enum bp_result construct_integrated_info(
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;
+}
+
static struct integrated_info *bios_parser_create_integrated_info(
struct dc_bios *dcb)
{
@@ -1829,7 +2650,6 @@ static enum bp_result bios_get_board_layout_info(
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] = {
@@ -1838,7 +2658,6 @@ 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;
@@ -1868,6 +2687,187 @@ static enum bp_result bios_get_board_layout_info(
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,
@@ -1881,8 +2881,6 @@ static const struct dc_vbios_funcs vbios_funcs = {
.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,
.get_ss_entry_number = bios_parser_get_ss_entry_number,
@@ -1918,9 +2916,22 @@ static const struct dc_vbios_funcs vbios_funcs = {
.bios_parser_destroy = firmware_parser_destroy,
.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,
+
+ .get_disp_connector_caps_info = bios_parser_get_disp_connector_caps_info,
+
+ .get_lttpr_caps = bios_parser_get_lttpr_caps,
+
+ .get_lttpr_interop = bios_parser_get_lttpr_interop,
};
-static bool bios_parser_construct(
+static bool bios_parser2_construct(
struct bios_parser *bp,
struct bp_init_data *init,
enum dce_version dce_version)
@@ -1982,7 +2993,7 @@ static bool bios_parser_construct(
&bp->object_info_tbl.revision);
if (bp->object_info_tbl.revision.major == 1
- && bp->object_info_tbl.revision.minor >= 4) {
+ && bp->object_info_tbl.revision.minor == 4) {
struct display_object_info_table_v1_4 *tbl_v1_4;
tbl_v1_4 = GET_IMAGE(struct display_object_info_table_v1_4,
@@ -1991,13 +3002,17 @@ static bool bios_parser_construct(
return false;
bp->object_info_tbl.v1_4 = tbl_v1_4;
- } else
+ } else {
+ ASSERT(0);
return false;
+ }
dal_firmware_parser_init_cmd_tbl(bp);
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;
}
@@ -2012,7 +3027,7 @@ struct dc_bios *firmware_parser_create(
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);