cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bios_parser2.c (88462B)


      1/*
      2 * Copyright 2012-15 Advanced Micro Devices, Inc.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included in
     12 * all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 * OTHER DEALINGS IN THE SOFTWARE.
     21 *
     22 * Authors: AMD
     23 *
     24 */
     25
     26#include <linux/slab.h>
     27
     28#include "dm_services.h"
     29
     30#include "ObjectID.h"
     31#include "atomfirmware.h"
     32
     33#include "dc_bios_types.h"
     34#include "include/grph_object_ctrl_defs.h"
     35#include "include/bios_parser_interface.h"
     36#include "include/i2caux_interface.h"
     37#include "include/logger_interface.h"
     38
     39#include "command_table2.h"
     40
     41#include "bios_parser_helper.h"
     42#include "command_table_helper2.h"
     43#include "bios_parser2.h"
     44#include "bios_parser_types_internal2.h"
     45#include "bios_parser_interface.h"
     46
     47#include "bios_parser_common.h"
     48
     49/* Temporarily add in defines until ObjectID.h patch is updated in a few days */
     50#ifndef GENERIC_OBJECT_ID_BRACKET_LAYOUT
     51#define GENERIC_OBJECT_ID_BRACKET_LAYOUT          0x05
     52#endif /* GENERIC_OBJECT_ID_BRACKET_LAYOUT */
     53
     54#ifndef GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1
     55#define GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1	\
     56	(GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\
     57	GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
     58	GENERIC_OBJECT_ID_BRACKET_LAYOUT << OBJECT_ID_SHIFT)
     59#endif /* GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1 */
     60
     61#ifndef GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2
     62#define GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2	\
     63	(GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\
     64	GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
     65	GENERIC_OBJECT_ID_BRACKET_LAYOUT << OBJECT_ID_SHIFT)
     66#endif /* GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2 */
     67
     68#define DC_LOGGER \
     69	bp->base.ctx->logger
     70
     71#define LAST_RECORD_TYPE 0xff
     72#define SMU9_SYSPLL0_ID  0
     73
     74struct i2c_id_config_access {
     75	uint8_t bfI2C_LineMux:4;
     76	uint8_t bfHW_EngineID:3;
     77	uint8_t bfHW_Capable:1;
     78	uint8_t ucAccess;
     79};
     80
     81static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
     82	struct atom_i2c_record *record,
     83	struct graphics_object_i2c_info *info);
     84
     85static enum bp_result bios_parser_get_firmware_info(
     86	struct dc_bios *dcb,
     87	struct dc_firmware_info *info);
     88
     89static enum bp_result bios_parser_get_encoder_cap_info(
     90	struct dc_bios *dcb,
     91	struct graphics_object_id object_id,
     92	struct bp_encoder_cap_info *info);
     93
     94static enum bp_result get_firmware_info_v3_1(
     95	struct bios_parser *bp,
     96	struct dc_firmware_info *info);
     97
     98static enum bp_result get_firmware_info_v3_2(
     99	struct bios_parser *bp,
    100	struct dc_firmware_info *info);
    101
    102static enum bp_result get_firmware_info_v3_4(
    103	struct bios_parser *bp,
    104	struct dc_firmware_info *info);
    105
    106static struct atom_hpd_int_record *get_hpd_record(struct bios_parser *bp,
    107		struct atom_display_object_path_v2 *object);
    108
    109static struct atom_encoder_caps_record *get_encoder_cap_record(
    110	struct bios_parser *bp,
    111	struct atom_display_object_path_v2 *object);
    112
    113#define BIOS_IMAGE_SIZE_OFFSET 2
    114#define BIOS_IMAGE_SIZE_UNIT 512
    115
    116#define DATA_TABLES(table) (bp->master_data_tbl->listOfdatatables.table)
    117
    118static void bios_parser2_destruct(struct bios_parser *bp)
    119{
    120	kfree(bp->base.bios_local_image);
    121	kfree(bp->base.integrated_info);
    122}
    123
    124static void firmware_parser_destroy(struct dc_bios **dcb)
    125{
    126	struct bios_parser *bp = BP_FROM_DCB(*dcb);
    127
    128	if (!bp) {
    129		BREAK_TO_DEBUGGER();
    130		return;
    131	}
    132
    133	bios_parser2_destruct(bp);
    134
    135	kfree(bp);
    136	*dcb = NULL;
    137}
    138
    139static void get_atom_data_table_revision(
    140	struct atom_common_table_header *atom_data_tbl,
    141	struct atom_data_revision *tbl_revision)
    142{
    143	if (!tbl_revision)
    144		return;
    145
    146	/* initialize the revision to 0 which is invalid revision */
    147	tbl_revision->major = 0;
    148	tbl_revision->minor = 0;
    149
    150	if (!atom_data_tbl)
    151		return;
    152
    153	tbl_revision->major =
    154			(uint32_t) atom_data_tbl->format_revision & 0x3f;
    155	tbl_revision->minor =
    156			(uint32_t) atom_data_tbl->content_revision & 0x3f;
    157}
    158
    159/* BIOS oject table displaypath is per connector.
    160 * There is extra path not for connector. BIOS fill its encoderid as 0
    161 */
    162static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)
    163{
    164	struct bios_parser *bp = BP_FROM_DCB(dcb);
    165	unsigned int count = 0;
    166	unsigned int i;
    167
    168	for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) {
    169		if (bp->object_info_tbl.v1_4->display_path[i].encoderobjid != 0)
    170			count++;
    171	}
    172	return count;
    173}
    174
    175static struct graphics_object_id bios_parser_get_connector_id(
    176	struct dc_bios *dcb,
    177	uint8_t i)
    178{
    179	struct bios_parser *bp = BP_FROM_DCB(dcb);
    180	struct graphics_object_id object_id = dal_graphics_object_id_init(
    181		0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
    182	struct object_info_table *tbl = &bp->object_info_tbl;
    183	struct display_object_info_table_v1_4 *v1_4 = tbl->v1_4;
    184
    185	if (v1_4->number_of_path > i) {
    186		/* If display_objid is generic object id,  the encoderObj
    187		 * /extencoderobjId should be 0
    188		 */
    189		if (v1_4->display_path[i].encoderobjid != 0 &&
    190				v1_4->display_path[i].display_objid != 0)
    191			object_id = object_id_from_bios_object_id(
    192					v1_4->display_path[i].display_objid);
    193	}
    194
    195	return object_id;
    196}
    197
    198static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
    199	struct graphics_object_id object_id, uint32_t index,
    200	struct graphics_object_id *src_object_id)
    201{
    202	struct bios_parser *bp = BP_FROM_DCB(dcb);
    203	unsigned int i;
    204	enum bp_result  bp_result = BP_RESULT_BADINPUT;
    205	struct graphics_object_id obj_id = {0};
    206	struct object_info_table *tbl = &bp->object_info_tbl;
    207
    208	if (!src_object_id)
    209		return bp_result;
    210
    211	switch (object_id.type) {
    212	/* Encoder's Source is GPU.  BIOS does not provide GPU, since all
    213	 * displaypaths point to same GPU (0x1100).  Hardcode GPU object type
    214	 */
    215	case OBJECT_TYPE_ENCODER:
    216		/* TODO: since num of src must be less than 2.
    217		 * If found in for loop, should break.
    218		 * DAL2 implementation may be changed too
    219		 */
    220		for (i = 0; i < tbl->v1_4->number_of_path; i++) {
    221			obj_id = object_id_from_bios_object_id(
    222			tbl->v1_4->display_path[i].encoderobjid);
    223			if (object_id.type == obj_id.type &&
    224					object_id.id == obj_id.id &&
    225						object_id.enum_id ==
    226							obj_id.enum_id) {
    227				*src_object_id =
    228				object_id_from_bios_object_id(0x1100);
    229				/* break; */
    230			}
    231		}
    232		bp_result = BP_RESULT_OK;
    233		break;
    234	case OBJECT_TYPE_CONNECTOR:
    235		for (i = 0; i < tbl->v1_4->number_of_path; i++) {
    236			obj_id = object_id_from_bios_object_id(
    237				tbl->v1_4->display_path[i].display_objid);
    238
    239			if (object_id.type == obj_id.type &&
    240				object_id.id == obj_id.id &&
    241					object_id.enum_id == obj_id.enum_id) {
    242				*src_object_id =
    243				object_id_from_bios_object_id(
    244				tbl->v1_4->display_path[i].encoderobjid);
    245				/* break; */
    246			}
    247		}
    248		bp_result = BP_RESULT_OK;
    249		break;
    250	default:
    251		break;
    252	}
    253
    254	return bp_result;
    255}
    256
    257/* from graphics_object_id, find display path which includes the object_id */
    258static struct atom_display_object_path_v2 *get_bios_object(
    259		struct bios_parser *bp,
    260		struct graphics_object_id id)
    261{
    262	unsigned int i;
    263	struct graphics_object_id obj_id = {0};
    264
    265	switch (id.type) {
    266	case OBJECT_TYPE_ENCODER:
    267		for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) {
    268			obj_id = object_id_from_bios_object_id(
    269					bp->object_info_tbl.v1_4->display_path[i].encoderobjid);
    270			if (id.type == obj_id.type && id.id == obj_id.id
    271					&& id.enum_id == obj_id.enum_id)
    272				return &bp->object_info_tbl.v1_4->display_path[i];
    273		}
    274		fallthrough;
    275	case OBJECT_TYPE_CONNECTOR:
    276	case OBJECT_TYPE_GENERIC:
    277		/* Both Generic and Connector Object ID
    278		 * will be stored on display_objid
    279		 */
    280		for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) {
    281			obj_id = object_id_from_bios_object_id(
    282					bp->object_info_tbl.v1_4->display_path[i].display_objid);
    283			if (id.type == obj_id.type && id.id == obj_id.id
    284					&& id.enum_id == obj_id.enum_id)
    285				return &bp->object_info_tbl.v1_4->display_path[i];
    286		}
    287		fallthrough;
    288	default:
    289		return NULL;
    290	}
    291}
    292
    293static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
    294	struct graphics_object_id id,
    295	struct graphics_object_i2c_info *info)
    296{
    297	uint32_t offset;
    298	struct atom_display_object_path_v2 *object;
    299	struct atom_common_record_header *header;
    300	struct atom_i2c_record *record;
    301	struct atom_i2c_record dummy_record = {0};
    302	struct bios_parser *bp = BP_FROM_DCB(dcb);
    303
    304	if (!info)
    305		return BP_RESULT_BADINPUT;
    306
    307	if (id.type == OBJECT_TYPE_GENERIC) {
    308		dummy_record.i2c_id = id.id;
    309
    310		if (get_gpio_i2c_info(bp, &dummy_record, info) == BP_RESULT_OK)
    311			return BP_RESULT_OK;
    312		else
    313			return BP_RESULT_NORECORD;
    314	}
    315
    316	object = get_bios_object(bp, id);
    317
    318	if (!object)
    319		return BP_RESULT_BADINPUT;
    320
    321	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
    322
    323	for (;;) {
    324		header = GET_IMAGE(struct atom_common_record_header, offset);
    325
    326		if (!header)
    327			return BP_RESULT_BADBIOSTABLE;
    328
    329		if (header->record_type == LAST_RECORD_TYPE ||
    330			!header->record_size)
    331			break;
    332
    333		if (header->record_type == ATOM_I2C_RECORD_TYPE
    334			&& sizeof(struct atom_i2c_record) <=
    335							header->record_size) {
    336			/* get the I2C info */
    337			record = (struct atom_i2c_record *) header;
    338
    339			if (get_gpio_i2c_info(bp, record, info) ==
    340								BP_RESULT_OK)
    341				return BP_RESULT_OK;
    342		}
    343
    344		offset += header->record_size;
    345	}
    346
    347	return BP_RESULT_NORECORD;
    348}
    349
    350static enum bp_result get_gpio_i2c_info(
    351	struct bios_parser *bp,
    352	struct atom_i2c_record *record,
    353	struct graphics_object_i2c_info *info)
    354{
    355	struct atom_gpio_pin_lut_v2_1 *header;
    356	uint32_t count = 0;
    357	unsigned int table_index = 0;
    358	bool find_valid = false;
    359
    360	if (!info)
    361		return BP_RESULT_BADINPUT;
    362
    363	/* get the GPIO_I2C info */
    364	if (!DATA_TABLES(gpio_pin_lut))
    365		return BP_RESULT_BADBIOSTABLE;
    366
    367	header = GET_IMAGE(struct atom_gpio_pin_lut_v2_1,
    368					DATA_TABLES(gpio_pin_lut));
    369	if (!header)
    370		return BP_RESULT_BADBIOSTABLE;
    371
    372	if (sizeof(struct atom_common_table_header) +
    373			sizeof(struct atom_gpio_pin_assignment)	>
    374			le16_to_cpu(header->table_header.structuresize))
    375		return BP_RESULT_BADBIOSTABLE;
    376
    377	/* TODO: is version change? */
    378	if (header->table_header.content_revision != 1)
    379		return BP_RESULT_UNSUPPORTED;
    380
    381	/* get data count */
    382	count = (le16_to_cpu(header->table_header.structuresize)
    383			- sizeof(struct atom_common_table_header))
    384				/ sizeof(struct atom_gpio_pin_assignment);
    385
    386	for (table_index = 0; table_index < count; table_index++) {
    387		if (((record->i2c_id & I2C_HW_CAP) == (
    388		header->gpio_pin[table_index].gpio_id &
    389						I2C_HW_CAP)) &&
    390		((record->i2c_id & I2C_HW_ENGINE_ID_MASK)  ==
    391		(header->gpio_pin[table_index].gpio_id &
    392					I2C_HW_ENGINE_ID_MASK)) &&
    393		((record->i2c_id & I2C_HW_LANE_MUX) ==
    394		(header->gpio_pin[table_index].gpio_id &
    395						I2C_HW_LANE_MUX))) {
    396			/* still valid */
    397			find_valid = true;
    398			break;
    399		}
    400	}
    401
    402	/* If we don't find the entry that we are looking for then
    403	 *  we will return BP_Result_BadBiosTable.
    404	 */
    405	if (find_valid == false)
    406		return BP_RESULT_BADBIOSTABLE;
    407
    408	/* get the GPIO_I2C_INFO */
    409	info->i2c_hw_assist = (record->i2c_id & I2C_HW_CAP) ? true : false;
    410	info->i2c_line = record->i2c_id & I2C_HW_LANE_MUX;
    411	info->i2c_engine_id = (record->i2c_id & I2C_HW_ENGINE_ID_MASK) >> 4;
    412	info->i2c_slave_address = record->i2c_slave_addr;
    413
    414	/* TODO: check how to get register offset for en, Y, etc. */
    415	info->gpio_info.clk_a_register_index =
    416			le16_to_cpu(
    417			header->gpio_pin[table_index].data_a_reg_index);
    418	info->gpio_info.clk_a_shift =
    419			header->gpio_pin[table_index].gpio_bitshift;
    420
    421	return BP_RESULT_OK;
    422}
    423
    424static enum bp_result bios_parser_get_hpd_info(
    425	struct dc_bios *dcb,
    426	struct graphics_object_id id,
    427	struct graphics_object_hpd_info *info)
    428{
    429	struct bios_parser *bp = BP_FROM_DCB(dcb);
    430	struct atom_display_object_path_v2 *object;
    431	struct atom_hpd_int_record *record = NULL;
    432
    433	if (!info)
    434		return BP_RESULT_BADINPUT;
    435
    436	object = get_bios_object(bp, id);
    437
    438	if (!object)
    439		return BP_RESULT_BADINPUT;
    440
    441	record = get_hpd_record(bp, object);
    442
    443	if (record != NULL) {
    444		info->hpd_int_gpio_uid = record->pin_id;
    445		info->hpd_active = record->plugin_pin_state;
    446		return BP_RESULT_OK;
    447	}
    448
    449	return BP_RESULT_NORECORD;
    450}
    451
    452static struct atom_hpd_int_record *get_hpd_record(
    453	struct bios_parser *bp,
    454	struct atom_display_object_path_v2 *object)
    455{
    456	struct atom_common_record_header *header;
    457	uint32_t offset;
    458
    459	if (!object) {
    460		BREAK_TO_DEBUGGER(); /* Invalid object */
    461		return NULL;
    462	}
    463
    464	offset = le16_to_cpu(object->disp_recordoffset)
    465			+ bp->object_info_tbl_offset;
    466
    467	for (;;) {
    468		header = GET_IMAGE(struct atom_common_record_header, offset);
    469
    470		if (!header)
    471			return NULL;
    472
    473		if (header->record_type == LAST_RECORD_TYPE ||
    474			!header->record_size)
    475			break;
    476
    477		if (header->record_type == ATOM_HPD_INT_RECORD_TYPE
    478			&& sizeof(struct atom_hpd_int_record) <=
    479							header->record_size)
    480			return (struct atom_hpd_int_record *) header;
    481
    482		offset += header->record_size;
    483	}
    484
    485	return NULL;
    486}
    487
    488/**
    489 * bios_parser_get_gpio_pin_info
    490 * Get GpioPin information of input gpio id
    491 *
    492 * @dcb:     pointer to the DC BIOS
    493 * @gpio_id: GPIO ID
    494 * @info:    GpioPin information structure
    495 * return: Bios parser result code
    496 * note:
    497 *  to get the GPIO PIN INFO, we need:
    498 *  1. get the GPIO_ID from other object table, see GetHPDInfo()
    499 *  2. in DATA_TABLE.GPIO_Pin_LUT, search all records,
    500 *	to get the registerA  offset/mask
    501 */
    502static enum bp_result bios_parser_get_gpio_pin_info(
    503	struct dc_bios *dcb,
    504	uint32_t gpio_id,
    505	struct gpio_pin_info *info)
    506{
    507	struct bios_parser *bp = BP_FROM_DCB(dcb);
    508	struct atom_gpio_pin_lut_v2_1 *header;
    509	uint32_t count = 0;
    510	uint32_t i = 0;
    511
    512	if (!DATA_TABLES(gpio_pin_lut))
    513		return BP_RESULT_BADBIOSTABLE;
    514
    515	header = GET_IMAGE(struct atom_gpio_pin_lut_v2_1,
    516						DATA_TABLES(gpio_pin_lut));
    517	if (!header)
    518		return BP_RESULT_BADBIOSTABLE;
    519
    520	if (sizeof(struct atom_common_table_header) +
    521			sizeof(struct atom_gpio_pin_assignment)
    522			> le16_to_cpu(header->table_header.structuresize))
    523		return BP_RESULT_BADBIOSTABLE;
    524
    525	if (header->table_header.content_revision != 1)
    526		return BP_RESULT_UNSUPPORTED;
    527
    528	/* Temporary hard code gpio pin info */
    529#if defined(FOR_SIMNOW_BOOT)
    530	{
    531		struct  atom_gpio_pin_assignment  gpio_pin[8] = {
    532				{0x5db5, 0, 0, 1, 0},
    533				{0x5db5, 8, 8, 2, 0},
    534				{0x5db5, 0x10, 0x10, 3, 0},
    535				{0x5db5, 0x18, 0x14, 4, 0},
    536				{0x5db5, 0x1A, 0x18, 5, 0},
    537				{0x5db5, 0x1C, 0x1C, 6, 0},
    538		};
    539
    540		count = 6;
    541		memmove(header->gpio_pin, gpio_pin, sizeof(gpio_pin));
    542	}
    543#else
    544	count = (le16_to_cpu(header->table_header.structuresize)
    545			- sizeof(struct atom_common_table_header))
    546				/ sizeof(struct atom_gpio_pin_assignment);
    547#endif
    548	for (i = 0; i < count; ++i) {
    549		if (header->gpio_pin[i].gpio_id != gpio_id)
    550			continue;
    551
    552		info->offset =
    553			(uint32_t) le16_to_cpu(
    554					header->gpio_pin[i].data_a_reg_index);
    555		info->offset_y = info->offset + 2;
    556		info->offset_en = info->offset + 1;
    557		info->offset_mask = info->offset - 1;
    558
    559		info->mask = (uint32_t) (1 <<
    560			header->gpio_pin[i].gpio_bitshift);
    561		info->mask_y = info->mask + 2;
    562		info->mask_en = info->mask + 1;
    563		info->mask_mask = info->mask - 1;
    564
    565		return BP_RESULT_OK;
    566	}
    567
    568	return BP_RESULT_NORECORD;
    569}
    570
    571static struct device_id device_type_from_device_id(uint16_t device_id)
    572{
    573
    574	struct device_id result_device_id;
    575
    576	result_device_id.raw_device_tag = device_id;
    577
    578	switch (device_id) {
    579	case ATOM_DISPLAY_LCD1_SUPPORT:
    580		result_device_id.device_type = DEVICE_TYPE_LCD;
    581		result_device_id.enum_id = 1;
    582		break;
    583
    584	case ATOM_DISPLAY_LCD2_SUPPORT:
    585		result_device_id.device_type = DEVICE_TYPE_LCD;
    586		result_device_id.enum_id = 2;
    587		break;
    588
    589	case ATOM_DISPLAY_DFP1_SUPPORT:
    590		result_device_id.device_type = DEVICE_TYPE_DFP;
    591		result_device_id.enum_id = 1;
    592		break;
    593
    594	case ATOM_DISPLAY_DFP2_SUPPORT:
    595		result_device_id.device_type = DEVICE_TYPE_DFP;
    596		result_device_id.enum_id = 2;
    597		break;
    598
    599	case ATOM_DISPLAY_DFP3_SUPPORT:
    600		result_device_id.device_type = DEVICE_TYPE_DFP;
    601		result_device_id.enum_id = 3;
    602		break;
    603
    604	case ATOM_DISPLAY_DFP4_SUPPORT:
    605		result_device_id.device_type = DEVICE_TYPE_DFP;
    606		result_device_id.enum_id = 4;
    607		break;
    608
    609	case ATOM_DISPLAY_DFP5_SUPPORT:
    610		result_device_id.device_type = DEVICE_TYPE_DFP;
    611		result_device_id.enum_id = 5;
    612		break;
    613
    614	case ATOM_DISPLAY_DFP6_SUPPORT:
    615		result_device_id.device_type = DEVICE_TYPE_DFP;
    616		result_device_id.enum_id = 6;
    617		break;
    618
    619	default:
    620		BREAK_TO_DEBUGGER(); /* Invalid device Id */
    621		result_device_id.device_type = DEVICE_TYPE_UNKNOWN;
    622		result_device_id.enum_id = 0;
    623	}
    624	return result_device_id;
    625}
    626
    627static enum bp_result bios_parser_get_device_tag(
    628	struct dc_bios *dcb,
    629	struct graphics_object_id connector_object_id,
    630	uint32_t device_tag_index,
    631	struct connector_device_tag_info *info)
    632{
    633	struct bios_parser *bp = BP_FROM_DCB(dcb);
    634	struct atom_display_object_path_v2 *object;
    635
    636	if (!info)
    637		return BP_RESULT_BADINPUT;
    638
    639	/* getBiosObject will return MXM object */
    640	object = get_bios_object(bp, connector_object_id);
    641
    642	if (!object) {
    643		BREAK_TO_DEBUGGER(); /* Invalid object id */
    644		return BP_RESULT_BADINPUT;
    645	}
    646
    647	info->acpi_device = 0; /* BIOS no longer provides this */
    648	info->dev_id = device_type_from_device_id(object->device_tag);
    649
    650	return BP_RESULT_OK;
    651}
    652
    653static enum bp_result get_ss_info_v4_1(
    654	struct bios_parser *bp,
    655	uint32_t id,
    656	uint32_t index,
    657	struct spread_spectrum_info *ss_info)
    658{
    659	enum bp_result result = BP_RESULT_OK;
    660	struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL;
    661	struct atom_smu_info_v3_3 *smu_info = NULL;
    662
    663	if (!ss_info)
    664		return BP_RESULT_BADINPUT;
    665
    666	if (!DATA_TABLES(dce_info))
    667		return BP_RESULT_BADBIOSTABLE;
    668
    669	disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_1,
    670							DATA_TABLES(dce_info));
    671	if (!disp_cntl_tbl)
    672		return BP_RESULT_BADBIOSTABLE;
    673
    674
    675	ss_info->type.STEP_AND_DELAY_INFO = false;
    676	ss_info->spread_percentage_divider = 1000;
    677	/* BIOS no longer uses target clock.  Always enable for now */
    678	ss_info->target_clock_range = 0xffffffff;
    679
    680	switch (id) {
    681	case AS_SIGNAL_TYPE_DVI:
    682		ss_info->spread_spectrum_percentage =
    683				disp_cntl_tbl->dvi_ss_percentage;
    684		ss_info->spread_spectrum_range =
    685				disp_cntl_tbl->dvi_ss_rate_10hz * 10;
    686		if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
    687			ss_info->type.CENTER_MODE = true;
    688		break;
    689	case AS_SIGNAL_TYPE_HDMI:
    690		ss_info->spread_spectrum_percentage =
    691				disp_cntl_tbl->hdmi_ss_percentage;
    692		ss_info->spread_spectrum_range =
    693				disp_cntl_tbl->hdmi_ss_rate_10hz * 10;
    694		if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
    695			ss_info->type.CENTER_MODE = true;
    696		break;
    697	/* TODO LVDS not support anymore? */
    698	case AS_SIGNAL_TYPE_DISPLAY_PORT:
    699		ss_info->spread_spectrum_percentage =
    700				disp_cntl_tbl->dp_ss_percentage;
    701		ss_info->spread_spectrum_range =
    702				disp_cntl_tbl->dp_ss_rate_10hz * 10;
    703		if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
    704			ss_info->type.CENTER_MODE = true;
    705		break;
    706	case AS_SIGNAL_TYPE_GPU_PLL:
    707		/* atom_firmware: DAL only get data from dce_info table.
    708		 * if data within smu_info is needed for DAL, VBIOS should
    709		 * copy it into dce_info
    710		 */
    711		result = BP_RESULT_UNSUPPORTED;
    712		break;
    713	case AS_SIGNAL_TYPE_XGMI:
    714		smu_info =  GET_IMAGE(struct atom_smu_info_v3_3,
    715				      DATA_TABLES(smu_info));
    716		if (!smu_info)
    717			return BP_RESULT_BADBIOSTABLE;
    718
    719		ss_info->spread_spectrum_percentage =
    720				smu_info->waflclk_ss_percentage;
    721		ss_info->spread_spectrum_range =
    722				smu_info->gpuclk_ss_rate_10hz * 10;
    723		if (smu_info->waflclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
    724			ss_info->type.CENTER_MODE = true;
    725		break;
    726	default:
    727		result = BP_RESULT_UNSUPPORTED;
    728	}
    729
    730	return result;
    731}
    732
    733static enum bp_result get_ss_info_v4_2(
    734	struct bios_parser *bp,
    735	uint32_t id,
    736	uint32_t index,
    737	struct spread_spectrum_info *ss_info)
    738{
    739	enum bp_result result = BP_RESULT_OK;
    740	struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL;
    741	struct atom_smu_info_v3_1 *smu_info = NULL;
    742
    743	if (!ss_info)
    744		return BP_RESULT_BADINPUT;
    745
    746	if (!DATA_TABLES(dce_info))
    747		return BP_RESULT_BADBIOSTABLE;
    748
    749	if (!DATA_TABLES(smu_info))
    750		return BP_RESULT_BADBIOSTABLE;
    751
    752	disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_2,
    753							DATA_TABLES(dce_info));
    754	if (!disp_cntl_tbl)
    755		return BP_RESULT_BADBIOSTABLE;
    756
    757	smu_info =  GET_IMAGE(struct atom_smu_info_v3_1, DATA_TABLES(smu_info));
    758	if (!smu_info)
    759		return BP_RESULT_BADBIOSTABLE;
    760
    761	ss_info->type.STEP_AND_DELAY_INFO = false;
    762	ss_info->spread_percentage_divider = 1000;
    763	/* BIOS no longer uses target clock.  Always enable for now */
    764	ss_info->target_clock_range = 0xffffffff;
    765
    766	switch (id) {
    767	case AS_SIGNAL_TYPE_DVI:
    768		ss_info->spread_spectrum_percentage =
    769				disp_cntl_tbl->dvi_ss_percentage;
    770		ss_info->spread_spectrum_range =
    771				disp_cntl_tbl->dvi_ss_rate_10hz * 10;
    772		if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
    773			ss_info->type.CENTER_MODE = true;
    774		break;
    775	case AS_SIGNAL_TYPE_HDMI:
    776		ss_info->spread_spectrum_percentage =
    777				disp_cntl_tbl->hdmi_ss_percentage;
    778		ss_info->spread_spectrum_range =
    779				disp_cntl_tbl->hdmi_ss_rate_10hz * 10;
    780		if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
    781			ss_info->type.CENTER_MODE = true;
    782		break;
    783	/* TODO LVDS not support anymore? */
    784	case AS_SIGNAL_TYPE_DISPLAY_PORT:
    785		ss_info->spread_spectrum_percentage =
    786				smu_info->gpuclk_ss_percentage;
    787		ss_info->spread_spectrum_range =
    788				smu_info->gpuclk_ss_rate_10hz * 10;
    789		if (smu_info->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
    790			ss_info->type.CENTER_MODE = true;
    791		break;
    792	case AS_SIGNAL_TYPE_GPU_PLL:
    793		/* atom_firmware: DAL only get data from dce_info table.
    794		 * if data within smu_info is needed for DAL, VBIOS should
    795		 * copy it into dce_info
    796		 */
    797		result = BP_RESULT_UNSUPPORTED;
    798		break;
    799	default:
    800		result = BP_RESULT_UNSUPPORTED;
    801	}
    802
    803	return result;
    804}
    805
    806/**
    807 * bios_parser_get_spread_spectrum_info
    808 * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or
    809 * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info
    810 * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info
    811 * ver 3.1,
    812 * there is only one entry for each signal /ss id.  However, there is
    813 * no planning of supporting multiple spread Sprectum entry for EverGreen
    814 * @dcb:     pointer to the DC BIOS
    815 * @signal:  ASSignalType to be converted to info index
    816 * @index:   number of entries that match the converted info index
    817 * @ss_info: sprectrum information structure,
    818 * return: Bios parser result code
    819 */
    820static enum bp_result bios_parser_get_spread_spectrum_info(
    821	struct dc_bios *dcb,
    822	enum as_signal_type signal,
    823	uint32_t index,
    824	struct spread_spectrum_info *ss_info)
    825{
    826	struct bios_parser *bp = BP_FROM_DCB(dcb);
    827	enum bp_result result = BP_RESULT_UNSUPPORTED;
    828	struct atom_common_table_header *header;
    829	struct atom_data_revision tbl_revision;
    830
    831	if (!ss_info) /* check for bad input */
    832		return BP_RESULT_BADINPUT;
    833
    834	if (!DATA_TABLES(dce_info))
    835		return BP_RESULT_UNSUPPORTED;
    836
    837	header = GET_IMAGE(struct atom_common_table_header,
    838						DATA_TABLES(dce_info));
    839	get_atom_data_table_revision(header, &tbl_revision);
    840
    841	switch (tbl_revision.major) {
    842	case 4:
    843		switch (tbl_revision.minor) {
    844		case 1:
    845			return get_ss_info_v4_1(bp, signal, index, ss_info);
    846		case 2:
    847		case 3:
    848		case 4:
    849			return get_ss_info_v4_2(bp, signal, index, ss_info);
    850		default:
    851			ASSERT(0);
    852			break;
    853		}
    854		break;
    855	default:
    856		break;
    857	}
    858	/* there can not be more then one entry for SS Info table */
    859	return result;
    860}
    861
    862static enum bp_result get_soc_bb_info_v4_4(
    863	struct bios_parser *bp,
    864	struct bp_soc_bb_info *soc_bb_info)
    865{
    866	enum bp_result result = BP_RESULT_OK;
    867	struct atom_display_controller_info_v4_4 *disp_cntl_tbl = NULL;
    868
    869	if (!soc_bb_info)
    870		return BP_RESULT_BADINPUT;
    871
    872	if (!DATA_TABLES(dce_info))
    873		return BP_RESULT_BADBIOSTABLE;
    874
    875	if (!DATA_TABLES(smu_info))
    876		return BP_RESULT_BADBIOSTABLE;
    877
    878	disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_4,
    879							DATA_TABLES(dce_info));
    880	if (!disp_cntl_tbl)
    881		return BP_RESULT_BADBIOSTABLE;
    882
    883	soc_bb_info->dram_clock_change_latency_100ns = disp_cntl_tbl->max_mclk_chg_lat;
    884	soc_bb_info->dram_sr_enter_exit_latency_100ns = disp_cntl_tbl->max_sr_enter_exit_lat;
    885	soc_bb_info->dram_sr_exit_latency_100ns = disp_cntl_tbl->max_sr_exit_lat;
    886
    887	return result;
    888}
    889
    890static enum bp_result bios_parser_get_soc_bb_info(
    891	struct dc_bios *dcb,
    892	struct bp_soc_bb_info *soc_bb_info)
    893{
    894	struct bios_parser *bp = BP_FROM_DCB(dcb);
    895	enum bp_result result = BP_RESULT_UNSUPPORTED;
    896	struct atom_common_table_header *header;
    897	struct atom_data_revision tbl_revision;
    898
    899	if (!soc_bb_info) /* check for bad input */
    900		return BP_RESULT_BADINPUT;
    901
    902	if (!DATA_TABLES(dce_info))
    903		return BP_RESULT_UNSUPPORTED;
    904
    905	header = GET_IMAGE(struct atom_common_table_header,
    906						DATA_TABLES(dce_info));
    907	get_atom_data_table_revision(header, &tbl_revision);
    908
    909	switch (tbl_revision.major) {
    910	case 4:
    911		switch (tbl_revision.minor) {
    912		case 1:
    913		case 2:
    914		case 3:
    915			break;
    916		case 4:
    917			result = get_soc_bb_info_v4_4(bp, soc_bb_info);
    918			break;
    919		default:
    920			break;
    921		}
    922		break;
    923	default:
    924		break;
    925	}
    926
    927	return result;
    928}
    929
    930static enum bp_result get_disp_caps_v4_1(
    931	struct bios_parser *bp,
    932	uint8_t *dce_caps)
    933{
    934	enum bp_result result = BP_RESULT_OK;
    935	struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL;
    936
    937	if (!dce_caps)
    938		return BP_RESULT_BADINPUT;
    939
    940	if (!DATA_TABLES(dce_info))
    941		return BP_RESULT_BADBIOSTABLE;
    942
    943	disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_1,
    944							DATA_TABLES(dce_info));
    945
    946	if (!disp_cntl_tbl)
    947		return BP_RESULT_BADBIOSTABLE;
    948
    949	*dce_caps = disp_cntl_tbl->display_caps;
    950
    951	return result;
    952}
    953
    954static enum bp_result get_disp_caps_v4_2(
    955	struct bios_parser *bp,
    956	uint8_t *dce_caps)
    957{
    958	enum bp_result result = BP_RESULT_OK;
    959	struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL;
    960
    961	if (!dce_caps)
    962		return BP_RESULT_BADINPUT;
    963
    964	if (!DATA_TABLES(dce_info))
    965		return BP_RESULT_BADBIOSTABLE;
    966
    967	disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_2,
    968							DATA_TABLES(dce_info));
    969
    970	if (!disp_cntl_tbl)
    971		return BP_RESULT_BADBIOSTABLE;
    972
    973	*dce_caps = disp_cntl_tbl->display_caps;
    974
    975	return result;
    976}
    977
    978static enum bp_result get_disp_caps_v4_3(
    979	struct bios_parser *bp,
    980	uint8_t *dce_caps)
    981{
    982	enum bp_result result = BP_RESULT_OK;
    983	struct atom_display_controller_info_v4_3 *disp_cntl_tbl = NULL;
    984
    985	if (!dce_caps)
    986		return BP_RESULT_BADINPUT;
    987
    988	if (!DATA_TABLES(dce_info))
    989		return BP_RESULT_BADBIOSTABLE;
    990
    991	disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_3,
    992							DATA_TABLES(dce_info));
    993
    994	if (!disp_cntl_tbl)
    995		return BP_RESULT_BADBIOSTABLE;
    996
    997	*dce_caps = disp_cntl_tbl->display_caps;
    998
    999	return result;
   1000}
   1001
   1002static enum bp_result get_disp_caps_v4_4(
   1003	struct bios_parser *bp,
   1004	uint8_t *dce_caps)
   1005{
   1006	enum bp_result result = BP_RESULT_OK;
   1007	struct atom_display_controller_info_v4_4 *disp_cntl_tbl = NULL;
   1008
   1009	if (!dce_caps)
   1010		return BP_RESULT_BADINPUT;
   1011
   1012	if (!DATA_TABLES(dce_info))
   1013		return BP_RESULT_BADBIOSTABLE;
   1014
   1015	disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_4,
   1016							DATA_TABLES(dce_info));
   1017
   1018	if (!disp_cntl_tbl)
   1019		return BP_RESULT_BADBIOSTABLE;
   1020
   1021	*dce_caps = disp_cntl_tbl->display_caps;
   1022
   1023	return result;
   1024}
   1025
   1026static enum bp_result bios_parser_get_lttpr_interop(
   1027	struct dc_bios *dcb,
   1028	uint8_t *dce_caps)
   1029{
   1030	struct bios_parser *bp = BP_FROM_DCB(dcb);
   1031	enum bp_result result = BP_RESULT_UNSUPPORTED;
   1032	struct atom_common_table_header *header;
   1033	struct atom_data_revision tbl_revision;
   1034
   1035	if (!DATA_TABLES(dce_info))
   1036		return BP_RESULT_UNSUPPORTED;
   1037
   1038	header = GET_IMAGE(struct atom_common_table_header,
   1039						DATA_TABLES(dce_info));
   1040	get_atom_data_table_revision(header, &tbl_revision);
   1041	switch (tbl_revision.major) {
   1042	case 4:
   1043		switch (tbl_revision.minor) {
   1044		case 1:
   1045			result = get_disp_caps_v4_1(bp, dce_caps);
   1046			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
   1047			break;
   1048		case 2:
   1049			result = get_disp_caps_v4_2(bp, dce_caps);
   1050			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
   1051			break;
   1052		case 3:
   1053			result = get_disp_caps_v4_3(bp, dce_caps);
   1054			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
   1055			break;
   1056		case 4:
   1057			result = get_disp_caps_v4_4(bp, dce_caps);
   1058			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
   1059			break;
   1060		default:
   1061			break;
   1062		}
   1063		break;
   1064	default:
   1065		break;
   1066	}
   1067
   1068	return result;
   1069}
   1070
   1071static enum bp_result bios_parser_get_lttpr_caps(
   1072	struct dc_bios *dcb,
   1073	uint8_t *dce_caps)
   1074{
   1075	struct bios_parser *bp = BP_FROM_DCB(dcb);
   1076	enum bp_result result = BP_RESULT_UNSUPPORTED;
   1077	struct atom_common_table_header *header;
   1078	struct atom_data_revision tbl_revision;
   1079
   1080	if (!DATA_TABLES(dce_info))
   1081		return BP_RESULT_UNSUPPORTED;
   1082
   1083	header = GET_IMAGE(struct atom_common_table_header,
   1084						DATA_TABLES(dce_info));
   1085	get_atom_data_table_revision(header, &tbl_revision);
   1086	switch (tbl_revision.major) {
   1087	case 4:
   1088		switch (tbl_revision.minor) {
   1089		case 1:
   1090			result = get_disp_caps_v4_1(bp, dce_caps);
   1091			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
   1092			break;
   1093		case 2:
   1094			result = get_disp_caps_v4_2(bp, dce_caps);
   1095			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
   1096			break;
   1097		case 3:
   1098			result = get_disp_caps_v4_3(bp, dce_caps);
   1099			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
   1100			break;
   1101		case 4:
   1102			result = get_disp_caps_v4_4(bp, dce_caps);
   1103			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
   1104			break;
   1105		default:
   1106			break;
   1107		}
   1108		break;
   1109	default:
   1110		break;
   1111	}
   1112
   1113	return result;
   1114}
   1115
   1116static enum bp_result get_embedded_panel_info_v2_1(
   1117		struct bios_parser *bp,
   1118		struct embedded_panel_info *info)
   1119{
   1120	struct lcd_info_v2_1 *lvds;
   1121
   1122	if (!info)
   1123		return BP_RESULT_BADINPUT;
   1124
   1125	if (!DATA_TABLES(lcd_info))
   1126		return BP_RESULT_UNSUPPORTED;
   1127
   1128	lvds = GET_IMAGE(struct lcd_info_v2_1, DATA_TABLES(lcd_info));
   1129
   1130	if (!lvds)
   1131		return BP_RESULT_BADBIOSTABLE;
   1132
   1133	/* TODO: previous vv1_3, should v2_1 */
   1134	if (!((lvds->table_header.format_revision == 2)
   1135			&& (lvds->table_header.content_revision >= 1)))
   1136		return BP_RESULT_UNSUPPORTED;
   1137
   1138	memset(info, 0, sizeof(struct embedded_panel_info));
   1139
   1140	/* We need to convert from 10KHz units into KHz units */
   1141	info->lcd_timing.pixel_clk = le16_to_cpu(lvds->lcd_timing.pixclk) * 10;
   1142	/* usHActive does not include borders, according to VBIOS team */
   1143	info->lcd_timing.horizontal_addressable = le16_to_cpu(lvds->lcd_timing.h_active);
   1144	/* usHBlanking_Time includes borders, so we should really be
   1145	 * subtractingborders duing this translation, but LVDS generally
   1146	 * doesn't have borders, so we should be okay leaving this as is for
   1147	 * now.  May need to revisit if we ever have LVDS with borders
   1148	 */
   1149	info->lcd_timing.horizontal_blanking_time = le16_to_cpu(lvds->lcd_timing.h_blanking_time);
   1150	/* usVActive does not include borders, according to VBIOS team*/
   1151	info->lcd_timing.vertical_addressable = le16_to_cpu(lvds->lcd_timing.v_active);
   1152	/* usVBlanking_Time includes borders, so we should really be
   1153	 * subtracting borders duing this translation, but LVDS generally
   1154	 * doesn't have borders, so we should be okay leaving this as is for
   1155	 * now. May need to revisit if we ever have LVDS with borders
   1156	 */
   1157	info->lcd_timing.vertical_blanking_time = le16_to_cpu(lvds->lcd_timing.v_blanking_time);
   1158	info->lcd_timing.horizontal_sync_offset = le16_to_cpu(lvds->lcd_timing.h_sync_offset);
   1159	info->lcd_timing.horizontal_sync_width = le16_to_cpu(lvds->lcd_timing.h_sync_width);
   1160	info->lcd_timing.vertical_sync_offset = le16_to_cpu(lvds->lcd_timing.v_sync_offset);
   1161	info->lcd_timing.vertical_sync_width = le16_to_cpu(lvds->lcd_timing.v_syncwidth);
   1162	info->lcd_timing.horizontal_border = lvds->lcd_timing.h_border;
   1163	info->lcd_timing.vertical_border = lvds->lcd_timing.v_border;
   1164
   1165	/* not provided by VBIOS */
   1166	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 0;
   1167
   1168	info->lcd_timing.misc_info.H_SYNC_POLARITY = ~(uint32_t) (lvds->lcd_timing.miscinfo
   1169			& ATOM_HSYNC_POLARITY);
   1170	info->lcd_timing.misc_info.V_SYNC_POLARITY = ~(uint32_t) (lvds->lcd_timing.miscinfo
   1171			& ATOM_VSYNC_POLARITY);
   1172
   1173	/* not provided by VBIOS */
   1174	info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0;
   1175
   1176	info->lcd_timing.misc_info.H_REPLICATION_BY2 = !!(lvds->lcd_timing.miscinfo
   1177			& ATOM_H_REPLICATIONBY2);
   1178	info->lcd_timing.misc_info.V_REPLICATION_BY2 = !!(lvds->lcd_timing.miscinfo
   1179			& ATOM_V_REPLICATIONBY2);
   1180	info->lcd_timing.misc_info.COMPOSITE_SYNC = !!(lvds->lcd_timing.miscinfo
   1181			& ATOM_COMPOSITESYNC);
   1182	info->lcd_timing.misc_info.INTERLACE = !!(lvds->lcd_timing.miscinfo & ATOM_INTERLACE);
   1183
   1184	/* not provided by VBIOS*/
   1185	info->lcd_timing.misc_info.DOUBLE_CLOCK = 0;
   1186	/* not provided by VBIOS*/
   1187	info->ss_id = 0;
   1188
   1189	info->realtek_eDPToLVDS = !!(lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID);
   1190
   1191	return BP_RESULT_OK;
   1192}
   1193
   1194static enum bp_result bios_parser_get_embedded_panel_info(
   1195		struct dc_bios *dcb,
   1196		struct embedded_panel_info *info)
   1197{
   1198	struct bios_parser
   1199	*bp = BP_FROM_DCB(dcb);
   1200	struct atom_common_table_header *header;
   1201	struct atom_data_revision tbl_revision;
   1202
   1203	if (!DATA_TABLES(lcd_info))
   1204		return BP_RESULT_FAILURE;
   1205
   1206	header = GET_IMAGE(struct atom_common_table_header, DATA_TABLES(lcd_info));
   1207
   1208	if (!header)
   1209		return BP_RESULT_BADBIOSTABLE;
   1210
   1211	get_atom_data_table_revision(header, &tbl_revision);
   1212
   1213	switch (tbl_revision.major) {
   1214	case 2:
   1215		switch (tbl_revision.minor) {
   1216		case 1:
   1217			return get_embedded_panel_info_v2_1(bp, info);
   1218		default:
   1219			break;
   1220		}
   1221		break;
   1222	default:
   1223		break;
   1224	}
   1225
   1226	return BP_RESULT_FAILURE;
   1227}
   1228
   1229static uint32_t get_support_mask_for_device_id(struct device_id device_id)
   1230{
   1231	enum dal_device_type device_type = device_id.device_type;
   1232	uint32_t enum_id = device_id.enum_id;
   1233
   1234	switch (device_type) {
   1235	case DEVICE_TYPE_LCD:
   1236		switch (enum_id) {
   1237		case 1:
   1238			return ATOM_DISPLAY_LCD1_SUPPORT;
   1239		default:
   1240			break;
   1241		}
   1242		break;
   1243	case DEVICE_TYPE_DFP:
   1244		switch (enum_id) {
   1245		case 1:
   1246			return ATOM_DISPLAY_DFP1_SUPPORT;
   1247		case 2:
   1248			return ATOM_DISPLAY_DFP2_SUPPORT;
   1249		case 3:
   1250			return ATOM_DISPLAY_DFP3_SUPPORT;
   1251		case 4:
   1252			return ATOM_DISPLAY_DFP4_SUPPORT;
   1253		case 5:
   1254			return ATOM_DISPLAY_DFP5_SUPPORT;
   1255		case 6:
   1256			return ATOM_DISPLAY_DFP6_SUPPORT;
   1257		default:
   1258			break;
   1259		}
   1260		break;
   1261	default:
   1262		break;
   1263	}
   1264
   1265	/* Unidentified device ID, return empty support mask. */
   1266	return 0;
   1267}
   1268
   1269static bool bios_parser_is_device_id_supported(
   1270	struct dc_bios *dcb,
   1271	struct device_id id)
   1272{
   1273	struct bios_parser *bp = BP_FROM_DCB(dcb);
   1274
   1275	uint32_t mask = get_support_mask_for_device_id(id);
   1276
   1277	return (le16_to_cpu(bp->object_info_tbl.v1_4->supporteddevices) &
   1278								mask) != 0;
   1279}
   1280
   1281static uint32_t bios_parser_get_ss_entry_number(
   1282	struct dc_bios *dcb,
   1283	enum as_signal_type signal)
   1284{
   1285	/* TODO: DAL2 atomfirmware implementation does not need this.
   1286	 * why DAL3 need this?
   1287	 */
   1288	return 1;
   1289}
   1290
   1291static enum bp_result bios_parser_transmitter_control(
   1292	struct dc_bios *dcb,
   1293	struct bp_transmitter_control *cntl)
   1294{
   1295	struct bios_parser *bp = BP_FROM_DCB(dcb);
   1296
   1297	if (!bp->cmd_tbl.transmitter_control)
   1298		return BP_RESULT_FAILURE;
   1299
   1300	return bp->cmd_tbl.transmitter_control(bp, cntl);
   1301}
   1302
   1303static enum bp_result bios_parser_encoder_control(
   1304	struct dc_bios *dcb,
   1305	struct bp_encoder_control *cntl)
   1306{
   1307	struct bios_parser *bp = BP_FROM_DCB(dcb);
   1308
   1309	if (!bp->cmd_tbl.dig_encoder_control)
   1310		return BP_RESULT_FAILURE;
   1311
   1312	return bp->cmd_tbl.dig_encoder_control(bp, cntl);
   1313}
   1314
   1315static enum bp_result bios_parser_set_pixel_clock(
   1316	struct dc_bios *dcb,
   1317	struct bp_pixel_clock_parameters *bp_params)
   1318{
   1319	struct bios_parser *bp = BP_FROM_DCB(dcb);
   1320
   1321	if (!bp->cmd_tbl.set_pixel_clock)
   1322		return BP_RESULT_FAILURE;
   1323
   1324	return bp->cmd_tbl.set_pixel_clock(bp, bp_params);
   1325}
   1326
   1327static enum bp_result bios_parser_set_dce_clock(
   1328	struct dc_bios *dcb,
   1329	struct bp_set_dce_clock_parameters *bp_params)
   1330{
   1331	struct bios_parser *bp = BP_FROM_DCB(dcb);
   1332
   1333	if (!bp->cmd_tbl.set_dce_clock)
   1334		return BP_RESULT_FAILURE;
   1335
   1336	return bp->cmd_tbl.set_dce_clock(bp, bp_params);
   1337}
   1338
   1339static enum bp_result bios_parser_program_crtc_timing(
   1340	struct dc_bios *dcb,
   1341	struct bp_hw_crtc_timing_parameters *bp_params)
   1342{
   1343	struct bios_parser *bp = BP_FROM_DCB(dcb);
   1344
   1345	if (!bp->cmd_tbl.set_crtc_timing)
   1346		return BP_RESULT_FAILURE;
   1347
   1348	return bp->cmd_tbl.set_crtc_timing(bp, bp_params);
   1349}
   1350
   1351static enum bp_result bios_parser_enable_crtc(
   1352	struct dc_bios *dcb,
   1353	enum controller_id id,
   1354	bool enable)
   1355{
   1356	struct bios_parser *bp = BP_FROM_DCB(dcb);
   1357
   1358	if (!bp->cmd_tbl.enable_crtc)
   1359		return BP_RESULT_FAILURE;
   1360
   1361	return bp->cmd_tbl.enable_crtc(bp, id, enable);
   1362}
   1363
   1364static enum bp_result bios_parser_enable_disp_power_gating(
   1365	struct dc_bios *dcb,
   1366	enum controller_id controller_id,
   1367	enum bp_pipe_control_action action)
   1368{
   1369	struct bios_parser *bp = BP_FROM_DCB(dcb);
   1370
   1371	if (!bp->cmd_tbl.enable_disp_power_gating)
   1372		return BP_RESULT_FAILURE;
   1373
   1374	return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id,
   1375		action);
   1376}
   1377
   1378static enum bp_result bios_parser_enable_lvtma_control(
   1379	struct dc_bios *dcb,
   1380	uint8_t uc_pwr_on,
   1381	uint8_t panel_instance)
   1382{
   1383	struct bios_parser *bp = BP_FROM_DCB(dcb);
   1384
   1385	if (!bp->cmd_tbl.enable_lvtma_control)
   1386		return BP_RESULT_FAILURE;
   1387
   1388	return bp->cmd_tbl.enable_lvtma_control(bp, uc_pwr_on, panel_instance);
   1389}
   1390
   1391static bool bios_parser_is_accelerated_mode(
   1392	struct dc_bios *dcb)
   1393{
   1394	return bios_is_accelerated_mode(dcb);
   1395}
   1396
   1397/**
   1398 * bios_parser_set_scratch_critical_state - update critical state bit
   1399 *                                          in VBIOS scratch register
   1400 *
   1401 * @dcb:   pointer to the DC BIO
   1402 * @state: set or reset state
   1403 */
   1404static void bios_parser_set_scratch_critical_state(
   1405	struct dc_bios *dcb,
   1406	bool state)
   1407{
   1408	bios_set_scratch_critical_state(dcb, state);
   1409}
   1410
   1411static enum bp_result bios_parser_get_firmware_info(
   1412	struct dc_bios *dcb,
   1413	struct dc_firmware_info *info)
   1414{
   1415	struct bios_parser *bp = BP_FROM_DCB(dcb);
   1416	enum bp_result result = BP_RESULT_BADBIOSTABLE;
   1417	struct atom_common_table_header *header;
   1418
   1419	struct atom_data_revision revision;
   1420
   1421	if (info && DATA_TABLES(firmwareinfo)) {
   1422		header = GET_IMAGE(struct atom_common_table_header,
   1423				DATA_TABLES(firmwareinfo));
   1424		get_atom_data_table_revision(header, &revision);
   1425		switch (revision.major) {
   1426		case 3:
   1427			switch (revision.minor) {
   1428			case 1:
   1429				result = get_firmware_info_v3_1(bp, info);
   1430				break;
   1431			case 2:
   1432			case 3:
   1433				result = get_firmware_info_v3_2(bp, info);
   1434                                break;
   1435			case 4:
   1436				result = get_firmware_info_v3_4(bp, info);
   1437				break;
   1438			default:
   1439				break;
   1440			}
   1441			break;
   1442		default:
   1443			break;
   1444		}
   1445	}
   1446
   1447	return result;
   1448}
   1449
   1450static enum bp_result get_firmware_info_v3_1(
   1451	struct bios_parser *bp,
   1452	struct dc_firmware_info *info)
   1453{
   1454	struct atom_firmware_info_v3_1 *firmware_info;
   1455	struct atom_display_controller_info_v4_1 *dce_info = NULL;
   1456
   1457	if (!info)
   1458		return BP_RESULT_BADINPUT;
   1459
   1460	firmware_info = GET_IMAGE(struct atom_firmware_info_v3_1,
   1461			DATA_TABLES(firmwareinfo));
   1462
   1463	dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1,
   1464			DATA_TABLES(dce_info));
   1465
   1466	if (!firmware_info || !dce_info)
   1467		return BP_RESULT_BADBIOSTABLE;
   1468
   1469	memset(info, 0, sizeof(*info));
   1470
   1471	/* Pixel clock pll information. */
   1472	 /* We need to convert from 10KHz units into KHz units */
   1473	info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
   1474	info->default_engine_clk = firmware_info->bootup_sclk_in10khz * 10;
   1475
   1476	 /* 27MHz for Vega10: */
   1477	info->pll_info.crystal_frequency = dce_info->dce_refclk_10khz * 10;
   1478
   1479	/* Hardcode frequency if BIOS gives no DCE Ref Clk */
   1480	if (info->pll_info.crystal_frequency == 0)
   1481		info->pll_info.crystal_frequency = 27000;
   1482	/*dp_phy_ref_clk is not correct for atom_display_controller_info_v4_2, but we don't use it*/
   1483	info->dp_phy_ref_clk     = dce_info->dpphy_refclk_10khz * 10;
   1484	info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10;
   1485
   1486	/* Get GPU PLL VCO Clock */
   1487
   1488	if (bp->cmd_tbl.get_smu_clock_info != NULL) {
   1489		/* VBIOS gives in 10KHz */
   1490		info->smu_gpu_pll_output_freq =
   1491				bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;
   1492	}
   1493
   1494	info->oem_i2c_present = false;
   1495
   1496	return BP_RESULT_OK;
   1497}
   1498
   1499static enum bp_result get_firmware_info_v3_2(
   1500	struct bios_parser *bp,
   1501	struct dc_firmware_info *info)
   1502{
   1503	struct atom_firmware_info_v3_2 *firmware_info;
   1504	struct atom_display_controller_info_v4_1 *dce_info = NULL;
   1505	struct atom_common_table_header *header;
   1506	struct atom_data_revision revision;
   1507	struct atom_smu_info_v3_2 *smu_info_v3_2 = NULL;
   1508	struct atom_smu_info_v3_3 *smu_info_v3_3 = NULL;
   1509
   1510	if (!info)
   1511		return BP_RESULT_BADINPUT;
   1512
   1513	firmware_info = GET_IMAGE(struct atom_firmware_info_v3_2,
   1514			DATA_TABLES(firmwareinfo));
   1515
   1516	dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1,
   1517			DATA_TABLES(dce_info));
   1518
   1519	if (!firmware_info || !dce_info)
   1520		return BP_RESULT_BADBIOSTABLE;
   1521
   1522	memset(info, 0, sizeof(*info));
   1523
   1524	header = GET_IMAGE(struct atom_common_table_header,
   1525					DATA_TABLES(smu_info));
   1526	get_atom_data_table_revision(header, &revision);
   1527
   1528	if (revision.minor == 2) {
   1529		/* Vega12 */
   1530		smu_info_v3_2 = GET_IMAGE(struct atom_smu_info_v3_2,
   1531							DATA_TABLES(smu_info));
   1532
   1533		if (!smu_info_v3_2)
   1534			return BP_RESULT_BADBIOSTABLE;
   1535
   1536		info->default_engine_clk = smu_info_v3_2->bootup_dcefclk_10khz * 10;
   1537	} else if (revision.minor == 3) {
   1538		/* Vega20 */
   1539		smu_info_v3_3 = GET_IMAGE(struct atom_smu_info_v3_3,
   1540							DATA_TABLES(smu_info));
   1541
   1542		if (!smu_info_v3_3)
   1543			return BP_RESULT_BADBIOSTABLE;
   1544
   1545		info->default_engine_clk = smu_info_v3_3->bootup_dcefclk_10khz * 10;
   1546	}
   1547
   1548	 // We need to convert from 10KHz units into KHz units.
   1549	info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
   1550
   1551	 /* 27MHz for Vega10 & Vega12; 100MHz for Vega20 */
   1552	info->pll_info.crystal_frequency = dce_info->dce_refclk_10khz * 10;
   1553	/* Hardcode frequency if BIOS gives no DCE Ref Clk */
   1554	if (info->pll_info.crystal_frequency == 0) {
   1555		if (revision.minor == 2)
   1556			info->pll_info.crystal_frequency = 27000;
   1557		else if (revision.minor == 3)
   1558			info->pll_info.crystal_frequency = 100000;
   1559	}
   1560	/*dp_phy_ref_clk is not correct for atom_display_controller_info_v4_2, but we don't use it*/
   1561	info->dp_phy_ref_clk     = dce_info->dpphy_refclk_10khz * 10;
   1562	info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10;
   1563
   1564	/* Get GPU PLL VCO Clock */
   1565	if (bp->cmd_tbl.get_smu_clock_info != NULL) {
   1566		if (revision.minor == 2)
   1567			info->smu_gpu_pll_output_freq =
   1568					bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;
   1569		else if (revision.minor == 3)
   1570			info->smu_gpu_pll_output_freq =
   1571					bp->cmd_tbl.get_smu_clock_info(bp, SMU11_SYSPLL3_0_ID) * 10;
   1572	}
   1573
   1574	if (firmware_info->board_i2c_feature_id == 0x2) {
   1575		info->oem_i2c_present = true;
   1576		info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;
   1577	} else {
   1578		info->oem_i2c_present = false;
   1579	}
   1580
   1581	return BP_RESULT_OK;
   1582}
   1583
   1584static enum bp_result get_firmware_info_v3_4(
   1585	struct bios_parser *bp,
   1586	struct dc_firmware_info *info)
   1587{
   1588	struct atom_firmware_info_v3_4 *firmware_info;
   1589	struct atom_common_table_header *header;
   1590	struct atom_data_revision revision;
   1591	struct atom_display_controller_info_v4_1 *dce_info_v4_1 = NULL;
   1592	struct atom_display_controller_info_v4_4 *dce_info_v4_4 = NULL;
   1593	if (!info)
   1594		return BP_RESULT_BADINPUT;
   1595
   1596	firmware_info = GET_IMAGE(struct atom_firmware_info_v3_4,
   1597			DATA_TABLES(firmwareinfo));
   1598
   1599	if (!firmware_info)
   1600		return BP_RESULT_BADBIOSTABLE;
   1601
   1602	memset(info, 0, sizeof(*info));
   1603
   1604	header = GET_IMAGE(struct atom_common_table_header,
   1605					DATA_TABLES(dce_info));
   1606
   1607	get_atom_data_table_revision(header, &revision);
   1608
   1609	switch (revision.major) {
   1610	case 4:
   1611		switch (revision.minor) {
   1612		case 4:
   1613			dce_info_v4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,
   1614							DATA_TABLES(dce_info));
   1615
   1616			if (!dce_info_v4_4)
   1617				return BP_RESULT_BADBIOSTABLE;
   1618
   1619			/* 100MHz expected */
   1620			info->pll_info.crystal_frequency = dce_info_v4_4->dce_refclk_10khz * 10;
   1621			info->dp_phy_ref_clk             = dce_info_v4_4->dpphy_refclk_10khz * 10;
   1622			/* 50MHz expected */
   1623			info->i2c_engine_ref_clk         = dce_info_v4_4->i2c_engine_refclk_10khz * 10;
   1624
   1625			/* Get SMU Display PLL VCO Frequency in KHz*/
   1626			info->smu_gpu_pll_output_freq =	dce_info_v4_4->dispclk_pll_vco_freq * 10;
   1627			break;
   1628
   1629		default:
   1630			/* should not come here, keep as backup, as was before */
   1631			dce_info_v4_1 = GET_IMAGE(struct atom_display_controller_info_v4_1,
   1632							DATA_TABLES(dce_info));
   1633
   1634			if (!dce_info_v4_1)
   1635				return BP_RESULT_BADBIOSTABLE;
   1636
   1637			info->pll_info.crystal_frequency = dce_info_v4_1->dce_refclk_10khz * 10;
   1638			info->dp_phy_ref_clk             = dce_info_v4_1->dpphy_refclk_10khz * 10;
   1639			info->i2c_engine_ref_clk         = dce_info_v4_1->i2c_engine_refclk_10khz * 10;
   1640			break;
   1641		}
   1642		break;
   1643
   1644	default:
   1645		ASSERT(0);
   1646		break;
   1647	}
   1648
   1649	header = GET_IMAGE(struct atom_common_table_header,
   1650					DATA_TABLES(smu_info));
   1651	get_atom_data_table_revision(header, &revision);
   1652
   1653	 // We need to convert from 10KHz units into KHz units.
   1654	info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
   1655
   1656	if (firmware_info->board_i2c_feature_id == 0x2) {
   1657		info->oem_i2c_present = true;
   1658		info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;
   1659	} else {
   1660		info->oem_i2c_present = false;
   1661	}
   1662
   1663	return BP_RESULT_OK;
   1664}
   1665
   1666static enum bp_result bios_parser_get_encoder_cap_info(
   1667	struct dc_bios *dcb,
   1668	struct graphics_object_id object_id,
   1669	struct bp_encoder_cap_info *info)
   1670{
   1671	struct bios_parser *bp = BP_FROM_DCB(dcb);
   1672	struct atom_display_object_path_v2 *object;
   1673	struct atom_encoder_caps_record *record = NULL;
   1674
   1675	if (!info)
   1676		return BP_RESULT_BADINPUT;
   1677
   1678	object = get_bios_object(bp, object_id);
   1679
   1680	if (!object)
   1681		return BP_RESULT_BADINPUT;
   1682
   1683	record = get_encoder_cap_record(bp, object);
   1684	if (!record)
   1685		return BP_RESULT_NORECORD;
   1686
   1687	info->DP_HBR2_CAP = (record->encodercaps &
   1688			ATOM_ENCODER_CAP_RECORD_HBR2) ? 1 : 0;
   1689	info->DP_HBR2_EN = (record->encodercaps &
   1690			ATOM_ENCODER_CAP_RECORD_HBR2_EN) ? 1 : 0;
   1691	info->DP_HBR3_EN = (record->encodercaps &
   1692			ATOM_ENCODER_CAP_RECORD_HBR3_EN) ? 1 : 0;
   1693	info->HDMI_6GB_EN = (record->encodercaps &
   1694			ATOM_ENCODER_CAP_RECORD_HDMI6Gbps_EN) ? 1 : 0;
   1695	info->IS_DP2_CAPABLE = (record->encodercaps &
   1696			ATOM_ENCODER_CAP_RECORD_DP2) ? 1 : 0;
   1697	info->DP_UHBR10_EN = (record->encodercaps &
   1698			ATOM_ENCODER_CAP_RECORD_UHBR10_EN) ? 1 : 0;
   1699	info->DP_UHBR13_5_EN = (record->encodercaps &
   1700			ATOM_ENCODER_CAP_RECORD_UHBR13_5_EN) ? 1 : 0;
   1701	info->DP_UHBR20_EN = (record->encodercaps &
   1702			ATOM_ENCODER_CAP_RECORD_UHBR20_EN) ? 1 : 0;
   1703	info->DP_IS_USB_C = (record->encodercaps &
   1704			ATOM_ENCODER_CAP_RECORD_USB_C_TYPE) ? 1 : 0;
   1705
   1706	return BP_RESULT_OK;
   1707}
   1708
   1709
   1710static struct atom_encoder_caps_record *get_encoder_cap_record(
   1711	struct bios_parser *bp,
   1712	struct atom_display_object_path_v2 *object)
   1713{
   1714	struct atom_common_record_header *header;
   1715	uint32_t offset;
   1716
   1717	if (!object) {
   1718		BREAK_TO_DEBUGGER(); /* Invalid object */
   1719		return NULL;
   1720	}
   1721
   1722	offset = object->encoder_recordoffset + bp->object_info_tbl_offset;
   1723
   1724	for (;;) {
   1725		header = GET_IMAGE(struct atom_common_record_header, offset);
   1726
   1727		if (!header)
   1728			return NULL;
   1729
   1730		offset += header->record_size;
   1731
   1732		if (header->record_type == LAST_RECORD_TYPE ||
   1733				!header->record_size)
   1734			break;
   1735
   1736		if (header->record_type != ATOM_ENCODER_CAP_RECORD_TYPE)
   1737			continue;
   1738
   1739		if (sizeof(struct atom_encoder_caps_record) <=
   1740							header->record_size)
   1741			return (struct atom_encoder_caps_record *)header;
   1742	}
   1743
   1744	return NULL;
   1745}
   1746
   1747static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
   1748	struct bios_parser *bp,
   1749	struct atom_display_object_path_v2 *object)
   1750{
   1751	struct atom_common_record_header *header;
   1752	uint32_t offset;
   1753
   1754	if (!object) {
   1755		BREAK_TO_DEBUGGER(); /* Invalid object */
   1756		return NULL;
   1757	}
   1758
   1759	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
   1760
   1761	for (;;) {
   1762		header = GET_IMAGE(struct atom_common_record_header, offset);
   1763
   1764		if (!header)
   1765			return NULL;
   1766
   1767		offset += header->record_size;
   1768
   1769		if (header->record_type == LAST_RECORD_TYPE ||
   1770				!header->record_size)
   1771			break;
   1772
   1773		if (header->record_type != ATOM_DISP_CONNECTOR_CAPS_RECORD_TYPE)
   1774			continue;
   1775
   1776		if (sizeof(struct atom_disp_connector_caps_record) <=
   1777							header->record_size)
   1778			return (struct atom_disp_connector_caps_record *)header;
   1779	}
   1780
   1781	return NULL;
   1782}
   1783
   1784static enum bp_result bios_parser_get_disp_connector_caps_info(
   1785	struct dc_bios *dcb,
   1786	struct graphics_object_id object_id,
   1787	struct bp_disp_connector_caps_info *info)
   1788{
   1789	struct bios_parser *bp = BP_FROM_DCB(dcb);
   1790	struct atom_display_object_path_v2 *object;
   1791	struct atom_disp_connector_caps_record *record = NULL;
   1792
   1793	if (!info)
   1794		return BP_RESULT_BADINPUT;
   1795
   1796	object = get_bios_object(bp, object_id);
   1797
   1798	if (!object)
   1799		return BP_RESULT_BADINPUT;
   1800
   1801	record = get_disp_connector_caps_record(bp, object);
   1802	if (!record)
   1803		return BP_RESULT_NORECORD;
   1804
   1805	info->INTERNAL_DISPLAY = (record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY)
   1806									? 1 : 0;
   1807	info->INTERNAL_DISPLAY_BL = (record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL)
   1808											? 1 : 0;
   1809
   1810	return BP_RESULT_OK;
   1811}
   1812
   1813static enum bp_result get_vram_info_v23(
   1814	struct bios_parser *bp,
   1815	struct dc_vram_info *info)
   1816{
   1817	struct atom_vram_info_header_v2_3 *info_v23;
   1818	enum bp_result result = BP_RESULT_OK;
   1819
   1820	info_v23 = GET_IMAGE(struct atom_vram_info_header_v2_3,
   1821						DATA_TABLES(vram_info));
   1822
   1823	if (info_v23 == NULL)
   1824		return BP_RESULT_BADBIOSTABLE;
   1825
   1826	info->num_chans = info_v23->vram_module[0].channel_num;
   1827	info->dram_channel_width_bytes = (1 << info_v23->vram_module[0].channel_width) / 8;
   1828
   1829	return result;
   1830}
   1831
   1832static enum bp_result get_vram_info_v24(
   1833	struct bios_parser *bp,
   1834	struct dc_vram_info *info)
   1835{
   1836	struct atom_vram_info_header_v2_4 *info_v24;
   1837	enum bp_result result = BP_RESULT_OK;
   1838
   1839	info_v24 = GET_IMAGE(struct atom_vram_info_header_v2_4,
   1840						DATA_TABLES(vram_info));
   1841
   1842	if (info_v24 == NULL)
   1843		return BP_RESULT_BADBIOSTABLE;
   1844
   1845	info->num_chans = info_v24->vram_module[0].channel_num;
   1846	info->dram_channel_width_bytes = (1 << info_v24->vram_module[0].channel_width) / 8;
   1847
   1848	return result;
   1849}
   1850
   1851static enum bp_result get_vram_info_v25(
   1852	struct bios_parser *bp,
   1853	struct dc_vram_info *info)
   1854{
   1855	struct atom_vram_info_header_v2_5 *info_v25;
   1856	enum bp_result result = BP_RESULT_OK;
   1857
   1858	info_v25 = GET_IMAGE(struct atom_vram_info_header_v2_5,
   1859						DATA_TABLES(vram_info));
   1860
   1861	if (info_v25 == NULL)
   1862		return BP_RESULT_BADBIOSTABLE;
   1863
   1864	info->num_chans = info_v25->vram_module[0].channel_num;
   1865	info->dram_channel_width_bytes = (1 << info_v25->vram_module[0].channel_width) / 8;
   1866
   1867	return result;
   1868}
   1869
   1870/*
   1871 * get_integrated_info_v11
   1872 *
   1873 * @brief
   1874 * Get V8 integrated BIOS information
   1875 *
   1876 * @param
   1877 * bios_parser *bp - [in]BIOS parser handler to get master data table
   1878 * integrated_info *info - [out] store and output integrated info
   1879 *
   1880 * @return
   1881 * enum bp_result - BP_RESULT_OK if information is available,
   1882 *                  BP_RESULT_BADBIOSTABLE otherwise.
   1883 */
   1884static enum bp_result get_integrated_info_v11(
   1885	struct bios_parser *bp,
   1886	struct integrated_info *info)
   1887{
   1888	struct atom_integrated_system_info_v1_11 *info_v11;
   1889	uint32_t i;
   1890
   1891	info_v11 = GET_IMAGE(struct atom_integrated_system_info_v1_11,
   1892					DATA_TABLES(integratedsysteminfo));
   1893
   1894	if (info_v11 == NULL)
   1895		return BP_RESULT_BADBIOSTABLE;
   1896
   1897	info->gpu_cap_info =
   1898	le32_to_cpu(info_v11->gpucapinfo);
   1899	/*
   1900	* system_config: Bit[0] = 0 : PCIE power gating disabled
   1901	*                       = 1 : PCIE power gating enabled
   1902	*                Bit[1] = 0 : DDR-PLL shut down disabled
   1903	*                       = 1 : DDR-PLL shut down enabled
   1904	*                Bit[2] = 0 : DDR-PLL power down disabled
   1905	*                       = 1 : DDR-PLL power down enabled
   1906	*/
   1907	info->system_config = le32_to_cpu(info_v11->system_config);
   1908	info->cpu_cap_info = le32_to_cpu(info_v11->cpucapinfo);
   1909	info->memory_type = info_v11->memorytype;
   1910	info->ma_channel_number = info_v11->umachannelnumber;
   1911	info->lvds_ss_percentage =
   1912	le16_to_cpu(info_v11->lvds_ss_percentage);
   1913	info->dp_ss_control =
   1914	le16_to_cpu(info_v11->reserved1);
   1915	info->lvds_sspread_rate_in_10hz =
   1916	le16_to_cpu(info_v11->lvds_ss_rate_10hz);
   1917	info->hdmi_ss_percentage =
   1918	le16_to_cpu(info_v11->hdmi_ss_percentage);
   1919	info->hdmi_sspread_rate_in_10hz =
   1920	le16_to_cpu(info_v11->hdmi_ss_rate_10hz);
   1921	info->dvi_ss_percentage =
   1922	le16_to_cpu(info_v11->dvi_ss_percentage);
   1923	info->dvi_sspread_rate_in_10_hz =
   1924	le16_to_cpu(info_v11->dvi_ss_rate_10hz);
   1925	info->lvds_misc = info_v11->lvds_misc;
   1926	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
   1927		info->ext_disp_conn_info.gu_id[i] =
   1928				info_v11->extdispconninfo.guid[i];
   1929	}
   1930
   1931	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
   1932		info->ext_disp_conn_info.path[i].device_connector_id =
   1933		object_id_from_bios_object_id(
   1934		le16_to_cpu(info_v11->extdispconninfo.path[i].connectorobjid));
   1935
   1936		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
   1937		object_id_from_bios_object_id(
   1938			le16_to_cpu(
   1939			info_v11->extdispconninfo.path[i].ext_encoder_objid));
   1940
   1941		info->ext_disp_conn_info.path[i].device_tag =
   1942			le16_to_cpu(
   1943				info_v11->extdispconninfo.path[i].device_tag);
   1944		info->ext_disp_conn_info.path[i].device_acpi_enum =
   1945		le16_to_cpu(
   1946			info_v11->extdispconninfo.path[i].device_acpi_enum);
   1947		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
   1948			info_v11->extdispconninfo.path[i].auxddclut_index;
   1949		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
   1950			info_v11->extdispconninfo.path[i].hpdlut_index;
   1951		info->ext_disp_conn_info.path[i].channel_mapping.raw =
   1952			info_v11->extdispconninfo.path[i].channelmapping;
   1953		info->ext_disp_conn_info.path[i].caps =
   1954				le16_to_cpu(info_v11->extdispconninfo.path[i].caps);
   1955	}
   1956	info->ext_disp_conn_info.checksum =
   1957	info_v11->extdispconninfo.checksum;
   1958
   1959	info->dp0_ext_hdmi_slv_addr = info_v11->dp0_retimer_set.HdmiSlvAddr;
   1960	info->dp0_ext_hdmi_reg_num = info_v11->dp0_retimer_set.HdmiRegNum;
   1961	for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
   1962		info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
   1963				info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
   1964		info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
   1965				info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
   1966	}
   1967	info->dp0_ext_hdmi_6g_reg_num = info_v11->dp0_retimer_set.Hdmi6GRegNum;
   1968	for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
   1969		info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
   1970				info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
   1971		info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
   1972				info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
   1973	}
   1974
   1975	info->dp1_ext_hdmi_slv_addr = info_v11->dp1_retimer_set.HdmiSlvAddr;
   1976	info->dp1_ext_hdmi_reg_num = info_v11->dp1_retimer_set.HdmiRegNum;
   1977	for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
   1978		info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
   1979				info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
   1980		info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
   1981				info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
   1982	}
   1983	info->dp1_ext_hdmi_6g_reg_num = info_v11->dp1_retimer_set.Hdmi6GRegNum;
   1984	for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
   1985		info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
   1986				info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
   1987		info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
   1988				info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
   1989	}
   1990
   1991	info->dp2_ext_hdmi_slv_addr = info_v11->dp2_retimer_set.HdmiSlvAddr;
   1992	info->dp2_ext_hdmi_reg_num = info_v11->dp2_retimer_set.HdmiRegNum;
   1993	for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
   1994		info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
   1995				info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
   1996		info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
   1997				info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
   1998	}
   1999	info->dp2_ext_hdmi_6g_reg_num = info_v11->dp2_retimer_set.Hdmi6GRegNum;
   2000	for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
   2001		info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
   2002				info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
   2003		info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
   2004				info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
   2005	}
   2006
   2007	info->dp3_ext_hdmi_slv_addr = info_v11->dp3_retimer_set.HdmiSlvAddr;
   2008	info->dp3_ext_hdmi_reg_num = info_v11->dp3_retimer_set.HdmiRegNum;
   2009	for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
   2010		info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
   2011				info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
   2012		info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
   2013				info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
   2014	}
   2015	info->dp3_ext_hdmi_6g_reg_num = info_v11->dp3_retimer_set.Hdmi6GRegNum;
   2016	for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
   2017		info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
   2018				info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
   2019		info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
   2020				info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
   2021	}
   2022
   2023
   2024	/** TODO - review **/
   2025	#if 0
   2026	info->boot_up_engine_clock = le32_to_cpu(info_v11->ulBootUpEngineClock)
   2027									* 10;
   2028	info->dentist_vco_freq = le32_to_cpu(info_v11->ulDentistVCOFreq) * 10;
   2029	info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
   2030
   2031	for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
   2032		/* Convert [10KHz] into [KHz] */
   2033		info->disp_clk_voltage[i].max_supported_clk =
   2034		le32_to_cpu(info_v11->sDISPCLK_Voltage[i].
   2035			ulMaximumSupportedCLK) * 10;
   2036		info->disp_clk_voltage[i].voltage_index =
   2037		le32_to_cpu(info_v11->sDISPCLK_Voltage[i].ulVoltageIndex);
   2038	}
   2039
   2040	info->boot_up_req_display_vector =
   2041			le32_to_cpu(info_v11->ulBootUpReqDisplayVector);
   2042	info->boot_up_nb_voltage =
   2043			le16_to_cpu(info_v11->usBootUpNBVoltage);
   2044	info->ext_disp_conn_info_offset =
   2045			le16_to_cpu(info_v11->usExtDispConnInfoOffset);
   2046	info->gmc_restore_reset_time =
   2047			le32_to_cpu(info_v11->ulGMCRestoreResetTime);
   2048	info->minimum_n_clk =
   2049			le32_to_cpu(info_v11->ulNbpStateNClkFreq[0]);
   2050	for (i = 1; i < 4; ++i)
   2051		info->minimum_n_clk =
   2052				info->minimum_n_clk <
   2053				le32_to_cpu(info_v11->ulNbpStateNClkFreq[i]) ?
   2054				info->minimum_n_clk : le32_to_cpu(
   2055					info_v11->ulNbpStateNClkFreq[i]);
   2056
   2057	info->idle_n_clk = le32_to_cpu(info_v11->ulIdleNClk);
   2058	info->ddr_dll_power_up_time =
   2059	    le32_to_cpu(info_v11->ulDDR_DLL_PowerUpTime);
   2060	info->ddr_pll_power_up_time =
   2061		le32_to_cpu(info_v11->ulDDR_PLL_PowerUpTime);
   2062	info->pcie_clk_ss_type = le16_to_cpu(info_v11->usPCIEClkSSType);
   2063	info->max_lvds_pclk_freq_in_single_link =
   2064		le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink);
   2065	info->max_lvds_pclk_freq_in_single_link =
   2066		le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink);
   2067	info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
   2068		info_v11->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
   2069	info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
   2070		info_v11->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
   2071	info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
   2072		info_v11->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
   2073	info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
   2074		info_v11->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
   2075	info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
   2076		info_v11->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
   2077	info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
   2078		info_v11->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
   2079	info->lvds_off_to_on_delay_in_4ms =
   2080		info_v11->ucLVDSOffToOnDelay_in4Ms;
   2081	info->lvds_bit_depth_control_val =
   2082		le32_to_cpu(info_v11->ulLCDBitDepthControlVal);
   2083
   2084	for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
   2085		/* Convert [10KHz] into [KHz] */
   2086		info->avail_s_clk[i].supported_s_clk =
   2087			le32_to_cpu(info_v11->sAvail_SCLK[i].ulSupportedSCLK)
   2088									* 10;
   2089		info->avail_s_clk[i].voltage_index =
   2090			le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageIndex);
   2091		info->avail_s_clk[i].voltage_id =
   2092			le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageID);
   2093	}
   2094	#endif /* TODO*/
   2095
   2096	return BP_RESULT_OK;
   2097}
   2098
   2099static enum bp_result get_integrated_info_v2_1(
   2100	struct bios_parser *bp,
   2101	struct integrated_info *info)
   2102{
   2103	struct atom_integrated_system_info_v2_1 *info_v2_1;
   2104	uint32_t i;
   2105
   2106	info_v2_1 = GET_IMAGE(struct atom_integrated_system_info_v2_1,
   2107					DATA_TABLES(integratedsysteminfo));
   2108
   2109	if (info_v2_1 == NULL)
   2110		return BP_RESULT_BADBIOSTABLE;
   2111
   2112	info->gpu_cap_info =
   2113	le32_to_cpu(info_v2_1->gpucapinfo);
   2114	/*
   2115	* system_config: Bit[0] = 0 : PCIE power gating disabled
   2116	*                       = 1 : PCIE power gating enabled
   2117	*                Bit[1] = 0 : DDR-PLL shut down disabled
   2118	*                       = 1 : DDR-PLL shut down enabled
   2119	*                Bit[2] = 0 : DDR-PLL power down disabled
   2120	*                       = 1 : DDR-PLL power down enabled
   2121	*/
   2122	info->system_config = le32_to_cpu(info_v2_1->system_config);
   2123	info->cpu_cap_info = le32_to_cpu(info_v2_1->cpucapinfo);
   2124	info->memory_type = info_v2_1->memorytype;
   2125	info->ma_channel_number = info_v2_1->umachannelnumber;
   2126	info->dp_ss_control =
   2127		le16_to_cpu(info_v2_1->reserved1);
   2128
   2129	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
   2130		info->ext_disp_conn_info.gu_id[i] =
   2131				info_v2_1->extdispconninfo.guid[i];
   2132	}
   2133
   2134	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
   2135		info->ext_disp_conn_info.path[i].device_connector_id =
   2136		object_id_from_bios_object_id(
   2137		le16_to_cpu(info_v2_1->extdispconninfo.path[i].connectorobjid));
   2138
   2139		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
   2140		object_id_from_bios_object_id(
   2141			le16_to_cpu(
   2142			info_v2_1->extdispconninfo.path[i].ext_encoder_objid));
   2143
   2144		info->ext_disp_conn_info.path[i].device_tag =
   2145			le16_to_cpu(
   2146				info_v2_1->extdispconninfo.path[i].device_tag);
   2147		info->ext_disp_conn_info.path[i].device_acpi_enum =
   2148		le16_to_cpu(
   2149			info_v2_1->extdispconninfo.path[i].device_acpi_enum);
   2150		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
   2151			info_v2_1->extdispconninfo.path[i].auxddclut_index;
   2152		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
   2153			info_v2_1->extdispconninfo.path[i].hpdlut_index;
   2154		info->ext_disp_conn_info.path[i].channel_mapping.raw =
   2155			info_v2_1->extdispconninfo.path[i].channelmapping;
   2156		info->ext_disp_conn_info.path[i].caps =
   2157				le16_to_cpu(info_v2_1->extdispconninfo.path[i].caps);
   2158	}
   2159
   2160	info->ext_disp_conn_info.checksum =
   2161		info_v2_1->extdispconninfo.checksum;
   2162	info->dp0_ext_hdmi_slv_addr = info_v2_1->dp0_retimer_set.HdmiSlvAddr;
   2163	info->dp0_ext_hdmi_reg_num = info_v2_1->dp0_retimer_set.HdmiRegNum;
   2164	for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
   2165		info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
   2166				info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
   2167		info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
   2168				info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
   2169	}
   2170	info->dp0_ext_hdmi_6g_reg_num = info_v2_1->dp0_retimer_set.Hdmi6GRegNum;
   2171	for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
   2172		info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
   2173				info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
   2174		info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
   2175				info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
   2176	}
   2177	info->dp1_ext_hdmi_slv_addr = info_v2_1->dp1_retimer_set.HdmiSlvAddr;
   2178	info->dp1_ext_hdmi_reg_num = info_v2_1->dp1_retimer_set.HdmiRegNum;
   2179	for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
   2180		info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
   2181				info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
   2182		info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
   2183				info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
   2184	}
   2185	info->dp1_ext_hdmi_6g_reg_num = info_v2_1->dp1_retimer_set.Hdmi6GRegNum;
   2186	for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
   2187		info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
   2188				info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
   2189		info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
   2190				info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
   2191	}
   2192	info->dp2_ext_hdmi_slv_addr = info_v2_1->dp2_retimer_set.HdmiSlvAddr;
   2193	info->dp2_ext_hdmi_reg_num = info_v2_1->dp2_retimer_set.HdmiRegNum;
   2194	for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
   2195		info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
   2196				info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
   2197		info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
   2198				info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
   2199	}
   2200	info->dp2_ext_hdmi_6g_reg_num = info_v2_1->dp2_retimer_set.Hdmi6GRegNum;
   2201	for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
   2202		info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
   2203				info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
   2204		info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
   2205				info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
   2206	}
   2207	info->dp3_ext_hdmi_slv_addr = info_v2_1->dp3_retimer_set.HdmiSlvAddr;
   2208	info->dp3_ext_hdmi_reg_num = info_v2_1->dp3_retimer_set.HdmiRegNum;
   2209	for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
   2210		info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
   2211				info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
   2212		info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
   2213				info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
   2214	}
   2215	info->dp3_ext_hdmi_6g_reg_num = info_v2_1->dp3_retimer_set.Hdmi6GRegNum;
   2216	for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
   2217		info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
   2218				info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
   2219		info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
   2220				info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
   2221	}
   2222
   2223	info->edp1_info.edp_backlight_pwm_hz =
   2224	le16_to_cpu(info_v2_1->edp1_info.edp_backlight_pwm_hz);
   2225	info->edp1_info.edp_ss_percentage =
   2226	le16_to_cpu(info_v2_1->edp1_info.edp_ss_percentage);
   2227	info->edp1_info.edp_ss_rate_10hz =
   2228	le16_to_cpu(info_v2_1->edp1_info.edp_ss_rate_10hz);
   2229	info->edp1_info.edp_pwr_on_off_delay =
   2230		info_v2_1->edp1_info.edp_pwr_on_off_delay;
   2231	info->edp1_info.edp_pwr_on_vary_bl_to_blon =
   2232		info_v2_1->edp1_info.edp_pwr_on_vary_bl_to_blon;
   2233	info->edp1_info.edp_pwr_down_bloff_to_vary_bloff =
   2234		info_v2_1->edp1_info.edp_pwr_down_bloff_to_vary_bloff;
   2235	info->edp1_info.edp_panel_bpc =
   2236		info_v2_1->edp1_info.edp_panel_bpc;
   2237	info->edp1_info.edp_bootup_bl_level = info_v2_1->edp1_info.edp_bootup_bl_level;
   2238
   2239	info->edp2_info.edp_backlight_pwm_hz =
   2240	le16_to_cpu(info_v2_1->edp2_info.edp_backlight_pwm_hz);
   2241	info->edp2_info.edp_ss_percentage =
   2242	le16_to_cpu(info_v2_1->edp2_info.edp_ss_percentage);
   2243	info->edp2_info.edp_ss_rate_10hz =
   2244	le16_to_cpu(info_v2_1->edp2_info.edp_ss_rate_10hz);
   2245	info->edp2_info.edp_pwr_on_off_delay =
   2246		info_v2_1->edp2_info.edp_pwr_on_off_delay;
   2247	info->edp2_info.edp_pwr_on_vary_bl_to_blon =
   2248		info_v2_1->edp2_info.edp_pwr_on_vary_bl_to_blon;
   2249	info->edp2_info.edp_pwr_down_bloff_to_vary_bloff =
   2250		info_v2_1->edp2_info.edp_pwr_down_bloff_to_vary_bloff;
   2251	info->edp2_info.edp_panel_bpc =
   2252		info_v2_1->edp2_info.edp_panel_bpc;
   2253	info->edp2_info.edp_bootup_bl_level =
   2254		info_v2_1->edp2_info.edp_bootup_bl_level;
   2255
   2256	return BP_RESULT_OK;
   2257}
   2258
   2259static enum bp_result get_integrated_info_v2_2(
   2260	struct bios_parser *bp,
   2261	struct integrated_info *info)
   2262{
   2263	struct atom_integrated_system_info_v2_2 *info_v2_2;
   2264	uint32_t i;
   2265
   2266	info_v2_2 = GET_IMAGE(struct atom_integrated_system_info_v2_2,
   2267					DATA_TABLES(integratedsysteminfo));
   2268
   2269	if (info_v2_2 == NULL)
   2270		return BP_RESULT_BADBIOSTABLE;
   2271
   2272	info->gpu_cap_info =
   2273	le32_to_cpu(info_v2_2->gpucapinfo);
   2274	/*
   2275	* system_config: Bit[0] = 0 : PCIE power gating disabled
   2276	*                       = 1 : PCIE power gating enabled
   2277	*                Bit[1] = 0 : DDR-PLL shut down disabled
   2278	*                       = 1 : DDR-PLL shut down enabled
   2279	*                Bit[2] = 0 : DDR-PLL power down disabled
   2280	*                       = 1 : DDR-PLL power down enabled
   2281	*/
   2282	info->system_config = le32_to_cpu(info_v2_2->system_config);
   2283	info->cpu_cap_info = le32_to_cpu(info_v2_2->cpucapinfo);
   2284	info->memory_type = info_v2_2->memorytype;
   2285	info->ma_channel_number = info_v2_2->umachannelnumber;
   2286	info->dp_ss_control =
   2287		le16_to_cpu(info_v2_2->reserved1);
   2288
   2289	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
   2290		info->ext_disp_conn_info.gu_id[i] =
   2291				info_v2_2->extdispconninfo.guid[i];
   2292	}
   2293
   2294	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
   2295		info->ext_disp_conn_info.path[i].device_connector_id =
   2296		object_id_from_bios_object_id(
   2297		le16_to_cpu(info_v2_2->extdispconninfo.path[i].connectorobjid));
   2298
   2299		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
   2300		object_id_from_bios_object_id(
   2301			le16_to_cpu(
   2302			info_v2_2->extdispconninfo.path[i].ext_encoder_objid));
   2303
   2304		info->ext_disp_conn_info.path[i].device_tag =
   2305			le16_to_cpu(
   2306				info_v2_2->extdispconninfo.path[i].device_tag);
   2307		info->ext_disp_conn_info.path[i].device_acpi_enum =
   2308		le16_to_cpu(
   2309			info_v2_2->extdispconninfo.path[i].device_acpi_enum);
   2310		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
   2311			info_v2_2->extdispconninfo.path[i].auxddclut_index;
   2312		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
   2313			info_v2_2->extdispconninfo.path[i].hpdlut_index;
   2314		info->ext_disp_conn_info.path[i].channel_mapping.raw =
   2315			info_v2_2->extdispconninfo.path[i].channelmapping;
   2316		info->ext_disp_conn_info.path[i].caps =
   2317				le16_to_cpu(info_v2_2->extdispconninfo.path[i].caps);
   2318	}
   2319
   2320	info->ext_disp_conn_info.checksum =
   2321		info_v2_2->extdispconninfo.checksum;
   2322	info->ext_disp_conn_info.fixdpvoltageswing =
   2323		info_v2_2->extdispconninfo.fixdpvoltageswing;
   2324
   2325	info->edp1_info.edp_backlight_pwm_hz =
   2326	le16_to_cpu(info_v2_2->edp1_info.edp_backlight_pwm_hz);
   2327	info->edp1_info.edp_ss_percentage =
   2328	le16_to_cpu(info_v2_2->edp1_info.edp_ss_percentage);
   2329	info->edp1_info.edp_ss_rate_10hz =
   2330	le16_to_cpu(info_v2_2->edp1_info.edp_ss_rate_10hz);
   2331	info->edp1_info.edp_pwr_on_off_delay =
   2332		info_v2_2->edp1_info.edp_pwr_on_off_delay;
   2333	info->edp1_info.edp_pwr_on_vary_bl_to_blon =
   2334		info_v2_2->edp1_info.edp_pwr_on_vary_bl_to_blon;
   2335	info->edp1_info.edp_pwr_down_bloff_to_vary_bloff =
   2336		info_v2_2->edp1_info.edp_pwr_down_bloff_to_vary_bloff;
   2337	info->edp1_info.edp_panel_bpc =
   2338		info_v2_2->edp1_info.edp_panel_bpc;
   2339	info->edp1_info.edp_bootup_bl_level =
   2340
   2341	info->edp2_info.edp_backlight_pwm_hz =
   2342	le16_to_cpu(info_v2_2->edp2_info.edp_backlight_pwm_hz);
   2343	info->edp2_info.edp_ss_percentage =
   2344	le16_to_cpu(info_v2_2->edp2_info.edp_ss_percentage);
   2345	info->edp2_info.edp_ss_rate_10hz =
   2346	le16_to_cpu(info_v2_2->edp2_info.edp_ss_rate_10hz);
   2347	info->edp2_info.edp_pwr_on_off_delay =
   2348		info_v2_2->edp2_info.edp_pwr_on_off_delay;
   2349	info->edp2_info.edp_pwr_on_vary_bl_to_blon =
   2350		info_v2_2->edp2_info.edp_pwr_on_vary_bl_to_blon;
   2351	info->edp2_info.edp_pwr_down_bloff_to_vary_bloff =
   2352		info_v2_2->edp2_info.edp_pwr_down_bloff_to_vary_bloff;
   2353	info->edp2_info.edp_panel_bpc =
   2354		info_v2_2->edp2_info.edp_panel_bpc;
   2355	info->edp2_info.edp_bootup_bl_level =
   2356		info_v2_2->edp2_info.edp_bootup_bl_level;
   2357
   2358	return BP_RESULT_OK;
   2359}
   2360
   2361/*
   2362 * construct_integrated_info
   2363 *
   2364 * @brief
   2365 * Get integrated BIOS information based on table revision
   2366 *
   2367 * @param
   2368 * bios_parser *bp - [in]BIOS parser handler to get master data table
   2369 * integrated_info *info - [out] store and output integrated info
   2370 *
   2371 * @return
   2372 * enum bp_result - BP_RESULT_OK if information is available,
   2373 *                  BP_RESULT_BADBIOSTABLE otherwise.
   2374 */
   2375static enum bp_result construct_integrated_info(
   2376	struct bios_parser *bp,
   2377	struct integrated_info *info)
   2378{
   2379	enum bp_result result = BP_RESULT_BADBIOSTABLE;
   2380
   2381	struct atom_common_table_header *header;
   2382	struct atom_data_revision revision;
   2383	uint32_t i;
   2384	uint32_t j;
   2385
   2386	if (info && DATA_TABLES(integratedsysteminfo)) {
   2387		header = GET_IMAGE(struct atom_common_table_header,
   2388					DATA_TABLES(integratedsysteminfo));
   2389
   2390		get_atom_data_table_revision(header, &revision);
   2391
   2392		switch (revision.major) {
   2393		case 1:
   2394			switch (revision.minor) {
   2395			case 11:
   2396			case 12:
   2397				result = get_integrated_info_v11(bp, info);
   2398				break;
   2399			default:
   2400				return result;
   2401			}
   2402			break;
   2403		case 2:
   2404			switch (revision.minor) {
   2405			case 1:
   2406				result = get_integrated_info_v2_1(bp, info);
   2407				break;
   2408			case 2:
   2409				result = get_integrated_info_v2_2(bp, info);
   2410				break;
   2411			default:
   2412				return result;
   2413			}
   2414			break;
   2415		default:
   2416			return result;
   2417		}
   2418	}
   2419
   2420	if (result != BP_RESULT_OK)
   2421		return result;
   2422
   2423	/* Sort voltage table from low to high*/
   2424	for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
   2425		for (j = i; j > 0; --j) {
   2426			if (info->disp_clk_voltage[j].max_supported_clk <
   2427				info->disp_clk_voltage[j-1].max_supported_clk
   2428				) {
   2429				/* swap j and j - 1*/
   2430				swap(info->disp_clk_voltage[j - 1],
   2431				     info->disp_clk_voltage[j]);
   2432			}
   2433		}
   2434	}
   2435
   2436	return result;
   2437}
   2438
   2439static enum bp_result bios_parser_get_vram_info(
   2440		struct dc_bios *dcb,
   2441		struct dc_vram_info *info)
   2442{
   2443	struct bios_parser *bp = BP_FROM_DCB(dcb);
   2444	enum bp_result result = BP_RESULT_BADBIOSTABLE;
   2445	struct atom_common_table_header *header;
   2446	struct atom_data_revision revision;
   2447
   2448	if (info && DATA_TABLES(vram_info)) {
   2449		header = GET_IMAGE(struct atom_common_table_header,
   2450					DATA_TABLES(vram_info));
   2451
   2452		get_atom_data_table_revision(header, &revision);
   2453
   2454		switch (revision.major) {
   2455		case 2:
   2456			switch (revision.minor) {
   2457			case 3:
   2458				result = get_vram_info_v23(bp, info);
   2459				break;
   2460			case 4:
   2461				result = get_vram_info_v24(bp, info);
   2462				break;
   2463			case 5:
   2464				result = get_vram_info_v25(bp, info);
   2465				break;
   2466			default:
   2467				break;
   2468			}
   2469			break;
   2470
   2471		default:
   2472			return result;
   2473		}
   2474
   2475	}
   2476	return result;
   2477}
   2478
   2479static struct integrated_info *bios_parser_create_integrated_info(
   2480	struct dc_bios *dcb)
   2481{
   2482	struct bios_parser *bp = BP_FROM_DCB(dcb);
   2483	struct integrated_info *info = NULL;
   2484
   2485	info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL);
   2486
   2487	if (info == NULL) {
   2488		ASSERT_CRITICAL(0);
   2489		return NULL;
   2490	}
   2491
   2492	if (construct_integrated_info(bp, info) == BP_RESULT_OK)
   2493		return info;
   2494
   2495	kfree(info);
   2496
   2497	return NULL;
   2498}
   2499
   2500static enum bp_result update_slot_layout_info(
   2501	struct dc_bios *dcb,
   2502	unsigned int i,
   2503	struct slot_layout_info *slot_layout_info)
   2504{
   2505	unsigned int record_offset;
   2506	unsigned int j;
   2507	struct atom_display_object_path_v2 *object;
   2508	struct atom_bracket_layout_record *record;
   2509	struct atom_common_record_header *record_header;
   2510	enum bp_result result;
   2511	struct bios_parser *bp;
   2512	struct object_info_table *tbl;
   2513	struct display_object_info_table_v1_4 *v1_4;
   2514
   2515	record = NULL;
   2516	record_header = NULL;
   2517	result = BP_RESULT_NORECORD;
   2518
   2519	bp = BP_FROM_DCB(dcb);
   2520	tbl = &bp->object_info_tbl;
   2521	v1_4 = tbl->v1_4;
   2522
   2523	object = &v1_4->display_path[i];
   2524	record_offset = (unsigned int)
   2525		(object->disp_recordoffset) +
   2526		(unsigned int)(bp->object_info_tbl_offset);
   2527
   2528	for (;;) {
   2529
   2530		record_header = (struct atom_common_record_header *)
   2531			GET_IMAGE(struct atom_common_record_header,
   2532			record_offset);
   2533		if (record_header == NULL) {
   2534			result = BP_RESULT_BADBIOSTABLE;
   2535			break;
   2536		}
   2537
   2538		/* the end of the list */
   2539		if (record_header->record_type == 0xff ||
   2540			record_header->record_size == 0)	{
   2541			break;
   2542		}
   2543
   2544		if (record_header->record_type ==
   2545			ATOM_BRACKET_LAYOUT_RECORD_TYPE &&
   2546			sizeof(struct atom_bracket_layout_record)
   2547			<= record_header->record_size) {
   2548			record = (struct atom_bracket_layout_record *)
   2549				(record_header);
   2550			result = BP_RESULT_OK;
   2551			break;
   2552		}
   2553
   2554		record_offset += record_header->record_size;
   2555	}
   2556
   2557	/* return if the record not found */
   2558	if (result != BP_RESULT_OK)
   2559		return result;
   2560
   2561	/* get slot sizes */
   2562	slot_layout_info->length = record->bracketlen;
   2563	slot_layout_info->width = record->bracketwidth;
   2564
   2565	/* get info for each connector in the slot */
   2566	slot_layout_info->num_of_connectors = record->conn_num;
   2567	for (j = 0; j < slot_layout_info->num_of_connectors; ++j) {
   2568		slot_layout_info->connectors[j].connector_type =
   2569			(enum connector_layout_type)
   2570			(record->conn_info[j].connector_type);
   2571		switch (record->conn_info[j].connector_type) {
   2572		case CONNECTOR_TYPE_DVI_D:
   2573			slot_layout_info->connectors[j].connector_type =
   2574				CONNECTOR_LAYOUT_TYPE_DVI_D;
   2575			slot_layout_info->connectors[j].length =
   2576				CONNECTOR_SIZE_DVI;
   2577			break;
   2578
   2579		case CONNECTOR_TYPE_HDMI:
   2580			slot_layout_info->connectors[j].connector_type =
   2581				CONNECTOR_LAYOUT_TYPE_HDMI;
   2582			slot_layout_info->connectors[j].length =
   2583				CONNECTOR_SIZE_HDMI;
   2584			break;
   2585
   2586		case CONNECTOR_TYPE_DISPLAY_PORT:
   2587			slot_layout_info->connectors[j].connector_type =
   2588				CONNECTOR_LAYOUT_TYPE_DP;
   2589			slot_layout_info->connectors[j].length =
   2590				CONNECTOR_SIZE_DP;
   2591			break;
   2592
   2593		case CONNECTOR_TYPE_MINI_DISPLAY_PORT:
   2594			slot_layout_info->connectors[j].connector_type =
   2595				CONNECTOR_LAYOUT_TYPE_MINI_DP;
   2596			slot_layout_info->connectors[j].length =
   2597				CONNECTOR_SIZE_MINI_DP;
   2598			break;
   2599
   2600		default:
   2601			slot_layout_info->connectors[j].connector_type =
   2602				CONNECTOR_LAYOUT_TYPE_UNKNOWN;
   2603			slot_layout_info->connectors[j].length =
   2604				CONNECTOR_SIZE_UNKNOWN;
   2605		}
   2606
   2607		slot_layout_info->connectors[j].position =
   2608			record->conn_info[j].position;
   2609		slot_layout_info->connectors[j].connector_id =
   2610			object_id_from_bios_object_id(
   2611				record->conn_info[j].connectorobjid);
   2612	}
   2613	return result;
   2614}
   2615
   2616
   2617static enum bp_result get_bracket_layout_record(
   2618	struct dc_bios *dcb,
   2619	unsigned int bracket_layout_id,
   2620	struct slot_layout_info *slot_layout_info)
   2621{
   2622	unsigned int i;
   2623	struct bios_parser *bp = BP_FROM_DCB(dcb);
   2624	enum bp_result result;
   2625	struct object_info_table *tbl;
   2626	struct display_object_info_table_v1_4 *v1_4;
   2627
   2628	if (slot_layout_info == NULL) {
   2629		DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");
   2630		return BP_RESULT_BADINPUT;
   2631	}
   2632	tbl = &bp->object_info_tbl;
   2633	v1_4 = tbl->v1_4;
   2634
   2635	result = BP_RESULT_NORECORD;
   2636	for (i = 0; i < v1_4->number_of_path; ++i)	{
   2637
   2638		if (bracket_layout_id ==
   2639			v1_4->display_path[i].display_objid) {
   2640			result = update_slot_layout_info(dcb, i,
   2641				slot_layout_info);
   2642			break;
   2643		}
   2644	}
   2645	return result;
   2646}
   2647
   2648static enum bp_result bios_get_board_layout_info(
   2649	struct dc_bios *dcb,
   2650	struct board_layout_info *board_layout_info)
   2651{
   2652	unsigned int i;
   2653	enum bp_result record_result;
   2654
   2655	const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {
   2656		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1,
   2657		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2,
   2658		0, 0
   2659	};
   2660
   2661	if (board_layout_info == NULL) {
   2662		DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");
   2663		return BP_RESULT_BADINPUT;
   2664	}
   2665
   2666	board_layout_info->num_of_slots = 0;
   2667
   2668	for (i = 0; i < MAX_BOARD_SLOTS; ++i) {
   2669		record_result = get_bracket_layout_record(dcb,
   2670			slot_index_to_vbios_id[i],
   2671			&board_layout_info->slots[i]);
   2672
   2673		if (record_result == BP_RESULT_NORECORD && i > 0)
   2674			break; /* no more slots present in bios */
   2675		else if (record_result != BP_RESULT_OK)
   2676			return record_result;  /* fail */
   2677
   2678		++board_layout_info->num_of_slots;
   2679	}
   2680
   2681	/* all data is valid */
   2682	board_layout_info->is_number_of_slots_valid = 1;
   2683	board_layout_info->is_slots_size_valid = 1;
   2684	board_layout_info->is_connector_offsets_valid = 1;
   2685	board_layout_info->is_connector_lengths_valid = 1;
   2686
   2687	return BP_RESULT_OK;
   2688}
   2689
   2690
   2691static uint16_t bios_parser_pack_data_tables(
   2692	struct dc_bios *dcb,
   2693	void *dst)
   2694{
   2695#ifdef PACK_BIOS_DATA
   2696	struct bios_parser *bp = BP_FROM_DCB(dcb);
   2697	struct atom_rom_header_v2_2 *rom_header = NULL;
   2698	struct atom_rom_header_v2_2 *packed_rom_header = NULL;
   2699	struct atom_common_table_header *data_tbl_header = NULL;
   2700	struct atom_master_list_of_data_tables_v2_1 *data_tbl_list = NULL;
   2701	struct atom_master_data_table_v2_1 *packed_master_data_tbl = NULL;
   2702	struct atom_data_revision tbl_rev = {0};
   2703	uint16_t *rom_header_offset = NULL;
   2704	const uint8_t *bios = bp->base.bios;
   2705	uint8_t *bios_dst = (uint8_t *)dst;
   2706	uint16_t packed_rom_header_offset;
   2707	uint16_t packed_masterdatatable_offset;
   2708	uint16_t packed_data_tbl_offset;
   2709	uint16_t data_tbl_offset;
   2710	unsigned int i;
   2711
   2712	rom_header_offset =
   2713		GET_IMAGE(uint16_t, OFFSET_TO_ATOM_ROM_HEADER_POINTER);
   2714
   2715	if (!rom_header_offset)
   2716		return 0;
   2717
   2718	rom_header = GET_IMAGE(struct atom_rom_header_v2_2, *rom_header_offset);
   2719
   2720	if (!rom_header)
   2721		return 0;
   2722
   2723	get_atom_data_table_revision(&rom_header->table_header, &tbl_rev);
   2724	if (!(tbl_rev.major >= 2 && tbl_rev.minor >= 2))
   2725		return 0;
   2726
   2727	get_atom_data_table_revision(&bp->master_data_tbl->table_header, &tbl_rev);
   2728	if (!(tbl_rev.major >= 2 && tbl_rev.minor >= 1))
   2729		return 0;
   2730
   2731	packed_rom_header_offset =
   2732		OFFSET_TO_ATOM_ROM_HEADER_POINTER + sizeof(*rom_header_offset);
   2733
   2734	packed_masterdatatable_offset =
   2735		packed_rom_header_offset + rom_header->table_header.structuresize;
   2736
   2737	packed_data_tbl_offset =
   2738		packed_masterdatatable_offset +
   2739		bp->master_data_tbl->table_header.structuresize;
   2740
   2741	packed_rom_header =
   2742		(struct atom_rom_header_v2_2 *)(bios_dst + packed_rom_header_offset);
   2743
   2744	packed_master_data_tbl =
   2745		(struct atom_master_data_table_v2_1 *)(bios_dst +
   2746		packed_masterdatatable_offset);
   2747
   2748	memcpy(bios_dst, bios, OFFSET_TO_ATOM_ROM_HEADER_POINTER);
   2749
   2750	*((uint16_t *)(bios_dst + OFFSET_TO_ATOM_ROM_HEADER_POINTER)) =
   2751		packed_rom_header_offset;
   2752
   2753	memcpy(bios_dst + packed_rom_header_offset, rom_header,
   2754		rom_header->table_header.structuresize);
   2755
   2756	packed_rom_header->masterdatatable_offset = packed_masterdatatable_offset;
   2757
   2758	memcpy(&packed_master_data_tbl->table_header,
   2759		&bp->master_data_tbl->table_header,
   2760		sizeof(bp->master_data_tbl->table_header));
   2761
   2762	data_tbl_list = &bp->master_data_tbl->listOfdatatables;
   2763
   2764	/* Each data table offset in data table list is 2 bytes,
   2765	 * we can use that to iterate through listOfdatatables
   2766	 * without knowing the name of each member.
   2767	 */
   2768	for (i = 0; i < sizeof(*data_tbl_list)/sizeof(uint16_t); i++) {
   2769		data_tbl_offset = *((uint16_t *)data_tbl_list + i);
   2770
   2771		if (data_tbl_offset) {
   2772			data_tbl_header =
   2773				(struct atom_common_table_header *)(bios + data_tbl_offset);
   2774
   2775			memcpy(bios_dst + packed_data_tbl_offset, data_tbl_header,
   2776				data_tbl_header->structuresize);
   2777
   2778			*((uint16_t *)&packed_master_data_tbl->listOfdatatables + i) =
   2779				packed_data_tbl_offset;
   2780
   2781			packed_data_tbl_offset += data_tbl_header->structuresize;
   2782		} else {
   2783			*((uint16_t *)&packed_master_data_tbl->listOfdatatables + i) = 0;
   2784		}
   2785	}
   2786	return packed_data_tbl_offset;
   2787#endif
   2788	// TODO: There is data bytes alignment issue, disable it for now.
   2789	return 0;
   2790}
   2791
   2792static struct atom_dc_golden_table_v1 *bios_get_golden_table(
   2793		struct bios_parser *bp,
   2794		uint32_t rev_major,
   2795		uint32_t rev_minor,
   2796		uint16_t *dc_golden_table_ver)
   2797{
   2798	struct atom_display_controller_info_v4_4 *disp_cntl_tbl_4_4 = NULL;
   2799	uint32_t dc_golden_offset = 0;
   2800	*dc_golden_table_ver = 0;
   2801
   2802	if (!DATA_TABLES(dce_info))
   2803		return NULL;
   2804
   2805	/* ver.4.4 or higher */
   2806	switch (rev_major) {
   2807	case 4:
   2808		switch (rev_minor) {
   2809		case 4:
   2810			disp_cntl_tbl_4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,
   2811									DATA_TABLES(dce_info));
   2812			if (!disp_cntl_tbl_4_4)
   2813				return NULL;
   2814			dc_golden_offset = DATA_TABLES(dce_info) + disp_cntl_tbl_4_4->dc_golden_table_offset;
   2815			*dc_golden_table_ver = disp_cntl_tbl_4_4->dc_golden_table_ver;
   2816			break;
   2817		}
   2818		break;
   2819	}
   2820
   2821	if (!dc_golden_offset)
   2822		return NULL;
   2823
   2824	if (*dc_golden_table_ver != 1)
   2825		return NULL;
   2826
   2827	return GET_IMAGE(struct atom_dc_golden_table_v1,
   2828			dc_golden_offset);
   2829}
   2830
   2831static enum bp_result bios_get_atom_dc_golden_table(
   2832	struct dc_bios *dcb)
   2833{
   2834	struct bios_parser *bp = BP_FROM_DCB(dcb);
   2835	enum bp_result result = BP_RESULT_OK;
   2836	struct atom_dc_golden_table_v1 *atom_dc_golden_table = NULL;
   2837	struct atom_common_table_header *header;
   2838	struct atom_data_revision tbl_revision;
   2839	uint16_t dc_golden_table_ver = 0;
   2840
   2841	header = GET_IMAGE(struct atom_common_table_header,
   2842							DATA_TABLES(dce_info));
   2843	if (!header)
   2844		return BP_RESULT_UNSUPPORTED;
   2845
   2846	get_atom_data_table_revision(header, &tbl_revision);
   2847
   2848	atom_dc_golden_table = bios_get_golden_table(bp,
   2849			tbl_revision.major,
   2850			tbl_revision.minor,
   2851			&dc_golden_table_ver);
   2852
   2853	if (!atom_dc_golden_table)
   2854		return BP_RESULT_UNSUPPORTED;
   2855
   2856	dcb->golden_table.dc_golden_table_ver = dc_golden_table_ver;
   2857	dcb->golden_table.aux_dphy_rx_control0_val = atom_dc_golden_table->aux_dphy_rx_control0_val;
   2858	dcb->golden_table.aux_dphy_rx_control1_val = atom_dc_golden_table->aux_dphy_rx_control1_val;
   2859	dcb->golden_table.aux_dphy_tx_control_val = atom_dc_golden_table->aux_dphy_tx_control_val;
   2860	dcb->golden_table.dc_gpio_aux_ctrl_0_val = atom_dc_golden_table->dc_gpio_aux_ctrl_0_val;
   2861	dcb->golden_table.dc_gpio_aux_ctrl_1_val = atom_dc_golden_table->dc_gpio_aux_ctrl_1_val;
   2862	dcb->golden_table.dc_gpio_aux_ctrl_2_val = atom_dc_golden_table->dc_gpio_aux_ctrl_2_val;
   2863	dcb->golden_table.dc_gpio_aux_ctrl_3_val = atom_dc_golden_table->dc_gpio_aux_ctrl_3_val;
   2864	dcb->golden_table.dc_gpio_aux_ctrl_4_val = atom_dc_golden_table->dc_gpio_aux_ctrl_4_val;
   2865	dcb->golden_table.dc_gpio_aux_ctrl_5_val = atom_dc_golden_table->dc_gpio_aux_ctrl_5_val;
   2866
   2867	return result;
   2868}
   2869
   2870
   2871static const struct dc_vbios_funcs vbios_funcs = {
   2872	.get_connectors_number = bios_parser_get_connectors_number,
   2873
   2874	.get_connector_id = bios_parser_get_connector_id,
   2875
   2876	.get_src_obj = bios_parser_get_src_obj,
   2877
   2878	.get_i2c_info = bios_parser_get_i2c_info,
   2879
   2880	.get_hpd_info = bios_parser_get_hpd_info,
   2881
   2882	.get_device_tag = bios_parser_get_device_tag,
   2883
   2884	.get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
   2885
   2886	.get_ss_entry_number = bios_parser_get_ss_entry_number,
   2887
   2888	.get_embedded_panel_info = bios_parser_get_embedded_panel_info,
   2889
   2890	.get_gpio_pin_info = bios_parser_get_gpio_pin_info,
   2891
   2892	.get_encoder_cap_info = bios_parser_get_encoder_cap_info,
   2893
   2894	.is_device_id_supported = bios_parser_is_device_id_supported,
   2895
   2896	.is_accelerated_mode = bios_parser_is_accelerated_mode,
   2897
   2898	.set_scratch_critical_state = bios_parser_set_scratch_critical_state,
   2899
   2900
   2901/*	 COMMANDS */
   2902	.encoder_control = bios_parser_encoder_control,
   2903
   2904	.transmitter_control = bios_parser_transmitter_control,
   2905
   2906	.enable_crtc = bios_parser_enable_crtc,
   2907
   2908	.set_pixel_clock = bios_parser_set_pixel_clock,
   2909
   2910	.set_dce_clock = bios_parser_set_dce_clock,
   2911
   2912	.program_crtc_timing = bios_parser_program_crtc_timing,
   2913
   2914	.enable_disp_power_gating = bios_parser_enable_disp_power_gating,
   2915
   2916	.bios_parser_destroy = firmware_parser_destroy,
   2917
   2918	.get_board_layout_info = bios_get_board_layout_info,
   2919	.pack_data_tables = bios_parser_pack_data_tables,
   2920
   2921	.get_atom_dc_golden_table = bios_get_atom_dc_golden_table,
   2922
   2923	.enable_lvtma_control = bios_parser_enable_lvtma_control,
   2924
   2925	.get_soc_bb_info = bios_parser_get_soc_bb_info,
   2926
   2927	.get_disp_connector_caps_info = bios_parser_get_disp_connector_caps_info,
   2928
   2929	.get_lttpr_caps = bios_parser_get_lttpr_caps,
   2930
   2931	.get_lttpr_interop = bios_parser_get_lttpr_interop,
   2932};
   2933
   2934static bool bios_parser2_construct(
   2935	struct bios_parser *bp,
   2936	struct bp_init_data *init,
   2937	enum dce_version dce_version)
   2938{
   2939	uint16_t *rom_header_offset = NULL;
   2940	struct atom_rom_header_v2_2 *rom_header = NULL;
   2941	struct display_object_info_table_v1_4 *object_info_tbl;
   2942	struct atom_data_revision tbl_rev = {0};
   2943
   2944	if (!init)
   2945		return false;
   2946
   2947	if (!init->bios)
   2948		return false;
   2949
   2950	bp->base.funcs = &vbios_funcs;
   2951	bp->base.bios = init->bios;
   2952	bp->base.bios_size = bp->base.bios[OFFSET_TO_ATOM_ROM_IMAGE_SIZE] * BIOS_IMAGE_SIZE_UNIT;
   2953
   2954	bp->base.ctx = init->ctx;
   2955
   2956	bp->base.bios_local_image = NULL;
   2957
   2958	rom_header_offset =
   2959			GET_IMAGE(uint16_t, OFFSET_TO_ATOM_ROM_HEADER_POINTER);
   2960
   2961	if (!rom_header_offset)
   2962		return false;
   2963
   2964	rom_header = GET_IMAGE(struct atom_rom_header_v2_2, *rom_header_offset);
   2965
   2966	if (!rom_header)
   2967		return false;
   2968
   2969	get_atom_data_table_revision(&rom_header->table_header, &tbl_rev);
   2970	if (!(tbl_rev.major >= 2 && tbl_rev.minor >= 2))
   2971		return false;
   2972
   2973	bp->master_data_tbl =
   2974		GET_IMAGE(struct atom_master_data_table_v2_1,
   2975				rom_header->masterdatatable_offset);
   2976
   2977	if (!bp->master_data_tbl)
   2978		return false;
   2979
   2980	bp->object_info_tbl_offset = DATA_TABLES(displayobjectinfo);
   2981
   2982	if (!bp->object_info_tbl_offset)
   2983		return false;
   2984
   2985	object_info_tbl =
   2986			GET_IMAGE(struct display_object_info_table_v1_4,
   2987						bp->object_info_tbl_offset);
   2988
   2989	if (!object_info_tbl)
   2990		return false;
   2991
   2992	get_atom_data_table_revision(&object_info_tbl->table_header,
   2993		&bp->object_info_tbl.revision);
   2994
   2995	if (bp->object_info_tbl.revision.major == 1
   2996		&& bp->object_info_tbl.revision.minor == 4) {
   2997		struct display_object_info_table_v1_4 *tbl_v1_4;
   2998
   2999		tbl_v1_4 = GET_IMAGE(struct display_object_info_table_v1_4,
   3000			bp->object_info_tbl_offset);
   3001		if (!tbl_v1_4)
   3002			return false;
   3003
   3004		bp->object_info_tbl.v1_4 = tbl_v1_4;
   3005	} else {
   3006		ASSERT(0);
   3007		return false;
   3008	}
   3009
   3010	dal_firmware_parser_init_cmd_tbl(bp);
   3011	dal_bios_parser_init_cmd_tbl_helper2(&bp->cmd_helper, dce_version);
   3012
   3013	bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);
   3014	bp->base.fw_info_valid = bios_parser_get_firmware_info(&bp->base, &bp->base.fw_info) == BP_RESULT_OK;
   3015	bios_parser_get_vram_info(&bp->base, &bp->base.vram_info);
   3016
   3017	return true;
   3018}
   3019
   3020struct dc_bios *firmware_parser_create(
   3021	struct bp_init_data *init,
   3022	enum dce_version dce_version)
   3023{
   3024	struct bios_parser *bp = NULL;
   3025
   3026	bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL);
   3027	if (!bp)
   3028		return NULL;
   3029
   3030	if (bios_parser2_construct(bp, init, dce_version))
   3031		return &bp->base;
   3032
   3033	kfree(bp);
   3034	return NULL;
   3035}
   3036
   3037