aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/4799-drm-amd-display-get-board-layout-for-edid-emulation.patch
diff options
context:
space:
mode:
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.patch583
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
+