diff options
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.c | 145 |
1 files changed, 132 insertions, 13 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 05f392501c0a..04eb647acc4e 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -75,6 +75,10 @@ static enum bp_result get_firmware_info_v3_4( struct bios_parser *bp, struct dc_firmware_info *info); +static enum bp_result get_firmware_info_v3_5( + 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); @@ -1594,8 +1598,6 @@ static bool bios_parser_is_device_id_supported( 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( @@ -1756,6 +1758,9 @@ static enum bp_result bios_parser_get_firmware_info( case 4: result = get_firmware_info_v3_4(bp, info); break; + case 5: + result = get_firmware_info_v3_5(bp, info); + break; default: break; } @@ -1773,6 +1778,7 @@ static enum bp_result get_firmware_info_v3_1( struct dc_firmware_info *info) { struct atom_firmware_info_v3_1 *firmware_info; + struct atom_firmware_info_v3_2 *firmware_info32; struct atom_display_controller_info_v4_1 *dce_info = NULL; if (!info) @@ -1780,11 +1786,13 @@ static enum bp_result get_firmware_info_v3_1( firmware_info = GET_IMAGE(struct atom_firmware_info_v3_1, DATA_TABLES(firmwareinfo)); + firmware_info32 = GET_IMAGE(struct atom_firmware_info_v3_2, + DATA_TABLES(firmwareinfo)); dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1, DATA_TABLES(dce_info)); - if (!firmware_info || !dce_info) + if (!firmware_info || !firmware_info32 || !dce_info) return BP_RESULT_BADBIOSTABLE; memset(info, 0, sizeof(*info)); @@ -1812,7 +1820,15 @@ 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; + /* These fields are marked as reserved in v3_1, but they appear to be populated + * properly. + */ + if (firmware_info32 && firmware_info32->board_i2c_feature_id == 0x2) { + info->oem_i2c_present = true; + info->oem_i2c_obj_id = firmware_info32->board_i2c_feature_gpio_id; + } else { + info->oem_i2c_present = false; + } return BP_RESULT_OK; } @@ -2046,6 +2062,63 @@ static enum bp_result get_firmware_info_v3_4( return BP_RESULT_OK; } +static enum bp_result get_firmware_info_v3_5( + struct bios_parser *bp, + struct dc_firmware_info *info) +{ + struct atom_firmware_info_v3_5 *firmware_info; + struct atom_common_table_header *header; + struct atom_data_revision revision; + struct atom_display_controller_info_v4_5 *dce_info_v4_5 = NULL; + + if (!info) + return BP_RESULT_BADINPUT; + + firmware_info = GET_IMAGE(struct atom_firmware_info_v3_5, + DATA_TABLES(firmwareinfo)); + + if (!firmware_info) + return BP_RESULT_BADBIOSTABLE; + + memset(info, 0, sizeof(*info)); + + 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; + } + + 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 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; + break; + default: + break; + } + break; + default: + break; + } + + + return BP_RESULT_OK; +} + static enum bp_result bios_parser_get_encoder_cap_info( struct dc_bios *dcb, struct graphics_object_id object_id, @@ -2400,6 +2473,25 @@ static enum bp_result get_vram_info_v30( return result; } +static enum bp_result get_vram_info_from_umc_info_v40( + struct bios_parser *bp, + struct dc_vram_info *info) +{ + struct atom_umc_info_v4_0 *info_v40; + enum bp_result result = BP_RESULT_OK; + + info_v40 = GET_IMAGE(struct atom_umc_info_v4_0, + DATA_TABLES(umc_info)); + + if (info_v40 == NULL) + return BP_RESULT_BADBIOSTABLE; + + info->num_chans = info_v40->channel_num; + info->dram_channel_width_bytes = (1 << info_v40->channel_width) / 8; + + return result; +} + /* * get_integrated_info_v11 * @@ -2922,8 +3014,11 @@ static enum bp_result construct_integrated_info( struct atom_common_table_header *header; struct atom_data_revision revision; - uint32_t i; - uint32_t j; + int32_t i; + int32_t j; + + if (!info) + return result; if (info && DATA_TABLES(integratedsysteminfo)) { header = GET_IMAGE(struct atom_common_table_header, @@ -2948,6 +3043,7 @@ static enum bp_result construct_integrated_info( result = get_integrated_info_v2_1(bp, info); break; case 2: + case 3: result = get_integrated_info_v2_2(bp, info); break; default: @@ -3003,11 +3099,12 @@ static enum bp_result construct_integrated_info( info->ext_disp_conn_info.path[i].ext_encoder_obj_id.id, info->ext_disp_conn_info.path[i].caps ); - if (info->ext_disp_conn_info.path[i].caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) - DC_LOG_BIOS("BIOS EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i); + if ((info->ext_disp_conn_info.path[i].caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) + DC_LOG_BIOS("BIOS AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i); else if (bp->base.ctx->dc->config.force_bios_fixed_vs) { - info->ext_disp_conn_info.path[i].caps |= EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN; - DC_LOG_BIOS("driver forced EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i); + info->ext_disp_conn_info.path[i].caps &= ~AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK; + info->ext_disp_conn_info.path[i].caps |= AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN; + DC_LOG_BIOS("driver forced AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i); } } // Log the Checksum and Voltage Swing @@ -3037,11 +3134,33 @@ static enum bp_result bios_parser_get_vram_info( struct dc_vram_info *info) { struct bios_parser *bp = BP_FROM_DCB(dcb); - static enum bp_result result = BP_RESULT_BADBIOSTABLE; + enum bp_result result = BP_RESULT_BADBIOSTABLE; struct atom_common_table_header *header; struct atom_data_revision revision; - if (info && DATA_TABLES(vram_info)) { + // vram info moved to umc_info for DCN4x + if (info && DATA_TABLES(umc_info)) { + header = GET_IMAGE(struct atom_common_table_header, + DATA_TABLES(umc_info)); + + get_atom_data_table_revision(header, &revision); + + switch (revision.major) { + case 4: + switch (revision.minor) { + case 0: + result = get_vram_info_from_umc_info_v40(bp, info); + break; + default: + break; + } + break; + default: + break; + } + } + + if (result != BP_RESULT_OK && info && DATA_TABLES(vram_info)) { header = GET_IMAGE(struct atom_common_table_header, DATA_TABLES(vram_info)); @@ -3664,7 +3783,7 @@ static bool bios_parser2_construct( 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); - + bios_parser_get_soc_bb_info(&bp->base, &bp->base.bb_info); return true; } |