Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1eeedbcc authored by Samson Tam's avatar Samson Tam Committed by Alex Deucher
Browse files

drm/amd/display: get board layout for edid emulation

parent 7f93c1de
Loading
Loading
Loading
Loading
+196 −0
Original line number Diff line number Diff line
@@ -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(
+217 −1
Original line number Diff line number Diff line
@@ -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(
+4 −0
Original line number Diff line number Diff line
@@ -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 {
+46 −0
Original line number Diff line number Diff line
@@ -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
+11 −0
Original line number Diff line number Diff line
@@ -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