[PATCH 16/27] drm/amd/display: vbios data table packing

Rodrigo Siqueira Rodrigo.Siqueira at amd.com
Fri May 15 18:13:03 UTC 2020


From: Jake Wang <haonan.wang2 at amd.com>

[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 at amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng at amd.com>
Acked-by: Nicholas Kazlauskas <Nicholas.Kazlauskas at amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira at amd.com>
---
 .../drm/amd/display/dc/bios/bios_parser2.c    | 98 +++++++++++++++++++
 .../gpu/drm/amd/display/dc/dc_bios_types.h    |  4 +-
 2 files changed, 101 insertions(+), 1 deletion(-)

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 {
-- 
2.26.2



More information about the amd-gfx mailing list