diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/bios')
15 files changed, 922 insertions, 736 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 3bacf470f7c5..fb30a3e5dfdb 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -67,7 +67,9 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, ATOM_OBJECT *object); static struct device_id device_type_from_device_id(uint16_t device_id); static uint32_t signal_to_ss_id(enum as_signal_type signal); -static uint32_t get_support_mask_for_device_id(struct device_id device_id); +static uint32_t get_support_mask_for_device_id( + enum dal_device_type device_type, + uint32_t enum_id); static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record( struct bios_parser *bp, ATOM_OBJECT *object); @@ -96,7 +98,7 @@ struct dc_bios *bios_parser_create( { struct bios_parser *bp; - bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL); + bp = kzalloc_obj(struct bios_parser); if (!bp) return NULL; @@ -174,11 +176,8 @@ static struct graphics_object_id bios_parser_get_connector_id( return object_id; } - if (tbl->ucNumberOfObjects <= i) { - dm_error("Can't find connector id %d in connector table of size %d.\n", - i, tbl->ucNumberOfObjects); + if (tbl->ucNumberOfObjects <= i) return object_id; - } id = le16_to_cpu(tbl->asObjects[i].usObjectID); object_id = object_id_from_bios_object_id(id); @@ -223,6 +222,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb, ATOM_COMMON_RECORD_HEADER *header; ATOM_I2C_RECORD *record; struct bios_parser *bp = BP_FROM_DCB(dcb); + int i; if (!info) return BP_RESULT_BADINPUT; @@ -235,7 +235,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb, offset = le16_to_cpu(object->usRecordOffset) + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); if (!header) @@ -294,11 +294,12 @@ static enum bp_result bios_parser_get_device_tag_record( { ATOM_COMMON_RECORD_HEADER *header; uint32_t offset; + int i; offset = le16_to_cpu(object->usRecordOffset) + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); if (!header) @@ -444,6 +445,7 @@ static enum bp_result get_firmware_info_v1_4( le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10; info->pll_info.max_output_pxl_clk_pll_frequency = le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10; + info->max_pixel_clock = le16_to_cpu(firmware_info->usMaxPixelClock) * 10; if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support) /* Since there is no information on the SS, report conservative @@ -500,6 +502,7 @@ static enum bp_result get_firmware_info_v2_1( info->external_clock_source_frequency_for_dp = le16_to_cpu(firmwareInfo->usUniphyDPModeExtClkFreq) * 10; info->min_allowed_bl_level = firmwareInfo->ucMinAllowedBL_Level; + info->max_pixel_clock = le16_to_cpu(firmwareInfo->usMaxPixelClock) * 10; /* There should be only one entry in the SS info table for Memory Clock */ @@ -739,18 +742,112 @@ static enum bp_result bios_parser_transmitter_control( return bp->cmd_tbl.transmitter_control(bp, cntl); } +static enum bp_result bios_parser_select_crtc_source( + 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_encoder_control( struct dc_bios *dcb, struct bp_encoder_control *cntl) { struct bios_parser *bp = BP_FROM_DCB(dcb); + if (cntl->engine_id == ENGINE_ID_DACA) { + if (!bp->cmd_tbl.dac1_encoder_control) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.dac1_encoder_control( + bp, cntl->action, + cntl->pixel_clock, ATOM_DAC1_PS2); + } else if (cntl->engine_id == ENGINE_ID_DACB) { + if (!bp->cmd_tbl.dac2_encoder_control) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.dac2_encoder_control( + bp, cntl->action, + cntl->pixel_clock, ATOM_DAC1_PS2); + } + if (!bp->cmd_tbl.dig_encoder_control) return BP_RESULT_FAILURE; return bp->cmd_tbl.dig_encoder_control(bp, cntl); } +static enum bp_result bios_parser_external_encoder_control( + struct dc_bios *dcb, + struct bp_external_encoder_control *cntl) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.external_encoder_control) + return BP_RESULT_UNSUPPORTED; + + return bp->cmd_tbl.external_encoder_control(bp, cntl); +} + +static enum bp_result bios_parser_dac_load_detection( + struct dc_bios *dcb, + enum engine_id engine_id, + struct graphics_object_id ext_enc_id) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + struct dc_context *ctx = dcb->ctx; + struct bp_load_detection_parameters bp_params = {0}; + struct bp_external_encoder_control ext_cntl = {0}; + enum bp_result bp_result = BP_RESULT_UNSUPPORTED; + uint32_t bios_0_scratch; + uint32_t device_id_mask = 0; + + bp_params.device_id = (uint16_t)get_support_mask_for_device_id( + DEVICE_TYPE_CRT, engine_id == ENGINE_ID_DACB ? 2 : 1); + + if (bp_params.device_id == ATOM_DEVICE_CRT1_SUPPORT) + device_id_mask = ATOM_S0_CRT1_MASK; + else if (bp_params.device_id == ATOM_DEVICE_CRT2_SUPPORT) + device_id_mask = ATOM_S0_CRT2_MASK; + else + return BP_RESULT_UNSUPPORTED; + + /* BIOS will write the detected devices to BIOS_SCRATCH_0, clear corresponding bit */ + bios_0_scratch = dm_read_reg(ctx, bp->base.regs->BIOS_SCRATCH_0); + bios_0_scratch &= ~device_id_mask; + dm_write_reg(ctx, bp->base.regs->BIOS_SCRATCH_0, bios_0_scratch); + + if (engine_id == ENGINE_ID_DACA || engine_id == ENGINE_ID_DACB) { + if (!bp->cmd_tbl.dac_load_detection) + return BP_RESULT_UNSUPPORTED; + + bp_params.engine_id = engine_id; + bp_result = bp->cmd_tbl.dac_load_detection(bp, &bp_params); + } else if (ext_enc_id.id) { + if (!bp->cmd_tbl.external_encoder_control) + return BP_RESULT_UNSUPPORTED; + + ext_cntl.action = EXTERNAL_ENCODER_CONTROL_DAC_LOAD_DETECT; + ext_cntl.encoder_id = ext_enc_id; + bp_result = bp->cmd_tbl.external_encoder_control(bp, &ext_cntl); + } + + if (bp_result != BP_RESULT_OK) + return bp_result; + + bios_0_scratch = dm_read_reg(ctx, bp->base.regs->BIOS_SCRATCH_0); + + if (bios_0_scratch & device_id_mask) + return BP_RESULT_OK; + + return BP_RESULT_FAILURE; +} + static enum bp_result bios_parser_adjust_pixel_clock( struct dc_bios *dcb, struct bp_adjust_pixel_clock_parameters *bp_params) @@ -861,7 +958,7 @@ static bool bios_parser_is_device_id_supported( { struct bios_parser *bp = BP_FROM_DCB(dcb); - uint32_t mask = get_support_mask_for_device_id(id); + uint32_t mask = get_support_mask_for_device_id(id.device_type, id.enum_id); return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0; } @@ -871,6 +968,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, { ATOM_COMMON_RECORD_HEADER *header; uint32_t offset; + int i; if (!object) { BREAK_TO_DEBUGGER(); /* Invalid object */ @@ -880,7 +978,7 @@ static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, offset = le16_to_cpu(object->usRecordOffset) + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); if (!header) @@ -1218,6 +1316,60 @@ static enum bp_result bios_parser_get_embedded_panel_info( return BP_RESULT_FAILURE; } +static enum bp_result get_embedded_panel_extra_info( + struct bios_parser *bp, + struct embedded_panel_info *info, + const uint32_t table_offset) +{ + uint8_t *record = bios_get_image(&bp->base, table_offset, 1); + ATOM_PANEL_RESOLUTION_PATCH_RECORD *panel_res_record; + ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record; + + while (*record != ATOM_RECORD_END_TYPE) { + switch (*record) { + case LCD_MODE_PATCH_RECORD_MODE_TYPE: + record += sizeof(ATOM_PATCH_RECORD_MODE); + break; + case LCD_RTS_RECORD_TYPE: + record += sizeof(ATOM_LCD_RTS_RECORD); + break; + case LCD_CAP_RECORD_TYPE: + record += sizeof(ATOM_LCD_MODE_CONTROL_CAP); + break; + case LCD_FAKE_EDID_PATCH_RECORD_TYPE: + fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record; + if (fake_edid_record->ucFakeEDIDLength) { + if (fake_edid_record->ucFakeEDIDLength == 128) + info->fake_edid_size = + fake_edid_record->ucFakeEDIDLength; + else + info->fake_edid_size = + fake_edid_record->ucFakeEDIDLength * 128; + + info->fake_edid = fake_edid_record->ucFakeEDIDString; + + record += struct_size(fake_edid_record, + ucFakeEDIDString, + info->fake_edid_size); + } else { + /* empty fake edid record must be 3 bytes long */ + record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1; + } + break; + case LCD_PANEL_RESOLUTION_RECORD_TYPE: + panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record; + info->panel_width_mm = panel_res_record->usHSize; + info->panel_height_mm = panel_res_record->usVSize; + record += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD); + break; + default: + return BP_RESULT_BADBIOSTABLE; + } + } + + return BP_RESULT_OK; +} + static enum bp_result get_embedded_panel_info_v1_2( struct bios_parser *bp, struct embedded_panel_info *info) @@ -1296,7 +1448,7 @@ static enum bp_result get_embedded_panel_info_v1_2( info->ss_id = lvds->ucSS_Id; { - uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate); + uint16_t rr = le16_to_cpu(lvds->usSupportedRefreshRate); /* Get minimum supported refresh rate*/ if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr) info->supported_rr.REFRESH_RATE_30HZ = 1; @@ -1334,6 +1486,10 @@ static enum bp_result get_embedded_panel_info_v1_2( if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc) info->lcd_timing.misc_info.API_ENABLED = true; + if (lvds->usExtInfoTableOffset) + return get_embedded_panel_extra_info(bp, info, + le16_to_cpu(lvds->usExtInfoTableOffset) + DATA_TABLES(LCD_Info)); + return BP_RESULT_OK; } @@ -1459,6 +1615,10 @@ static enum bp_result get_embedded_panel_info_v1_3( (uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL & lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT; + if (lvds->usExtInfoTableOffset) + return get_embedded_panel_extra_info(bp, info, + le16_to_cpu(lvds->usExtInfoTableOffset) + DATA_TABLES(LCD_Info)); + return BP_RESULT_OK; } @@ -1513,6 +1673,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record( { ATOM_COMMON_RECORD_HEADER *header; uint32_t offset; + int i; if (!object) { BREAK_TO_DEBUGGER(); /* Invalid object */ @@ -1522,7 +1683,7 @@ static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record( offset = le16_to_cpu(object->usRecordOffset) + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); if (!header) @@ -1877,7 +2038,7 @@ static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, count = (le16_to_cpu(header->sHeader.usStructureSize) - sizeof(ATOM_COMMON_TABLE_HEADER)) / sizeof(ATOM_GPIO_I2C_ASSIGMENT); - if (count < record->sucI2cId.bfI2C_LineMux) + if (count <= record->sucI2cId.bfI2C_LineMux) return BP_RESULT_BADBIOSTABLE; /* get the GPIO_I2C_INFO */ @@ -2152,11 +2313,10 @@ static uint32_t signal_to_ss_id(enum as_signal_type signal) return clk_id_ss; } -static uint32_t get_support_mask_for_device_id(struct device_id device_id) +static uint32_t get_support_mask_for_device_id( + enum dal_device_type device_type, + uint32_t enum_id) { - enum dal_device_type device_type = device_id.device_type; - uint32_t enum_id = device_id.enum_id; - switch (device_type) { case DEVICE_TYPE_LCD: switch (enum_id) { @@ -2263,15 +2423,6 @@ static enum bp_result get_integrated_info_v8( info->dentist_vco_freq = le32_to_cpu(info_v8->ulDentistVCOFreq) * 10; info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10; - for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - /* Convert [10KHz] into [KHz] */ - info->disp_clk_voltage[i].max_supported_clk = - le32_to_cpu(info_v8->sDISPCLK_Voltage[i]. - ulMaximumSupportedCLK) * 10; - info->disp_clk_voltage[i].voltage_index = - le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex); - } - info->boot_up_req_display_vector = le32_to_cpu(info_v8->ulBootUpReqDisplayVector); info->gpu_cap_info = @@ -2384,10 +2535,10 @@ static enum bp_result get_integrated_info_v8( } /* - * get_integrated_info_v8 + * get_integrated_info_v9 * * @brief - * Get V8 integrated BIOS information + * Get V9 integrated BIOS information * * @param * bios_parser *bp - [in]BIOS parser handler to get master data table @@ -2414,14 +2565,6 @@ static enum bp_result get_integrated_info_v9( info->dentist_vco_freq = le32_to_cpu(info_v9->ulDentistVCOFreq) * 10; info->boot_up_uma_clock = le32_to_cpu(info_v9->ulBootUpUMAClock) * 10; - for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - /* Convert [10KHz] into [KHz] */ - info->disp_clk_voltage[i].max_supported_clk = - le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10; - info->disp_clk_voltage[i].voltage_index = - le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex); - } - info->boot_up_req_display_vector = le32_to_cpu(info_v9->ulBootUpReqDisplayVector); info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo); @@ -2563,25 +2706,6 @@ static enum bp_result construct_integrated_info( } } - /* Sort voltage table from low to high*/ - if (result == BP_RESULT_OK) { - int32_t i; - int32_t j; - - for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - for (j = i; j > 0; --j) { - if ( - info->disp_clk_voltage[j].max_supported_clk < - info->disp_clk_voltage[j-1].max_supported_clk) { - /* swap j and j - 1*/ - swap(info->disp_clk_voltage[j - 1], - info->disp_clk_voltage[j]); - } - } - } - - } - return result; } @@ -2591,7 +2715,7 @@ static struct integrated_info *bios_parser_create_integrated_info( struct bios_parser *bp = BP_FROM_DCB(dcb); struct integrated_info *info; - info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL); + info = kzalloc_obj(struct integrated_info); if (info == NULL) { ASSERT_CRITICAL(0); @@ -2611,7 +2735,9 @@ static enum bp_result update_slot_layout_info(struct dc_bios *dcb, struct slot_layout_info *slot_layout_info, unsigned int record_offset) { + (void)i; unsigned int j; + unsigned int n; struct bios_parser *bp; ATOM_BRACKET_LAYOUT_RECORD *record; ATOM_COMMON_RECORD_HEADER *record_header; @@ -2621,7 +2747,7 @@ static enum bp_result update_slot_layout_info(struct dc_bios *dcb, record = NULL; record_header = NULL; - for (;;) { + for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) { record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset); if (record_header == NULL) { @@ -2832,8 +2958,14 @@ static const struct dc_vbios_funcs vbios_funcs = { .is_device_id_supported = bios_parser_is_device_id_supported, /* COMMANDS */ + .select_crtc_source = bios_parser_select_crtc_source, + .encoder_control = bios_parser_encoder_control, + .external_encoder_control = bios_parser_external_encoder_control, + + .dac_load_detection = bios_parser_dac_load_detection, + .transmitter_control = bios_parser_transmitter_control, .enable_crtc = bios_parser_enable_crtc, 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 a62f6c51301c..7a53b49dc4cd 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -157,7 +157,7 @@ static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb) break; } - return count; + return (uint8_t)count; } static struct graphics_object_id bios_parser_get_connector_id( @@ -205,6 +205,7 @@ static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb, struct graphics_object_id object_id, uint32_t index, struct graphics_object_id *src_object_id) { + (void)index; struct bios_parser *bp = BP_FROM_DCB(dcb); unsigned int i; enum bp_result bp_result = BP_RESULT_BADINPUT; @@ -395,12 +396,13 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb, struct atom_i2c_record *record; struct atom_i2c_record dummy_record = {0}; struct bios_parser *bp = BP_FROM_DCB(dcb); + int i; if (!info) return BP_RESULT_BADINPUT; if (id.type == OBJECT_TYPE_GENERIC) { - dummy_record.i2c_id = id.id; + dummy_record.i2c_id = (uint8_t)id.id; if (get_gpio_i2c_info(bp, &dummy_record, info) == BP_RESULT_OK) return BP_RESULT_OK; @@ -428,7 +430,7 @@ static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb, break; } - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(struct atom_common_record_header, offset); if (!header) @@ -492,6 +494,10 @@ static enum bp_result get_gpio_i2c_info( - sizeof(struct atom_common_table_header)) / sizeof(struct atom_gpio_pin_assignment); + if (!bios_get_image(&bp->base, DATA_TABLES(gpio_pin_lut), + le16_to_cpu(header->table_header.structuresize))) + return BP_RESULT_BADBIOSTABLE; + pin = (struct atom_gpio_pin_assignment *) header->gpio_pin; for (table_index = 0; table_index < count; table_index++) { @@ -529,6 +535,7 @@ static struct atom_hpd_int_record *get_hpd_record_for_path_v3(struct bios_parser { struct atom_common_record_header *header; uint32_t offset; + int i; if (!object) { BREAK_TO_DEBUGGER(); /* Invalid object */ @@ -537,7 +544,7 @@ static struct atom_hpd_int_record *get_hpd_record_for_path_v3(struct bios_parser offset = object->disp_recordoffset + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(struct atom_common_record_header, offset); if (!header) @@ -606,6 +613,7 @@ static struct atom_hpd_int_record *get_hpd_record( { struct atom_common_record_header *header; uint32_t offset; + int i; if (!object) { BREAK_TO_DEBUGGER(); /* Invalid object */ @@ -615,7 +623,7 @@ static struct atom_hpd_int_record *get_hpd_record( offset = le16_to_cpu(object->disp_recordoffset) + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(struct atom_common_record_header, offset); if (!header) @@ -680,6 +688,11 @@ static enum bp_result bios_parser_get_gpio_pin_info( count = (le16_to_cpu(header->table_header.structuresize) - sizeof(struct atom_common_table_header)) / sizeof(struct atom_gpio_pin_assignment); + + if (!bios_get_image(&bp->base, DATA_TABLES(gpio_pin_lut), + le16_to_cpu(header->table_header.structuresize))) + return BP_RESULT_BADBIOSTABLE; + for (i = 0; i < count; ++i) { if (header->gpio_pin[i].gpio_id != gpio_id) continue; @@ -691,8 +704,10 @@ static enum bp_result bios_parser_get_gpio_pin_info( info->offset_en = info->offset + 1; info->offset_mask = info->offset - 1; - info->mask = (uint32_t) (1 << - header->gpio_pin[i].gpio_bitshift); + if (header->gpio_pin[i].gpio_bitshift >= 32) + return BP_RESULT_BADBIOSTABLE; + + info->mask = 1u << header->gpio_pin[i].gpio_bitshift; info->mask_y = info->mask + 2; info->mask_en = info->mask + 1; info->mask_mask = info->mask - 1; @@ -703,6 +718,69 @@ static enum bp_result bios_parser_get_gpio_pin_info( return BP_RESULT_NORECORD; } +static enum bp_result bios_parser_get_connector_aux_info(struct dc_bios *dcb, + struct graphics_object_id id, + struct graphics_object_i2c_info *info) +{ + uint32_t offset; + struct atom_display_object_path_v2 *object; + struct atom_display_object_path_v3 *object_path_v3; + struct atom_common_record_header *header; + struct atom_i2c_record *record; + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!info) + return BP_RESULT_BADINPUT; + + switch (bp->object_info_tbl.revision.minor) { + case 4: + default: + object = get_bios_object(bp, id); + + if (!object) + return BP_RESULT_BADINPUT; + + offset = object->disp_recordoffset + bp->object_info_tbl_offset; + break; + case 5: + object_path_v3 = get_bios_object_from_path_v3(bp, id); + + if (!object_path_v3) + return BP_RESULT_BADINPUT; + + offset = object_path_v3->disp_recordoffset + bp->object_info_tbl_offset; + break; + } + + for (;;) { + header = GET_IMAGE(struct atom_common_record_header, offset); + + if (!header) + return BP_RESULT_BADBIOSTABLE; + + if (header->record_type == LAST_RECORD_TYPE || + !header->record_size) + break; + + if (header->record_type == ATOM_I2C_RECORD_TYPE + && sizeof(struct atom_i2c_record) <= + header->record_size) { + /* get_connector_aux_info - which aux instance is used it is based + * on record->i2c_id field only, does not need GPIO DDC + */ + record = (struct atom_i2c_record *)header; + + info->i2c_line = record->i2c_id & I2C_HW_LANE_MUX; + + return BP_RESULT_OK; + } + + offset += header->record_size; + } + + return BP_RESULT_NORECORD; +} + static struct device_id device_type_from_device_id(uint16_t device_id) { @@ -765,6 +843,7 @@ static enum bp_result bios_parser_get_device_tag( uint32_t device_tag_index, struct connector_device_tag_info *info) { + (void)device_tag_index; struct bios_parser *bp = BP_FROM_DCB(dcb); struct atom_display_object_path_v2 *object; @@ -809,6 +888,7 @@ static enum bp_result get_ss_info_v4_1( uint32_t index, struct spread_spectrum_info *ss_info) { + (void)index; 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; @@ -897,6 +977,7 @@ static enum bp_result get_ss_info_v4_2( uint32_t index, struct spread_spectrum_info *ss_info) { + (void)index; enum bp_result result = BP_RESULT_OK; struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL; struct atom_smu_info_v3_1 *smu_info = NULL; @@ -977,6 +1058,7 @@ static enum bp_result get_ss_info_v4_5( uint32_t index, struct spread_spectrum_info *ss_info) { + (void)index; enum bp_result result = BP_RESULT_OK; struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL; @@ -1223,7 +1305,7 @@ static enum bp_result get_disp_caps_v4_1( if (!disp_cntl_tbl) return BP_RESULT_BADBIOSTABLE; - *dce_caps = disp_cntl_tbl->display_caps; + *dce_caps = (uint8_t)disp_cntl_tbl->display_caps; return result; } @@ -1247,7 +1329,7 @@ static enum bp_result get_disp_caps_v4_2( if (!disp_cntl_tbl) return BP_RESULT_BADBIOSTABLE; - *dce_caps = disp_cntl_tbl->display_caps; + *dce_caps = (uint8_t)disp_cntl_tbl->display_caps; return result; } @@ -1271,7 +1353,7 @@ static enum bp_result get_disp_caps_v4_3( if (!disp_cntl_tbl) return BP_RESULT_BADBIOSTABLE; - *dce_caps = disp_cntl_tbl->display_caps; + *dce_caps = (uint8_t)disp_cntl_tbl->display_caps; return result; } @@ -1295,7 +1377,7 @@ static enum bp_result get_disp_caps_v4_4( if (!disp_cntl_tbl) return BP_RESULT_BADBIOSTABLE; - *dce_caps = disp_cntl_tbl->display_caps; + *dce_caps = (uint8_t)disp_cntl_tbl->display_caps; return result; } @@ -1319,7 +1401,7 @@ static enum bp_result get_disp_caps_v4_5( if (!disp_cntl_tbl) return BP_RESULT_BADBIOSTABLE; - *dce_caps = disp_cntl_tbl->display_caps; + *dce_caps = (uint8_t)disp_cntl_tbl->display_caps; return result; } @@ -1480,10 +1562,10 @@ static enum bp_result get_embedded_panel_info_v2_1( /* 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 = !(lvds->lcd_timing.miscinfo & + ATOM_HSYNC_POLARITY); + info->lcd_timing.misc_info.V_SYNC_POLARITY = !(lvds->lcd_timing.miscinfo & + ATOM_VSYNC_POLARITY); /* not provided by VBIOS */ info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0; @@ -1604,6 +1686,8 @@ static uint32_t bios_parser_get_ss_entry_number( struct dc_bios *dcb, enum as_signal_type signal) { + (void)dcb; + (void)signal; /* TODO: DAL2 atomfirmware implementation does not need this. * why DAL3 need this? */ @@ -1778,6 +1862,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) @@ -1785,11 +1870,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)); @@ -1817,7 +1904,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; } @@ -2108,6 +2203,12 @@ static enum bp_result get_firmware_info_v3_5( return BP_RESULT_OK; } +/* TODO: Remove this temp define after atomfirmware.h is updated */ +#define ATOM_ENCODER_CAP_RECORD_HDMI_FRL_TEMP 0x200 +#define ATOM_ENCODER_CAP_RECORD_HDMI_FRL_8GbEn_TEMP 0x400 // HDMI FRL 8Gb support +#define ATOM_ENCODER_CAP_RECORD_HDMI_FRL_10GbEn_TEMP 0x800 // HDMI FRL 10Gb support +#define ATOM_ENCODER_CAP_RECORD_HDMI_FRL_12GbEn_TEMP 0x1000 // HDMI FRL 12Gb support + static enum bp_result bios_parser_get_encoder_cap_info( struct dc_bios *dcb, struct graphics_object_id object_id, @@ -2155,6 +2256,15 @@ static enum bp_result bios_parser_get_encoder_cap_info( info->DP_IS_USB_C = (record->encodercaps & ATOM_ENCODER_CAP_RECORD_USB_C_TYPE) ? 1 : 0; DC_LOG_BIOS("\t info->DP_IS_USB_C %d", info->DP_IS_USB_C); + info->IS_HDMI_FRL_CAPABLE = (record->encodercaps & + ATOM_ENCODER_CAP_RECORD_HDMI_FRL_TEMP) ? 1 : 0; + info->FRL_8G_EN = (record->encodercaps & + ATOM_ENCODER_CAP_RECORD_HDMI_FRL_8GbEn_TEMP) ? 1 : 0; + info->FRL_10G_EN = (record->encodercaps & + ATOM_ENCODER_CAP_RECORD_HDMI_FRL_10GbEn_TEMP) ? 1 : 0; + info->FRL_12G_EN = (record->encodercaps & + ATOM_ENCODER_CAP_RECORD_HDMI_FRL_12GbEn_TEMP) ? 1 : 0; + DC_LOG_BIOS("\t info->IS_HDMI_FRL_CAPABLE %d\n", info->IS_HDMI_FRL_CAPABLE); return BP_RESULT_OK; } @@ -2166,6 +2276,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record( { struct atom_common_record_header *header; uint32_t offset; + int i; if (!object) { BREAK_TO_DEBUGGER(); /* Invalid object */ @@ -2174,7 +2285,7 @@ static struct atom_encoder_caps_record *get_encoder_cap_record( offset = object->encoder_recordoffset + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(struct atom_common_record_header, offset); if (!header) @@ -2203,6 +2314,7 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record( { struct atom_common_record_header *header; uint32_t offset; + int i; if (!object) { BREAK_TO_DEBUGGER(); /* Invalid object */ @@ -2211,7 +2323,7 @@ static struct atom_disp_connector_caps_record *get_disp_connector_caps_record( offset = object->disp_recordoffset + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(struct atom_common_record_header, offset); if (!header) @@ -2239,6 +2351,7 @@ static struct atom_connector_caps_record *get_connector_caps_record(struct bios_ { struct atom_common_record_header *header; uint32_t offset; + int i; if (!object) { BREAK_TO_DEBUGGER(); /* Invalid object */ @@ -2247,7 +2360,7 @@ static struct atom_connector_caps_record *get_connector_caps_record(struct bios_ offset = object->disp_recordoffset + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(struct atom_common_record_header, offset); if (!header) @@ -2314,6 +2427,9 @@ static enum bp_result bios_parser_get_disp_connector_caps_info( ? 1 : 0; info->INTERNAL_DISPLAY_BL = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL) ? 1 : 0; + // All aux transactions for this connector should rely only on aux instance, not on ddc instance + info->NO_DDC_PIN = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_DP_PLUS_PLUS_TYPE2_ONLY) ? 1 : 0; + break; } @@ -2325,6 +2441,7 @@ static struct atom_connector_speed_record *get_connector_speed_cap_record(struct { struct atom_common_record_header *header; uint32_t offset; + int i; if (!object) { BREAK_TO_DEBUGGER(); /* Invalid object */ @@ -2333,7 +2450,7 @@ static struct atom_connector_speed_record *get_connector_speed_cap_record(struct offset = object->disp_recordoffset + bp->object_info_tbl_offset; - for (;;) { + for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) { header = GET_IMAGE(struct atom_common_record_header, offset); if (!header) @@ -2383,6 +2500,12 @@ static enum bp_result bios_parser_get_connector_speed_cap_info( info->DP_UHBR10_EN = (record->connector_max_speed >= 10000) ? 1 : 0; info->DP_UHBR13_5_EN = (record->connector_max_speed >= 13500) ? 1 : 0; info->DP_UHBR20_EN = (record->connector_max_speed >= 20000) ? 1 : 0; + info->FRL_8G_EN = (record->connector_max_speed >= 8000) ? 1 : 0; + info->FRL_10G_EN = (record->connector_max_speed >= 10000) ? 1 : 0; + info->FRL_12G_EN = (record->connector_max_speed >= 12000) ? 1 : 0; + info->FRL_16G_EN = (record->connector_max_speed >= 16000) ? 1 : 0; + info->FRL_20G_EN = (record->connector_max_speed >= 20000) ? 1 : 0; + info->FRL_24G_EN = (record->connector_max_speed >= 24000) ? 1 : 0; return BP_RESULT_OK; } @@ -2567,20 +2690,22 @@ static enum bp_result get_integrated_info_v11( info->ext_disp_conn_info.path[i].channel_mapping.raw = info_v11->extdispconninfo.path[i].channelmapping; info->ext_disp_conn_info.path[i].caps = - le16_to_cpu(info_v11->extdispconninfo.path[i].caps); + (unsigned short)le16_to_cpu(info_v11->extdispconninfo.path[i].caps); } info->ext_disp_conn_info.checksum = info_v11->extdispconninfo.checksum; info->dp0_ext_hdmi_slv_addr = info_v11->dp0_retimer_set.HdmiSlvAddr; - info->dp0_ext_hdmi_reg_num = info_v11->dp0_retimer_set.HdmiRegNum; + info->dp0_ext_hdmi_reg_num = min_t(u8, info_v11->dp0_retimer_set.HdmiRegNum, + ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings)); for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) { info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index = info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val = info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal; } - info->dp0_ext_hdmi_6g_reg_num = info_v11->dp0_retimer_set.Hdmi6GRegNum; + info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp0_retimer_set.Hdmi6GRegNum, + ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings)); for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) { info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index = info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; @@ -2589,14 +2714,16 @@ static enum bp_result get_integrated_info_v11( } info->dp1_ext_hdmi_slv_addr = info_v11->dp1_retimer_set.HdmiSlvAddr; - info->dp1_ext_hdmi_reg_num = info_v11->dp1_retimer_set.HdmiRegNum; + info->dp1_ext_hdmi_reg_num = min_t(u8, info_v11->dp1_retimer_set.HdmiRegNum, + ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings)); for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) { info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index = info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val = info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal; } - info->dp1_ext_hdmi_6g_reg_num = info_v11->dp1_retimer_set.Hdmi6GRegNum; + info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp1_retimer_set.Hdmi6GRegNum, + ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings)); for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) { info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index = info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; @@ -2605,14 +2732,16 @@ static enum bp_result get_integrated_info_v11( } info->dp2_ext_hdmi_slv_addr = info_v11->dp2_retimer_set.HdmiSlvAddr; - info->dp2_ext_hdmi_reg_num = info_v11->dp2_retimer_set.HdmiRegNum; + info->dp2_ext_hdmi_reg_num = min_t(u8, info_v11->dp2_retimer_set.HdmiRegNum, + ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings)); for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) { info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index = info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val = info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal; } - info->dp2_ext_hdmi_6g_reg_num = info_v11->dp2_retimer_set.Hdmi6GRegNum; + info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp2_retimer_set.Hdmi6GRegNum, + ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings)); for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) { info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index = info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; @@ -2621,14 +2750,16 @@ static enum bp_result get_integrated_info_v11( } info->dp3_ext_hdmi_slv_addr = info_v11->dp3_retimer_set.HdmiSlvAddr; - info->dp3_ext_hdmi_reg_num = info_v11->dp3_retimer_set.HdmiRegNum; + info->dp3_ext_hdmi_reg_num = min_t(u8, info_v11->dp3_retimer_set.HdmiRegNum, + ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings)); for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) { info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index = info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex; info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val = info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal; } - info->dp3_ext_hdmi_6g_reg_num = info_v11->dp3_retimer_set.Hdmi6GRegNum; + info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp3_retimer_set.Hdmi6GRegNum, + ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings)); for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) { info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index = info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex; @@ -2644,15 +2775,6 @@ static enum bp_result get_integrated_info_v11( info->dentist_vco_freq = le32_to_cpu(info_v11->ulDentistVCOFreq) * 10; info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10; - for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - /* Convert [10KHz] into [KHz] */ - info->disp_clk_voltage[i].max_supported_clk = - le32_to_cpu(info_v11->sDISPCLK_Voltage[i]. - ulMaximumSupportedCLK) * 10; - info->disp_clk_voltage[i].voltage_index = - le32_to_cpu(info_v11->sDISPCLK_Voltage[i].ulVoltageIndex); - } - info->boot_up_req_display_vector = le32_to_cpu(info_v11->ulBootUpReqDisplayVector); info->boot_up_nb_voltage = @@ -2772,20 +2894,22 @@ static enum bp_result get_integrated_info_v2_1( 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); + (unsigned short)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; + info->dp0_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.HdmiRegNum, + ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings)); 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; + info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.Hdmi6GRegNum, + ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings)); 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; @@ -2793,14 +2917,16 @@ static enum bp_result get_integrated_info_v2_1( 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; + info->dp1_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.HdmiRegNum, + ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings)); 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; + info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.Hdmi6GRegNum, + ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings)); 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; @@ -2808,14 +2934,16 @@ static enum bp_result get_integrated_info_v2_1( 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; + info->dp2_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.HdmiRegNum, + ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings)); 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; + info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.Hdmi6GRegNum, + ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings)); 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; @@ -2823,14 +2951,16 @@ static enum bp_result get_integrated_info_v2_1( 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; + info->dp3_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.HdmiRegNum, + ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings)); 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; + info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.Hdmi6GRegNum, + ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings)); 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; @@ -2936,7 +3066,7 @@ static enum bp_result get_integrated_info_v2_2( 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); + (unsigned short)le16_to_cpu(info_v2_2->extdispconninfo.path[i].caps); } info->ext_disp_conn_info.checksum = @@ -2959,6 +3089,7 @@ static enum bp_result get_integrated_info_v2_2( info->edp1_info.edp_panel_bpc = info_v2_2->edp1_info.edp_panel_bpc; info->edp1_info.edp_bootup_bl_level = + info_v2_2->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); @@ -3004,7 +3135,6 @@ static enum bp_result construct_integrated_info( struct atom_data_revision revision; int32_t i; - int32_t j; if (!info) return result; @@ -3106,14 +3236,6 @@ static enum bp_result construct_integrated_info( DC_LOG_BIOS("driver forced fixdpvoltageswing = %d\n", info->ext_disp_conn_info.fixdpvoltageswing); } } - /* Sort voltage table from low to high*/ - for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { - for (j = i; j > 0; --j) { - if (info->disp_clk_voltage[j].max_supported_clk < - info->disp_clk_voltage[j-1].max_supported_clk) - swap(info->disp_clk_voltage[j-1], info->disp_clk_voltage[j]); - } - } return result; } @@ -3196,7 +3318,7 @@ static struct integrated_info *bios_parser_create_integrated_info( struct bios_parser *bp = BP_FROM_DCB(dcb); struct integrated_info *info; - info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL); + info = kzalloc_obj(struct integrated_info); if (info == NULL) { ASSERT_CRITICAL(0); @@ -3218,6 +3340,7 @@ static enum bp_result update_slot_layout_info( { unsigned int record_offset; unsigned int j; + unsigned int n; struct atom_display_object_path_v2 *object; struct atom_bracket_layout_record *record; struct atom_common_record_header *record_header; @@ -3239,7 +3362,7 @@ static enum bp_result update_slot_layout_info( (object->disp_recordoffset) + (unsigned int)(bp->object_info_tbl_offset); - for (;;) { + for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) { record_header = (struct atom_common_record_header *) GET_IMAGE(struct atom_common_record_header, @@ -3333,6 +3456,7 @@ static enum bp_result update_slot_layout_info_v2( struct slot_layout_info *slot_layout_info) { unsigned int record_offset; + unsigned int n; struct atom_display_object_path_v3 *object; struct atom_bracket_layout_record_v2 *record; struct atom_common_record_header *record_header; @@ -3355,7 +3479,7 @@ static enum bp_result update_slot_layout_info_v2( (object->disp_recordoffset) + (unsigned int)(bp->object_info_tbl_offset); - for (;;) { + for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) { record_header = (struct atom_common_record_header *) GET_IMAGE(struct atom_common_record_header, @@ -3525,6 +3649,8 @@ static uint16_t bios_parser_pack_data_tables( struct dc_bios *dcb, void *dst) { + (void)dcb; + (void)dst; // TODO: There is data bytes alignment issue, disable it for now. return 0; } @@ -3678,6 +3804,7 @@ static const struct dc_vbios_funcs vbios_funcs = { .get_lttpr_interop = bios_parser_get_lttpr_interop, .get_connector_speed_cap_info = bios_parser_get_connector_speed_cap_info, + .get_connector_aux_info = bios_parser_get_connector_aux_info, }; static bool bios_parser2_construct( @@ -3782,7 +3909,7 @@ struct dc_bios *firmware_parser_create( { struct bios_parser *bp; - bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL); + bp = kzalloc_obj(struct bios_parser); if (!bp) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c index 8d2cf95ae739..e00dc05c2d9d 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.c @@ -37,10 +37,13 @@ uint8_t *bios_get_image(struct dc_bios *bp, uint32_t offset, uint32_t size) { - if (bp->bios && offset + size < bp->bios_size) - return bp->bios + offset; - else + if (!bp->bios) return NULL; + + if (offset > bp->bios_size || size > bp->bios_size - offset) + return NULL; + + return bp->bios + offset; } #include "reg_helper.h" diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h index ab162f2fe577..19fd7aea18f1 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_helper.h @@ -37,4 +37,9 @@ void bios_set_scratch_critical_state(struct dc_bios *bios, bool state); #define GET_IMAGE(type, offset) ((type *) bios_get_image(&bp->base, offset, sizeof(type))) +/* Upper bound on the number of records in a VBIOS record chain. Prevents + * unbounded looping if the VBIOS image is malformed and lacks a terminator. + */ +#define BIOS_MAX_NUM_RECORD 256 + #endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index 2bcae0643e61..0df84394a325 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -52,7 +52,9 @@ static void init_transmitter_control(struct bios_parser *bp); static void init_set_pixel_clock(struct bios_parser *bp); static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp); static void init_adjust_display_pll(struct bios_parser *bp); +static void init_select_crtc_source(struct bios_parser *bp); static void init_dac_encoder_control(struct bios_parser *bp); +static void init_dac_load_detection(struct bios_parser *bp); static void init_dac_output_control(struct bios_parser *bp); static void init_set_crtc_timing(struct bios_parser *bp); static void init_enable_crtc(struct bios_parser *bp); @@ -69,7 +71,9 @@ void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp) init_set_pixel_clock(bp); init_enable_spread_spectrum_on_ppll(bp); init_adjust_display_pll(bp); + init_select_crtc_source(bp); init_dac_encoder_control(bp); + init_dac_load_detection(bp); init_dac_output_control(bp); init_set_crtc_timing(bp); init_enable_crtc(bp); @@ -222,6 +226,28 @@ static enum bp_result encoder_control_dig2_v1( return result; } +static uint8_t dc_color_depth_to_atom(enum dc_color_depth color_depth) +{ + switch (color_depth) { + case COLOR_DEPTH_UNDEFINED: + return PANEL_BPC_UNDEFINE; + case COLOR_DEPTH_666: + return PANEL_6BIT_PER_COLOR; + default: + case COLOR_DEPTH_888: + return PANEL_8BIT_PER_COLOR; + case COLOR_DEPTH_101010: + return PANEL_10BIT_PER_COLOR; + case COLOR_DEPTH_121212: + return PANEL_12BIT_PER_COLOR; + case COLOR_DEPTH_141414: + dm_error("14-bit color not supported by ATOMBIOS\n"); + return PANEL_BPC_UNDEFINE; + case COLOR_DEPTH_161616: + return PANEL_16BIT_PER_COLOR; + } +} + static enum bp_result encoder_control_digx_v3( struct bios_parser *bp, struct bp_encoder_control *cntl) @@ -244,23 +270,7 @@ static enum bp_result encoder_control_digx_v3( cntl->signal, cntl->enable_dp_audio); params.ucLaneNum = (uint8_t)(cntl->lanes_number); - - switch (cntl->color_depth) { - case COLOR_DEPTH_888: - params.ucBitPerColor = PANEL_8BIT_PER_COLOR; - break; - case COLOR_DEPTH_101010: - params.ucBitPerColor = PANEL_10BIT_PER_COLOR; - break; - case COLOR_DEPTH_121212: - params.ucBitPerColor = PANEL_12BIT_PER_COLOR; - break; - case COLOR_DEPTH_161616: - params.ucBitPerColor = PANEL_16BIT_PER_COLOR; - break; - default: - break; - } + params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) result = BP_RESULT_OK; @@ -290,23 +300,7 @@ static enum bp_result encoder_control_digx_v4( cntl->signal, cntl->enable_dp_audio)); params.ucLaneNum = (uint8_t)(cntl->lanes_number); - - switch (cntl->color_depth) { - case COLOR_DEPTH_888: - params.ucBitPerColor = PANEL_8BIT_PER_COLOR; - break; - case COLOR_DEPTH_101010: - params.ucBitPerColor = PANEL_10BIT_PER_COLOR; - break; - case COLOR_DEPTH_121212: - params.ucBitPerColor = PANEL_12BIT_PER_COLOR; - break; - case COLOR_DEPTH_161616: - params.ucBitPerColor = PANEL_16BIT_PER_COLOR; - break; - default: - break; - } + params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params)) result = BP_RESULT_OK; @@ -330,23 +324,7 @@ static enum bp_result encoder_control_digx_v5( cntl->signal, cntl->enable_dp_audio)); params.ucLaneNum = (uint8_t)(cntl->lanes_number); - - switch (cntl->color_depth) { - case COLOR_DEPTH_888: - params.ucBitPerColor = PANEL_8BIT_PER_COLOR; - break; - case COLOR_DEPTH_101010: - params.ucBitPerColor = PANEL_10BIT_PER_COLOR; - break; - case COLOR_DEPTH_121212: - params.ucBitPerColor = PANEL_12BIT_PER_COLOR; - break; - case COLOR_DEPTH_161616: - params.ucBitPerColor = PANEL_16BIT_PER_COLOR; - break; - default: - break; - } + params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) switch (cntl->color_depth) { @@ -993,7 +971,7 @@ static enum bp_result set_pixel_clock_v3( allocation.sPCLKInput.usFbDiv = cpu_to_le16((uint16_t)bp_params->feedback_divider); allocation.sPCLKInput.ucFracFbDiv = - (uint8_t)bp_params->fractional_feedback_divider; + (uint8_t)(bp_params->fractional_feedback_divider / 100000); allocation.sPCLKInput.ucPostDiv = (uint8_t)bp_params->pixel_clock_post_divider; @@ -1543,8 +1521,8 @@ static enum bp_result adjust_display_pll_v2( if (pixel_clock_10KHz_in != 0) { bp_params->adjusted_pixel_clock = - div_u64(pixel_clk * pixel_clk_10_khz_out, - pixel_clock_10KHz_in); + (uint32_t)div_u64(pixel_clk * pixel_clk_10_khz_out, + pixel_clock_10KHz_in); } else { bp_params->adjusted_pixel_clock = 0; BREAK_TO_DEBUGGER(); @@ -1593,8 +1571,8 @@ static enum bp_result adjust_display_pll_v3( if (pixel_clk_10_kHz_in != 0) { bp_params->adjusted_pixel_clock = - div_u64(pixel_clk * pixel_clk_10_khz_out, - pixel_clk_10_kHz_in); + (uint32_t)div_u64(pixel_clk * pixel_clk_10_khz_out, + pixel_clk_10_kHz_in); } else { bp_params->adjusted_pixel_clock = 0; BREAK_TO_DEBUGGER(); @@ -1612,6 +1590,198 @@ static enum bp_result adjust_display_pll_v3( /******************************************************************************* ******************************************************************************** ** + ** SELECT CRTC SOURCE + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result select_crtc_source_v1( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params); +static enum bp_result select_crtc_source_v2( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params); +static enum bp_result select_crtc_source_v3( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params); + +static void init_select_crtc_source(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(SelectCRTC_Source)) { + case 1: + bp->cmd_tbl.select_crtc_source = select_crtc_source_v1; + break; + case 2: + bp->cmd_tbl.select_crtc_source = select_crtc_source_v2; + break; + case 3: + bp->cmd_tbl.select_crtc_source = select_crtc_source_v3; + break; + default: + bp->cmd_tbl.select_crtc_source = NULL; + break; + } +} + +static enum bp_result select_crtc_source_v1( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + SELECT_CRTC_SOURCE_PS_ALLOCATION params; + + if (!bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, ¶ms.ucCRTC)) + return BP_RESULT_BADINPUT; + + switch (bp_params->engine_id) { + case ENGINE_ID_DACA: + params.ucDevice = ATOM_DEVICE_CRT1_INDEX; + break; + case ENGINE_ID_DACB: + params.ucDevice = ATOM_DEVICE_CRT2_INDEX; + break; + default: + return BP_RESULT_BADINPUT; + } + + if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params)) + result = BP_RESULT_OK; + + return result; +} + +static bool select_crtc_source_v2_encoder_id( + enum engine_id engine_id, uint8_t *out_encoder_id) +{ + uint8_t encoder_id = 0; + + switch (engine_id) { + case ENGINE_ID_DIGA: + encoder_id = ASIC_INT_DIG1_ENCODER_ID; + break; + case ENGINE_ID_DIGB: + encoder_id = ASIC_INT_DIG2_ENCODER_ID; + break; + case ENGINE_ID_DIGC: + encoder_id = ASIC_INT_DIG3_ENCODER_ID; + break; + case ENGINE_ID_DIGD: + encoder_id = ASIC_INT_DIG4_ENCODER_ID; + break; + case ENGINE_ID_DIGE: + encoder_id = ASIC_INT_DIG5_ENCODER_ID; + break; + case ENGINE_ID_DIGF: + encoder_id = ASIC_INT_DIG6_ENCODER_ID; + break; + case ENGINE_ID_DIGG: + encoder_id = ASIC_INT_DIG7_ENCODER_ID; + break; + case ENGINE_ID_DACA: + encoder_id = ASIC_INT_DAC1_ENCODER_ID; + break; + case ENGINE_ID_DACB: + encoder_id = ASIC_INT_DAC2_ENCODER_ID; + break; + default: + return false; + } + + *out_encoder_id = encoder_id; + return true; +} + +static bool select_crtc_source_v2_encoder_mode( + enum signal_type signal_type, uint8_t *out_encoder_mode) +{ + uint8_t encoder_mode = 0; + + switch (signal_type) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + encoder_mode = ATOM_ENCODER_MODE_DVI; + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + encoder_mode = ATOM_ENCODER_MODE_HDMI; + break; + case SIGNAL_TYPE_LVDS: + encoder_mode = ATOM_ENCODER_MODE_LVDS; + break; + case SIGNAL_TYPE_RGB: + encoder_mode = ATOM_ENCODER_MODE_CRT; + break; + case SIGNAL_TYPE_DISPLAY_PORT: + encoder_mode = ATOM_ENCODER_MODE_DP; + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + encoder_mode = ATOM_ENCODER_MODE_DP_MST; + break; + case SIGNAL_TYPE_EDP: + encoder_mode = ATOM_ENCODER_MODE_DP; + break; + default: + return false; + } + + *out_encoder_mode = encoder_mode; + return true; +} + +static enum bp_result select_crtc_source_v2( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + SELECT_CRTC_SOURCE_PARAMETERS_V3 params; + + if (!bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, ¶ms.ucCRTC)) + return BP_RESULT_BADINPUT; + + if (!select_crtc_source_v2_encoder_id( + bp_params->engine_id, + ¶ms.ucEncoderID)) + return BP_RESULT_BADINPUT; + if (!select_crtc_source_v2_encoder_mode( + bp_params->sink_signal, + ¶ms.ucEncodeMode)) + return BP_RESULT_BADINPUT; + + if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result select_crtc_source_v3( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + SELECT_CRTC_SOURCE_PARAMETERS_V3 params; + + if (!bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, ¶ms.ucCRTC)) + return BP_RESULT_BADINPUT; + + if (!select_crtc_source_v2_encoder_id( + bp_params->engine_id, + ¶ms.ucEncoderID)) + return BP_RESULT_BADINPUT; + if (!select_crtc_source_v2_encoder_mode( + bp_params->sink_signal, + ¶ms.ucEncodeMode)) + return BP_RESULT_BADINPUT; + + params.ucDstBpc = dc_color_depth_to_atom(bp_params->color_depth); + + if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** ** DAC ENCODER CONTROL ** ******************************************************************************** @@ -1619,12 +1789,12 @@ static enum bp_result adjust_display_pll_v3( static enum bp_result dac1_encoder_control_v1( struct bios_parser *bp, - bool enable, + enum bp_encoder_control_action action, uint32_t pixel_clock, uint8_t dac_standard); static enum bp_result dac2_encoder_control_v1( struct bios_parser *bp, - bool enable, + enum bp_encoder_control_action action, uint32_t pixel_clock, uint8_t dac_standard); @@ -1650,12 +1820,14 @@ static void init_dac_encoder_control(struct bios_parser *bp) static void dac_encoder_control_prepare_params( DAC_ENCODER_CONTROL_PS_ALLOCATION *params, - bool enable, + enum bp_encoder_control_action action, uint32_t pixel_clock, uint8_t dac_standard) { params->ucDacStandard = dac_standard; - if (enable) + if (action == ENCODER_CONTROL_INIT) + params->ucAction = ATOM_ENCODER_INIT; + else if (action == ENCODER_CONTROL_ENABLE) params->ucAction = ATOM_ENABLE; else params->ucAction = ATOM_DISABLE; @@ -1668,7 +1840,7 @@ static void dac_encoder_control_prepare_params( static enum bp_result dac1_encoder_control_v1( struct bios_parser *bp, - bool enable, + enum bp_encoder_control_action action, uint32_t pixel_clock, uint8_t dac_standard) { @@ -1677,7 +1849,7 @@ static enum bp_result dac1_encoder_control_v1( dac_encoder_control_prepare_params( ¶ms, - enable, + action, pixel_clock, dac_standard); @@ -1689,7 +1861,7 @@ static enum bp_result dac1_encoder_control_v1( static enum bp_result dac2_encoder_control_v1( struct bios_parser *bp, - bool enable, + enum bp_encoder_control_action action, uint32_t pixel_clock, uint8_t dac_standard) { @@ -1698,7 +1870,7 @@ static enum bp_result dac2_encoder_control_v1( dac_encoder_control_prepare_params( ¶ms, - enable, + action, pixel_clock, dac_standard); @@ -1711,6 +1883,96 @@ static enum bp_result dac2_encoder_control_v1( /******************************************************************************* ******************************************************************************** ** + ** DAC LOAD DETECTION + ** + ******************************************************************************** + *******************************************************************************/ + +static enum bp_result dac_load_detection_v1( + struct bios_parser *bp, + struct bp_load_detection_parameters *bp_params); + +static enum bp_result dac_load_detection_v3( + struct bios_parser *bp, + struct bp_load_detection_parameters *bp_params); + +static void init_dac_load_detection(struct bios_parser *bp) +{ + switch (BIOS_CMD_TABLE_PARA_REVISION(DAC_LoadDetection)) { + case 1: + case 2: + bp->cmd_tbl.dac_load_detection = dac_load_detection_v1; + break; + case 3: + default: + bp->cmd_tbl.dac_load_detection = dac_load_detection_v3; + break; + } +} + +static void dac_load_detect_prepare_params( + struct _DAC_LOAD_DETECTION_PS_ALLOCATION *params, + enum engine_id engine_id, + uint16_t device_id, + uint8_t misc) +{ + uint8_t dac_type = ENGINE_ID_DACA; + + if (engine_id == ENGINE_ID_DACB) + dac_type = ATOM_DAC_B; + + params->sDacload.usDeviceID = cpu_to_le16(device_id); + params->sDacload.ucDacType = dac_type; + params->sDacload.ucMisc = misc; +} + +static enum bp_result dac_load_detection_v1( + struct bios_parser *bp, + struct bp_load_detection_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + DAC_LOAD_DETECTION_PS_ALLOCATION params; + + dac_load_detect_prepare_params( + ¶ms, + bp_params->engine_id, + bp_params->device_id, + 0); + + if (EXEC_BIOS_CMD_TABLE(DAC_LoadDetection, params)) + result = BP_RESULT_OK; + + return result; +} + +static enum bp_result dac_load_detection_v3( + struct bios_parser *bp, + struct bp_load_detection_parameters *bp_params) +{ + enum bp_result result = BP_RESULT_FAILURE; + DAC_LOAD_DETECTION_PS_ALLOCATION params; + + uint8_t misc = 0; + + if (bp_params->device_id == ATOM_DEVICE_CV_SUPPORT || + bp_params->device_id == ATOM_DEVICE_TV1_SUPPORT) + misc = DAC_LOAD_MISC_YPrPb; + + dac_load_detect_prepare_params( + ¶ms, + bp_params->engine_id, + bp_params->device_id, + misc); + + if (EXEC_BIOS_CMD_TABLE(DAC_LoadDetection, params)) + result = BP_RESULT_OK; + + return result; +} + +/******************************************************************************* + ******************************************************************************** + ** ** DAC OUTPUT CONTROL ** ******************************************************************************** @@ -2258,6 +2520,7 @@ static enum bp_result external_encoder_control_v3( cpu_to_le16((uint16_t)cntl->connector_obj_id.id); break; case EXTERNAL_ENCODER_CONTROL_SETUP: + case EXTERNAL_ENCODER_CONTROL_ENABLE: /* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in * 10KHz * output display device pixel clock frequency in unit of 10KHz. @@ -2274,26 +2537,24 @@ static enum bp_result external_encoder_control_v3( if (is_input_signal_dp) { /* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz, * only valid in encoder setup with DP mode. */ - if (LINK_RATE_HIGH == cntl->link_rate) - cntl_params->ucConfig |= 1; + if (cntl->link_rate == LINK_RATE_LOW) + cntl_params->ucConfig |= + EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_1_62GHZ; + else if (cntl->link_rate == LINK_RATE_HIGH) + cntl_params->ucConfig |= + EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; + else + dm_error("Link rate not supported by external encoder"); + /* output color depth Indicate encoder data bpc format * in DP mode, only valid in encoder setup in DP mode. */ - cntl_params->ucBitPerColor = - (uint8_t)(cntl->color_depth); + cntl_params->ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); } /* Indicate how many lanes used by external encoder, only valid * in encoder setup and enableoutput. */ cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number); break; - case EXTERNAL_ENCODER_CONTROL_ENABLE: - cntl_params->usPixelClock = - cpu_to_le16((uint16_t)(cntl->pixel_clock / 10)); - cntl_params->ucEncoderMode = - (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom( - cntl->signal, false); - cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number; - break; default: break; } @@ -2401,8 +2662,8 @@ static enum bp_result set_dce_clock_v2_1( !cmd->dc_clock_type_to_atom(bp_params->clock_type, &atom_clock_type)) return BP_RESULT_BADINPUT; - params.asParam.ucDCEClkSrc = atom_pll_id; - params.asParam.ucDCEClkType = atom_clock_type; + params.asParam.ucDCEClkSrc = (uint8_t)atom_pll_id; + params.asParam.ucDCEClkType = (uint8_t)atom_clock_type; if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) { if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK) diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.h b/drivers/gpu/drm/amd/display/dc/bios/command_table.h index ad533775e724..78bdbcaa61c8 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.h +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.h @@ -52,14 +52,17 @@ struct cmd_tbl { enum bp_result (*adjust_display_pll)( struct bios_parser *bp, struct bp_adjust_pixel_clock_parameters *bp_params); + enum bp_result (*select_crtc_source)( + struct bios_parser *bp, + struct bp_crtc_source_select *bp_params); enum bp_result (*dac1_encoder_control)( struct bios_parser *bp, - bool enable, + enum bp_encoder_control_action action, uint32_t pixel_clock, uint8_t dac_standard); enum bp_result (*dac2_encoder_control)( struct bios_parser *bp, - bool enable, + enum bp_encoder_control_action action, uint32_t pixel_clock, uint8_t dac_standard); enum bp_result (*dac1_output_control)( @@ -68,6 +71,9 @@ struct cmd_tbl { enum bp_result (*dac2_output_control)( struct bios_parser *bp, bool enable); + enum bp_result (*dac_load_detection)( + struct bios_parser *bp, + struct bp_load_detection_parameters *bp_params); enum bp_result (*set_crtc_timing)( struct bios_parser *bp, struct bp_hw_crtc_timing_parameters *bp_params); diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index 7d18f372ce7a..5bca5e534277 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -101,7 +101,6 @@ static void init_dig_encoder_control(struct bios_parser *bp) bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v1_5; break; default: - dm_output_to_console("Don't have dig_encoder_control for v%d\n", version); bp->cmd_tbl.dig_encoder_control = encoder_control_fallback; break; } @@ -210,6 +209,7 @@ static enum bp_result encoder_control_fallback( ****************************************************************************** *****************************************************************************/ + static enum bp_result transmitter_control_v1_6( struct bios_parser *bp, struct bp_transmitter_control *cntl); @@ -238,7 +238,6 @@ static void init_transmitter_control(struct bios_parser *bp) bp->cmd_tbl.transmitter_control = transmitter_control_v1_7; break; default: - dm_output_to_console("Don't have transmitter_control for v%d\n", crev); bp->cmd_tbl.transmitter_control = transmitter_control_fallback; break; } @@ -325,6 +324,21 @@ static void transmitter_control_dmcub_v1_7( dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); } +static struct dc_link *get_link_by_phy_id(struct dc *p_dc, uint32_t phy_id) +{ + struct dc_link *link = NULL; + + // Get Transition Bitmask from dc_link structure associated with PHY + for (uint8_t link_id = 0; link_id < MAX_LINKS; link_id++) { + if (phy_id == p_dc->links[link_id]->link_enc->transmitter) { + link = p_dc->links[link_id]; + break; + } + } + + return link; +} + static enum bp_result transmitter_control_v1_7( struct bios_parser *bp, struct bp_transmitter_control *cntl) @@ -357,13 +371,50 @@ static enum bp_result transmitter_control_v1_7( if (cntl->action == TRANSMITTER_CONTROL_ENABLE || cntl->action == TRANSMITTER_CONTROL_ACTIAVATE || cntl->action == TRANSMITTER_CONTROL_DEACTIVATE) { + if (dc_is_hdmi_frl_signal(cntl->signal)) + DC_LOG_BIOS("%s:dig_v1_7.symclk_units.symclk_Hz = %d\n", + __func__, dig_v1_7.symclk_units.symclk_Hz); + else DC_LOG_BIOS("%s:dig_v1_7.symclk_units.symclk_10khz = %d\n", __func__, dig_v1_7.symclk_units.symclk_10khz); } if (bp->base.ctx->dc->ctx->dmub_srv && bp->base.ctx->dc->debug.dmub_command_table) { + struct dm_process_phy_transition_init_params process_phy_transition_init_params = {0}; + struct dc_link *link = get_link_by_phy_id(bp->base.ctx->dc, dig_v1_7.phyid); + bool is_phy_transition_interlock_allowed = false; + uint8_t action = dig_v1_7.action; + + if (link) { + if (link->phy_transition_bitmask && + (action == TRANSMITTER_CONTROL_ENABLE || action == TRANSMITTER_CONTROL_DISABLE)) { + is_phy_transition_interlock_allowed = true; + + // Prepare input parameters for processing ACPI retimers + process_phy_transition_init_params.action = action; + process_phy_transition_init_params.display_port_lanes_count = cntl->lanes_number; + process_phy_transition_init_params.phy_id = dig_v1_7.phyid; + process_phy_transition_init_params.signal = cntl->signal; + process_phy_transition_init_params.sym_clock_10khz = dig_v1_7.symclk_units.symclk_10khz; + process_phy_transition_init_params.display_port_link_rate = link->cur_link_settings.link_rate; + process_phy_transition_init_params.transition_bitmask = link->phy_transition_bitmask; + process_phy_transition_init_params.hdmi_frl_num_lanes = link->frl_link_settings.frl_num_lanes; + process_phy_transition_init_params.hdmi_frl_link_rate = link->frl_link_settings.frl_link_rate; + } + dig_v1_7.skip_phy_ssc_reduction = link->wa_flags.skip_phy_ssc_reduction; + } + + // Handle PRE_OFF_TO_ON: Process ACPI PHY Transition Interlock + if (is_phy_transition_interlock_allowed && action == TRANSMITTER_CONTROL_ENABLE) + dm_acpi_process_phy_transition_interlock(bp->base.ctx, process_phy_transition_init_params); + transmitter_control_dmcub_v1_7(bp->base.ctx->dmub_srv, &dig_v1_7); + + // Handle POST_ON_TO_OFF: Process ACPI PHY Transition Interlock + if (is_phy_transition_interlock_allowed && action == TRANSMITTER_CONTROL_DISABLE) + dm_acpi_process_phy_transition_interlock(bp->base.ctx, process_phy_transition_init_params); + return BP_RESULT_OK; } @@ -408,8 +459,6 @@ static void init_set_pixel_clock(struct bios_parser *bp) bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7; break; default: - dm_output_to_console("Don't have set_pixel_clock for v%d\n", - BIOS_CMD_TABLE_PARA_REVISION(setpixelclock)); bp->cmd_tbl.set_pixel_clock = set_pixel_clock_fallback; break; } @@ -554,7 +603,6 @@ static void init_set_crtc_timing(struct bios_parser *bp) set_crtc_using_dtd_timing_v3; break; default: - dm_output_to_console("Don't have set_crtc_timing for v%d\n", dtd_version); bp->cmd_tbl.set_crtc_timing = NULL; break; } @@ -671,8 +719,6 @@ static void init_enable_crtc(struct bios_parser *bp) bp->cmd_tbl.enable_crtc = enable_crtc_v1; break; default: - dm_output_to_console("Don't have enable_crtc for v%d\n", - BIOS_CMD_TABLE_PARA_REVISION(enablecrtc)); bp->cmd_tbl.enable_crtc = NULL; break; } @@ -743,6 +789,8 @@ static enum bp_result external_encoder_control_v3( struct bios_parser *bp, struct bp_external_encoder_control *cntl) { + (void)bp; + (void)cntl; /* TODO */ return BP_RESULT_OK; } @@ -864,8 +912,6 @@ static void init_set_dce_clock(struct bios_parser *bp) bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1; break; default: - dm_output_to_console("Don't have set_dce_clock for v%d\n", - BIOS_CMD_TABLE_PARA_REVISION(setdceclock)); bp->cmd_tbl.set_dce_clock = NULL; break; } @@ -889,8 +935,8 @@ static enum bp_result set_dce_clock_v2_1( &atom_clock_type)) return BP_RESULT_BADINPUT; - params.param.dceclksrc = atom_pll_id; - params.param.dceclktype = atom_clock_type; + params.param.dceclksrc = (uint8_t)atom_pll_id; + params.param.dceclktype = (uint8_t)atom_clock_type; if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) { if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK) @@ -1046,3 +1092,4 @@ void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp) init_enable_lvtma_control(bp); } + diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c index e317a3615147..91bc8a06e2cf 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c @@ -293,3 +293,107 @@ uint8_t dal_cmd_table_helper_encoder_id_to_atom( return ENCODER_OBJECT_ID_NONE; } } + +uint8_t phy_id_to_atom(enum transmitter t) +{ + uint8_t atom_phy_id; + + switch (t) { + case TRANSMITTER_UNIPHY_A: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + case TRANSMITTER_UNIPHY_B: + atom_phy_id = ATOM_PHY_ID_UNIPHYB; + break; + case TRANSMITTER_UNIPHY_C: + atom_phy_id = ATOM_PHY_ID_UNIPHYC; + break; + case TRANSMITTER_UNIPHY_D: + atom_phy_id = ATOM_PHY_ID_UNIPHYD; + break; + case TRANSMITTER_UNIPHY_E: + atom_phy_id = ATOM_PHY_ID_UNIPHYE; + break; + case TRANSMITTER_UNIPHY_F: + atom_phy_id = ATOM_PHY_ID_UNIPHYF; + break; + case TRANSMITTER_UNIPHY_G: + atom_phy_id = ATOM_PHY_ID_UNIPHYG; + break; + default: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + } + return atom_phy_id; +} + +uint8_t clock_source_id_to_atom_phy_clk_src_id( + enum clock_source_id id) +{ + uint8_t atom_phy_clk_src_id = 0; + + switch (id) { + case CLOCK_SOURCE_ID_PLL0: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; + break; + case CLOCK_SOURCE_ID_PLL1: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + case CLOCK_SOURCE_ID_PLL2: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; + break; + case CLOCK_SOURCE_ID_EXTERNAL: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; + break; + default: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + } + + return atom_phy_clk_src_id >> 2; +} + +bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) +{ + bool result = false; + + if (atom_engine_id != NULL) + switch (id) { + case ENGINE_ID_DIGA: + *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGB: + *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGC: + *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGD: + *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGE: + *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGF: + *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGG: + *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DACA: + *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; + result = true; + break; + default: + break; + } + + return result; +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h index dfd30aaf4032..547700e119a6 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h @@ -59,4 +59,12 @@ uint8_t dal_cmd_table_helper_transmitter_bp_to_atom( uint8_t dal_cmd_table_helper_encoder_id_to_atom( enum encoder_id id); + +uint8_t phy_id_to_atom(enum transmitter t); + +uint8_t clock_source_id_to_atom_phy_clk_src_id( + enum clock_source_id id); + +bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c index 73458e295103..902f06ac43c6 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -82,13 +82,15 @@ bool dal_bios_parser_init_cmd_tbl_helper2( case DCN_VERSION_3_21: case DCN_VERSION_3_5: case DCN_VERSION_3_51: + case DCN_VERSION_3_6: case DCN_VERSION_4_01: + case DCN_VERSION_4_2: + case DCN_VERSION_4_2B: *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; default: - /* Unsupported DCE */ - BREAK_TO_DEBUGGER(); + *h = dal_cmd_tbl_helper_dce112_get_table2(); return false; } } diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c index 11bf247bb180..cec61c9d7263 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c @@ -31,39 +31,6 @@ #include "../command_table_helper.h" -static uint8_t phy_id_to_atom(enum transmitter t) -{ - uint8_t atom_phy_id; - - switch (t) { - case TRANSMITTER_UNIPHY_A: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - case TRANSMITTER_UNIPHY_B: - atom_phy_id = ATOM_PHY_ID_UNIPHYB; - break; - case TRANSMITTER_UNIPHY_C: - atom_phy_id = ATOM_PHY_ID_UNIPHYC; - break; - case TRANSMITTER_UNIPHY_D: - atom_phy_id = ATOM_PHY_ID_UNIPHYD; - break; - case TRANSMITTER_UNIPHY_E: - atom_phy_id = ATOM_PHY_ID_UNIPHYE; - break; - case TRANSMITTER_UNIPHY_F: - atom_phy_id = ATOM_PHY_ID_UNIPHYF; - break; - case TRANSMITTER_UNIPHY_G: - atom_phy_id = ATOM_PHY_ID_UNIPHYG; - break; - default: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - } - return atom_phy_id; -} - static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) { uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; @@ -94,32 +61,6 @@ static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) return atom_dig_mode; } -static uint8_t clock_source_id_to_atom_phy_clk_src_id( - enum clock_source_id id) -{ - uint8_t atom_phy_clk_src_id = 0; - - switch (id) { - case CLOCK_SOURCE_ID_PLL0: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; - break; - case CLOCK_SOURCE_ID_PLL1: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - case CLOCK_SOURCE_ID_PLL2: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; - break; - case CLOCK_SOURCE_ID_EXTERNAL: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; - break; - default: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - } - - return atom_phy_clk_src_id >> 2; -} - static uint8_t hpd_sel_to_atom(enum hpd_source_id id) { uint8_t atom_hpd_sel = 0; @@ -153,6 +94,7 @@ static uint8_t hpd_sel_to_atom(enum hpd_source_id id) static uint8_t dig_encoder_sel_to_atom(enum engine_id id) { + (void)id; /* On any ASIC after DCE80, we manually program the DIG_FE * selection (see connect_dig_be_to_fe function of the link * encoder), so translation should always return 0 (no FE). @@ -207,51 +149,6 @@ static bool clock_source_id_to_atom( return result; } -static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) -{ - bool result = false; - - if (atom_engine_id != NULL) - switch (id) { - case ENGINE_ID_DIGA: - *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGB: - *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGC: - *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGD: - *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGE: - *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGF: - *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGG: - *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DACA: - *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; - result = true; - break; - default: - break; - } - - return result; -} - static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) { uint8_t atom_action = 0; diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c index 755b6e33140a..642bc52dcc40 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c @@ -29,40 +29,9 @@ #include "include/bios_parser_types.h" -#include "../command_table_helper2.h" - -static uint8_t phy_id_to_atom(enum transmitter t) -{ - uint8_t atom_phy_id; +#include "../command_table_helper.h" - switch (t) { - case TRANSMITTER_UNIPHY_A: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - case TRANSMITTER_UNIPHY_B: - atom_phy_id = ATOM_PHY_ID_UNIPHYB; - break; - case TRANSMITTER_UNIPHY_C: - atom_phy_id = ATOM_PHY_ID_UNIPHYC; - break; - case TRANSMITTER_UNIPHY_D: - atom_phy_id = ATOM_PHY_ID_UNIPHYD; - break; - case TRANSMITTER_UNIPHY_E: - atom_phy_id = ATOM_PHY_ID_UNIPHYE; - break; - case TRANSMITTER_UNIPHY_F: - atom_phy_id = ATOM_PHY_ID_UNIPHYF; - break; - case TRANSMITTER_UNIPHY_G: - atom_phy_id = ATOM_PHY_ID_UNIPHYG; - break; - default: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - } - return atom_phy_id; -} +#include "../command_table_helper2.h" static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) { @@ -80,6 +49,9 @@ static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) case SIGNAL_TYPE_HDMI_TYPE_A: atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_HDMI; break; + case SIGNAL_TYPE_HDMI_FRL: + atom_dig_mode = 4; + break; case SIGNAL_TYPE_DISPLAY_PORT_MST: atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP_MST; break; @@ -91,32 +63,6 @@ static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) return atom_dig_mode; } -static uint8_t clock_source_id_to_atom_phy_clk_src_id( - enum clock_source_id id) -{ - uint8_t atom_phy_clk_src_id = 0; - - switch (id) { - case CLOCK_SOURCE_ID_PLL0: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; - break; - case CLOCK_SOURCE_ID_PLL1: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - case CLOCK_SOURCE_ID_PLL2: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; - break; - case CLOCK_SOURCE_ID_EXTERNAL: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; - break; - default: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - } - - return atom_phy_clk_src_id >> 2; -} - static uint8_t hpd_sel_to_atom(enum hpd_source_id id) { uint8_t atom_hpd_sel = 0; @@ -150,6 +96,7 @@ static uint8_t hpd_sel_to_atom(enum hpd_source_id id) static uint8_t dig_encoder_sel_to_atom(enum engine_id id) { + (void)id; /* On any ASIC after DCE80, we manually program the DIG_FE * selection (see connect_dig_be_to_fe function of the link * encoder), so translation should always return 0 (no FE). @@ -209,51 +156,6 @@ static bool clock_source_id_to_atom( return result; } -static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) -{ - bool result = false; - - if (atom_engine_id != NULL) - switch (id) { - case ENGINE_ID_DIGA: - *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGB: - *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGC: - *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGD: - *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGE: - *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGF: - *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGG: - *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DACA: - *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; - result = true; - break; - default: - break; - } - - return result; -} - static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) { uint8_t atom_action = 0; diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c index 06b4f7fa4a50..41d11d8410a0 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c @@ -31,39 +31,6 @@ #include "../command_table_helper.h" -static uint8_t phy_id_to_atom(enum transmitter t) -{ - uint8_t atom_phy_id; - - switch (t) { - case TRANSMITTER_UNIPHY_A: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - case TRANSMITTER_UNIPHY_B: - atom_phy_id = ATOM_PHY_ID_UNIPHYB; - break; - case TRANSMITTER_UNIPHY_C: - atom_phy_id = ATOM_PHY_ID_UNIPHYC; - break; - case TRANSMITTER_UNIPHY_D: - atom_phy_id = ATOM_PHY_ID_UNIPHYD; - break; - case TRANSMITTER_UNIPHY_E: - atom_phy_id = ATOM_PHY_ID_UNIPHYE; - break; - case TRANSMITTER_UNIPHY_F: - atom_phy_id = ATOM_PHY_ID_UNIPHYF; - break; - case TRANSMITTER_UNIPHY_G: - atom_phy_id = ATOM_PHY_ID_UNIPHYG; - break; - default: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - } - return atom_phy_id; -} - static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) { uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP; @@ -80,6 +47,9 @@ static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) case SIGNAL_TYPE_HDMI_TYPE_A: atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_HDMI; break; + case SIGNAL_TYPE_HDMI_FRL: + atom_dig_mode = 4; + break; case SIGNAL_TYPE_DISPLAY_PORT_MST: atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP_MST; break; @@ -91,32 +61,6 @@ static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) return atom_dig_mode; } -static uint8_t clock_source_id_to_atom_phy_clk_src_id( - enum clock_source_id id) -{ - uint8_t atom_phy_clk_src_id = 0; - - switch (id) { - case CLOCK_SOURCE_ID_PLL0: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; - break; - case CLOCK_SOURCE_ID_PLL1: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - case CLOCK_SOURCE_ID_PLL2: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; - break; - case CLOCK_SOURCE_ID_EXTERNAL: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; - break; - default: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - } - - return atom_phy_clk_src_id >> 2; -} - static uint8_t hpd_sel_to_atom(enum hpd_source_id id) { uint8_t atom_hpd_sel = 0; @@ -150,6 +94,7 @@ static uint8_t hpd_sel_to_atom(enum hpd_source_id id) static uint8_t dig_encoder_sel_to_atom(enum engine_id id) { + (void)id; /* On any ASIC after DCE80, we manually program the DIG_FE * selection (see connect_dig_be_to_fe function of the link * encoder), so translation should always return 0 (no FE). @@ -209,51 +154,6 @@ static bool clock_source_id_to_atom( return result; } -static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) -{ - bool result = false; - - if (atom_engine_id != NULL) - switch (id) { - case ENGINE_ID_DIGA: - *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGB: - *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGC: - *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGD: - *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGE: - *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGF: - *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGG: - *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DACA: - *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; - result = true; - break; - default: - break; - } - - return result; -} - static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) { uint8_t atom_action = 0; diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.c b/drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.c index 710221b4f5c5..01ccc803040c 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.c @@ -58,51 +58,6 @@ static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) return atom_action; } -static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) -{ - bool result = false; - - if (atom_engine_id != NULL) - switch (id) { - case ENGINE_ID_DIGA: - *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGB: - *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGC: - *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGD: - *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGE: - *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGF: - *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGG: - *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DACA: - *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; - result = true; - break; - default: - break; - } - - return result; -} - static bool clock_source_id_to_atom( enum clock_source_id id, uint32_t *atom_pll_id) @@ -149,32 +104,6 @@ static bool clock_source_id_to_atom( return result; } -static uint8_t clock_source_id_to_atom_phy_clk_src_id( - enum clock_source_id id) -{ - uint8_t atom_phy_clk_src_id = 0; - - switch (id) { - case CLOCK_SOURCE_ID_PLL0: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; - break; - case CLOCK_SOURCE_ID_PLL1: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - case CLOCK_SOURCE_ID_PLL2: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; - break; - case CLOCK_SOURCE_ID_EXTERNAL: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; - break; - default: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - } - - return atom_phy_clk_src_id >> 2; -} - static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) { uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; @@ -270,39 +199,6 @@ static uint8_t dig_encoder_sel_to_atom(enum engine_id id) return atom_dig_encoder_sel; } -static uint8_t phy_id_to_atom(enum transmitter t) -{ - uint8_t atom_phy_id; - - switch (t) { - case TRANSMITTER_UNIPHY_A: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - case TRANSMITTER_UNIPHY_B: - atom_phy_id = ATOM_PHY_ID_UNIPHYB; - break; - case TRANSMITTER_UNIPHY_C: - atom_phy_id = ATOM_PHY_ID_UNIPHYC; - break; - case TRANSMITTER_UNIPHY_D: - atom_phy_id = ATOM_PHY_ID_UNIPHYD; - break; - case TRANSMITTER_UNIPHY_E: - atom_phy_id = ATOM_PHY_ID_UNIPHYE; - break; - case TRANSMITTER_UNIPHY_F: - atom_phy_id = ATOM_PHY_ID_UNIPHYF; - break; - case TRANSMITTER_UNIPHY_G: - atom_phy_id = ATOM_PHY_ID_UNIPHYG; - break; - default: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - } - return atom_phy_id; -} - static uint8_t disp_power_gating_action_to_atom( enum bp_pipe_control_action action) { diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c index 8b30b558cf1f..2ec5264536c7 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c +++ b/drivers/gpu/drm/amd/display/dc/bios/dce80/command_table_helper_dce80.c @@ -58,51 +58,6 @@ static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) return atom_action; } -static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) -{ - bool result = false; - - if (atom_engine_id != NULL) - switch (id) { - case ENGINE_ID_DIGA: - *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGB: - *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGC: - *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGD: - *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGE: - *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGF: - *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DIGG: - *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; - result = true; - break; - case ENGINE_ID_DACA: - *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; - result = true; - break; - default: - break; - } - - return result; -} - static bool clock_source_id_to_atom( enum clock_source_id id, uint32_t *atom_pll_id) @@ -149,32 +104,6 @@ static bool clock_source_id_to_atom( return result; } -static uint8_t clock_source_id_to_atom_phy_clk_src_id( - enum clock_source_id id) -{ - uint8_t atom_phy_clk_src_id = 0; - - switch (id) { - case CLOCK_SOURCE_ID_PLL0: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; - break; - case CLOCK_SOURCE_ID_PLL1: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - case CLOCK_SOURCE_ID_PLL2: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; - break; - case CLOCK_SOURCE_ID_EXTERNAL: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; - break; - default: - atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; - break; - } - - return atom_phy_clk_src_id >> 2; -} - static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) { uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; @@ -270,39 +199,6 @@ static uint8_t dig_encoder_sel_to_atom(enum engine_id id) return atom_dig_encoder_sel; } -static uint8_t phy_id_to_atom(enum transmitter t) -{ - uint8_t atom_phy_id; - - switch (t) { - case TRANSMITTER_UNIPHY_A: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - case TRANSMITTER_UNIPHY_B: - atom_phy_id = ATOM_PHY_ID_UNIPHYB; - break; - case TRANSMITTER_UNIPHY_C: - atom_phy_id = ATOM_PHY_ID_UNIPHYC; - break; - case TRANSMITTER_UNIPHY_D: - atom_phy_id = ATOM_PHY_ID_UNIPHYD; - break; - case TRANSMITTER_UNIPHY_E: - atom_phy_id = ATOM_PHY_ID_UNIPHYE; - break; - case TRANSMITTER_UNIPHY_F: - atom_phy_id = ATOM_PHY_ID_UNIPHYF; - break; - case TRANSMITTER_UNIPHY_G: - atom_phy_id = ATOM_PHY_ID_UNIPHYG; - break; - default: - atom_phy_id = ATOM_PHY_ID_UNIPHYA; - break; - } - return atom_phy_id; -} - static uint8_t disp_power_gating_action_to_atom( enum bp_pipe_control_action action) { |
