diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 98 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dc_bios_types.h | 4 |
2 files changed, 101 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 37fa7b48250e..7fb62780e8cf 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1877,6 +1877,103 @@ static enum bp_result bios_get_board_layout_info( return BP_RESULT_OK; } +static uint16_t bios_parser_pack_data_tables( + struct dc_bios *dcb, + void *dst) +{ + 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; +} + static const struct dc_vbios_funcs vbios_funcs = { .get_connectors_number = bios_parser_get_connectors_number, @@ -1925,6 +2022,7 @@ static const struct dc_vbios_funcs vbios_funcs = { .bios_parser_destroy = firmware_parser_destroy, .get_board_layout_info = bios_get_board_layout_info, + .pack_data_tables = bios_parser_pack_data_tables, }; static bool bios_parser2_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h index b1dd0d60d98e..441768aa53ff 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -89,7 +89,6 @@ struct dc_vbios_funcs { bool (*is_device_id_supported)( struct dc_bios *bios, struct device_id id); - /* COMMANDS */ enum bp_result (*encoder_control)( @@ -131,6 +130,9 @@ struct dc_vbios_funcs { enum bp_result (*get_board_layout_info)( struct dc_bios *dcb, struct board_layout_info *board_layout_info); + uint16_t (*pack_data_tables)( + struct dc_bios *dcb, + void *dst); }; struct bios_registers { |