aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc/bios
diff options
context:
space:
mode:
authorJake Wang <haonan.wang2@amd.com>2020-05-05 10:02:36 -0400
committerAlex Deucher <alexander.deucher@amd.com>2020-05-28 14:00:48 -0400
commit2847642a1875bae10aa80e81dd23652acc78ccb2 (patch)
treea1cf41d9232858210d25bff25a9f348e24304da9 /drivers/gpu/drm/amd/display/dc/bios
parentdrm/amd/display: DP link layer test 4.2.1.1 fix due to specs update (diff)
downloadlinux-dev-2847642a1875bae10aa80e81dd23652acc78ccb2.tar.xz
linux-dev-2847642a1875bae10aa80e81dd23652acc78ccb2.zip
drm/amd/display: vbios data table packing
[WHY] Currently we're copying the entire bios image into vbios. Loading time for FW with entire bios(54272 bytes) is 105138us. By copying only the sections of bios we're using(4436 bytes), loading time drops to 104326us which saves us 812us. [HOW] ROM header, master data table, and all data tables will be packed in contiguous manner. The offsets for the data tables are remapped to their newly packed location. Signed-off-by: Jake Wang <haonan.wang2@amd.com> Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> Acked-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/bios')
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c98
1 files changed, 98 insertions, 0 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(