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