Linux Audio

Check our new training course

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