brintos

brintos / linux-shallow public Read only

0
0
Text · 83.6 KiB · 3bacf47 Raw
2949 lines · c
1/*2 * Copyright 2012-15 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26#include <linux/slab.h>27 28#include "dm_services.h"29 30#include "atom.h"31 32#include "dc_bios_types.h"33#include "include/gpio_service_interface.h"34#include "include/grph_object_ctrl_defs.h"35#include "include/bios_parser_interface.h"36#include "include/logger_interface.h"37 38#include "command_table.h"39#include "bios_parser_helper.h"40#include "command_table_helper.h"41#include "bios_parser.h"42#include "bios_parser_types_internal.h"43#include "bios_parser_interface.h"44 45#include "bios_parser_common.h"46 47#define THREE_PERCENT_OF_10000 30048 49#define LAST_RECORD_TYPE 0xff50 51#define DC_LOGGER \52	bp->base.ctx->logger53 54#define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table)55 56static void get_atom_data_table_revision(57	ATOM_COMMON_TABLE_HEADER *atom_data_tbl,58	struct atom_data_revision *tbl_revision);59static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,60	uint16_t **id_list);61static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,62	struct graphics_object_id id);63static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,64	ATOM_I2C_RECORD *record,65	struct graphics_object_i2c_info *info);66static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,67	ATOM_OBJECT *object);68static struct device_id device_type_from_device_id(uint16_t device_id);69static uint32_t signal_to_ss_id(enum as_signal_type signal);70static uint32_t get_support_mask_for_device_id(struct device_id device_id);71static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(72	struct bios_parser *bp,73	ATOM_OBJECT *object);74 75#define BIOS_IMAGE_SIZE_OFFSET 276#define BIOS_IMAGE_SIZE_UNIT 51277 78/*****************************************************************************/79static bool bios_parser_construct(80	struct bios_parser *bp,81	struct bp_init_data *init,82	enum dce_version dce_version);83 84static uint8_t bios_parser_get_connectors_number(85	struct dc_bios *dcb);86 87static enum bp_result bios_parser_get_embedded_panel_info(88	struct dc_bios *dcb,89	struct embedded_panel_info *info);90 91/*****************************************************************************/92 93struct dc_bios *bios_parser_create(94	struct bp_init_data *init,95	enum dce_version dce_version)96{97	struct bios_parser *bp;98 99	bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL);100	if (!bp)101		return NULL;102 103	if (bios_parser_construct(bp, init, dce_version))104		return &bp->base;105 106	kfree(bp);107	BREAK_TO_DEBUGGER();108	return NULL;109}110 111static void bios_parser_destruct(struct bios_parser *bp)112{113	kfree(bp->base.bios_local_image);114	kfree(bp->base.integrated_info);115}116 117static void bios_parser_destroy(struct dc_bios **dcb)118{119	struct bios_parser *bp = BP_FROM_DCB(*dcb);120 121	if (!bp) {122		BREAK_TO_DEBUGGER();123		return;124	}125 126	bios_parser_destruct(bp);127 128	kfree(bp);129	*dcb = NULL;130}131 132static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset)133{134	ATOM_OBJECT_TABLE *table;135 136	uint32_t object_table_offset = bp->object_info_tbl_offset + offset;137 138	table = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base,139				object_table_offset,140				struct_size(table, asObjects, 1)));141 142	if (!table)143		return 0;144	else145		return table->ucNumberOfObjects;146}147 148static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)149{150	struct bios_parser *bp = BP_FROM_DCB(dcb);151 152	return get_number_of_objects(bp,153		le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset));154}155 156static struct graphics_object_id bios_parser_get_connector_id(157	struct dc_bios *dcb,158	uint8_t i)159{160	struct bios_parser *bp = BP_FROM_DCB(dcb);161	struct graphics_object_id object_id = dal_graphics_object_id_init(162		0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);163	uint16_t id;164 165	uint32_t connector_table_offset = bp->object_info_tbl_offset166		+ le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);167 168	ATOM_OBJECT_TABLE *tbl = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base,169				connector_table_offset,170				struct_size(tbl, asObjects, 1)));171 172	if (!tbl) {173		dm_error("Can't get connector table from atom bios.\n");174		return object_id;175	}176 177	if (tbl->ucNumberOfObjects <= i) {178		dm_error("Can't find connector id %d in connector table of size %d.\n",179			 i, tbl->ucNumberOfObjects);180		return object_id;181	}182 183	id = le16_to_cpu(tbl->asObjects[i].usObjectID);184	object_id = object_id_from_bios_object_id(id);185	return object_id;186}187 188static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,189	struct graphics_object_id object_id, uint32_t index,190	struct graphics_object_id *src_object_id)191{192	uint32_t number;193	uint16_t *id;194	ATOM_OBJECT *object;195	struct bios_parser *bp = BP_FROM_DCB(dcb);196 197	if (!src_object_id)198		return BP_RESULT_BADINPUT;199 200	object = get_bios_object(bp, object_id);201 202	if (!object) {203		BREAK_TO_DEBUGGER(); /* Invalid object id */204		return BP_RESULT_BADINPUT;205	}206 207	number = get_src_obj_list(bp, object, &id);208 209	if (number <= index)210		return BP_RESULT_BADINPUT;211 212	*src_object_id = object_id_from_bios_object_id(id[index]);213 214	return BP_RESULT_OK;215}216 217static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,218	struct graphics_object_id id,219	struct graphics_object_i2c_info *info)220{221	uint32_t offset;222	ATOM_OBJECT *object;223	ATOM_COMMON_RECORD_HEADER *header;224	ATOM_I2C_RECORD *record;225	struct bios_parser *bp = BP_FROM_DCB(dcb);226 227	if (!info)228		return BP_RESULT_BADINPUT;229 230	object = get_bios_object(bp, id);231 232	if (!object)233		return BP_RESULT_BADINPUT;234 235	offset = le16_to_cpu(object->usRecordOffset)236			+ bp->object_info_tbl_offset;237 238	for (;;) {239		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);240 241		if (!header)242			return BP_RESULT_BADBIOSTABLE;243 244		if (LAST_RECORD_TYPE == header->ucRecordType ||245			!header->ucRecordSize)246			break;247 248		if (ATOM_I2C_RECORD_TYPE == header->ucRecordType249			&& sizeof(ATOM_I2C_RECORD) <= header->ucRecordSize) {250			/* get the I2C info */251			record = (ATOM_I2C_RECORD *) header;252 253			if (get_gpio_i2c_info(bp, record, info) == BP_RESULT_OK)254				return BP_RESULT_OK;255		}256 257		offset += header->ucRecordSize;258	}259 260	return BP_RESULT_NORECORD;261}262 263static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb,264	struct graphics_object_id id,265	struct graphics_object_hpd_info *info)266{267	struct bios_parser *bp = BP_FROM_DCB(dcb);268	ATOM_OBJECT *object;269	ATOM_HPD_INT_RECORD *record = NULL;270 271	if (!info)272		return BP_RESULT_BADINPUT;273 274	object = get_bios_object(bp, id);275 276	if (!object)277		return BP_RESULT_BADINPUT;278 279	record = get_hpd_record(bp, object);280 281	if (record != NULL) {282		info->hpd_int_gpio_uid = record->ucHPDIntGPIOID;283		info->hpd_active = record->ucPlugged_PinState;284		return BP_RESULT_OK;285	}286 287	return BP_RESULT_NORECORD;288}289 290static enum bp_result bios_parser_get_device_tag_record(291	struct bios_parser *bp,292	ATOM_OBJECT *object,293	ATOM_CONNECTOR_DEVICE_TAG_RECORD **record)294{295	ATOM_COMMON_RECORD_HEADER *header;296	uint32_t offset;297 298	offset = le16_to_cpu(object->usRecordOffset)299			+ bp->object_info_tbl_offset;300 301	for (;;) {302		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);303 304		if (!header)305			return BP_RESULT_BADBIOSTABLE;306 307		offset += header->ucRecordSize;308 309		if (LAST_RECORD_TYPE == header->ucRecordType ||310			!header->ucRecordSize)311			break;312 313		if (ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE !=314			header->ucRecordType)315			continue;316 317		if (sizeof(ATOM_CONNECTOR_DEVICE_TAG) > header->ucRecordSize)318			continue;319 320		*record = (ATOM_CONNECTOR_DEVICE_TAG_RECORD *) header;321		return BP_RESULT_OK;322	}323 324	return BP_RESULT_NORECORD;325}326 327static enum bp_result bios_parser_get_device_tag(328	struct dc_bios *dcb,329	struct graphics_object_id connector_object_id,330	uint32_t device_tag_index,331	struct connector_device_tag_info *info)332{333	struct bios_parser *bp = BP_FROM_DCB(dcb);334	ATOM_OBJECT *object;335	ATOM_CONNECTOR_DEVICE_TAG_RECORD *record = NULL;336	ATOM_CONNECTOR_DEVICE_TAG *device_tag;337 338	if (!info)339		return BP_RESULT_BADINPUT;340 341	/* getBiosObject will return MXM object */342	object = get_bios_object(bp, connector_object_id);343 344	if (!object) {345		BREAK_TO_DEBUGGER(); /* Invalid object id */346		return BP_RESULT_BADINPUT;347	}348 349	if (bios_parser_get_device_tag_record(bp, object, &record)350		!= BP_RESULT_OK)351		return BP_RESULT_NORECORD;352 353	if (device_tag_index >= record->ucNumberOfDevice)354		return BP_RESULT_NORECORD;355 356	device_tag = &record->asDeviceTag[device_tag_index];357 358	info->acpi_device = le32_to_cpu(device_tag->ulACPIDeviceEnum);359	info->dev_id =360		device_type_from_device_id(le16_to_cpu(device_tag->usDeviceID));361 362	return BP_RESULT_OK;363}364 365static enum bp_result get_firmware_info_v1_4(366	struct bios_parser *bp,367	struct dc_firmware_info *info);368static enum bp_result get_firmware_info_v2_1(369	struct bios_parser *bp,370	struct dc_firmware_info *info);371static enum bp_result get_firmware_info_v2_2(372	struct bios_parser *bp,373	struct dc_firmware_info *info);374 375static enum bp_result bios_parser_get_firmware_info(376	struct dc_bios *dcb,377	struct dc_firmware_info *info)378{379	struct bios_parser *bp = BP_FROM_DCB(dcb);380	enum bp_result result = BP_RESULT_BADBIOSTABLE;381	ATOM_COMMON_TABLE_HEADER *header;382	struct atom_data_revision revision;383 384	if (info && DATA_TABLES(FirmwareInfo)) {385		header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,386			DATA_TABLES(FirmwareInfo));387		get_atom_data_table_revision(header, &revision);388		switch (revision.major) {389		case 1:390			switch (revision.minor) {391			case 4:392				result = get_firmware_info_v1_4(bp, info);393				break;394			default:395				break;396			}397			break;398 399		case 2:400			switch (revision.minor) {401			case 1:402				result = get_firmware_info_v2_1(bp, info);403				break;404			case 2:405				result = get_firmware_info_v2_2(bp, info);406				break;407			default:408				break;409			}410			break;411		default:412			break;413		}414	}415 416	return result;417}418 419static enum bp_result get_firmware_info_v1_4(420	struct bios_parser *bp,421	struct dc_firmware_info *info)422{423	ATOM_FIRMWARE_INFO_V1_4 *firmware_info =424		GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4,425			DATA_TABLES(FirmwareInfo));426 427	if (!info)428		return BP_RESULT_BADINPUT;429 430	if (!firmware_info)431		return BP_RESULT_BADBIOSTABLE;432 433	memset(info, 0, sizeof(*info));434 435	/* Pixel clock pll information. We need to convert from 10KHz units into436	 * KHz units */437	info->pll_info.crystal_frequency =438		le16_to_cpu(firmware_info->usReferenceClock) * 10;439	info->pll_info.min_input_pxl_clk_pll_frequency =440		le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;441	info->pll_info.max_input_pxl_clk_pll_frequency =442		le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;443	info->pll_info.min_output_pxl_clk_pll_frequency =444		le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;445	info->pll_info.max_output_pxl_clk_pll_frequency =446		le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;447 448	if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)449		/* Since there is no information on the SS, report conservative450		 * value 3% for bandwidth calculation */451		/* unit of 0.01% */452		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;453 454	if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)455		/* Since there is no information on the SS,report conservative456		 * value 3% for bandwidth calculation */457		/* unit of 0.01% */458		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;459 460	return BP_RESULT_OK;461}462 463static enum bp_result get_ss_info_v3_1(464	struct bios_parser *bp,465	uint32_t id,466	uint32_t index,467	struct spread_spectrum_info *ss_info);468 469static enum bp_result get_firmware_info_v2_1(470	struct bios_parser *bp,471	struct dc_firmware_info *info)472{473	ATOM_FIRMWARE_INFO_V2_1 *firmwareInfo =474		GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1, DATA_TABLES(FirmwareInfo));475	struct spread_spectrum_info internalSS;476	uint32_t index;477 478	if (!info)479		return BP_RESULT_BADINPUT;480 481	if (!firmwareInfo)482		return BP_RESULT_BADBIOSTABLE;483 484	memset(info, 0, sizeof(*info));485 486	/* Pixel clock pll information. We need to convert from 10KHz units into487	 * KHz units */488	info->pll_info.crystal_frequency =489		le16_to_cpu(firmwareInfo->usCoreReferenceClock) * 10;490	info->pll_info.min_input_pxl_clk_pll_frequency =491		le16_to_cpu(firmwareInfo->usMinPixelClockPLL_Input) * 10;492	info->pll_info.max_input_pxl_clk_pll_frequency =493		le16_to_cpu(firmwareInfo->usMaxPixelClockPLL_Input) * 10;494	info->pll_info.min_output_pxl_clk_pll_frequency =495		le32_to_cpu(firmwareInfo->ulMinPixelClockPLL_Output) * 10;496	info->pll_info.max_output_pxl_clk_pll_frequency =497		le32_to_cpu(firmwareInfo->ulMaxPixelClockPLL_Output) * 10;498	info->default_display_engine_pll_frequency =499		le32_to_cpu(firmwareInfo->ulDefaultDispEngineClkFreq) * 10;500	info->external_clock_source_frequency_for_dp =501		le16_to_cpu(firmwareInfo->usUniphyDPModeExtClkFreq) * 10;502	info->min_allowed_bl_level = firmwareInfo->ucMinAllowedBL_Level;503 504	/* There should be only one entry in the SS info table for Memory Clock505	 */506	index = 0;507	if (firmwareInfo->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)508		/* Since there is no information for external SS, report509		 *  conservative value 3% for bandwidth calculation */510		/* unit of 0.01% */511		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;512	else if (get_ss_info_v3_1(bp,513		ASIC_INTERNAL_MEMORY_SS, index, &internalSS) == BP_RESULT_OK) {514		if (internalSS.spread_spectrum_percentage) {515			info->feature.memory_clk_ss_percentage =516				internalSS.spread_spectrum_percentage;517			if (internalSS.type.CENTER_MODE) {518				/* if it is centermode, the exact SS Percentage519				 * will be round up of half of the percentage520				 * reported in the SS table */521				++info->feature.memory_clk_ss_percentage;522				info->feature.memory_clk_ss_percentage /= 2;523			}524		}525	}526 527	/* There should be only one entry in the SS info table for Engine Clock528	 */529	index = 1;530	if (firmwareInfo->usFirmwareCapability.sbfAccess.EngineClockSS_Support)531		/* Since there is no information for external SS, report532		 * conservative value 3% for bandwidth calculation */533		/* unit of 0.01% */534		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;535	else if (get_ss_info_v3_1(bp,536		ASIC_INTERNAL_ENGINE_SS, index, &internalSS) == BP_RESULT_OK) {537		if (internalSS.spread_spectrum_percentage) {538			info->feature.engine_clk_ss_percentage =539				internalSS.spread_spectrum_percentage;540			if (internalSS.type.CENTER_MODE) {541				/* if it is centermode, the exact SS Percentage542				 * will be round up of half of the percentage543				 * reported in the SS table */544				++info->feature.engine_clk_ss_percentage;545				info->feature.engine_clk_ss_percentage /= 2;546			}547		}548	}549 550	return BP_RESULT_OK;551}552 553static enum bp_result get_firmware_info_v2_2(554	struct bios_parser *bp,555	struct dc_firmware_info *info)556{557	ATOM_FIRMWARE_INFO_V2_2 *firmware_info;558	struct spread_spectrum_info internal_ss;559	uint32_t index;560 561	if (!info)562		return BP_RESULT_BADINPUT;563 564	firmware_info = GET_IMAGE(ATOM_FIRMWARE_INFO_V2_2,565		DATA_TABLES(FirmwareInfo));566 567	if (!firmware_info)568		return BP_RESULT_BADBIOSTABLE;569 570	memset(info, 0, sizeof(*info));571 572	/* Pixel clock pll information. We need to convert from 10KHz units into573	 * KHz units */574	info->pll_info.crystal_frequency =575		le16_to_cpu(firmware_info->usCoreReferenceClock) * 10;576	info->pll_info.min_input_pxl_clk_pll_frequency =577		le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;578	info->pll_info.max_input_pxl_clk_pll_frequency =579		le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;580	info->pll_info.min_output_pxl_clk_pll_frequency =581		le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;582	info->pll_info.max_output_pxl_clk_pll_frequency =583		le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;584	info->default_display_engine_pll_frequency =585		le32_to_cpu(firmware_info->ulDefaultDispEngineClkFreq) * 10;586	info->external_clock_source_frequency_for_dp =587		le16_to_cpu(firmware_info->usUniphyDPModeExtClkFreq) * 10;588 589	/* There should be only one entry in the SS info table for Memory Clock590	 */591	index = 0;592	if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)593		/* Since there is no information for external SS, report594		 *  conservative value 3% for bandwidth calculation */595		/* unit of 0.01% */596		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;597	else if (get_ss_info_v3_1(bp,598			ASIC_INTERNAL_MEMORY_SS, index, &internal_ss) == BP_RESULT_OK) {599		if (internal_ss.spread_spectrum_percentage) {600			info->feature.memory_clk_ss_percentage =601					internal_ss.spread_spectrum_percentage;602			if (internal_ss.type.CENTER_MODE) {603				/* if it is centermode, the exact SS Percentage604				 * will be round up of half of the percentage605				 * reported in the SS table */606				++info->feature.memory_clk_ss_percentage;607				info->feature.memory_clk_ss_percentage /= 2;608			}609		}610	}611 612	/* There should be only one entry in the SS info table for Engine Clock613	 */614	index = 1;615	if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)616		/* Since there is no information for external SS, report617		 * conservative value 3% for bandwidth calculation */618		/* unit of 0.01% */619		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;620	else if (get_ss_info_v3_1(bp,621			ASIC_INTERNAL_ENGINE_SS, index, &internal_ss) == BP_RESULT_OK) {622		if (internal_ss.spread_spectrum_percentage) {623			info->feature.engine_clk_ss_percentage =624					internal_ss.spread_spectrum_percentage;625			if (internal_ss.type.CENTER_MODE) {626				/* if it is centermode, the exact SS Percentage627				 * will be round up of half of the percentage628				 * reported in the SS table */629				++info->feature.engine_clk_ss_percentage;630				info->feature.engine_clk_ss_percentage /= 2;631			}632		}633	}634 635	/* Remote Display */636	info->remote_display_config = firmware_info->ucRemoteDisplayConfig;637 638	/* Is allowed minimum BL level */639	info->min_allowed_bl_level = firmware_info->ucMinAllowedBL_Level;640	/* Used starting from CI */641	info->smu_gpu_pll_output_freq =642			(uint32_t) (le32_to_cpu(firmware_info->ulGPUPLL_OutputFreq) * 10);643 644	return BP_RESULT_OK;645}646 647static enum bp_result get_ss_info_v3_1(648	struct bios_parser *bp,649	uint32_t id,650	uint32_t index,651	struct spread_spectrum_info *ss_info)652{653	ATOM_ASIC_INTERNAL_SS_INFO_V3 *ss_table_header_include;654	ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;655	uint32_t table_size;656	uint32_t i;657	uint32_t table_index = 0;658 659	if (!ss_info)660		return BP_RESULT_BADINPUT;661 662	if (!DATA_TABLES(ASIC_InternalSS_Info))663		return BP_RESULT_UNSUPPORTED;664 665	ss_table_header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V3 *) bios_get_image(&bp->base,666				DATA_TABLES(ASIC_InternalSS_Info),667				struct_size(ss_table_header_include, asSpreadSpectrum, 1)));668	if (!ss_table_header_include)669		return BP_RESULT_UNSUPPORTED;670 671	table_size =672		(le16_to_cpu(ss_table_header_include->sHeader.usStructureSize)673				- sizeof(ATOM_COMMON_TABLE_HEADER))674				/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);675 676	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)677				&ss_table_header_include->asSpreadSpectrum[0];678 679	memset(ss_info, 0, sizeof(struct spread_spectrum_info));680 681	for (i = 0; i < table_size; i++) {682		if (tbl[i].ucClockIndication != (uint8_t) id)683			continue;684 685		if (table_index != index) {686			table_index++;687			continue;688		}689		/* VBIOS introduced new defines for Version 3, same values as690		 *  before, so now use these new ones for Version 3.691		 * Shouldn't affect field VBIOS's V3 as define values are still692		 *  same.693		 * #define SS_MODE_V3_CENTRE_SPREAD_MASK                0x01694		 * #define SS_MODE_V3_EXTERNAL_SS_MASK                  0x02695 696		 * Old VBIOS defines:697		 * #define ATOM_SS_CENTRE_SPREAD_MODE_MASK        0x00000001698		 * #define ATOM_EXTERNAL_SS_MASK                  0x00000002699		 */700 701		if (SS_MODE_V3_EXTERNAL_SS_MASK & tbl[i].ucSpreadSpectrumMode)702			ss_info->type.EXTERNAL = true;703 704		if (SS_MODE_V3_CENTRE_SPREAD_MASK & tbl[i].ucSpreadSpectrumMode)705			ss_info->type.CENTER_MODE = true;706 707		/* Older VBIOS (in field) always provides SS percentage in 0.01%708		 * units set Divider to 100 */709		ss_info->spread_percentage_divider = 100;710 711		/* #define SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 0x10 */712		if (SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK713				& tbl[i].ucSpreadSpectrumMode)714			ss_info->spread_percentage_divider = 1000;715 716		ss_info->type.STEP_AND_DELAY_INFO = false;717		/* convert [10KHz] into [KHz] */718		ss_info->target_clock_range =719				le32_to_cpu(tbl[i].ulTargetClockRange) * 10;720		ss_info->spread_spectrum_percentage =721				(uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);722		ss_info->spread_spectrum_range =723				(uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);724 725		return BP_RESULT_OK;726	}727	return BP_RESULT_NORECORD;728}729 730static enum bp_result bios_parser_transmitter_control(731	struct dc_bios *dcb,732	struct bp_transmitter_control *cntl)733{734	struct bios_parser *bp = BP_FROM_DCB(dcb);735 736	if (!bp->cmd_tbl.transmitter_control)737		return BP_RESULT_FAILURE;738 739	return bp->cmd_tbl.transmitter_control(bp, cntl);740}741 742static enum bp_result bios_parser_encoder_control(743	struct dc_bios *dcb,744	struct bp_encoder_control *cntl)745{746	struct bios_parser *bp = BP_FROM_DCB(dcb);747 748	if (!bp->cmd_tbl.dig_encoder_control)749		return BP_RESULT_FAILURE;750 751	return bp->cmd_tbl.dig_encoder_control(bp, cntl);752}753 754static enum bp_result bios_parser_adjust_pixel_clock(755	struct dc_bios *dcb,756	struct bp_adjust_pixel_clock_parameters *bp_params)757{758	struct bios_parser *bp = BP_FROM_DCB(dcb);759 760	if (!bp->cmd_tbl.adjust_display_pll)761		return BP_RESULT_FAILURE;762 763	return bp->cmd_tbl.adjust_display_pll(bp, bp_params);764}765 766static enum bp_result bios_parser_set_pixel_clock(767	struct dc_bios *dcb,768	struct bp_pixel_clock_parameters *bp_params)769{770	struct bios_parser *bp = BP_FROM_DCB(dcb);771 772	if (!bp->cmd_tbl.set_pixel_clock)773		return BP_RESULT_FAILURE;774 775	return bp->cmd_tbl.set_pixel_clock(bp, bp_params);776}777 778static enum bp_result bios_parser_set_dce_clock(779	struct dc_bios *dcb,780	struct bp_set_dce_clock_parameters *bp_params)781{782	struct bios_parser *bp = BP_FROM_DCB(dcb);783 784	if (!bp->cmd_tbl.set_dce_clock)785		return BP_RESULT_FAILURE;786 787	return bp->cmd_tbl.set_dce_clock(bp, bp_params);788}789 790static enum bp_result bios_parser_enable_spread_spectrum_on_ppll(791	struct dc_bios *dcb,792	struct bp_spread_spectrum_parameters *bp_params,793	bool enable)794{795	struct bios_parser *bp = BP_FROM_DCB(dcb);796 797	if (!bp->cmd_tbl.enable_spread_spectrum_on_ppll)798		return BP_RESULT_FAILURE;799 800	return bp->cmd_tbl.enable_spread_spectrum_on_ppll(801			bp, bp_params, enable);802 803}804 805static enum bp_result bios_parser_program_crtc_timing(806	struct dc_bios *dcb,807	struct bp_hw_crtc_timing_parameters *bp_params)808{809	struct bios_parser *bp = BP_FROM_DCB(dcb);810 811	if (!bp->cmd_tbl.set_crtc_timing)812		return BP_RESULT_FAILURE;813 814	return bp->cmd_tbl.set_crtc_timing(bp, bp_params);815}816 817static enum bp_result bios_parser_program_display_engine_pll(818	struct dc_bios *dcb,819	struct bp_pixel_clock_parameters *bp_params)820{821	struct bios_parser *bp = BP_FROM_DCB(dcb);822 823	if (!bp->cmd_tbl.program_clock)824		return BP_RESULT_FAILURE;825 826	return bp->cmd_tbl.program_clock(bp, bp_params);827 828}829 830 831static enum bp_result bios_parser_enable_crtc(832	struct dc_bios *dcb,833	enum controller_id id,834	bool enable)835{836	struct bios_parser *bp = BP_FROM_DCB(dcb);837 838	if (!bp->cmd_tbl.enable_crtc)839		return BP_RESULT_FAILURE;840 841	return bp->cmd_tbl.enable_crtc(bp, id, enable);842}843 844static enum bp_result bios_parser_enable_disp_power_gating(845	struct dc_bios *dcb,846	enum controller_id controller_id,847	enum bp_pipe_control_action action)848{849	struct bios_parser *bp = BP_FROM_DCB(dcb);850 851	if (!bp->cmd_tbl.enable_disp_power_gating)852		return BP_RESULT_FAILURE;853 854	return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id,855		action);856}857 858static bool bios_parser_is_device_id_supported(859	struct dc_bios *dcb,860	struct device_id id)861{862	struct bios_parser *bp = BP_FROM_DCB(dcb);863 864	uint32_t mask = get_support_mask_for_device_id(id);865 866	return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0;867}868 869static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,870	ATOM_OBJECT *object)871{872	ATOM_COMMON_RECORD_HEADER *header;873	uint32_t offset;874 875	if (!object) {876		BREAK_TO_DEBUGGER(); /* Invalid object */877		return NULL;878	}879 880	offset = le16_to_cpu(object->usRecordOffset)881			+ bp->object_info_tbl_offset;882 883	for (;;) {884		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);885 886		if (!header)887			return NULL;888 889		if (LAST_RECORD_TYPE == header->ucRecordType ||890			!header->ucRecordSize)891			break;892 893		if (ATOM_HPD_INT_RECORD_TYPE == header->ucRecordType894			&& sizeof(ATOM_HPD_INT_RECORD) <= header->ucRecordSize)895			return (ATOM_HPD_INT_RECORD *) header;896 897		offset += header->ucRecordSize;898	}899 900	return NULL;901}902 903static enum bp_result get_ss_info_from_ss_info_table(904	struct bios_parser *bp,905	uint32_t id,906	struct spread_spectrum_info *ss_info);907static enum bp_result get_ss_info_from_tbl(908	struct bios_parser *bp,909	uint32_t id,910	struct spread_spectrum_info *ss_info);911/**912 * bios_parser_get_spread_spectrum_info913 * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or914 * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info915 * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info ver 3.1,916 * there is only one entry for each signal /ss id.  However, there is917 * no planning of supporting multiple spread Sprectum entry for EverGreen918 * @dcb:     pointer to the DC BIOS919 * @signal:  ASSignalType to be converted to info index920 * @index:   number of entries that match the converted info index921 * @ss_info: sprectrum information structure,922 * return:   Bios parser result code923 */924static enum bp_result bios_parser_get_spread_spectrum_info(925	struct dc_bios *dcb,926	enum as_signal_type signal,927	uint32_t index,928	struct spread_spectrum_info *ss_info)929{930	struct bios_parser *bp = BP_FROM_DCB(dcb);931	enum bp_result result = BP_RESULT_UNSUPPORTED;932	uint32_t clk_id_ss = 0;933	ATOM_COMMON_TABLE_HEADER *header;934	struct atom_data_revision tbl_revision;935 936	if (!ss_info) /* check for bad input */937		return BP_RESULT_BADINPUT;938	/* signal translation */939	clk_id_ss = signal_to_ss_id(signal);940 941	if (!DATA_TABLES(ASIC_InternalSS_Info))942		if (!index)943			return get_ss_info_from_ss_info_table(bp, clk_id_ss,944				ss_info);945 946	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,947		DATA_TABLES(ASIC_InternalSS_Info));948	get_atom_data_table_revision(header, &tbl_revision);949 950	switch (tbl_revision.major) {951	case 2:952		switch (tbl_revision.minor) {953		case 1:954			/* there can not be more then one entry for Internal955			 * SS Info table version 2.1 */956			if (!index)957				return get_ss_info_from_tbl(bp, clk_id_ss,958						ss_info);959			break;960		default:961			break;962		}963		break;964 965	case 3:966		switch (tbl_revision.minor) {967		case 1:968			return get_ss_info_v3_1(bp, clk_id_ss, index, ss_info);969		default:970			break;971		}972		break;973	default:974		break;975	}976	/* there can not be more then one entry for SS Info table */977	return result;978}979 980static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(981	struct bios_parser *bp,982	uint32_t id,983	struct spread_spectrum_info *info);984 985/**986 * get_ss_info_from_tbl987 * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or988 * SS_Info table from the VBIOS989 * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or990 * SS_Info.991 *992 * @bp:      pointer to the BIOS parser993 * @id:      spread sprectrum info index994 * @ss_info: sprectrum information structure,995 * return:   BIOS parser result code996 */997static enum bp_result get_ss_info_from_tbl(998	struct bios_parser *bp,999	uint32_t id,1000	struct spread_spectrum_info *ss_info)1001{1002	if (!ss_info) /* check for bad input, if ss_info is not NULL */1003		return BP_RESULT_BADINPUT;1004	/* for SS_Info table only support DP and LVDS */1005	if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)1006		return get_ss_info_from_ss_info_table(bp, id, ss_info);1007	else1008		return get_ss_info_from_internal_ss_info_tbl_V2_1(bp, id,1009			ss_info);1010}1011 1012/**1013 * get_ss_info_from_internal_ss_info_tbl_V2_11014 * Get spread sprectrum information from the ASIC_InternalSS_Info table Ver 2.11015 * from the VBIOS1016 * There will not be multiple entry for Ver 2.11017 *1018 * @bp:    pointer to the Bios parser1019 * @id:    spread sprectrum info index1020 * @info:  sprectrum information structure,1021 * return: Bios parser result code1022 */1023static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(1024	struct bios_parser *bp,1025	uint32_t id,1026	struct spread_spectrum_info *info)1027{1028	enum bp_result result = BP_RESULT_UNSUPPORTED;1029	ATOM_ASIC_INTERNAL_SS_INFO_V2 *header;1030	ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;1031	uint32_t tbl_size, i;1032 1033	if (!DATA_TABLES(ASIC_InternalSS_Info))1034		return result;1035 1036	header = ((ATOM_ASIC_INTERNAL_SS_INFO_V2 *) bios_get_image(1037				&bp->base,1038				DATA_TABLES(ASIC_InternalSS_Info),1039				struct_size(header, asSpreadSpectrum, 1)));1040	if (!header)1041		return result;1042 1043	memset(info, 0, sizeof(struct spread_spectrum_info));1044 1045	tbl_size = (le16_to_cpu(header->sHeader.usStructureSize)1046			- sizeof(ATOM_COMMON_TABLE_HEADER))1047					/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);1048 1049	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)1050					&(header->asSpreadSpectrum[0]);1051	for (i = 0; i < tbl_size; i++) {1052		result = BP_RESULT_NORECORD;1053 1054		if (tbl[i].ucClockIndication != (uint8_t)id)1055			continue;1056 1057		if (ATOM_EXTERNAL_SS_MASK1058			& tbl[i].ucSpreadSpectrumMode) {1059			info->type.EXTERNAL = true;1060		}1061		if (ATOM_SS_CENTRE_SPREAD_MODE_MASK1062			& tbl[i].ucSpreadSpectrumMode) {1063			info->type.CENTER_MODE = true;1064		}1065		info->type.STEP_AND_DELAY_INFO = false;1066		/* convert [10KHz] into [KHz] */1067		info->target_clock_range =1068			le32_to_cpu(tbl[i].ulTargetClockRange) * 10;1069		info->spread_spectrum_percentage =1070			(uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);1071		info->spread_spectrum_range =1072			(uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);1073		result = BP_RESULT_OK;1074		break;1075	}1076 1077	return result;1078 1079}1080 1081/**1082 * get_ss_info_from_ss_info_table1083 * Get spread sprectrum information from the SS_Info table from the VBIOS1084 * if the pointer to info is NULL, indicate the caller what to know the number1085 * of entries that matches the id1086 * for, the SS_Info table, there should not be more than 1 entry match.1087 *1088 * @bp:      pointer to the Bios parser1089 * @id:      spread sprectrum id1090 * @ss_info: sprectrum information structure,1091 * return:   Bios parser result code1092 */1093static enum bp_result get_ss_info_from_ss_info_table(1094	struct bios_parser *bp,1095	uint32_t id,1096	struct spread_spectrum_info *ss_info)1097{1098	enum bp_result result = BP_RESULT_UNSUPPORTED;1099	ATOM_SPREAD_SPECTRUM_INFO *tbl;1100	ATOM_COMMON_TABLE_HEADER *header;1101	uint32_t table_size;1102	uint32_t i;1103	uint32_t id_local = SS_ID_UNKNOWN;1104	struct atom_data_revision revision;1105 1106	/* exist of the SS_Info table */1107	/* check for bad input, pSSinfo can not be NULL */1108	if (!DATA_TABLES(SS_Info) || !ss_info)1109		return result;1110 1111	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(SS_Info));1112	get_atom_data_table_revision(header, &revision);1113 1114	tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, DATA_TABLES(SS_Info));1115	if (!tbl)1116		return result;1117 1118	if (1 != revision.major || 2 > revision.minor)1119		return result;1120 1121	/* have to convert from Internal_SS format to SS_Info format */1122	switch (id) {1123	case ASIC_INTERNAL_SS_ON_DP:1124		id_local = SS_ID_DP1;1125		break;1126	case ASIC_INTERNAL_SS_ON_LVDS:1127	{1128		struct embedded_panel_info panel_info;1129 1130		if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)1131				== BP_RESULT_OK)1132			id_local = panel_info.ss_id;1133		break;1134	}1135	default:1136		break;1137	}1138 1139	if (id_local == SS_ID_UNKNOWN)1140		return result;1141 1142	table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -1143			sizeof(ATOM_COMMON_TABLE_HEADER)) /1144					sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);1145 1146	for (i = 0; i < table_size; i++) {1147		if (id_local != (uint32_t)tbl->asSS_Info[i].ucSS_Id)1148			continue;1149 1150		memset(ss_info, 0, sizeof(struct spread_spectrum_info));1151 1152		if (ATOM_EXTERNAL_SS_MASK &1153				tbl->asSS_Info[i].ucSpreadSpectrumType)1154			ss_info->type.EXTERNAL = true;1155 1156		if (ATOM_SS_CENTRE_SPREAD_MODE_MASK &1157				tbl->asSS_Info[i].ucSpreadSpectrumType)1158			ss_info->type.CENTER_MODE = true;1159 1160		ss_info->type.STEP_AND_DELAY_INFO = true;1161		ss_info->spread_spectrum_percentage =1162			(uint32_t)le16_to_cpu(tbl->asSS_Info[i].usSpreadSpectrumPercentage);1163		ss_info->step_and_delay_info.step = tbl->asSS_Info[i].ucSS_Step;1164		ss_info->step_and_delay_info.delay =1165			tbl->asSS_Info[i].ucSS_Delay;1166		ss_info->step_and_delay_info.recommended_ref_div =1167			tbl->asSS_Info[i].ucRecommendedRef_Div;1168		ss_info->spread_spectrum_range =1169			(uint32_t)tbl->asSS_Info[i].ucSS_Range * 10000;1170 1171		/* there will be only one entry for each display type in SS_info1172		 * table */1173		result = BP_RESULT_OK;1174		break;1175	}1176 1177	return result;1178}1179static enum bp_result get_embedded_panel_info_v1_2(1180	struct bios_parser *bp,1181	struct embedded_panel_info *info);1182static enum bp_result get_embedded_panel_info_v1_3(1183	struct bios_parser *bp,1184	struct embedded_panel_info *info);1185 1186static enum bp_result bios_parser_get_embedded_panel_info(1187	struct dc_bios *dcb,1188	struct embedded_panel_info *info)1189{1190	struct bios_parser *bp = BP_FROM_DCB(dcb);1191	ATOM_COMMON_TABLE_HEADER *hdr;1192 1193	if (!DATA_TABLES(LCD_Info))1194		return BP_RESULT_FAILURE;1195 1196	hdr = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(LCD_Info));1197 1198	if (!hdr)1199		return BP_RESULT_BADBIOSTABLE;1200 1201	switch (hdr->ucTableFormatRevision) {1202	case 1:1203		switch (hdr->ucTableContentRevision) {1204		case 0:1205		case 1:1206		case 2:1207			return get_embedded_panel_info_v1_2(bp, info);1208		case 3:1209			return get_embedded_panel_info_v1_3(bp, info);1210		default:1211			break;1212		}1213		break;1214	default:1215		break;1216	}1217 1218	return BP_RESULT_FAILURE;1219}1220 1221static enum bp_result get_embedded_panel_info_v1_2(1222	struct bios_parser *bp,1223	struct embedded_panel_info *info)1224{1225	ATOM_LVDS_INFO_V12 *lvds;1226 1227	if (!info)1228		return BP_RESULT_BADINPUT;1229 1230	if (!DATA_TABLES(LVDS_Info))1231		return BP_RESULT_UNSUPPORTED;1232 1233	lvds =1234		GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info));1235 1236	if (!lvds)1237		return BP_RESULT_BADBIOSTABLE;1238 1239	if (1 != lvds->sHeader.ucTableFormatRevision1240		|| 2 > lvds->sHeader.ucTableContentRevision)1241		return BP_RESULT_UNSUPPORTED;1242 1243	memset(info, 0, sizeof(struct embedded_panel_info));1244 1245	/* We need to convert from 10KHz units into KHz units*/1246	info->lcd_timing.pixel_clk =1247		le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;1248	/* usHActive does not include borders, according to VBIOS team*/1249	info->lcd_timing.horizontal_addressable =1250		le16_to_cpu(lvds->sLCDTiming.usHActive);1251	/* usHBlanking_Time includes borders, so we should really be subtracting1252	 * borders duing this translation, but LVDS generally*/1253	/* doesn't have borders, so we should be okay leaving this as is for1254	 * now.  May need to revisit if we ever have LVDS with borders*/1255	info->lcd_timing.horizontal_blanking_time =1256			le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);1257	/* usVActive does not include borders, according to VBIOS team*/1258	info->lcd_timing.vertical_addressable =1259			le16_to_cpu(lvds->sLCDTiming.usVActive);1260	/* usVBlanking_Time includes borders, so we should really be subtracting1261	 * borders duing this translation, but LVDS generally*/1262	/* doesn't have borders, so we should be okay leaving this as is for1263	 * now. May need to revisit if we ever have LVDS with borders*/1264	info->lcd_timing.vertical_blanking_time =1265		le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);1266	info->lcd_timing.horizontal_sync_offset =1267		le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);1268	info->lcd_timing.horizontal_sync_width =1269		le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);1270	info->lcd_timing.vertical_sync_offset =1271		le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);1272	info->lcd_timing.vertical_sync_width =1273		le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);1274	info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;1275	info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;1276	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =1277		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;1278	info->lcd_timing.misc_info.H_SYNC_POLARITY =1279		~(uint32_t)1280		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;1281	info->lcd_timing.misc_info.V_SYNC_POLARITY =1282		~(uint32_t)1283		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;1284	info->lcd_timing.misc_info.VERTICAL_CUT_OFF =1285		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;1286	info->lcd_timing.misc_info.H_REPLICATION_BY2 =1287		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;1288	info->lcd_timing.misc_info.V_REPLICATION_BY2 =1289		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;1290	info->lcd_timing.misc_info.COMPOSITE_SYNC =1291		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;1292	info->lcd_timing.misc_info.INTERLACE =1293		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;1294	info->lcd_timing.misc_info.DOUBLE_CLOCK =1295		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;1296	info->ss_id = lvds->ucSS_Id;1297 1298	{1299		uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate);1300		/* Get minimum supported refresh rate*/1301		if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)1302			info->supported_rr.REFRESH_RATE_30HZ = 1;1303		else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)1304			info->supported_rr.REFRESH_RATE_40HZ = 1;1305		else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)1306			info->supported_rr.REFRESH_RATE_48HZ = 1;1307		else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)1308			info->supported_rr.REFRESH_RATE_50HZ = 1;1309		else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)1310			info->supported_rr.REFRESH_RATE_60HZ = 1;1311	}1312 1313	/*Drr panel support can be reported by VBIOS*/1314	if (LCDPANEL_CAP_DRR_SUPPORTED1315			& lvds->ucLCDPanel_SpecialHandlingCap)1316		info->drr_enabled = 1;1317 1318	if (ATOM_PANEL_MISC_DUAL & lvds->ucLVDS_Misc)1319		info->lcd_timing.misc_info.DOUBLE_CLOCK = true;1320 1321	if (ATOM_PANEL_MISC_888RGB & lvds->ucLVDS_Misc)1322		info->lcd_timing.misc_info.RGB888 = true;1323 1324	info->lcd_timing.misc_info.GREY_LEVEL =1325		(uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL &1326			lvds->ucLVDS_Misc) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT;1327 1328	if (ATOM_PANEL_MISC_SPATIAL & lvds->ucLVDS_Misc)1329		info->lcd_timing.misc_info.SPATIAL = true;1330 1331	if (ATOM_PANEL_MISC_TEMPORAL & lvds->ucLVDS_Misc)1332		info->lcd_timing.misc_info.TEMPORAL = true;1333 1334	if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc)1335		info->lcd_timing.misc_info.API_ENABLED = true;1336 1337	return BP_RESULT_OK;1338}1339 1340static enum bp_result get_embedded_panel_info_v1_3(1341	struct bios_parser *bp,1342	struct embedded_panel_info *info)1343{1344	ATOM_LCD_INFO_V13 *lvds;1345 1346	if (!info)1347		return BP_RESULT_BADINPUT;1348 1349	if (!DATA_TABLES(LCD_Info))1350		return BP_RESULT_UNSUPPORTED;1351 1352	lvds = GET_IMAGE(ATOM_LCD_INFO_V13, DATA_TABLES(LCD_Info));1353 1354	if (!lvds)1355		return BP_RESULT_BADBIOSTABLE;1356 1357	if (!((1 == lvds->sHeader.ucTableFormatRevision)1358			&& (3 <= lvds->sHeader.ucTableContentRevision)))1359		return BP_RESULT_UNSUPPORTED;1360 1361	memset(info, 0, sizeof(struct embedded_panel_info));1362 1363	/* We need to convert from 10KHz units into KHz units */1364	info->lcd_timing.pixel_clk =1365			le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;1366	/* usHActive does not include borders, according to VBIOS team */1367	info->lcd_timing.horizontal_addressable =1368			le16_to_cpu(lvds->sLCDTiming.usHActive);1369	/* usHBlanking_Time includes borders, so we should really be subtracting1370	 * borders duing this translation, but LVDS generally*/1371	/* doesn't have borders, so we should be okay leaving this as is for1372	 * now.  May need to revisit if we ever have LVDS with borders*/1373	info->lcd_timing.horizontal_blanking_time =1374		le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);1375	/* usVActive does not include borders, according to VBIOS team*/1376	info->lcd_timing.vertical_addressable =1377		le16_to_cpu(lvds->sLCDTiming.usVActive);1378	/* usVBlanking_Time includes borders, so we should really be subtracting1379	 * borders duing this translation, but LVDS generally*/1380	/* doesn't have borders, so we should be okay leaving this as is for1381	 * now. May need to revisit if we ever have LVDS with borders*/1382	info->lcd_timing.vertical_blanking_time =1383		le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);1384	info->lcd_timing.horizontal_sync_offset =1385		le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);1386	info->lcd_timing.horizontal_sync_width =1387		le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);1388	info->lcd_timing.vertical_sync_offset =1389		le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);1390	info->lcd_timing.vertical_sync_width =1391		le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);1392	info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;1393	info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;1394	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =1395		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;1396	info->lcd_timing.misc_info.H_SYNC_POLARITY =1397		~(uint32_t)1398		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;1399	info->lcd_timing.misc_info.V_SYNC_POLARITY =1400		~(uint32_t)1401		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;1402	info->lcd_timing.misc_info.VERTICAL_CUT_OFF =1403		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;1404	info->lcd_timing.misc_info.H_REPLICATION_BY2 =1405		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;1406	info->lcd_timing.misc_info.V_REPLICATION_BY2 =1407		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;1408	info->lcd_timing.misc_info.COMPOSITE_SYNC =1409		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;1410	info->lcd_timing.misc_info.INTERLACE =1411		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;1412	info->lcd_timing.misc_info.DOUBLE_CLOCK =1413		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;1414	info->ss_id = lvds->ucSS_Id;1415 1416	/* Drr panel support can be reported by VBIOS*/1417	if (LCDPANEL_CAP_V13_DRR_SUPPORTED1418			& lvds->ucLCDPanel_SpecialHandlingCap)1419		info->drr_enabled = 1;1420 1421	/* Get supported refresh rate*/1422	if (info->drr_enabled == 1) {1423		uint8_t min_rr =1424				lvds->sRefreshRateSupport.ucMinRefreshRateForDRR;1425		uint8_t rr = lvds->sRefreshRateSupport.ucSupportedRefreshRate;1426 1427		if (min_rr != 0) {1428			if (SUPPORTED_LCD_REFRESHRATE_30Hz & min_rr)1429				info->supported_rr.REFRESH_RATE_30HZ = 1;1430			else if (SUPPORTED_LCD_REFRESHRATE_40Hz & min_rr)1431				info->supported_rr.REFRESH_RATE_40HZ = 1;1432			else if (SUPPORTED_LCD_REFRESHRATE_48Hz & min_rr)1433				info->supported_rr.REFRESH_RATE_48HZ = 1;1434			else if (SUPPORTED_LCD_REFRESHRATE_50Hz & min_rr)1435				info->supported_rr.REFRESH_RATE_50HZ = 1;1436			else if (SUPPORTED_LCD_REFRESHRATE_60Hz & min_rr)1437				info->supported_rr.REFRESH_RATE_60HZ = 1;1438		} else {1439			if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)1440				info->supported_rr.REFRESH_RATE_30HZ = 1;1441			else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)1442				info->supported_rr.REFRESH_RATE_40HZ = 1;1443			else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)1444				info->supported_rr.REFRESH_RATE_48HZ = 1;1445			else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)1446				info->supported_rr.REFRESH_RATE_50HZ = 1;1447			else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)1448				info->supported_rr.REFRESH_RATE_60HZ = 1;1449		}1450	}1451 1452	if (ATOM_PANEL_MISC_V13_DUAL & lvds->ucLCD_Misc)1453		info->lcd_timing.misc_info.DOUBLE_CLOCK = true;1454 1455	if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR & lvds->ucLCD_Misc)1456		info->lcd_timing.misc_info.RGB888 = true;1457 1458	info->lcd_timing.misc_info.GREY_LEVEL =1459			(uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL &1460				lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT;1461 1462	return BP_RESULT_OK;1463}1464 1465/**1466 * bios_parser_get_encoder_cap_info - get encoder capability1467 *                                    information of input object id1468 *1469 * @dcb:       pointer to the DC BIOS1470 * @object_id: object id1471 * @info:      encoder cap information structure1472 *1473 * return: Bios parser result code1474 */1475static enum bp_result bios_parser_get_encoder_cap_info(1476	struct dc_bios *dcb,1477	struct graphics_object_id object_id,1478	struct bp_encoder_cap_info *info)1479{1480	struct bios_parser *bp = BP_FROM_DCB(dcb);1481	ATOM_OBJECT *object;1482	ATOM_ENCODER_CAP_RECORD_V2 *record = NULL;1483 1484	if (!info)1485		return BP_RESULT_BADINPUT;1486 1487	object = get_bios_object(bp, object_id);1488 1489	if (!object)1490		return BP_RESULT_BADINPUT;1491 1492	record = get_encoder_cap_record(bp, object);1493	if (!record)1494		return BP_RESULT_NORECORD;1495 1496	info->DP_HBR2_EN = record->usHBR2En;1497	info->DP_HBR3_EN = record->usHBR3En;1498	info->HDMI_6GB_EN = record->usHDMI6GEn;1499	return BP_RESULT_OK;1500}1501 1502/**1503 * get_encoder_cap_record - Get encoder cap record for the object1504 *1505 * @bp:      pointer to the BIOS parser1506 * @object:  ATOM object1507 * return:   atom encoder cap record1508 * note:     search all records to find the ATOM_ENCODER_CAP_RECORD_V2 record1509 */1510static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(1511	struct bios_parser *bp,1512	ATOM_OBJECT *object)1513{1514	ATOM_COMMON_RECORD_HEADER *header;1515	uint32_t offset;1516 1517	if (!object) {1518		BREAK_TO_DEBUGGER(); /* Invalid object */1519		return NULL;1520	}1521 1522	offset = le16_to_cpu(object->usRecordOffset)1523					+ bp->object_info_tbl_offset;1524 1525	for (;;) {1526		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);1527 1528		if (!header)1529			return NULL;1530 1531		offset += header->ucRecordSize;1532 1533		if (LAST_RECORD_TYPE == header->ucRecordType ||1534				!header->ucRecordSize)1535			break;1536 1537		if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType)1538			continue;1539 1540		if (sizeof(ATOM_ENCODER_CAP_RECORD_V2) <= header->ucRecordSize)1541			return (ATOM_ENCODER_CAP_RECORD_V2 *)header;1542	}1543 1544	return NULL;1545}1546 1547static uint32_t get_ss_entry_number(1548	struct bios_parser *bp,1549	uint32_t id);1550static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(1551	struct bios_parser *bp,1552	uint32_t id);1553static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(1554	struct bios_parser *bp,1555	uint32_t id);1556static uint32_t get_ss_entry_number_from_ss_info_tbl(1557	struct bios_parser *bp,1558	uint32_t id);1559 1560/**1561 * bios_parser_get_ss_entry_number1562 * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from1563 * the VBIOS that match the SSid (to be converted from signal)1564 *1565 * @dcb:    pointer to the DC BIOS1566 * @signal: ASSignalType to be converted to SSid1567 * return: number of SS Entry that match the signal1568 */1569static uint32_t bios_parser_get_ss_entry_number(1570	struct dc_bios *dcb,1571	enum as_signal_type signal)1572{1573	struct bios_parser *bp = BP_FROM_DCB(dcb);1574	uint32_t ss_id = 0;1575	ATOM_COMMON_TABLE_HEADER *header;1576	struct atom_data_revision revision;1577 1578	ss_id = signal_to_ss_id(signal);1579 1580	if (!DATA_TABLES(ASIC_InternalSS_Info))1581		return get_ss_entry_number_from_ss_info_tbl(bp, ss_id);1582 1583	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,1584			DATA_TABLES(ASIC_InternalSS_Info));1585	get_atom_data_table_revision(header, &revision);1586 1587	switch (revision.major) {1588	case 2:1589		switch (revision.minor) {1590		case 1:1591			return get_ss_entry_number(bp, ss_id);1592		default:1593			break;1594		}1595		break;1596	case 3:1597		switch (revision.minor) {1598		case 1:1599			return1600				get_ss_entry_number_from_internal_ss_info_tbl_V3_1(1601						bp, ss_id);1602		default:1603			break;1604		}1605		break;1606	default:1607		break;1608	}1609 1610	return 0;1611}1612 1613/**1614 * get_ss_entry_number_from_ss_info_tbl1615 * Get Number of spread spectrum entry from the SS_Info table from the VBIOS.1616 *1617 * @bp:  pointer to the BIOS parser1618 * @id:  spread spectrum id1619 * return: number of SS Entry that match the id1620 * note: There can only be one entry for each id for SS_Info Table1621 */1622static uint32_t get_ss_entry_number_from_ss_info_tbl(1623	struct bios_parser *bp,1624	uint32_t id)1625{1626	ATOM_SPREAD_SPECTRUM_INFO *tbl;1627	ATOM_COMMON_TABLE_HEADER *header;1628	uint32_t table_size;1629	uint32_t i;1630	uint32_t number = 0;1631	uint32_t id_local = SS_ID_UNKNOWN;1632	struct atom_data_revision revision;1633 1634	/* SS_Info table exist */1635	if (!DATA_TABLES(SS_Info))1636		return number;1637 1638	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,1639			DATA_TABLES(SS_Info));1640	get_atom_data_table_revision(header, &revision);1641 1642	tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO,1643			DATA_TABLES(SS_Info));1644	if (!tbl)1645		return number;1646 1647	if (1 != revision.major || 2 > revision.minor)1648		return number;1649 1650	/* have to convert from Internal_SS format to SS_Info format */1651	switch (id) {1652	case ASIC_INTERNAL_SS_ON_DP:1653		id_local = SS_ID_DP1;1654		break;1655	case ASIC_INTERNAL_SS_ON_LVDS: {1656		struct embedded_panel_info panel_info;1657 1658		if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)1659				== BP_RESULT_OK)1660			id_local = panel_info.ss_id;1661		break;1662	}1663	default:1664		break;1665	}1666 1667	if (id_local == SS_ID_UNKNOWN)1668		return number;1669 1670	table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -1671			sizeof(ATOM_COMMON_TABLE_HEADER)) /1672					sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);1673 1674	for (i = 0; i < table_size; i++)1675		if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) {1676			number = 1;1677			break;1678		}1679 1680	return number;1681}1682 1683/**1684 * get_ss_entry_number1685 * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or1686 * SS_Info table from the VBIOS1687 * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or1688 * SS_Info.1689 *1690 * @bp:    pointer to the BIOS parser1691 * @id:    spread sprectrum info index1692 * return: Bios parser result code1693 */1694static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id)1695{1696	if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)1697		return get_ss_entry_number_from_ss_info_tbl(bp, id);1698 1699	return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id);1700}1701 1702/**1703 * get_ss_entry_number_from_internal_ss_info_tbl_v2_11704 * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table1705 * Ver 2.1 from the VBIOS1706 * There will not be multiple entry for Ver 2.11707 *1708 * @bp:    pointer to the BIOS parser1709 * @id:    spread sprectrum info index1710 * return: number of SS Entry that match the id1711 */1712static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(1713	struct bios_parser *bp,1714	uint32_t id)1715{1716	ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include;1717	ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;1718	uint32_t size;1719	uint32_t i;1720 1721	if (!DATA_TABLES(ASIC_InternalSS_Info))1722		return 0;1723 1724	header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V2 *) bios_get_image(1725				&bp->base,1726				DATA_TABLES(ASIC_InternalSS_Info),1727				struct_size(header_include, asSpreadSpectrum, 1)));1728	if (!header_include)1729		return 0;1730 1731	size = (le16_to_cpu(header_include->sHeader.usStructureSize)1732			- sizeof(ATOM_COMMON_TABLE_HEADER))1733						/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);1734 1735	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)1736				&header_include->asSpreadSpectrum[0];1737	for (i = 0; i < size; i++)1738		if (tbl[i].ucClockIndication == (uint8_t)id)1739			return 1;1740 1741	return 0;1742}1743 1744/**1745 * get_ss_entry_number_from_internal_ss_info_tbl_V3_11746 * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of1747 * the VBIOS that matches id1748 *1749 * @bp:    pointer to the BIOS parser1750 * @id:    spread sprectrum id1751 * return: number of SS Entry that match the id1752 */1753static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(1754	struct bios_parser *bp,1755	uint32_t id)1756{1757	uint32_t number = 0;1758	ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include;1759	ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;1760	uint32_t size;1761	uint32_t i;1762 1763	if (!DATA_TABLES(ASIC_InternalSS_Info))1764		return number;1765 1766	header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V3 *) bios_get_image(&bp->base,1767				DATA_TABLES(ASIC_InternalSS_Info),1768				struct_size(header_include, asSpreadSpectrum, 1)));1769	if (!header_include)1770		return number;1771 1772	size = (le16_to_cpu(header_include->sHeader.usStructureSize) -1773			sizeof(ATOM_COMMON_TABLE_HEADER)) /1774					sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);1775 1776	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)1777				&header_include->asSpreadSpectrum[0];1778 1779	for (i = 0; i < size; i++)1780		if (tbl[i].ucClockIndication == (uint8_t)id)1781			number++;1782 1783	return number;1784}1785 1786/**1787 * bios_parser_get_gpio_pin_info1788 * Get GpioPin information of input gpio id1789 *1790 * @dcb:     pointer to the DC BIOS1791 * @gpio_id: GPIO ID1792 * @info:    GpioPin information structure1793 * return:   Bios parser result code1794 * note:1795 *  to get the GPIO PIN INFO, we need:1796 *  1. get the GPIO_ID from other object table, see GetHPDInfo()1797 *  2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA1798 *  offset/mask1799 */1800static enum bp_result bios_parser_get_gpio_pin_info(1801	struct dc_bios *dcb,1802	uint32_t gpio_id,1803	struct gpio_pin_info *info)1804{1805	struct bios_parser *bp = BP_FROM_DCB(dcb);1806	ATOM_GPIO_PIN_LUT *header;1807	uint32_t count = 0;1808	uint32_t i = 0;1809 1810	if (!DATA_TABLES(GPIO_Pin_LUT))1811		return BP_RESULT_BADBIOSTABLE;1812 1813	header = ((ATOM_GPIO_PIN_LUT *) bios_get_image(&bp->base,1814				DATA_TABLES(GPIO_Pin_LUT),1815				struct_size(header, asGPIO_Pin, 1)));1816	if (!header)1817		return BP_RESULT_BADBIOSTABLE;1818 1819	if (sizeof(ATOM_COMMON_TABLE_HEADER) + struct_size(header, asGPIO_Pin, 1)1820			> le16_to_cpu(header->sHeader.usStructureSize))1821		return BP_RESULT_BADBIOSTABLE;1822 1823	if (1 != header->sHeader.ucTableContentRevision)1824		return BP_RESULT_UNSUPPORTED;1825 1826	count = (le16_to_cpu(header->sHeader.usStructureSize)1827			- sizeof(ATOM_COMMON_TABLE_HEADER))1828				/ sizeof(ATOM_GPIO_PIN_ASSIGNMENT);1829	for (i = 0; i < count; ++i) {1830		if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id)1831			continue;1832 1833		info->offset =1834			(uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex);1835		info->offset_y = info->offset + 2;1836		info->offset_en = info->offset + 1;1837		info->offset_mask = info->offset - 1;1838 1839		info->mask = (uint32_t) (1 <<1840			header->asGPIO_Pin[i].ucGpioPinBitShift);1841		info->mask_y = info->mask + 2;1842		info->mask_en = info->mask + 1;1843		info->mask_mask = info->mask - 1;1844 1845		return BP_RESULT_OK;1846	}1847 1848	return BP_RESULT_NORECORD;1849}1850 1851static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,1852	ATOM_I2C_RECORD *record,1853	struct graphics_object_i2c_info *info)1854{1855	ATOM_GPIO_I2C_INFO *header;1856	uint32_t count = 0;1857 1858	if (!info)1859		return BP_RESULT_BADINPUT;1860 1861	/* get the GPIO_I2C info */1862	if (!DATA_TABLES(GPIO_I2C_Info))1863		return BP_RESULT_BADBIOSTABLE;1864 1865	header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info));1866	if (!header)1867		return BP_RESULT_BADBIOSTABLE;1868 1869	if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT)1870			> le16_to_cpu(header->sHeader.usStructureSize))1871		return BP_RESULT_BADBIOSTABLE;1872 1873	if (1 != header->sHeader.ucTableContentRevision)1874		return BP_RESULT_UNSUPPORTED;1875 1876	/* get data count */1877	count = (le16_to_cpu(header->sHeader.usStructureSize)1878			- sizeof(ATOM_COMMON_TABLE_HEADER))1879				/ sizeof(ATOM_GPIO_I2C_ASSIGMENT);1880	if (count < record->sucI2cId.bfI2C_LineMux)1881		return BP_RESULT_BADBIOSTABLE;1882 1883	/* get the GPIO_I2C_INFO */1884	info->i2c_hw_assist = record->sucI2cId.bfHW_Capable;1885	info->i2c_line = record->sucI2cId.bfI2C_LineMux;1886	info->i2c_engine_id = record->sucI2cId.bfHW_EngineID;1887	info->i2c_slave_address = record->ucI2CAddr;1888 1889	info->gpio_info.clk_mask_register_index =1890			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex);1891	info->gpio_info.clk_en_register_index =1892			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex);1893	info->gpio_info.clk_y_register_index =1894			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex);1895	info->gpio_info.clk_a_register_index =1896			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex);1897	info->gpio_info.data_mask_register_index =1898			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex);1899	info->gpio_info.data_en_register_index =1900			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex);1901	info->gpio_info.data_y_register_index =1902			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex);1903	info->gpio_info.data_a_register_index =1904			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex);1905 1906	info->gpio_info.clk_mask_shift =1907			header->asGPIO_Info[info->i2c_line].ucClkMaskShift;1908	info->gpio_info.clk_en_shift =1909			header->asGPIO_Info[info->i2c_line].ucClkEnShift;1910	info->gpio_info.clk_y_shift =1911			header->asGPIO_Info[info->i2c_line].ucClkY_Shift;1912	info->gpio_info.clk_a_shift =1913			header->asGPIO_Info[info->i2c_line].ucClkA_Shift;1914	info->gpio_info.data_mask_shift =1915			header->asGPIO_Info[info->i2c_line].ucDataMaskShift;1916	info->gpio_info.data_en_shift =1917			header->asGPIO_Info[info->i2c_line].ucDataEnShift;1918	info->gpio_info.data_y_shift =1919			header->asGPIO_Info[info->i2c_line].ucDataY_Shift;1920	info->gpio_info.data_a_shift =1921			header->asGPIO_Info[info->i2c_line].ucDataA_Shift;1922 1923	return BP_RESULT_OK;1924}1925 1926static bool dal_graphics_object_id_is_valid(struct graphics_object_id id)1927{1928	bool rc = true;1929 1930	switch (id.type) {1931	case OBJECT_TYPE_UNKNOWN:1932		rc = false;1933		break;1934	case OBJECT_TYPE_GPU:1935	case OBJECT_TYPE_ENGINE:1936		/* do NOT check for id.id == 0 */1937		if (id.enum_id == ENUM_ID_UNKNOWN)1938			rc = false;1939		break;1940	default:1941		if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN)1942			rc = false;1943		break;1944	}1945 1946	return rc;1947}1948 1949static bool dal_graphics_object_id_is_equal(1950	struct graphics_object_id id1,1951	struct graphics_object_id id2)1952{1953	if (false == dal_graphics_object_id_is_valid(id1)) {1954		dm_output_to_console(1955		"%s: Warning: comparing invalid object 'id1'!\n", __func__);1956		return false;1957	}1958 1959	if (false == dal_graphics_object_id_is_valid(id2)) {1960		dm_output_to_console(1961		"%s: Warning: comparing invalid object 'id2'!\n", __func__);1962		return false;1963	}1964 1965	if (id1.id == id2.id && id1.enum_id == id2.enum_id1966		&& id1.type == id2.type)1967		return true;1968 1969	return false;1970}1971 1972static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,1973	struct graphics_object_id id)1974{1975	uint32_t offset;1976	ATOM_OBJECT_TABLE *tbl;1977	uint32_t i;1978 1979	switch (id.type) {1980	case OBJECT_TYPE_ENCODER:1981		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);1982		break;1983 1984	case OBJECT_TYPE_CONNECTOR:1985		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);1986		break;1987 1988	case OBJECT_TYPE_ROUTER:1989		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset);1990		break;1991 1992	case OBJECT_TYPE_GENERIC:1993		if (bp->object_info_tbl.revision.minor < 3)1994			return NULL;1995		offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset);1996		break;1997 1998	default:1999		return NULL;2000	}2001 2002	offset += bp->object_info_tbl_offset;2003 2004	tbl = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base, offset,2005				struct_size(tbl, asObjects, 1)));2006	if (!tbl)2007		return NULL;2008 2009	for (i = 0; i < tbl->ucNumberOfObjects; i++)2010		if (dal_graphics_object_id_is_equal(id,2011				object_id_from_bios_object_id(2012						le16_to_cpu(tbl->asObjects[i].usObjectID))))2013			return &tbl->asObjects[i];2014 2015	return NULL;2016}2017 2018static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,2019	uint16_t **id_list)2020{2021	uint32_t offset;2022	uint8_t *number;2023 2024	if (!object) {2025		BREAK_TO_DEBUGGER(); /* Invalid object id */2026		return 0;2027	}2028 2029	offset = le16_to_cpu(object->usSrcDstTableOffset)2030					+ bp->object_info_tbl_offset;2031 2032	number = GET_IMAGE(uint8_t, offset);2033	if (!number)2034		return 0;2035 2036	offset += sizeof(uint8_t);2037	*id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t));2038 2039	if (!*id_list)2040		return 0;2041 2042	return *number;2043}2044 2045static struct device_id device_type_from_device_id(uint16_t device_id)2046{2047 2048	struct device_id result_device_id = {0};2049 2050	switch (device_id) {2051	case ATOM_DEVICE_LCD1_SUPPORT:2052		result_device_id.device_type = DEVICE_TYPE_LCD;2053		result_device_id.enum_id = 1;2054		break;2055 2056	case ATOM_DEVICE_LCD2_SUPPORT:2057		result_device_id.device_type = DEVICE_TYPE_LCD;2058		result_device_id.enum_id = 2;2059		break;2060 2061	case ATOM_DEVICE_CRT1_SUPPORT:2062		result_device_id.device_type = DEVICE_TYPE_CRT;2063		result_device_id.enum_id = 1;2064		break;2065 2066	case ATOM_DEVICE_CRT2_SUPPORT:2067		result_device_id.device_type = DEVICE_TYPE_CRT;2068		result_device_id.enum_id = 2;2069		break;2070 2071	case ATOM_DEVICE_DFP1_SUPPORT:2072		result_device_id.device_type = DEVICE_TYPE_DFP;2073		result_device_id.enum_id = 1;2074		break;2075 2076	case ATOM_DEVICE_DFP2_SUPPORT:2077		result_device_id.device_type = DEVICE_TYPE_DFP;2078		result_device_id.enum_id = 2;2079		break;2080 2081	case ATOM_DEVICE_DFP3_SUPPORT:2082		result_device_id.device_type = DEVICE_TYPE_DFP;2083		result_device_id.enum_id = 3;2084		break;2085 2086	case ATOM_DEVICE_DFP4_SUPPORT:2087		result_device_id.device_type = DEVICE_TYPE_DFP;2088		result_device_id.enum_id = 4;2089		break;2090 2091	case ATOM_DEVICE_DFP5_SUPPORT:2092		result_device_id.device_type = DEVICE_TYPE_DFP;2093		result_device_id.enum_id = 5;2094		break;2095 2096	case ATOM_DEVICE_DFP6_SUPPORT:2097		result_device_id.device_type = DEVICE_TYPE_DFP;2098		result_device_id.enum_id = 6;2099		break;2100 2101	default:2102		BREAK_TO_DEBUGGER(); /* Invalid device Id */2103		result_device_id.device_type = DEVICE_TYPE_UNKNOWN;2104		result_device_id.enum_id = 0;2105	}2106	return result_device_id;2107}2108 2109static void get_atom_data_table_revision(2110	ATOM_COMMON_TABLE_HEADER *atom_data_tbl,2111	struct atom_data_revision *tbl_revision)2112{2113	if (!tbl_revision)2114		return;2115 2116	/* initialize the revision to 0 which is invalid revision */2117	tbl_revision->major = 0;2118	tbl_revision->minor = 0;2119 2120	if (!atom_data_tbl)2121		return;2122 2123	tbl_revision->major =2124			(uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl);2125	tbl_revision->minor =2126			(uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl);2127}2128 2129static uint32_t signal_to_ss_id(enum as_signal_type signal)2130{2131	uint32_t clk_id_ss = 0;2132 2133	switch (signal) {2134	case AS_SIGNAL_TYPE_DVI:2135		clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS;2136		break;2137	case AS_SIGNAL_TYPE_HDMI:2138		clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI;2139		break;2140	case AS_SIGNAL_TYPE_LVDS:2141		clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS;2142		break;2143	case AS_SIGNAL_TYPE_DISPLAY_PORT:2144		clk_id_ss = ASIC_INTERNAL_SS_ON_DP;2145		break;2146	case AS_SIGNAL_TYPE_GPU_PLL:2147		clk_id_ss = ASIC_INTERNAL_GPUPLL_SS;2148		break;2149	default:2150		break;2151	}2152	return clk_id_ss;2153}2154 2155static uint32_t get_support_mask_for_device_id(struct device_id device_id)2156{2157	enum dal_device_type device_type = device_id.device_type;2158	uint32_t enum_id = device_id.enum_id;2159 2160	switch (device_type) {2161	case DEVICE_TYPE_LCD:2162		switch (enum_id) {2163		case 1:2164			return ATOM_DEVICE_LCD1_SUPPORT;2165		case 2:2166			return ATOM_DEVICE_LCD2_SUPPORT;2167		default:2168			break;2169		}2170		break;2171	case DEVICE_TYPE_CRT:2172		switch (enum_id) {2173		case 1:2174			return ATOM_DEVICE_CRT1_SUPPORT;2175		case 2:2176			return ATOM_DEVICE_CRT2_SUPPORT;2177		default:2178			break;2179		}2180		break;2181	case DEVICE_TYPE_DFP:2182		switch (enum_id) {2183		case 1:2184			return ATOM_DEVICE_DFP1_SUPPORT;2185		case 2:2186			return ATOM_DEVICE_DFP2_SUPPORT;2187		case 3:2188			return ATOM_DEVICE_DFP3_SUPPORT;2189		case 4:2190			return ATOM_DEVICE_DFP4_SUPPORT;2191		case 5:2192			return ATOM_DEVICE_DFP5_SUPPORT;2193		case 6:2194			return ATOM_DEVICE_DFP6_SUPPORT;2195		default:2196			break;2197		}2198		break;2199	case DEVICE_TYPE_CV:2200		switch (enum_id) {2201		case 1:2202			return ATOM_DEVICE_CV_SUPPORT;2203		default:2204			break;2205		}2206		break;2207	case DEVICE_TYPE_TV:2208		switch (enum_id) {2209		case 1:2210			return ATOM_DEVICE_TV1_SUPPORT;2211		default:2212			break;2213		}2214		break;2215	default:2216		break;2217	}2218 2219	/* Unidentified device ID, return empty support mask. */2220	return 0;2221}2222 2223/**2224 * bios_parser_set_scratch_critical_state - update critical state2225 *                                          bit in VBIOS scratch register2226 * @dcb:    pointer to the DC BIOS2227 * @state:  set or reset state2228 */2229static void bios_parser_set_scratch_critical_state(2230	struct dc_bios *dcb,2231	bool state)2232{2233	bios_set_scratch_critical_state(dcb, state);2234}2235 2236/*2237 * get_integrated_info_v82238 *2239 * @brief2240 * Get V8 integrated BIOS information2241 *2242 * @param2243 * bios_parser *bp - [in]BIOS parser handler to get master data table2244 * integrated_info *info - [out] store and output integrated info2245 *2246 * return:2247 * enum bp_result - BP_RESULT_OK if information is available,2248 *                  BP_RESULT_BADBIOSTABLE otherwise.2249 */2250static enum bp_result get_integrated_info_v8(2251	struct bios_parser *bp,2252	struct integrated_info *info)2253{2254	ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8;2255	uint32_t i;2256 2257	info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8,2258			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);2259 2260	if (info_v8 == NULL)2261		return BP_RESULT_BADBIOSTABLE;2262	info->boot_up_engine_clock = le32_to_cpu(info_v8->ulBootUpEngineClock) * 10;2263	info->dentist_vco_freq = le32_to_cpu(info_v8->ulDentistVCOFreq) * 10;2264	info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;2265 2266	for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {2267		/* Convert [10KHz] into [KHz] */2268		info->disp_clk_voltage[i].max_supported_clk =2269			le32_to_cpu(info_v8->sDISPCLK_Voltage[i].2270				    ulMaximumSupportedCLK) * 10;2271		info->disp_clk_voltage[i].voltage_index =2272			le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex);2273	}2274 2275	info->boot_up_req_display_vector =2276		le32_to_cpu(info_v8->ulBootUpReqDisplayVector);2277	info->gpu_cap_info =2278		le32_to_cpu(info_v8->ulGPUCapInfo);2279 2280	/*2281	 * system_config: Bit[0] = 0 : PCIE power gating disabled2282	 *                       = 1 : PCIE power gating enabled2283	 *                Bit[1] = 0 : DDR-PLL shut down disabled2284	 *                       = 1 : DDR-PLL shut down enabled2285	 *                Bit[2] = 0 : DDR-PLL power down disabled2286	 *                       = 1 : DDR-PLL power down enabled2287	 */2288	info->system_config = le32_to_cpu(info_v8->ulSystemConfig);2289	info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo);2290	info->boot_up_nb_voltage =2291		le16_to_cpu(info_v8->usBootUpNBVoltage);2292	info->ext_disp_conn_info_offset =2293		le16_to_cpu(info_v8->usExtDispConnInfoOffset);2294	info->memory_type = info_v8->ucMemoryType;2295	info->ma_channel_number = info_v8->ucUMAChannelNumber;2296	info->gmc_restore_reset_time =2297		le32_to_cpu(info_v8->ulGMCRestoreResetTime);2298 2299	info->minimum_n_clk =2300		le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]);2301	for (i = 1; i < 4; ++i)2302		info->minimum_n_clk =2303			info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ?2304			info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]);2305 2306	info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk);2307	info->ddr_dll_power_up_time =2308		le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime);2309	info->ddr_pll_power_up_time =2310		le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime);2311	info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType);2312	info->lvds_ss_percentage =2313		le16_to_cpu(info_v8->usLvdsSSPercentage);2314	info->lvds_sspread_rate_in_10hz =2315		le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz);2316	info->hdmi_ss_percentage =2317		le16_to_cpu(info_v8->usHDMISSPercentage);2318	info->hdmi_sspread_rate_in_10hz =2319		le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz);2320	info->dvi_ss_percentage =2321		le16_to_cpu(info_v8->usDVISSPercentage);2322	info->dvi_sspread_rate_in_10_hz =2323		le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz);2324 2325	info->max_lvds_pclk_freq_in_single_link =2326		le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink);2327	info->lvds_misc = info_v8->ucLvdsMisc;2328	info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =2329		info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;2330	info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =2331		info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;2332	info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =2333		info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;2334	info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =2335		info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;2336	info->lvds_pwr_off_seq_de_to_dig_on_in4ms =2337		info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;2338	info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =2339		info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;2340	info->lvds_off_to_on_delay_in_4ms =2341		info_v8->ucLVDSOffToOnDelay_in4Ms;2342	info->lvds_bit_depth_control_val =2343		le32_to_cpu(info_v8->ulLCDBitDepthControlVal);2344 2345	for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {2346		/* Convert [10KHz] into [KHz] */2347		info->avail_s_clk[i].supported_s_clk =2348			le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10;2349		info->avail_s_clk[i].voltage_index =2350			le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex);2351		info->avail_s_clk[i].voltage_id =2352			le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID);2353	}2354 2355	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {2356		info->ext_disp_conn_info.gu_id[i] =2357			info_v8->sExtDispConnInfo.ucGuid[i];2358	}2359 2360	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {2361		info->ext_disp_conn_info.path[i].device_connector_id =2362			object_id_from_bios_object_id(2363				le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector));2364 2365		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =2366			object_id_from_bios_object_id(2367				le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId));2368 2369		info->ext_disp_conn_info.path[i].device_tag =2370			le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag);2371		info->ext_disp_conn_info.path[i].device_acpi_enum =2372			le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);2373		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =2374			info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;2375		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =2376			info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;2377		info->ext_disp_conn_info.path[i].channel_mapping.raw =2378			info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping;2379	}2380	info->ext_disp_conn_info.checksum =2381		info_v8->sExtDispConnInfo.ucChecksum;2382 2383	return BP_RESULT_OK;2384}2385 2386/*2387 * get_integrated_info_v82388 *2389 * @brief2390 * Get V8 integrated BIOS information2391 *2392 * @param2393 * bios_parser *bp - [in]BIOS parser handler to get master data table2394 * integrated_info *info - [out] store and output integrated info2395 *2396 * return:2397 * enum bp_result - BP_RESULT_OK if information is available,2398 *                  BP_RESULT_BADBIOSTABLE otherwise.2399 */2400static enum bp_result get_integrated_info_v9(2401	struct bios_parser *bp,2402	struct integrated_info *info)2403{2404	ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9;2405	uint32_t i;2406 2407	info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9,2408			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);2409 2410	if (!info_v9)2411		return BP_RESULT_BADBIOSTABLE;2412 2413	info->boot_up_engine_clock = le32_to_cpu(info_v9->ulBootUpEngineClock) * 10;2414	info->dentist_vco_freq = le32_to_cpu(info_v9->ulDentistVCOFreq) * 10;2415	info->boot_up_uma_clock = le32_to_cpu(info_v9->ulBootUpUMAClock) * 10;2416 2417	for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {2418		/* Convert [10KHz] into [KHz] */2419		info->disp_clk_voltage[i].max_supported_clk =2420			le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10;2421		info->disp_clk_voltage[i].voltage_index =2422			le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex);2423	}2424 2425	info->boot_up_req_display_vector =2426		le32_to_cpu(info_v9->ulBootUpReqDisplayVector);2427	info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo);2428 2429	/*2430	 * system_config: Bit[0] = 0 : PCIE power gating disabled2431	 *                       = 1 : PCIE power gating enabled2432	 *                Bit[1] = 0 : DDR-PLL shut down disabled2433	 *                       = 1 : DDR-PLL shut down enabled2434	 *                Bit[2] = 0 : DDR-PLL power down disabled2435	 *                       = 1 : DDR-PLL power down enabled2436	 */2437	info->system_config = le32_to_cpu(info_v9->ulSystemConfig);2438	info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo);2439	info->boot_up_nb_voltage = le16_to_cpu(info_v9->usBootUpNBVoltage);2440	info->ext_disp_conn_info_offset = le16_to_cpu(info_v9->usExtDispConnInfoOffset);2441	info->memory_type = info_v9->ucMemoryType;2442	info->ma_channel_number = info_v9->ucUMAChannelNumber;2443	info->gmc_restore_reset_time = le32_to_cpu(info_v9->ulGMCRestoreResetTime);2444 2445	info->minimum_n_clk = le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]);2446	for (i = 1; i < 4; ++i)2447		info->minimum_n_clk =2448			info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ?2449			info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]);2450 2451	info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk);2452	info->ddr_dll_power_up_time = le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime);2453	info->ddr_pll_power_up_time = le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime);2454	info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType);2455	info->lvds_ss_percentage = le16_to_cpu(info_v9->usLvdsSSPercentage);2456	info->lvds_sspread_rate_in_10hz = le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz);2457	info->hdmi_ss_percentage = le16_to_cpu(info_v9->usHDMISSPercentage);2458	info->hdmi_sspread_rate_in_10hz = le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz);2459	info->dvi_ss_percentage = le16_to_cpu(info_v9->usDVISSPercentage);2460	info->dvi_sspread_rate_in_10_hz = le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz);2461 2462	info->max_lvds_pclk_freq_in_single_link =2463		le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink);2464	info->lvds_misc = info_v9->ucLvdsMisc;2465	info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =2466		info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;2467	info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =2468		info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;2469	info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =2470		info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;2471	info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =2472		info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;2473	info->lvds_pwr_off_seq_de_to_dig_on_in4ms =2474		info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;2475	info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =2476		info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;2477	info->lvds_off_to_on_delay_in_4ms =2478		info_v9->ucLVDSOffToOnDelay_in4Ms;2479	info->lvds_bit_depth_control_val =2480		le32_to_cpu(info_v9->ulLCDBitDepthControlVal);2481 2482	for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {2483		/* Convert [10KHz] into [KHz] */2484		info->avail_s_clk[i].supported_s_clk =2485			le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10;2486		info->avail_s_clk[i].voltage_index =2487			le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex);2488		info->avail_s_clk[i].voltage_id =2489			le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID);2490	}2491 2492	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {2493		info->ext_disp_conn_info.gu_id[i] =2494			info_v9->sExtDispConnInfo.ucGuid[i];2495	}2496 2497	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {2498		info->ext_disp_conn_info.path[i].device_connector_id =2499			object_id_from_bios_object_id(2500				le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector));2501 2502		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =2503			object_id_from_bios_object_id(2504				le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId));2505 2506		info->ext_disp_conn_info.path[i].device_tag =2507			le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag);2508		info->ext_disp_conn_info.path[i].device_acpi_enum =2509			le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);2510		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =2511			info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;2512		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =2513			info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;2514		info->ext_disp_conn_info.path[i].channel_mapping.raw =2515			info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping;2516	}2517	info->ext_disp_conn_info.checksum =2518		info_v9->sExtDispConnInfo.ucChecksum;2519 2520	return BP_RESULT_OK;2521}2522 2523/*2524 * construct_integrated_info2525 *2526 * @brief2527 * Get integrated BIOS information based on table revision2528 *2529 * @param2530 * bios_parser *bp - [in]BIOS parser handler to get master data table2531 * integrated_info *info - [out] store and output integrated info2532 *2533 * return:2534 * enum bp_result - BP_RESULT_OK if information is available,2535 *                  BP_RESULT_BADBIOSTABLE otherwise.2536 */2537static enum bp_result construct_integrated_info(2538	struct bios_parser *bp,2539	struct integrated_info *info)2540{2541	enum bp_result result = BP_RESULT_BADBIOSTABLE;2542 2543	ATOM_COMMON_TABLE_HEADER *header;2544	struct atom_data_revision revision;2545 2546	if (bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) {2547		header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,2548				bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);2549 2550		get_atom_data_table_revision(header, &revision);2551 2552		/* Don't need to check major revision as they are all 1 */2553		switch (revision.minor) {2554		case 8:2555			result = get_integrated_info_v8(bp, info);2556			break;2557		case 9:2558			result = get_integrated_info_v9(bp, info);2559			break;2560		default:2561			return result;2562 2563		}2564	}2565 2566	/* Sort voltage table from low to high*/2567	if (result == BP_RESULT_OK) {2568		int32_t i;2569		int32_t j;2570 2571		for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {2572			for (j = i; j > 0; --j) {2573				if (2574						info->disp_clk_voltage[j].max_supported_clk <2575						info->disp_clk_voltage[j-1].max_supported_clk) {2576					/* swap j and j - 1*/2577					swap(info->disp_clk_voltage[j - 1],2578					     info->disp_clk_voltage[j]);2579				}2580			}2581		}2582 2583	}2584 2585	return result;2586}2587 2588static struct integrated_info *bios_parser_create_integrated_info(2589	struct dc_bios *dcb)2590{2591	struct bios_parser *bp = BP_FROM_DCB(dcb);2592	struct integrated_info *info;2593 2594	info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL);2595 2596	if (info == NULL) {2597		ASSERT_CRITICAL(0);2598		return NULL;2599	}2600 2601	if (construct_integrated_info(bp, info) == BP_RESULT_OK)2602		return info;2603 2604	kfree(info);2605 2606	return NULL;2607}2608 2609static enum bp_result update_slot_layout_info(struct dc_bios *dcb,2610					      unsigned int i,2611					      struct slot_layout_info *slot_layout_info,2612					      unsigned int record_offset)2613{2614	unsigned int j;2615	struct bios_parser *bp;2616	ATOM_BRACKET_LAYOUT_RECORD *record;2617	ATOM_COMMON_RECORD_HEADER *record_header;2618	enum bp_result result = BP_RESULT_NORECORD;2619 2620	bp = BP_FROM_DCB(dcb);2621	record = NULL;2622	record_header = NULL;2623 2624	for (;;) {2625 2626		record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);2627		if (record_header == NULL) {2628			result = BP_RESULT_BADBIOSTABLE;2629			break;2630		}2631 2632		/* the end of the list */2633		if (record_header->ucRecordType == 0xff ||2634			record_header->ucRecordSize == 0)	{2635			break;2636		}2637 2638		if (record_header->ucRecordType ==2639			ATOM_BRACKET_LAYOUT_RECORD_TYPE &&2640			struct_size(record, asConnInfo, 1)2641			<= record_header->ucRecordSize) {2642			record = (ATOM_BRACKET_LAYOUT_RECORD *)2643				(record_header);2644			result = BP_RESULT_OK;2645			break;2646		}2647 2648		record_offset += record_header->ucRecordSize;2649	}2650 2651	/* return if the record not found */2652	if (result != BP_RESULT_OK)2653		return result;2654 2655	/* get slot sizes */2656	slot_layout_info->length = record->ucLength;2657	slot_layout_info->width = record->ucWidth;2658 2659	/* get info for each connector in the slot */2660	slot_layout_info->num_of_connectors = record->ucConnNum;2661	for (j = 0; j < slot_layout_info->num_of_connectors; ++j) {2662		slot_layout_info->connectors[j].connector_type =2663			(enum connector_layout_type)2664			(record->asConnInfo[j].ucConnectorType);2665		switch (record->asConnInfo[j].ucConnectorType) {2666		case CONNECTOR_TYPE_DVI_D:2667			slot_layout_info->connectors[j].connector_type =2668				CONNECTOR_LAYOUT_TYPE_DVI_D;2669			slot_layout_info->connectors[j].length =2670				CONNECTOR_SIZE_DVI;2671			break;2672 2673		case CONNECTOR_TYPE_HDMI:2674			slot_layout_info->connectors[j].connector_type =2675				CONNECTOR_LAYOUT_TYPE_HDMI;2676			slot_layout_info->connectors[j].length =2677				CONNECTOR_SIZE_HDMI;2678			break;2679 2680		case CONNECTOR_TYPE_DISPLAY_PORT:2681			slot_layout_info->connectors[j].connector_type =2682				CONNECTOR_LAYOUT_TYPE_DP;2683			slot_layout_info->connectors[j].length =2684				CONNECTOR_SIZE_DP;2685			break;2686 2687		case CONNECTOR_TYPE_MINI_DISPLAY_PORT:2688			slot_layout_info->connectors[j].connector_type =2689				CONNECTOR_LAYOUT_TYPE_MINI_DP;2690			slot_layout_info->connectors[j].length =2691				CONNECTOR_SIZE_MINI_DP;2692			break;2693 2694		default:2695			slot_layout_info->connectors[j].connector_type =2696				CONNECTOR_LAYOUT_TYPE_UNKNOWN;2697			slot_layout_info->connectors[j].length =2698				CONNECTOR_SIZE_UNKNOWN;2699		}2700 2701		slot_layout_info->connectors[j].position =2702			record->asConnInfo[j].ucPosition;2703		slot_layout_info->connectors[j].connector_id =2704			object_id_from_bios_object_id(2705				record->asConnInfo[j].usConnectorObjectId);2706	}2707	return result;2708}2709 2710 2711static enum bp_result get_bracket_layout_record(struct dc_bios *dcb,2712						unsigned int bracket_layout_id,2713						struct slot_layout_info *slot_layout_info)2714{2715	unsigned int i;2716	unsigned int record_offset;2717	struct bios_parser *bp;2718	enum bp_result result;2719	ATOM_OBJECT *object;2720	ATOM_OBJECT_TABLE *object_table;2721	unsigned int genericTableOffset;2722 2723	bp = BP_FROM_DCB(dcb);2724	object = NULL;2725	if (slot_layout_info == NULL) {2726		DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");2727		return BP_RESULT_BADINPUT;2728	}2729 2730 2731	genericTableOffset = bp->object_info_tbl_offset +2732		bp->object_info_tbl.v1_3->usMiscObjectTableOffset;2733	object_table = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base,2734				genericTableOffset,2735				struct_size(object_table, asObjects, 1)));2736	if (!object_table)2737		return BP_RESULT_FAILURE;2738 2739	result = BP_RESULT_NORECORD;2740	for (i = 0; i < object_table->ucNumberOfObjects; ++i) {2741 2742		if (bracket_layout_id ==2743			object_table->asObjects[i].usObjectID) {2744 2745			object = &object_table->asObjects[i];2746			record_offset = object->usRecordOffset +2747				bp->object_info_tbl_offset;2748 2749			result = update_slot_layout_info(dcb, i,2750				slot_layout_info, record_offset);2751			break;2752		}2753	}2754	return result;2755}2756 2757static enum bp_result bios_get_board_layout_info(2758	struct dc_bios *dcb,2759	struct board_layout_info *board_layout_info)2760{2761	unsigned int i;2762	struct bios_parser *bp;2763	enum bp_result record_result;2764 2765	const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {2766		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1,2767		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2,2768		0, 02769	};2770 2771	bp = BP_FROM_DCB(dcb);2772 2773	if (board_layout_info == NULL) {2774		DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");2775		return BP_RESULT_BADINPUT;2776	}2777 2778	board_layout_info->num_of_slots = 0;2779 2780	for (i = 0; i < MAX_BOARD_SLOTS; ++i) {2781		record_result = get_bracket_layout_record(dcb,2782			slot_index_to_vbios_id[i],2783			&board_layout_info->slots[i]);2784 2785		if (record_result == BP_RESULT_NORECORD && i > 0)2786			break; /* no more slots present in bios */2787		else if (record_result != BP_RESULT_OK)2788			return record_result;  /* fail */2789 2790		++board_layout_info->num_of_slots;2791	}2792 2793	/* all data is valid */2794	board_layout_info->is_number_of_slots_valid = 1;2795	board_layout_info->is_slots_size_valid = 1;2796	board_layout_info->is_connector_offsets_valid = 1;2797	board_layout_info->is_connector_lengths_valid = 1;2798 2799	return BP_RESULT_OK;2800}2801 2802/******************************************************************************/2803 2804static const struct dc_vbios_funcs vbios_funcs = {2805	.get_connectors_number = bios_parser_get_connectors_number,2806 2807	.get_connector_id = bios_parser_get_connector_id,2808 2809	.get_src_obj = bios_parser_get_src_obj,2810 2811	.get_i2c_info = bios_parser_get_i2c_info,2812 2813	.get_hpd_info = bios_parser_get_hpd_info,2814 2815	.get_device_tag = bios_parser_get_device_tag,2816 2817	.get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,2818 2819	.get_ss_entry_number = bios_parser_get_ss_entry_number,2820 2821	.get_embedded_panel_info = bios_parser_get_embedded_panel_info,2822 2823	.get_gpio_pin_info = bios_parser_get_gpio_pin_info,2824 2825	.get_encoder_cap_info = bios_parser_get_encoder_cap_info,2826 2827	/* bios scratch register communication */2828	.is_accelerated_mode = bios_is_accelerated_mode,2829 2830	.set_scratch_critical_state = bios_parser_set_scratch_critical_state,2831 2832	.is_device_id_supported = bios_parser_is_device_id_supported,2833 2834	/* COMMANDS */2835	.encoder_control = bios_parser_encoder_control,2836 2837	.transmitter_control = bios_parser_transmitter_control,2838 2839	.enable_crtc = bios_parser_enable_crtc,2840 2841	.adjust_pixel_clock = bios_parser_adjust_pixel_clock,2842 2843	.set_pixel_clock = bios_parser_set_pixel_clock,2844 2845	.set_dce_clock = bios_parser_set_dce_clock,2846 2847	.enable_spread_spectrum_on_ppll = bios_parser_enable_spread_spectrum_on_ppll,2848 2849	.program_crtc_timing = bios_parser_program_crtc_timing, /* still use.  should probably retire and program directly */2850 2851	.program_display_engine_pll = bios_parser_program_display_engine_pll,2852 2853	.enable_disp_power_gating = bios_parser_enable_disp_power_gating,2854 2855	/* SW init and patch */2856 2857	.bios_parser_destroy = bios_parser_destroy,2858 2859	.get_board_layout_info = bios_get_board_layout_info,2860 2861	.get_atom_dc_golden_table = NULL2862};2863 2864static bool bios_parser_construct(2865	struct bios_parser *bp,2866	struct bp_init_data *init,2867	enum dce_version dce_version)2868{2869	uint16_t *rom_header_offset = NULL;2870	ATOM_ROM_HEADER *rom_header = NULL;2871	ATOM_OBJECT_HEADER *object_info_tbl;2872	struct atom_data_revision tbl_rev = {0};2873 2874	if (!init)2875		return false;2876 2877	if (!init->bios)2878		return false;2879 2880	bp->base.funcs = &vbios_funcs;2881	bp->base.bios = init->bios;2882	bp->base.bios_size = bp->base.bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT;2883 2884	bp->base.ctx = init->ctx;2885	bp->base.bios_local_image = NULL;2886 2887	rom_header_offset =2888	GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER);2889 2890	if (!rom_header_offset)2891		return false;2892 2893	rom_header = GET_IMAGE(ATOM_ROM_HEADER, *rom_header_offset);2894 2895	if (!rom_header)2896		return false;2897 2898	get_atom_data_table_revision(&rom_header->sHeader, &tbl_rev);2899	if (tbl_rev.major >= 2 && tbl_rev.minor >= 2)2900		return false;2901 2902	bp->master_data_tbl =2903	GET_IMAGE(ATOM_MASTER_DATA_TABLE,2904		rom_header->usMasterDataTableOffset);2905 2906	if (!bp->master_data_tbl)2907		return false;2908 2909	bp->object_info_tbl_offset = DATA_TABLES(Object_Header);2910 2911	if (!bp->object_info_tbl_offset)2912		return false;2913 2914	object_info_tbl =2915	GET_IMAGE(ATOM_OBJECT_HEADER, bp->object_info_tbl_offset);2916 2917	if (!object_info_tbl)2918		return false;2919 2920	get_atom_data_table_revision(&object_info_tbl->sHeader,2921		&bp->object_info_tbl.revision);2922 2923	if (bp->object_info_tbl.revision.major == 12924		&& bp->object_info_tbl.revision.minor >= 3) {2925		ATOM_OBJECT_HEADER_V3 *tbl_v3;2926 2927		tbl_v3 = GET_IMAGE(ATOM_OBJECT_HEADER_V3,2928			bp->object_info_tbl_offset);2929		if (!tbl_v3)2930			return false;2931 2932		bp->object_info_tbl.v1_3 = tbl_v3;2933	} else if (bp->object_info_tbl.revision.major == 12934		&& bp->object_info_tbl.revision.minor >= 1)2935		bp->object_info_tbl.v1_1 = object_info_tbl;2936	else2937		return false;2938 2939	dal_bios_parser_init_cmd_tbl(bp);2940	dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version);2941 2942	bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);2943	bp->base.fw_info_valid = bios_parser_get_firmware_info(&bp->base, &bp->base.fw_info) == BP_RESULT_OK;2944 2945	return true;2946}2947 2948/******************************************************************************/2949