diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/4799-drm-amd-display-get-board-layout-for-edid-emulation.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.14.71/4799-drm-amd-display-get-board-layout-for-edid-emulation.patch | 583 |
1 files changed, 583 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/4799-drm-amd-display-get-board-layout-for-edid-emulation.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/4799-drm-amd-display-get-board-layout-for-edid-emulation.patch new file mode 100644 index 00000000..bfece697 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/4799-drm-amd-display-get-board-layout-for-edid-emulation.patch @@ -0,0 +1,583 @@ +From 8401f0d64d68522e6807550d5b7d38ff319b6b1a Mon Sep 17 00:00:00 2001 +From: Samson Tam <Samson.Tam@amd.com> +Date: Wed, 30 May 2018 15:44:50 -0400 +Subject: [PATCH 4799/5725] drm/amd/display: get board layout for edid + emulation + +Signed-off-by: Samson Tam <Samson.Tam@amd.com> +Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> +Acked-by: Harry Wentland <harry.wentland@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 196 ++++++++++++++++++ + drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 218 ++++++++++++++++++++- + drivers/gpu/drm/amd/display/dc/dc_bios_types.h | 4 + + .../gpu/drm/amd/display/include/grph_object_defs.h | 46 +++++ + .../gpu/drm/amd/display/include/grph_object_id.h | 11 ++ + 5 files changed, 474 insertions(+), 1 deletion(-) + +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 c7f0b27..be8a249 100644 +--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c ++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +@@ -3762,6 +3762,200 @@ static struct integrated_info *bios_parser_create_integrated_info( + return NULL; + } + ++enum bp_result update_slot_layout_info( ++ struct dc_bios *dcb, ++ unsigned int i, ++ struct slot_layout_info *slot_layout_info, ++ unsigned int record_offset) ++{ ++ unsigned int j; ++ struct bios_parser *bp; ++ ATOM_BRACKET_LAYOUT_RECORD *record; ++ ATOM_COMMON_RECORD_HEADER *record_header; ++ enum bp_result result = BP_RESULT_NORECORD; ++ ++ bp = BP_FROM_DCB(dcb); ++ record = NULL; ++ record_header = NULL; ++ ++ for (;;) { ++ ++ record_header = (ATOM_COMMON_RECORD_HEADER *) ++ GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset); ++ if (record_header == NULL) { ++ result = BP_RESULT_BADBIOSTABLE; ++ break; ++ } ++ ++ /* the end of the list */ ++ if (record_header->ucRecordType == 0xff || ++ record_header->ucRecordSize == 0) { ++ break; ++ } ++ ++ if (record_header->ucRecordType == ++ ATOM_BRACKET_LAYOUT_RECORD_TYPE && ++ sizeof(ATOM_BRACKET_LAYOUT_RECORD) ++ <= record_header->ucRecordSize) { ++ record = (ATOM_BRACKET_LAYOUT_RECORD *) ++ (record_header); ++ result = BP_RESULT_OK; ++ break; ++ } ++ ++ record_offset += record_header->ucRecordSize; ++ } ++ ++ /* return if the record not found */ ++ if (result != BP_RESULT_OK) ++ return result; ++ ++ /* get slot sizes */ ++ slot_layout_info->length = record->ucLength; ++ slot_layout_info->width = record->ucWidth; ++ ++ /* get info for each connector in the slot */ ++ slot_layout_info->num_of_connectors = record->ucConnNum; ++ for (j = 0; j < slot_layout_info->num_of_connectors; ++j) { ++ slot_layout_info->connectors[j].connector_type = ++ (enum connector_layout_type) ++ (record->asConnInfo[j].ucConnectorType); ++ switch (record->asConnInfo[j].ucConnectorType) { ++ case CONNECTOR_TYPE_DVI_D: ++ slot_layout_info->connectors[j].connector_type = ++ CONNECTOR_LAYOUT_TYPE_DVI_D; ++ slot_layout_info->connectors[j].length = ++ CONNECTOR_SIZE_DVI; ++ break; ++ ++ case CONNECTOR_TYPE_HDMI: ++ slot_layout_info->connectors[j].connector_type = ++ CONNECTOR_LAYOUT_TYPE_HDMI; ++ slot_layout_info->connectors[j].length = ++ CONNECTOR_SIZE_HDMI; ++ break; ++ ++ case CONNECTOR_TYPE_DISPLAY_PORT: ++ slot_layout_info->connectors[j].connector_type = ++ CONNECTOR_LAYOUT_TYPE_DP; ++ slot_layout_info->connectors[j].length = ++ CONNECTOR_SIZE_DP; ++ break; ++ ++ case CONNECTOR_TYPE_MINI_DISPLAY_PORT: ++ slot_layout_info->connectors[j].connector_type = ++ CONNECTOR_LAYOUT_TYPE_MINI_DP; ++ slot_layout_info->connectors[j].length = ++ CONNECTOR_SIZE_MINI_DP; ++ break; ++ ++ default: ++ slot_layout_info->connectors[j].connector_type = ++ CONNECTOR_LAYOUT_TYPE_UNKNOWN; ++ slot_layout_info->connectors[j].length = ++ CONNECTOR_SIZE_UNKNOWN; ++ } ++ ++ slot_layout_info->connectors[j].position = ++ record->asConnInfo[j].ucPosition; ++ slot_layout_info->connectors[j].connector_id = ++ object_id_from_bios_object_id( ++ record->asConnInfo[j].usConnectorObjectId); ++ } ++ return result; ++} ++ ++ ++enum bp_result get_bracket_layout_record( ++ struct dc_bios *dcb, ++ unsigned int bracket_layout_id, ++ struct slot_layout_info *slot_layout_info) ++{ ++ unsigned int i; ++ unsigned int record_offset; ++ struct bios_parser *bp; ++ enum bp_result result; ++ ATOM_OBJECT *object; ++ ATOM_OBJECT_TABLE *object_table; ++ unsigned int genericTableOffset; ++ ++ bp = BP_FROM_DCB(dcb); ++ object = NULL; ++ if (slot_layout_info == NULL) { ++ DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n"); ++ return BP_RESULT_BADINPUT; ++ } ++ ++ ++ genericTableOffset = bp->object_info_tbl_offset + ++ bp->object_info_tbl.v1_3->usMiscObjectTableOffset; ++ object_table = (ATOM_OBJECT_TABLE *) ++ GET_IMAGE(ATOM_OBJECT_TABLE, genericTableOffset); ++ if (!object_table) ++ return BP_RESULT_FAILURE; ++ ++ result = BP_RESULT_NORECORD; ++ for (i = 0; i < object_table->ucNumberOfObjects; ++i) { ++ ++ if (bracket_layout_id == ++ object_table->asObjects[i].usObjectID) { ++ ++ object = &object_table->asObjects[i]; ++ record_offset = object->usRecordOffset + ++ bp->object_info_tbl_offset; ++ ++ result = update_slot_layout_info(dcb, i, ++ slot_layout_info, record_offset); ++ break; ++ } ++ } ++ return result; ++} ++ ++static enum bp_result bios_get_board_layout_info( ++ struct dc_bios *dcb, ++ struct board_layout_info *board_layout_info) ++{ ++ unsigned int i; ++ struct bios_parser *bp; ++ enum bp_result record_result; ++ ++ const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = { ++ GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1, ++ GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2, ++ 0, 0 ++ }; ++ ++ bp = BP_FROM_DCB(dcb); ++ if (board_layout_info == NULL) { ++ DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n"); ++ return BP_RESULT_BADINPUT; ++ } ++ ++ board_layout_info->num_of_slots = 0; ++ ++ for (i = 0; i < MAX_BOARD_SLOTS; ++i) { ++ record_result = get_bracket_layout_record(dcb, ++ slot_index_to_vbios_id[i], ++ &board_layout_info->slots[i]); ++ ++ if (record_result == BP_RESULT_NORECORD && i > 0) ++ break; /* no more slots present in bios */ ++ else if (record_result != BP_RESULT_OK) ++ return record_result; /* fail */ ++ ++ ++board_layout_info->num_of_slots; ++ } ++ ++ /* all data is valid */ ++ board_layout_info->is_number_of_slots_valid = 1; ++ board_layout_info->is_slots_size_valid = 1; ++ board_layout_info->is_connector_offsets_valid = 1; ++ board_layout_info->is_connector_lengths_valid = 1; ++ ++ return BP_RESULT_OK; ++} ++ + /******************************************************************************/ + + static const struct dc_vbios_funcs vbios_funcs = { +@@ -3836,6 +4030,8 @@ static const struct dc_vbios_funcs vbios_funcs = { + .post_init = bios_parser_post_init, /* patch vbios table for mxm module by reading i2c */ + + .bios_parser_destroy = bios_parser_destroy, ++ ++ .get_board_layout_info = bios_get_board_layout_info, + }; + + static bool bios_parser_construct( +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 b8cef7a..aeb56e4 100644 +--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c ++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +@@ -43,6 +43,29 @@ + #include "bios_parser_interface.h" + + #include "bios_parser_common.h" ++ ++/* Temporarily add in defines until ObjectID.h patch is updated in a few days */ ++#ifndef GENERIC_OBJECT_ID_BRACKET_LAYOUT ++#define GENERIC_OBJECT_ID_BRACKET_LAYOUT 0x05 ++#endif /* GENERIC_OBJECT_ID_BRACKET_LAYOUT */ ++ ++#ifndef GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1 ++#define GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1 \ ++ (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\ ++ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ ++ GENERIC_OBJECT_ID_BRACKET_LAYOUT << OBJECT_ID_SHIFT) ++#endif /* GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1 */ ++ ++#ifndef GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2 ++#define GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2 \ ++ (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\ ++ GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ ++ GENERIC_OBJECT_ID_BRACKET_LAYOUT << OBJECT_ID_SHIFT) ++#endif /* GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2 */ ++ ++#define DC_LOGGER \ ++ bp->base.ctx->logger ++ + #define LAST_RECORD_TYPE 0xff + #define SMU9_SYSPLL0_ID 0 + +@@ -86,7 +109,6 @@ static struct atom_encoder_caps_record *get_encoder_cap_record( + + #define DATA_TABLES(table) (bp->master_data_tbl->listOfdatatables.table) + +- + static void destruct(struct bios_parser *bp) + { + kfree(bp->base.bios_local_image); +@@ -1854,6 +1876,198 @@ static struct integrated_info *bios_parser_create_integrated_info( + return NULL; + } + ++static enum bp_result update_slot_layout_info( ++ struct dc_bios *dcb, ++ unsigned int i, ++ struct slot_layout_info *slot_layout_info) ++{ ++ unsigned int record_offset; ++ unsigned int j; ++ struct atom_display_object_path_v2 *object; ++ struct atom_bracket_layout_record *record; ++ struct atom_common_record_header *record_header; ++ enum bp_result result; ++ struct bios_parser *bp; ++ struct object_info_table *tbl; ++ struct display_object_info_table_v1_4 *v1_4; ++ ++ record = NULL; ++ record_header = NULL; ++ result = BP_RESULT_NORECORD; ++ ++ bp = BP_FROM_DCB(dcb); ++ tbl = &bp->object_info_tbl; ++ v1_4 = tbl->v1_4; ++ ++ object = &v1_4->display_path[i]; ++ record_offset = (unsigned int) ++ (object->disp_recordoffset) + ++ (unsigned int)(bp->object_info_tbl_offset); ++ ++ for (;;) { ++ ++ record_header = (struct atom_common_record_header *) ++ GET_IMAGE(struct atom_common_record_header, ++ record_offset); ++ if (record_header == NULL) { ++ result = BP_RESULT_BADBIOSTABLE; ++ break; ++ } ++ ++ /* the end of the list */ ++ if (record_header->record_type == 0xff || ++ record_header->record_size == 0) { ++ break; ++ } ++ ++ if (record_header->record_type == ++ ATOM_BRACKET_LAYOUT_RECORD_TYPE && ++ sizeof(struct atom_bracket_layout_record) ++ <= record_header->record_size) { ++ record = (struct atom_bracket_layout_record *) ++ (record_header); ++ result = BP_RESULT_OK; ++ break; ++ } ++ ++ record_offset += record_header->record_size; ++ } ++ ++ /* return if the record not found */ ++ if (result != BP_RESULT_OK) ++ return result; ++ ++ /* get slot sizes */ ++ slot_layout_info->length = record->bracketlen; ++ slot_layout_info->width = record->bracketwidth; ++ ++ /* get info for each connector in the slot */ ++ slot_layout_info->num_of_connectors = record->conn_num; ++ for (j = 0; j < slot_layout_info->num_of_connectors; ++j) { ++ slot_layout_info->connectors[j].connector_type = ++ (enum connector_layout_type) ++ (record->conn_info[j].connector_type); ++ switch (record->conn_info[j].connector_type) { ++ case CONNECTOR_TYPE_DVI_D: ++ slot_layout_info->connectors[j].connector_type = ++ CONNECTOR_LAYOUT_TYPE_DVI_D; ++ slot_layout_info->connectors[j].length = ++ CONNECTOR_SIZE_DVI; ++ break; ++ ++ case CONNECTOR_TYPE_HDMI: ++ slot_layout_info->connectors[j].connector_type = ++ CONNECTOR_LAYOUT_TYPE_HDMI; ++ slot_layout_info->connectors[j].length = ++ CONNECTOR_SIZE_HDMI; ++ break; ++ ++ case CONNECTOR_TYPE_DISPLAY_PORT: ++ slot_layout_info->connectors[j].connector_type = ++ CONNECTOR_LAYOUT_TYPE_DP; ++ slot_layout_info->connectors[j].length = ++ CONNECTOR_SIZE_DP; ++ break; ++ ++ case CONNECTOR_TYPE_MINI_DISPLAY_PORT: ++ slot_layout_info->connectors[j].connector_type = ++ CONNECTOR_LAYOUT_TYPE_MINI_DP; ++ slot_layout_info->connectors[j].length = ++ CONNECTOR_SIZE_MINI_DP; ++ break; ++ ++ default: ++ slot_layout_info->connectors[j].connector_type = ++ CONNECTOR_LAYOUT_TYPE_UNKNOWN; ++ slot_layout_info->connectors[j].length = ++ CONNECTOR_SIZE_UNKNOWN; ++ } ++ ++ slot_layout_info->connectors[j].position = ++ record->conn_info[j].position; ++ slot_layout_info->connectors[j].connector_id = ++ object_id_from_bios_object_id( ++ record->conn_info[j].connectorobjid); ++ } ++ return result; ++} ++ ++ ++static enum bp_result get_bracket_layout_record( ++ struct dc_bios *dcb, ++ unsigned int bracket_layout_id, ++ struct slot_layout_info *slot_layout_info) ++{ ++ unsigned int i; ++ struct bios_parser *bp = BP_FROM_DCB(dcb); ++ enum bp_result result; ++ struct object_info_table *tbl; ++ struct display_object_info_table_v1_4 *v1_4; ++ ++ if (slot_layout_info == NULL) { ++ DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n"); ++ return BP_RESULT_BADINPUT; ++ } ++ tbl = &bp->object_info_tbl; ++ v1_4 = tbl->v1_4; ++ ++ result = BP_RESULT_NORECORD; ++ for (i = 0; i < v1_4->number_of_path; ++i) { ++ ++ if (bracket_layout_id == ++ v1_4->display_path[i].display_objid) { ++ result = update_slot_layout_info(dcb, i, ++ slot_layout_info); ++ break; ++ } ++ } ++ return result; ++} ++ ++static enum bp_result bios_get_board_layout_info( ++ struct dc_bios *dcb, ++ struct board_layout_info *board_layout_info) ++{ ++ unsigned int i; ++ struct bios_parser *bp; ++ enum bp_result record_result; ++ ++ const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = { ++ GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1, ++ GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2, ++ 0, 0 ++ }; ++ ++ bp = BP_FROM_DCB(dcb); ++ if (board_layout_info == NULL) { ++ DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n"); ++ return BP_RESULT_BADINPUT; ++ } ++ ++ board_layout_info->num_of_slots = 0; ++ ++ for (i = 0; i < MAX_BOARD_SLOTS; ++i) { ++ record_result = get_bracket_layout_record(dcb, ++ slot_index_to_vbios_id[i], ++ &board_layout_info->slots[i]); ++ ++ if (record_result == BP_RESULT_NORECORD && i > 0) ++ break; /* no more slots present in bios */ ++ else if (record_result != BP_RESULT_OK) ++ return record_result; /* fail */ ++ ++ ++board_layout_info->num_of_slots; ++ } ++ ++ /* all data is valid */ ++ board_layout_info->is_number_of_slots_valid = 1; ++ board_layout_info->is_slots_size_valid = 1; ++ board_layout_info->is_connector_offsets_valid = 1; ++ board_layout_info->is_connector_lengths_valid = 1; ++ ++ return BP_RESULT_OK; ++} ++ + static const struct dc_vbios_funcs vbios_funcs = { + .get_connectors_number = bios_parser_get_connectors_number, + +@@ -1925,6 +2139,8 @@ static const struct dc_vbios_funcs vbios_funcs = { + .bios_parser_destroy = firmware_parser_destroy, + + .get_smu_clock_info = bios_parser_get_smu_clock_info, ++ ++ .get_board_layout_info = bios_get_board_layout_info, + }; + + static bool bios_parser_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 d9b84ec..90082ba 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +@@ -198,6 +198,10 @@ struct dc_vbios_funcs { + void (*post_init)(struct dc_bios *bios); + + void (*bios_parser_destroy)(struct dc_bios **dcb); ++ ++ enum bp_result (*get_board_layout_info)( ++ struct dc_bios *dcb, ++ struct board_layout_info *board_layout_info); + }; + + struct bios_registers { +diff --git a/drivers/gpu/drm/amd/display/include/grph_object_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_defs.h +index 2941b88..58bb42e 100644 +--- a/drivers/gpu/drm/amd/display/include/grph_object_defs.h ++++ b/drivers/gpu/drm/amd/display/include/grph_object_defs.h +@@ -37,6 +37,10 @@ + * ******************************************************************** + */ + ++#define MAX_CONNECTOR_NUMBER_PER_SLOT (16) ++#define MAX_BOARD_SLOTS (4) ++#define INVALID_CONNECTOR_INDEX ((unsigned int)(-1)) ++ + /* HPD unit id - HW direct translation */ + enum hpd_source_id { + HPD_SOURCEID1 = 0, +@@ -136,5 +140,47 @@ enum sync_source { + SYNC_SOURCE_DUAL_GPU_PIN + }; + ++/* connector sizes in millimeters - from BiosParserTypes.hpp */ ++#define CONNECTOR_SIZE_DVI 40 ++#define CONNECTOR_SIZE_VGA 32 ++#define CONNECTOR_SIZE_HDMI 16 ++#define CONNECTOR_SIZE_DP 16 ++#define CONNECTOR_SIZE_MINI_DP 9 ++#define CONNECTOR_SIZE_UNKNOWN 30 ++ ++enum connector_layout_type { ++ CONNECTOR_LAYOUT_TYPE_UNKNOWN, ++ CONNECTOR_LAYOUT_TYPE_DVI_D, ++ CONNECTOR_LAYOUT_TYPE_DVI_I, ++ CONNECTOR_LAYOUT_TYPE_VGA, ++ CONNECTOR_LAYOUT_TYPE_HDMI, ++ CONNECTOR_LAYOUT_TYPE_DP, ++ CONNECTOR_LAYOUT_TYPE_MINI_DP, ++}; ++struct connector_layout_info { ++ struct graphics_object_id connector_id; ++ enum connector_layout_type connector_type; ++ unsigned int length; ++ unsigned int position; /* offset in mm from right side of the board */ ++}; ++ ++/* length and width in mm */ ++struct slot_layout_info { ++ unsigned int length; ++ unsigned int width; ++ unsigned int num_of_connectors; ++ struct connector_layout_info connectors[MAX_CONNECTOR_NUMBER_PER_SLOT]; ++}; ++ ++struct board_layout_info { ++ unsigned int num_of_slots; + ++ /* indicates valid information in bracket layout structure. */ ++ unsigned int is_number_of_slots_valid : 1; ++ unsigned int is_slots_size_valid : 1; ++ unsigned int is_connector_offsets_valid : 1; ++ unsigned int is_connector_lengths_valid : 1; ++ ++ struct slot_layout_info slots[MAX_BOARD_SLOTS]; ++}; + #endif +diff --git a/drivers/gpu/drm/amd/display/include/grph_object_id.h b/drivers/gpu/drm/amd/display/include/grph_object_id.h +index 92cc6c1..33b3d75 100644 +--- a/drivers/gpu/drm/amd/display/include/grph_object_id.h ++++ b/drivers/gpu/drm/amd/display/include/grph_object_id.h +@@ -292,4 +292,15 @@ static inline enum engine_id dal_graphics_object_id_get_engine_id( + return (enum engine_id) id.id; + return ENGINE_ID_UNKNOWN; + } ++ ++static inline bool dal_graphics_object_id_equal( ++ struct graphics_object_id id_1, ++ struct graphics_object_id id_2) ++{ ++ if ((id_1.id == id_2.id) && (id_1.enum_id == id_2.enum_id) && ++ (id_1.type == id_2.type)) { ++ return true; ++ } ++ return false; ++} + #endif +-- +2.7.4 + |