Linux Audio

Check our new training course

Loading...
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/******************************************************************************/
v6.2
   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/i2caux_interface.h"
  37#include "include/logger_interface.h"
  38
  39#include "command_table.h"
  40#include "bios_parser_helper.h"
  41#include "command_table_helper.h"
  42#include "bios_parser.h"
  43#include "bios_parser_types_internal.h"
  44#include "bios_parser_interface.h"
  45
  46#include "bios_parser_common.h"
  47
  48#include "dc.h"
  49
  50#define THREE_PERCENT_OF_10000 300
  51
  52#define LAST_RECORD_TYPE 0xff
  53
  54#define DC_LOGGER \
  55	bp->base.ctx->logger
  56
  57#define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table)
  58
  59static void get_atom_data_table_revision(
  60	ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
  61	struct atom_data_revision *tbl_revision);
  62static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
  63	uint16_t **id_list);
  64static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
  65	struct graphics_object_id id);
  66static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
  67	ATOM_I2C_RECORD *record,
  68	struct graphics_object_i2c_info *info);
  69static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
  70	ATOM_OBJECT *object);
  71static struct device_id device_type_from_device_id(uint16_t device_id);
  72static uint32_t signal_to_ss_id(enum as_signal_type signal);
  73static uint32_t get_support_mask_for_device_id(struct device_id device_id);
  74static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
  75	struct bios_parser *bp,
  76	ATOM_OBJECT *object);
  77
  78#define BIOS_IMAGE_SIZE_OFFSET 2
  79#define BIOS_IMAGE_SIZE_UNIT 512
  80
  81/*****************************************************************************/
  82static bool bios_parser_construct(
  83	struct bios_parser *bp,
  84	struct bp_init_data *init,
  85	enum dce_version dce_version);
  86
  87static uint8_t bios_parser_get_connectors_number(
  88	struct dc_bios *dcb);
  89
  90static enum bp_result bios_parser_get_embedded_panel_info(
  91	struct dc_bios *dcb,
  92	struct embedded_panel_info *info);
  93
  94/*****************************************************************************/
  95
  96struct dc_bios *bios_parser_create(
  97	struct bp_init_data *init,
  98	enum dce_version dce_version)
  99{
 100	struct bios_parser *bp = NULL;
 101
 102	bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL);
 103	if (!bp)
 104		return NULL;
 105
 106	if (bios_parser_construct(bp, init, dce_version))
 107		return &bp->base;
 108
 109	kfree(bp);
 110	BREAK_TO_DEBUGGER();
 111	return NULL;
 112}
 113
 114static void bios_parser_destruct(struct bios_parser *bp)
 115{
 116	kfree(bp->base.bios_local_image);
 117	kfree(bp->base.integrated_info);
 118}
 119
 120static void bios_parser_destroy(struct dc_bios **dcb)
 121{
 122	struct bios_parser *bp = BP_FROM_DCB(*dcb);
 123
 124	if (!bp) {
 125		BREAK_TO_DEBUGGER();
 126		return;
 127	}
 128
 129	bios_parser_destruct(bp);
 130
 131	kfree(bp);
 132	*dcb = NULL;
 133}
 134
 135static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset)
 136{
 137	ATOM_OBJECT_TABLE *table;
 138
 139	uint32_t object_table_offset = bp->object_info_tbl_offset + offset;
 140
 141	table = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base,
 142				object_table_offset,
 143				struct_size(table, asObjects, 1)));
 144
 145	if (!table)
 146		return 0;
 147	else
 148		return table->ucNumberOfObjects;
 149}
 150
 151static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)
 152{
 153	struct bios_parser *bp = BP_FROM_DCB(dcb);
 154
 155	return get_number_of_objects(bp,
 156		le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset));
 157}
 158
 159static struct graphics_object_id bios_parser_get_connector_id(
 160	struct dc_bios *dcb,
 161	uint8_t i)
 162{
 163	struct bios_parser *bp = BP_FROM_DCB(dcb);
 164	struct graphics_object_id object_id = dal_graphics_object_id_init(
 165		0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
 166	uint16_t id;
 167
 168	uint32_t connector_table_offset = bp->object_info_tbl_offset
 169		+ le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
 170
 171	ATOM_OBJECT_TABLE *tbl = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base,
 172				connector_table_offset,
 173				struct_size(tbl, asObjects, 1)));
 174
 175	if (!tbl) {
 176		dm_error("Can't get connector table from atom bios.\n");
 177		return object_id;
 178	}
 179
 180	if (tbl->ucNumberOfObjects <= i) {
 181		dm_error("Can't find connector id %d in connector table of size %d.\n",
 182			 i, tbl->ucNumberOfObjects);
 183		return object_id;
 184	}
 185
 186	id = le16_to_cpu(tbl->asObjects[i].usObjectID);
 187	object_id = object_id_from_bios_object_id(id);
 188	return object_id;
 189}
 190
 191static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
 192	struct graphics_object_id object_id, uint32_t index,
 193	struct graphics_object_id *src_object_id)
 194{
 195	uint32_t number;
 196	uint16_t *id;
 197	ATOM_OBJECT *object;
 198	struct bios_parser *bp = BP_FROM_DCB(dcb);
 199
 200	if (!src_object_id)
 201		return BP_RESULT_BADINPUT;
 202
 203	object = get_bios_object(bp, object_id);
 204
 205	if (!object) {
 206		BREAK_TO_DEBUGGER(); /* Invalid object id */
 207		return BP_RESULT_BADINPUT;
 208	}
 209
 210	number = get_src_obj_list(bp, object, &id);
 211
 212	if (number <= index)
 213		return BP_RESULT_BADINPUT;
 214
 215	*src_object_id = object_id_from_bios_object_id(id[index]);
 216
 217	return BP_RESULT_OK;
 218}
 219
 220static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
 221	struct graphics_object_id id,
 222	struct graphics_object_i2c_info *info)
 223{
 224	uint32_t offset;
 225	ATOM_OBJECT *object;
 226	ATOM_COMMON_RECORD_HEADER *header;
 227	ATOM_I2C_RECORD *record;
 228	struct bios_parser *bp = BP_FROM_DCB(dcb);
 229
 230	if (!info)
 231		return BP_RESULT_BADINPUT;
 232
 233	object = get_bios_object(bp, id);
 234
 235	if (!object)
 236		return BP_RESULT_BADINPUT;
 237
 238	offset = le16_to_cpu(object->usRecordOffset)
 239			+ bp->object_info_tbl_offset;
 240
 241	for (;;) {
 242		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
 243
 244		if (!header)
 245			return BP_RESULT_BADBIOSTABLE;
 246
 247		if (LAST_RECORD_TYPE == header->ucRecordType ||
 248			!header->ucRecordSize)
 249			break;
 250
 251		if (ATOM_I2C_RECORD_TYPE == header->ucRecordType
 252			&& sizeof(ATOM_I2C_RECORD) <= header->ucRecordSize) {
 253			/* get the I2C info */
 254			record = (ATOM_I2C_RECORD *) header;
 255
 256			if (get_gpio_i2c_info(bp, record, info) == BP_RESULT_OK)
 257				return BP_RESULT_OK;
 258		}
 259
 260		offset += header->ucRecordSize;
 261	}
 262
 263	return BP_RESULT_NORECORD;
 264}
 265
 266static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb,
 267	struct graphics_object_id id,
 268	struct graphics_object_hpd_info *info)
 269{
 270	struct bios_parser *bp = BP_FROM_DCB(dcb);
 271	ATOM_OBJECT *object;
 272	ATOM_HPD_INT_RECORD *record = NULL;
 273
 274	if (!info)
 275		return BP_RESULT_BADINPUT;
 276
 277	object = get_bios_object(bp, id);
 278
 279	if (!object)
 280		return BP_RESULT_BADINPUT;
 281
 282	record = get_hpd_record(bp, object);
 283
 284	if (record != NULL) {
 285		info->hpd_int_gpio_uid = record->ucHPDIntGPIOID;
 286		info->hpd_active = record->ucPlugged_PinState;
 287		return BP_RESULT_OK;
 288	}
 289
 290	return BP_RESULT_NORECORD;
 291}
 292
 293static enum bp_result bios_parser_get_device_tag_record(
 294	struct bios_parser *bp,
 295	ATOM_OBJECT *object,
 296	ATOM_CONNECTOR_DEVICE_TAG_RECORD **record)
 297{
 298	ATOM_COMMON_RECORD_HEADER *header;
 299	uint32_t offset;
 300
 301	offset = le16_to_cpu(object->usRecordOffset)
 302			+ bp->object_info_tbl_offset;
 303
 304	for (;;) {
 305		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
 306
 307		if (!header)
 308			return BP_RESULT_BADBIOSTABLE;
 309
 310		offset += header->ucRecordSize;
 311
 312		if (LAST_RECORD_TYPE == header->ucRecordType ||
 313			!header->ucRecordSize)
 314			break;
 315
 316		if (ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE !=
 317			header->ucRecordType)
 318			continue;
 319
 320		if (sizeof(ATOM_CONNECTOR_DEVICE_TAG) > header->ucRecordSize)
 321			continue;
 322
 323		*record = (ATOM_CONNECTOR_DEVICE_TAG_RECORD *) header;
 324		return BP_RESULT_OK;
 325	}
 326
 327	return BP_RESULT_NORECORD;
 328}
 329
 330static enum bp_result bios_parser_get_device_tag(
 331	struct dc_bios *dcb,
 332	struct graphics_object_id connector_object_id,
 333	uint32_t device_tag_index,
 334	struct connector_device_tag_info *info)
 335{
 336	struct bios_parser *bp = BP_FROM_DCB(dcb);
 337	ATOM_OBJECT *object;
 338	ATOM_CONNECTOR_DEVICE_TAG_RECORD *record = NULL;
 339	ATOM_CONNECTOR_DEVICE_TAG *device_tag;
 340
 341	if (!info)
 342		return BP_RESULT_BADINPUT;
 343
 344	/* getBiosObject will return MXM object */
 345	object = get_bios_object(bp, connector_object_id);
 346
 347	if (!object) {
 348		BREAK_TO_DEBUGGER(); /* Invalid object id */
 349		return BP_RESULT_BADINPUT;
 350	}
 351
 352	if (bios_parser_get_device_tag_record(bp, object, &record)
 353		!= BP_RESULT_OK)
 354		return BP_RESULT_NORECORD;
 355
 356	if (device_tag_index >= record->ucNumberOfDevice)
 357		return BP_RESULT_NORECORD;
 358
 359	device_tag = &record->asDeviceTag[device_tag_index];
 360
 361	info->acpi_device = le32_to_cpu(device_tag->ulACPIDeviceEnum);
 362	info->dev_id =
 363		device_type_from_device_id(le16_to_cpu(device_tag->usDeviceID));
 364
 365	return BP_RESULT_OK;
 366}
 367
 368static enum bp_result get_firmware_info_v1_4(
 369	struct bios_parser *bp,
 370	struct dc_firmware_info *info);
 371static enum bp_result get_firmware_info_v2_1(
 372	struct bios_parser *bp,
 373	struct dc_firmware_info *info);
 374static enum bp_result get_firmware_info_v2_2(
 375	struct bios_parser *bp,
 376	struct dc_firmware_info *info);
 377
 378static enum bp_result bios_parser_get_firmware_info(
 379	struct dc_bios *dcb,
 380	struct dc_firmware_info *info)
 381{
 382	struct bios_parser *bp = BP_FROM_DCB(dcb);
 383	enum bp_result result = BP_RESULT_BADBIOSTABLE;
 384	ATOM_COMMON_TABLE_HEADER *header;
 385	struct atom_data_revision revision;
 386
 387	if (info && DATA_TABLES(FirmwareInfo)) {
 388		header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
 389			DATA_TABLES(FirmwareInfo));
 390		get_atom_data_table_revision(header, &revision);
 391		switch (revision.major) {
 392		case 1:
 393			switch (revision.minor) {
 394			case 4:
 395				result = get_firmware_info_v1_4(bp, info);
 396				break;
 397			default:
 398				break;
 399			}
 400			break;
 401
 402		case 2:
 403			switch (revision.minor) {
 404			case 1:
 405				result = get_firmware_info_v2_1(bp, info);
 406				break;
 407			case 2:
 408				result = get_firmware_info_v2_2(bp, info);
 409				break;
 410			default:
 411				break;
 412			}
 413			break;
 414		default:
 415			break;
 416		}
 417	}
 418
 419	return result;
 420}
 421
 422static enum bp_result get_firmware_info_v1_4(
 423	struct bios_parser *bp,
 424	struct dc_firmware_info *info)
 425{
 426	ATOM_FIRMWARE_INFO_V1_4 *firmware_info =
 427		GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4,
 428			DATA_TABLES(FirmwareInfo));
 429
 430	if (!info)
 431		return BP_RESULT_BADINPUT;
 432
 433	if (!firmware_info)
 434		return BP_RESULT_BADBIOSTABLE;
 435
 436	memset(info, 0, sizeof(*info));
 437
 438	/* Pixel clock pll information. We need to convert from 10KHz units into
 439	 * KHz units */
 440	info->pll_info.crystal_frequency =
 441		le16_to_cpu(firmware_info->usReferenceClock) * 10;
 442	info->pll_info.min_input_pxl_clk_pll_frequency =
 443		le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
 444	info->pll_info.max_input_pxl_clk_pll_frequency =
 445		le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
 446	info->pll_info.min_output_pxl_clk_pll_frequency =
 447		le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
 448	info->pll_info.max_output_pxl_clk_pll_frequency =
 449		le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
 450
 451	if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
 452		/* Since there is no information on the SS, report conservative
 453		 * value 3% for bandwidth calculation */
 454		/* unit of 0.01% */
 455		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
 456
 457	if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
 458		/* Since there is no information on the SS,report conservative
 459		 * value 3% for bandwidth calculation */
 460		/* unit of 0.01% */
 461		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
 462
 463	return BP_RESULT_OK;
 464}
 465
 466static enum bp_result get_ss_info_v3_1(
 467	struct bios_parser *bp,
 468	uint32_t id,
 469	uint32_t index,
 470	struct spread_spectrum_info *ss_info);
 471
 472static enum bp_result get_firmware_info_v2_1(
 473	struct bios_parser *bp,
 474	struct dc_firmware_info *info)
 475{
 476	ATOM_FIRMWARE_INFO_V2_1 *firmwareInfo =
 477		GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1, DATA_TABLES(FirmwareInfo));
 478	struct spread_spectrum_info internalSS;
 479	uint32_t index;
 480
 481	if (!info)
 482		return BP_RESULT_BADINPUT;
 483
 484	if (!firmwareInfo)
 485		return BP_RESULT_BADBIOSTABLE;
 486
 487	memset(info, 0, sizeof(*info));
 488
 489	/* Pixel clock pll information. We need to convert from 10KHz units into
 490	 * KHz units */
 491	info->pll_info.crystal_frequency =
 492		le16_to_cpu(firmwareInfo->usCoreReferenceClock) * 10;
 493	info->pll_info.min_input_pxl_clk_pll_frequency =
 494		le16_to_cpu(firmwareInfo->usMinPixelClockPLL_Input) * 10;
 495	info->pll_info.max_input_pxl_clk_pll_frequency =
 496		le16_to_cpu(firmwareInfo->usMaxPixelClockPLL_Input) * 10;
 497	info->pll_info.min_output_pxl_clk_pll_frequency =
 498		le32_to_cpu(firmwareInfo->ulMinPixelClockPLL_Output) * 10;
 499	info->pll_info.max_output_pxl_clk_pll_frequency =
 500		le32_to_cpu(firmwareInfo->ulMaxPixelClockPLL_Output) * 10;
 501	info->default_display_engine_pll_frequency =
 502		le32_to_cpu(firmwareInfo->ulDefaultDispEngineClkFreq) * 10;
 503	info->external_clock_source_frequency_for_dp =
 504		le16_to_cpu(firmwareInfo->usUniphyDPModeExtClkFreq) * 10;
 505	info->min_allowed_bl_level = firmwareInfo->ucMinAllowedBL_Level;
 506
 507	/* There should be only one entry in the SS info table for Memory Clock
 508	 */
 509	index = 0;
 510	if (firmwareInfo->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
 511		/* Since there is no information for external SS, report
 512		 *  conservative value 3% for bandwidth calculation */
 513		/* unit of 0.01% */
 514		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
 515	else if (get_ss_info_v3_1(bp,
 516		ASIC_INTERNAL_MEMORY_SS, index, &internalSS) == BP_RESULT_OK) {
 517		if (internalSS.spread_spectrum_percentage) {
 518			info->feature.memory_clk_ss_percentage =
 519				internalSS.spread_spectrum_percentage;
 520			if (internalSS.type.CENTER_MODE) {
 521				/* if it is centermode, the exact SS Percentage
 522				 * will be round up of half of the percentage
 523				 * reported in the SS table */
 524				++info->feature.memory_clk_ss_percentage;
 525				info->feature.memory_clk_ss_percentage /= 2;
 526			}
 527		}
 528	}
 529
 530	/* There should be only one entry in the SS info table for Engine Clock
 531	 */
 532	index = 1;
 533	if (firmwareInfo->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
 534		/* Since there is no information for external SS, report
 535		 * conservative value 3% for bandwidth calculation */
 536		/* unit of 0.01% */
 537		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
 538	else if (get_ss_info_v3_1(bp,
 539		ASIC_INTERNAL_ENGINE_SS, index, &internalSS) == BP_RESULT_OK) {
 540		if (internalSS.spread_spectrum_percentage) {
 541			info->feature.engine_clk_ss_percentage =
 542				internalSS.spread_spectrum_percentage;
 543			if (internalSS.type.CENTER_MODE) {
 544				/* if it is centermode, the exact SS Percentage
 545				 * will be round up of half of the percentage
 546				 * reported in the SS table */
 547				++info->feature.engine_clk_ss_percentage;
 548				info->feature.engine_clk_ss_percentage /= 2;
 549			}
 550		}
 551	}
 552
 553	return BP_RESULT_OK;
 554}
 555
 556static enum bp_result get_firmware_info_v2_2(
 557	struct bios_parser *bp,
 558	struct dc_firmware_info *info)
 559{
 560	ATOM_FIRMWARE_INFO_V2_2 *firmware_info;
 561	struct spread_spectrum_info internal_ss;
 562	uint32_t index;
 563
 564	if (!info)
 565		return BP_RESULT_BADINPUT;
 566
 567	firmware_info = GET_IMAGE(ATOM_FIRMWARE_INFO_V2_2,
 568		DATA_TABLES(FirmwareInfo));
 569
 570	if (!firmware_info)
 571		return BP_RESULT_BADBIOSTABLE;
 572
 573	memset(info, 0, sizeof(*info));
 574
 575	/* Pixel clock pll information. We need to convert from 10KHz units into
 576	 * KHz units */
 577	info->pll_info.crystal_frequency =
 578		le16_to_cpu(firmware_info->usCoreReferenceClock) * 10;
 579	info->pll_info.min_input_pxl_clk_pll_frequency =
 580		le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
 581	info->pll_info.max_input_pxl_clk_pll_frequency =
 582		le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
 583	info->pll_info.min_output_pxl_clk_pll_frequency =
 584		le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
 585	info->pll_info.max_output_pxl_clk_pll_frequency =
 586		le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
 587	info->default_display_engine_pll_frequency =
 588		le32_to_cpu(firmware_info->ulDefaultDispEngineClkFreq) * 10;
 589	info->external_clock_source_frequency_for_dp =
 590		le16_to_cpu(firmware_info->usUniphyDPModeExtClkFreq) * 10;
 591
 592	/* There should be only one entry in the SS info table for Memory Clock
 593	 */
 594	index = 0;
 595	if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
 596		/* Since there is no information for external SS, report
 597		 *  conservative value 3% for bandwidth calculation */
 598		/* unit of 0.01% */
 599		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
 600	else if (get_ss_info_v3_1(bp,
 601			ASIC_INTERNAL_MEMORY_SS, index, &internal_ss) == BP_RESULT_OK) {
 602		if (internal_ss.spread_spectrum_percentage) {
 603			info->feature.memory_clk_ss_percentage =
 604					internal_ss.spread_spectrum_percentage;
 605			if (internal_ss.type.CENTER_MODE) {
 606				/* if it is centermode, the exact SS Percentage
 607				 * will be round up of half of the percentage
 608				 * reported in the SS table */
 609				++info->feature.memory_clk_ss_percentage;
 610				info->feature.memory_clk_ss_percentage /= 2;
 611			}
 612		}
 613	}
 614
 615	/* There should be only one entry in the SS info table for Engine Clock
 616	 */
 617	index = 1;
 618	if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
 619		/* Since there is no information for external SS, report
 620		 * conservative value 3% for bandwidth calculation */
 621		/* unit of 0.01% */
 622		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
 623	else if (get_ss_info_v3_1(bp,
 624			ASIC_INTERNAL_ENGINE_SS, index, &internal_ss) == BP_RESULT_OK) {
 625		if (internal_ss.spread_spectrum_percentage) {
 626			info->feature.engine_clk_ss_percentage =
 627					internal_ss.spread_spectrum_percentage;
 628			if (internal_ss.type.CENTER_MODE) {
 629				/* if it is centermode, the exact SS Percentage
 630				 * will be round up of half of the percentage
 631				 * reported in the SS table */
 632				++info->feature.engine_clk_ss_percentage;
 633				info->feature.engine_clk_ss_percentage /= 2;
 634			}
 635		}
 636	}
 637
 638	/* Remote Display */
 639	info->remote_display_config = firmware_info->ucRemoteDisplayConfig;
 640
 641	/* Is allowed minimum BL level */
 642	info->min_allowed_bl_level = firmware_info->ucMinAllowedBL_Level;
 643	/* Used starting from CI */
 644	info->smu_gpu_pll_output_freq =
 645			(uint32_t) (le32_to_cpu(firmware_info->ulGPUPLL_OutputFreq) * 10);
 646
 647	return BP_RESULT_OK;
 648}
 649
 650static enum bp_result get_ss_info_v3_1(
 651	struct bios_parser *bp,
 652	uint32_t id,
 653	uint32_t index,
 654	struct spread_spectrum_info *ss_info)
 655{
 656	ATOM_ASIC_INTERNAL_SS_INFO_V3 *ss_table_header_include;
 657	ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
 658	uint32_t table_size;
 659	uint32_t i;
 660	uint32_t table_index = 0;
 661
 662	if (!ss_info)
 663		return BP_RESULT_BADINPUT;
 664
 665	if (!DATA_TABLES(ASIC_InternalSS_Info))
 666		return BP_RESULT_UNSUPPORTED;
 667
 668	ss_table_header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V3 *) bios_get_image(&bp->base,
 669				DATA_TABLES(ASIC_InternalSS_Info),
 670				struct_size(ss_table_header_include, asSpreadSpectrum, 1)));
 
 
 
 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
1041	memset(info, 0, sizeof(struct spread_spectrum_info));
1042
1043	tbl_size = (le16_to_cpu(header->sHeader.usStructureSize)
1044			- sizeof(ATOM_COMMON_TABLE_HEADER))
1045					/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
1046
1047	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
1048					&(header->asSpreadSpectrum[0]);
1049	for (i = 0; i < tbl_size; i++) {
1050		result = BP_RESULT_NORECORD;
1051
1052		if (tbl[i].ucClockIndication != (uint8_t)id)
1053			continue;
1054
1055		if (ATOM_EXTERNAL_SS_MASK
1056			& tbl[i].ucSpreadSpectrumMode) {
1057			info->type.EXTERNAL = true;
1058		}
1059		if (ATOM_SS_CENTRE_SPREAD_MODE_MASK
1060			& tbl[i].ucSpreadSpectrumMode) {
1061			info->type.CENTER_MODE = true;
1062		}
1063		info->type.STEP_AND_DELAY_INFO = false;
1064		/* convert [10KHz] into [KHz] */
1065		info->target_clock_range =
1066			le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
1067		info->spread_spectrum_percentage =
1068			(uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
1069		info->spread_spectrum_range =
1070			(uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
1071		result = BP_RESULT_OK;
1072		break;
1073	}
1074
1075	return result;
1076
1077}
1078
1079/**
1080 * get_ss_info_from_ss_info_table
1081 * Get spread sprectrum information from the SS_Info table from the VBIOS
1082 * if the pointer to info is NULL, indicate the caller what to know the number
1083 * of entries that matches the id
1084 * for, the SS_Info table, there should not be more than 1 entry match.
1085 *
1086 * @bp:      pointer to the Bios parser
1087 * @id:      spread sprectrum id
1088 * @ss_info: sprectrum information structure,
1089 * return:   Bios parser result code
1090 */
1091static enum bp_result get_ss_info_from_ss_info_table(
1092	struct bios_parser *bp,
1093	uint32_t id,
1094	struct spread_spectrum_info *ss_info)
1095{
1096	enum bp_result result = BP_RESULT_UNSUPPORTED;
1097	ATOM_SPREAD_SPECTRUM_INFO *tbl;
1098	ATOM_COMMON_TABLE_HEADER *header;
1099	uint32_t table_size;
1100	uint32_t i;
1101	uint32_t id_local = SS_ID_UNKNOWN;
1102	struct atom_data_revision revision;
1103
1104	/* exist of the SS_Info table */
1105	/* check for bad input, pSSinfo can not be NULL */
1106	if (!DATA_TABLES(SS_Info) || !ss_info)
1107		return result;
1108
1109	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(SS_Info));
1110	get_atom_data_table_revision(header, &revision);
1111
1112	tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, DATA_TABLES(SS_Info));
 
 
1113
1114	if (1 != revision.major || 2 > revision.minor)
1115		return result;
1116
1117	/* have to convert from Internal_SS format to SS_Info format */
1118	switch (id) {
1119	case ASIC_INTERNAL_SS_ON_DP:
1120		id_local = SS_ID_DP1;
1121		break;
1122	case ASIC_INTERNAL_SS_ON_LVDS:
1123	{
1124		struct embedded_panel_info panel_info;
1125
1126		if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
1127				== BP_RESULT_OK)
1128			id_local = panel_info.ss_id;
1129		break;
1130	}
1131	default:
1132		break;
1133	}
1134
1135	if (id_local == SS_ID_UNKNOWN)
1136		return result;
1137
1138	table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
1139			sizeof(ATOM_COMMON_TABLE_HEADER)) /
1140					sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
1141
1142	for (i = 0; i < table_size; i++) {
1143		if (id_local != (uint32_t)tbl->asSS_Info[i].ucSS_Id)
1144			continue;
1145
1146		memset(ss_info, 0, sizeof(struct spread_spectrum_info));
1147
1148		if (ATOM_EXTERNAL_SS_MASK &
1149				tbl->asSS_Info[i].ucSpreadSpectrumType)
1150			ss_info->type.EXTERNAL = true;
1151
1152		if (ATOM_SS_CENTRE_SPREAD_MODE_MASK &
1153				tbl->asSS_Info[i].ucSpreadSpectrumType)
1154			ss_info->type.CENTER_MODE = true;
1155
1156		ss_info->type.STEP_AND_DELAY_INFO = true;
1157		ss_info->spread_spectrum_percentage =
1158			(uint32_t)le16_to_cpu(tbl->asSS_Info[i].usSpreadSpectrumPercentage);
1159		ss_info->step_and_delay_info.step = tbl->asSS_Info[i].ucSS_Step;
1160		ss_info->step_and_delay_info.delay =
1161			tbl->asSS_Info[i].ucSS_Delay;
1162		ss_info->step_and_delay_info.recommended_ref_div =
1163			tbl->asSS_Info[i].ucRecommendedRef_Div;
1164		ss_info->spread_spectrum_range =
1165			(uint32_t)tbl->asSS_Info[i].ucSS_Range * 10000;
1166
1167		/* there will be only one entry for each display type in SS_info
1168		 * table */
1169		result = BP_RESULT_OK;
1170		break;
1171	}
1172
1173	return result;
1174}
1175static enum bp_result get_embedded_panel_info_v1_2(
1176	struct bios_parser *bp,
1177	struct embedded_panel_info *info);
1178static enum bp_result get_embedded_panel_info_v1_3(
1179	struct bios_parser *bp,
1180	struct embedded_panel_info *info);
1181
1182static enum bp_result bios_parser_get_embedded_panel_info(
1183	struct dc_bios *dcb,
1184	struct embedded_panel_info *info)
1185{
1186	struct bios_parser *bp = BP_FROM_DCB(dcb);
1187	ATOM_COMMON_TABLE_HEADER *hdr;
1188
1189	if (!DATA_TABLES(LCD_Info))
1190		return BP_RESULT_FAILURE;
1191
1192	hdr = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(LCD_Info));
1193
1194	if (!hdr)
1195		return BP_RESULT_BADBIOSTABLE;
1196
1197	switch (hdr->ucTableFormatRevision) {
1198	case 1:
1199		switch (hdr->ucTableContentRevision) {
1200		case 0:
1201		case 1:
1202		case 2:
1203			return get_embedded_panel_info_v1_2(bp, info);
1204		case 3:
1205			return get_embedded_panel_info_v1_3(bp, info);
1206		default:
1207			break;
1208		}
1209		break;
1210	default:
1211		break;
1212	}
1213
1214	return BP_RESULT_FAILURE;
1215}
1216
1217static enum bp_result get_embedded_panel_info_v1_2(
1218	struct bios_parser *bp,
1219	struct embedded_panel_info *info)
1220{
1221	ATOM_LVDS_INFO_V12 *lvds;
1222
1223	if (!info)
1224		return BP_RESULT_BADINPUT;
1225
1226	if (!DATA_TABLES(LVDS_Info))
1227		return BP_RESULT_UNSUPPORTED;
1228
1229	lvds =
1230		GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info));
1231
1232	if (!lvds)
1233		return BP_RESULT_BADBIOSTABLE;
1234
1235	if (1 != lvds->sHeader.ucTableFormatRevision
1236		|| 2 > lvds->sHeader.ucTableContentRevision)
1237		return BP_RESULT_UNSUPPORTED;
1238
1239	memset(info, 0, sizeof(struct embedded_panel_info));
1240
1241	/* We need to convert from 10KHz units into KHz units*/
1242	info->lcd_timing.pixel_clk =
1243		le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
1244	/* usHActive does not include borders, according to VBIOS team*/
1245	info->lcd_timing.horizontal_addressable =
1246		le16_to_cpu(lvds->sLCDTiming.usHActive);
1247	/* usHBlanking_Time includes borders, so we should really be subtracting
1248	 * borders duing this translation, but LVDS generally*/
1249	/* doesn't have borders, so we should be okay leaving this as is for
1250	 * now.  May need to revisit if we ever have LVDS with borders*/
1251	info->lcd_timing.horizontal_blanking_time =
1252			le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
1253	/* usVActive does not include borders, according to VBIOS team*/
1254	info->lcd_timing.vertical_addressable =
1255			le16_to_cpu(lvds->sLCDTiming.usVActive);
1256	/* usVBlanking_Time includes borders, so we should really be subtracting
1257	 * borders duing this translation, but LVDS generally*/
1258	/* doesn't have borders, so we should be okay leaving this as is for
1259	 * now. May need to revisit if we ever have LVDS with borders*/
1260	info->lcd_timing.vertical_blanking_time =
1261		le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
1262	info->lcd_timing.horizontal_sync_offset =
1263		le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
1264	info->lcd_timing.horizontal_sync_width =
1265		le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
1266	info->lcd_timing.vertical_sync_offset =
1267		le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
1268	info->lcd_timing.vertical_sync_width =
1269		le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
1270	info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
1271	info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
1272	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
1273		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
1274	info->lcd_timing.misc_info.H_SYNC_POLARITY =
1275		~(uint32_t)
1276		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
1277	info->lcd_timing.misc_info.V_SYNC_POLARITY =
1278		~(uint32_t)
1279		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
1280	info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
1281		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
1282	info->lcd_timing.misc_info.H_REPLICATION_BY2 =
1283		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
1284	info->lcd_timing.misc_info.V_REPLICATION_BY2 =
1285		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
1286	info->lcd_timing.misc_info.COMPOSITE_SYNC =
1287		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
1288	info->lcd_timing.misc_info.INTERLACE =
1289		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
1290	info->lcd_timing.misc_info.DOUBLE_CLOCK =
1291		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
1292	info->ss_id = lvds->ucSS_Id;
1293
1294	{
1295		uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate);
1296		/* Get minimum supported refresh rate*/
1297		if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
1298			info->supported_rr.REFRESH_RATE_30HZ = 1;
1299		else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
1300			info->supported_rr.REFRESH_RATE_40HZ = 1;
1301		else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
1302			info->supported_rr.REFRESH_RATE_48HZ = 1;
1303		else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
1304			info->supported_rr.REFRESH_RATE_50HZ = 1;
1305		else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
1306			info->supported_rr.REFRESH_RATE_60HZ = 1;
1307	}
1308
1309	/*Drr panel support can be reported by VBIOS*/
1310	if (LCDPANEL_CAP_DRR_SUPPORTED
1311			& lvds->ucLCDPanel_SpecialHandlingCap)
1312		info->drr_enabled = 1;
1313
1314	if (ATOM_PANEL_MISC_DUAL & lvds->ucLVDS_Misc)
1315		info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
1316
1317	if (ATOM_PANEL_MISC_888RGB & lvds->ucLVDS_Misc)
1318		info->lcd_timing.misc_info.RGB888 = true;
1319
1320	info->lcd_timing.misc_info.GREY_LEVEL =
1321		(uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL &
1322			lvds->ucLVDS_Misc) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT;
1323
1324	if (ATOM_PANEL_MISC_SPATIAL & lvds->ucLVDS_Misc)
1325		info->lcd_timing.misc_info.SPATIAL = true;
1326
1327	if (ATOM_PANEL_MISC_TEMPORAL & lvds->ucLVDS_Misc)
1328		info->lcd_timing.misc_info.TEMPORAL = true;
1329
1330	if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc)
1331		info->lcd_timing.misc_info.API_ENABLED = true;
1332
1333	return BP_RESULT_OK;
1334}
1335
1336static enum bp_result get_embedded_panel_info_v1_3(
1337	struct bios_parser *bp,
1338	struct embedded_panel_info *info)
1339{
1340	ATOM_LCD_INFO_V13 *lvds;
1341
1342	if (!info)
1343		return BP_RESULT_BADINPUT;
1344
1345	if (!DATA_TABLES(LCD_Info))
1346		return BP_RESULT_UNSUPPORTED;
1347
1348	lvds = GET_IMAGE(ATOM_LCD_INFO_V13, DATA_TABLES(LCD_Info));
1349
1350	if (!lvds)
1351		return BP_RESULT_BADBIOSTABLE;
1352
1353	if (!((1 == lvds->sHeader.ucTableFormatRevision)
1354			&& (3 <= lvds->sHeader.ucTableContentRevision)))
1355		return BP_RESULT_UNSUPPORTED;
1356
1357	memset(info, 0, sizeof(struct embedded_panel_info));
1358
1359	/* We need to convert from 10KHz units into KHz units */
1360	info->lcd_timing.pixel_clk =
1361			le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
1362	/* usHActive does not include borders, according to VBIOS team */
1363	info->lcd_timing.horizontal_addressable =
1364			le16_to_cpu(lvds->sLCDTiming.usHActive);
1365	/* usHBlanking_Time includes borders, so we should really be subtracting
1366	 * borders duing this translation, but LVDS generally*/
1367	/* doesn't have borders, so we should be okay leaving this as is for
1368	 * now.  May need to revisit if we ever have LVDS with borders*/
1369	info->lcd_timing.horizontal_blanking_time =
1370		le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
1371	/* usVActive does not include borders, according to VBIOS team*/
1372	info->lcd_timing.vertical_addressable =
1373		le16_to_cpu(lvds->sLCDTiming.usVActive);
1374	/* usVBlanking_Time includes borders, so we should really be subtracting
1375	 * borders duing this translation, but LVDS generally*/
1376	/* doesn't have borders, so we should be okay leaving this as is for
1377	 * now. May need to revisit if we ever have LVDS with borders*/
1378	info->lcd_timing.vertical_blanking_time =
1379		le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
1380	info->lcd_timing.horizontal_sync_offset =
1381		le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
1382	info->lcd_timing.horizontal_sync_width =
1383		le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
1384	info->lcd_timing.vertical_sync_offset =
1385		le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
1386	info->lcd_timing.vertical_sync_width =
1387		le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
1388	info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
1389	info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
1390	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
1391		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
1392	info->lcd_timing.misc_info.H_SYNC_POLARITY =
1393		~(uint32_t)
1394		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
1395	info->lcd_timing.misc_info.V_SYNC_POLARITY =
1396		~(uint32_t)
1397		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
1398	info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
1399		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
1400	info->lcd_timing.misc_info.H_REPLICATION_BY2 =
1401		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
1402	info->lcd_timing.misc_info.V_REPLICATION_BY2 =
1403		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
1404	info->lcd_timing.misc_info.COMPOSITE_SYNC =
1405		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
1406	info->lcd_timing.misc_info.INTERLACE =
1407		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
1408	info->lcd_timing.misc_info.DOUBLE_CLOCK =
1409		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
1410	info->ss_id = lvds->ucSS_Id;
1411
1412	/* Drr panel support can be reported by VBIOS*/
1413	if (LCDPANEL_CAP_V13_DRR_SUPPORTED
1414			& lvds->ucLCDPanel_SpecialHandlingCap)
1415		info->drr_enabled = 1;
1416
1417	/* Get supported refresh rate*/
1418	if (info->drr_enabled == 1) {
1419		uint8_t min_rr =
1420				lvds->sRefreshRateSupport.ucMinRefreshRateForDRR;
1421		uint8_t rr = lvds->sRefreshRateSupport.ucSupportedRefreshRate;
1422
1423		if (min_rr != 0) {
1424			if (SUPPORTED_LCD_REFRESHRATE_30Hz & min_rr)
1425				info->supported_rr.REFRESH_RATE_30HZ = 1;
1426			else if (SUPPORTED_LCD_REFRESHRATE_40Hz & min_rr)
1427				info->supported_rr.REFRESH_RATE_40HZ = 1;
1428			else if (SUPPORTED_LCD_REFRESHRATE_48Hz & min_rr)
1429				info->supported_rr.REFRESH_RATE_48HZ = 1;
1430			else if (SUPPORTED_LCD_REFRESHRATE_50Hz & min_rr)
1431				info->supported_rr.REFRESH_RATE_50HZ = 1;
1432			else if (SUPPORTED_LCD_REFRESHRATE_60Hz & min_rr)
1433				info->supported_rr.REFRESH_RATE_60HZ = 1;
1434		} else {
1435			if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
1436				info->supported_rr.REFRESH_RATE_30HZ = 1;
1437			else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
1438				info->supported_rr.REFRESH_RATE_40HZ = 1;
1439			else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
1440				info->supported_rr.REFRESH_RATE_48HZ = 1;
1441			else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
1442				info->supported_rr.REFRESH_RATE_50HZ = 1;
1443			else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
1444				info->supported_rr.REFRESH_RATE_60HZ = 1;
1445		}
1446	}
1447
1448	if (ATOM_PANEL_MISC_V13_DUAL & lvds->ucLCD_Misc)
1449		info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
1450
1451	if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR & lvds->ucLCD_Misc)
1452		info->lcd_timing.misc_info.RGB888 = true;
1453
1454	info->lcd_timing.misc_info.GREY_LEVEL =
1455			(uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL &
1456				lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT;
1457
1458	return BP_RESULT_OK;
1459}
1460
1461/**
1462 * bios_parser_get_encoder_cap_info - get encoder capability
1463 *                                    information of input object id
1464 *
1465 * @dcb:       pointer to the DC BIOS
1466 * @object_id: object id
1467 * @info:      encoder cap information structure
1468 *
1469 * return: Bios parser result code
1470 */
1471static enum bp_result bios_parser_get_encoder_cap_info(
1472	struct dc_bios *dcb,
1473	struct graphics_object_id object_id,
1474	struct bp_encoder_cap_info *info)
1475{
1476	struct bios_parser *bp = BP_FROM_DCB(dcb);
1477	ATOM_OBJECT *object;
1478	ATOM_ENCODER_CAP_RECORD_V2 *record = NULL;
1479
1480	if (!info)
1481		return BP_RESULT_BADINPUT;
1482
1483	object = get_bios_object(bp, object_id);
1484
1485	if (!object)
1486		return BP_RESULT_BADINPUT;
1487
1488	record = get_encoder_cap_record(bp, object);
1489	if (!record)
1490		return BP_RESULT_NORECORD;
1491
1492	info->DP_HBR2_EN = record->usHBR2En;
1493	info->DP_HBR3_EN = record->usHBR3En;
1494	info->HDMI_6GB_EN = record->usHDMI6GEn;
1495	return BP_RESULT_OK;
1496}
1497
1498/**
1499 * get_encoder_cap_record - Get encoder cap record for the object
1500 *
1501 * @bp:      pointer to the BIOS parser
1502 * @object:  ATOM object
1503 * return:   atom encoder cap record
1504 * note:     search all records to find the ATOM_ENCODER_CAP_RECORD_V2 record
1505 */
1506static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
1507	struct bios_parser *bp,
1508	ATOM_OBJECT *object)
1509{
1510	ATOM_COMMON_RECORD_HEADER *header;
1511	uint32_t offset;
1512
1513	if (!object) {
1514		BREAK_TO_DEBUGGER(); /* Invalid object */
1515		return NULL;
1516	}
1517
1518	offset = le16_to_cpu(object->usRecordOffset)
1519					+ bp->object_info_tbl_offset;
1520
1521	for (;;) {
1522		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
1523
1524		if (!header)
1525			return NULL;
1526
1527		offset += header->ucRecordSize;
1528
1529		if (LAST_RECORD_TYPE == header->ucRecordType ||
1530				!header->ucRecordSize)
1531			break;
1532
1533		if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType)
1534			continue;
1535
1536		if (sizeof(ATOM_ENCODER_CAP_RECORD_V2) <= header->ucRecordSize)
1537			return (ATOM_ENCODER_CAP_RECORD_V2 *)header;
1538	}
1539
1540	return NULL;
1541}
1542
1543static uint32_t get_ss_entry_number(
1544	struct bios_parser *bp,
1545	uint32_t id);
1546static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
1547	struct bios_parser *bp,
1548	uint32_t id);
1549static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1550	struct bios_parser *bp,
1551	uint32_t id);
1552static uint32_t get_ss_entry_number_from_ss_info_tbl(
1553	struct bios_parser *bp,
1554	uint32_t id);
1555
1556/**
1557 * bios_parser_get_ss_entry_number
1558 * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from
1559 * the VBIOS that match the SSid (to be converted from signal)
1560 *
1561 * @dcb:    pointer to the DC BIOS
1562 * @signal: ASSignalType to be converted to SSid
1563 * return: number of SS Entry that match the signal
1564 */
1565static uint32_t bios_parser_get_ss_entry_number(
1566	struct dc_bios *dcb,
1567	enum as_signal_type signal)
1568{
1569	struct bios_parser *bp = BP_FROM_DCB(dcb);
1570	uint32_t ss_id = 0;
1571	ATOM_COMMON_TABLE_HEADER *header;
1572	struct atom_data_revision revision;
1573
1574	ss_id = signal_to_ss_id(signal);
1575
1576	if (!DATA_TABLES(ASIC_InternalSS_Info))
1577		return get_ss_entry_number_from_ss_info_tbl(bp, ss_id);
1578
1579	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
1580			DATA_TABLES(ASIC_InternalSS_Info));
1581	get_atom_data_table_revision(header, &revision);
1582
1583	switch (revision.major) {
1584	case 2:
1585		switch (revision.minor) {
1586		case 1:
1587			return get_ss_entry_number(bp, ss_id);
1588		default:
1589			break;
1590		}
1591		break;
1592	case 3:
1593		switch (revision.minor) {
1594		case 1:
1595			return
1596				get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1597						bp, ss_id);
1598		default:
1599			break;
1600		}
1601		break;
1602	default:
1603		break;
1604	}
1605
1606	return 0;
1607}
1608
1609/**
1610 * get_ss_entry_number_from_ss_info_tbl
1611 * Get Number of spread spectrum entry from the SS_Info table from the VBIOS.
1612 *
1613 * @bp:  pointer to the BIOS parser
1614 * @id:  spread spectrum id
1615 * return: number of SS Entry that match the id
1616 * note: There can only be one entry for each id for SS_Info Table
1617 */
1618static uint32_t get_ss_entry_number_from_ss_info_tbl(
1619	struct bios_parser *bp,
1620	uint32_t id)
1621{
1622	ATOM_SPREAD_SPECTRUM_INFO *tbl;
1623	ATOM_COMMON_TABLE_HEADER *header;
1624	uint32_t table_size;
1625	uint32_t i;
1626	uint32_t number = 0;
1627	uint32_t id_local = SS_ID_UNKNOWN;
1628	struct atom_data_revision revision;
1629
1630	/* SS_Info table exist */
1631	if (!DATA_TABLES(SS_Info))
1632		return number;
1633
1634	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
1635			DATA_TABLES(SS_Info));
1636	get_atom_data_table_revision(header, &revision);
1637
1638	tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO,
1639			DATA_TABLES(SS_Info));
 
 
1640
1641	if (1 != revision.major || 2 > revision.minor)
1642		return number;
1643
1644	/* have to convert from Internal_SS format to SS_Info format */
1645	switch (id) {
1646	case ASIC_INTERNAL_SS_ON_DP:
1647		id_local = SS_ID_DP1;
1648		break;
1649	case ASIC_INTERNAL_SS_ON_LVDS: {
1650		struct embedded_panel_info panel_info;
1651
1652		if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
1653				== BP_RESULT_OK)
1654			id_local = panel_info.ss_id;
1655		break;
1656	}
1657	default:
1658		break;
1659	}
1660
1661	if (id_local == SS_ID_UNKNOWN)
1662		return number;
1663
1664	table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
1665			sizeof(ATOM_COMMON_TABLE_HEADER)) /
1666					sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
1667
1668	for (i = 0; i < table_size; i++)
1669		if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) {
1670			number = 1;
1671			break;
1672		}
1673
1674	return number;
1675}
1676
1677/**
1678 * get_ss_entry_number
1679 * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
1680 * SS_Info table from the VBIOS
1681 * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or
1682 * SS_Info.
1683 *
1684 * @bp:    pointer to the BIOS parser
1685 * @id:    spread sprectrum info index
1686 * return: Bios parser result code
1687 */
1688static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id)
1689{
1690	if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
1691		return get_ss_entry_number_from_ss_info_tbl(bp, id);
1692
1693	return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id);
1694}
1695
1696/**
1697 * get_ss_entry_number_from_internal_ss_info_tbl_v2_1
1698 * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table
1699 * Ver 2.1 from the VBIOS
1700 * There will not be multiple entry for Ver 2.1
1701 *
1702 * @bp:    pointer to the BIOS parser
1703 * @id:    spread sprectrum info index
1704 * return: number of SS Entry that match the id
1705 */
1706static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
1707	struct bios_parser *bp,
1708	uint32_t id)
1709{
1710	ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include;
1711	ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
1712	uint32_t size;
1713	uint32_t i;
1714
1715	if (!DATA_TABLES(ASIC_InternalSS_Info))
1716		return 0;
1717
1718	header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V2 *) bios_get_image(
1719				&bp->base,
1720				DATA_TABLES(ASIC_InternalSS_Info),
1721				struct_size(header_include, asSpreadSpectrum, 1)));
 
 
1722
1723	size = (le16_to_cpu(header_include->sHeader.usStructureSize)
1724			- sizeof(ATOM_COMMON_TABLE_HEADER))
1725						/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
1726
1727	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
1728				&header_include->asSpreadSpectrum[0];
1729	for (i = 0; i < size; i++)
1730		if (tbl[i].ucClockIndication == (uint8_t)id)
1731			return 1;
1732
1733	return 0;
1734}
 
1735/**
1736 * get_ss_entry_number_from_internal_ss_info_tbl_V3_1
1737 * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of
1738 * the VBIOS that matches id
1739 *
1740 * @bp:    pointer to the BIOS parser
1741 * @id:    spread sprectrum id
1742 * return: number of SS Entry that match the id
1743 */
1744static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1745	struct bios_parser *bp,
1746	uint32_t id)
1747{
1748	uint32_t number = 0;
1749	ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include;
1750	ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
1751	uint32_t size;
1752	uint32_t i;
1753
1754	if (!DATA_TABLES(ASIC_InternalSS_Info))
1755		return number;
1756
1757	header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V3 *) bios_get_image(&bp->base,
1758				DATA_TABLES(ASIC_InternalSS_Info),
1759				struct_size(header_include, asSpreadSpectrum, 1)));
 
 
 
1760	size = (le16_to_cpu(header_include->sHeader.usStructureSize) -
1761			sizeof(ATOM_COMMON_TABLE_HEADER)) /
1762					sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
1763
1764	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
1765				&header_include->asSpreadSpectrum[0];
1766
1767	for (i = 0; i < size; i++)
1768		if (tbl[i].ucClockIndication == (uint8_t)id)
1769			number++;
1770
1771	return number;
1772}
1773
1774/**
1775 * bios_parser_get_gpio_pin_info
1776 * Get GpioPin information of input gpio id
1777 *
1778 * @dcb:     pointer to the DC BIOS
1779 * @gpio_id: GPIO ID
1780 * @info:    GpioPin information structure
1781 * return:   Bios parser result code
1782 * note:
1783 *  to get the GPIO PIN INFO, we need:
1784 *  1. get the GPIO_ID from other object table, see GetHPDInfo()
1785 *  2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA
1786 *  offset/mask
1787 */
1788static enum bp_result bios_parser_get_gpio_pin_info(
1789	struct dc_bios *dcb,
1790	uint32_t gpio_id,
1791	struct gpio_pin_info *info)
1792{
1793	struct bios_parser *bp = BP_FROM_DCB(dcb);
1794	ATOM_GPIO_PIN_LUT *header;
1795	uint32_t count = 0;
1796	uint32_t i = 0;
1797
1798	if (!DATA_TABLES(GPIO_Pin_LUT))
1799		return BP_RESULT_BADBIOSTABLE;
1800
1801	header = ((ATOM_GPIO_PIN_LUT *) bios_get_image(&bp->base,
1802				DATA_TABLES(GPIO_Pin_LUT),
1803				struct_size(header, asGPIO_Pin, 1)));
1804	if (!header)
1805		return BP_RESULT_BADBIOSTABLE;
1806
1807	if (sizeof(ATOM_COMMON_TABLE_HEADER) + struct_size(header, asGPIO_Pin, 1)
1808			> le16_to_cpu(header->sHeader.usStructureSize))
1809		return BP_RESULT_BADBIOSTABLE;
1810
1811	if (1 != header->sHeader.ucTableContentRevision)
1812		return BP_RESULT_UNSUPPORTED;
1813
1814	count = (le16_to_cpu(header->sHeader.usStructureSize)
1815			- sizeof(ATOM_COMMON_TABLE_HEADER))
1816				/ sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
1817	for (i = 0; i < count; ++i) {
1818		if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id)
1819			continue;
1820
1821		info->offset =
1822			(uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex);
1823		info->offset_y = info->offset + 2;
1824		info->offset_en = info->offset + 1;
1825		info->offset_mask = info->offset - 1;
1826
1827		info->mask = (uint32_t) (1 <<
1828			header->asGPIO_Pin[i].ucGpioPinBitShift);
1829		info->mask_y = info->mask + 2;
1830		info->mask_en = info->mask + 1;
1831		info->mask_mask = info->mask - 1;
1832
1833		return BP_RESULT_OK;
1834	}
1835
1836	return BP_RESULT_NORECORD;
1837}
1838
1839static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
1840	ATOM_I2C_RECORD *record,
1841	struct graphics_object_i2c_info *info)
1842{
1843	ATOM_GPIO_I2C_INFO *header;
1844	uint32_t count = 0;
1845
1846	if (!info)
1847		return BP_RESULT_BADINPUT;
1848
1849	/* get the GPIO_I2C info */
1850	if (!DATA_TABLES(GPIO_I2C_Info))
1851		return BP_RESULT_BADBIOSTABLE;
1852
1853	header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info));
1854	if (!header)
1855		return BP_RESULT_BADBIOSTABLE;
1856
1857	if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT)
1858			> le16_to_cpu(header->sHeader.usStructureSize))
1859		return BP_RESULT_BADBIOSTABLE;
1860
1861	if (1 != header->sHeader.ucTableContentRevision)
1862		return BP_RESULT_UNSUPPORTED;
1863
1864	/* get data count */
1865	count = (le16_to_cpu(header->sHeader.usStructureSize)
1866			- sizeof(ATOM_COMMON_TABLE_HEADER))
1867				/ sizeof(ATOM_GPIO_I2C_ASSIGMENT);
1868	if (count < record->sucI2cId.bfI2C_LineMux)
1869		return BP_RESULT_BADBIOSTABLE;
1870
1871	/* get the GPIO_I2C_INFO */
1872	info->i2c_hw_assist = record->sucI2cId.bfHW_Capable;
1873	info->i2c_line = record->sucI2cId.bfI2C_LineMux;
1874	info->i2c_engine_id = record->sucI2cId.bfHW_EngineID;
1875	info->i2c_slave_address = record->ucI2CAddr;
1876
1877	info->gpio_info.clk_mask_register_index =
1878			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex);
1879	info->gpio_info.clk_en_register_index =
1880			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex);
1881	info->gpio_info.clk_y_register_index =
1882			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex);
1883	info->gpio_info.clk_a_register_index =
1884			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex);
1885	info->gpio_info.data_mask_register_index =
1886			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex);
1887	info->gpio_info.data_en_register_index =
1888			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex);
1889	info->gpio_info.data_y_register_index =
1890			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex);
1891	info->gpio_info.data_a_register_index =
1892			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex);
1893
1894	info->gpio_info.clk_mask_shift =
1895			header->asGPIO_Info[info->i2c_line].ucClkMaskShift;
1896	info->gpio_info.clk_en_shift =
1897			header->asGPIO_Info[info->i2c_line].ucClkEnShift;
1898	info->gpio_info.clk_y_shift =
1899			header->asGPIO_Info[info->i2c_line].ucClkY_Shift;
1900	info->gpio_info.clk_a_shift =
1901			header->asGPIO_Info[info->i2c_line].ucClkA_Shift;
1902	info->gpio_info.data_mask_shift =
1903			header->asGPIO_Info[info->i2c_line].ucDataMaskShift;
1904	info->gpio_info.data_en_shift =
1905			header->asGPIO_Info[info->i2c_line].ucDataEnShift;
1906	info->gpio_info.data_y_shift =
1907			header->asGPIO_Info[info->i2c_line].ucDataY_Shift;
1908	info->gpio_info.data_a_shift =
1909			header->asGPIO_Info[info->i2c_line].ucDataA_Shift;
1910
1911	return BP_RESULT_OK;
1912}
1913
1914static bool dal_graphics_object_id_is_valid(struct graphics_object_id id)
1915{
1916	bool rc = true;
1917
1918	switch (id.type) {
1919	case OBJECT_TYPE_UNKNOWN:
1920		rc = false;
1921		break;
1922	case OBJECT_TYPE_GPU:
1923	case OBJECT_TYPE_ENGINE:
1924		/* do NOT check for id.id == 0 */
1925		if (id.enum_id == ENUM_ID_UNKNOWN)
1926			rc = false;
1927		break;
1928	default:
1929		if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN)
1930			rc = false;
1931		break;
1932	}
1933
1934	return rc;
1935}
1936
1937static bool dal_graphics_object_id_is_equal(
1938	struct graphics_object_id id1,
1939	struct graphics_object_id id2)
1940{
1941	if (false == dal_graphics_object_id_is_valid(id1)) {
1942		dm_output_to_console(
1943		"%s: Warning: comparing invalid object 'id1'!\n", __func__);
1944		return false;
1945	}
1946
1947	if (false == dal_graphics_object_id_is_valid(id2)) {
1948		dm_output_to_console(
1949		"%s: Warning: comparing invalid object 'id2'!\n", __func__);
1950		return false;
1951	}
1952
1953	if (id1.id == id2.id && id1.enum_id == id2.enum_id
1954		&& id1.type == id2.type)
1955		return true;
1956
1957	return false;
1958}
1959
1960static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
1961	struct graphics_object_id id)
1962{
1963	uint32_t offset;
1964	ATOM_OBJECT_TABLE *tbl;
1965	uint32_t i;
1966
1967	switch (id.type) {
1968	case OBJECT_TYPE_ENCODER:
1969		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
1970		break;
1971
1972	case OBJECT_TYPE_CONNECTOR:
1973		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
1974		break;
1975
1976	case OBJECT_TYPE_ROUTER:
1977		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset);
1978		break;
1979
1980	case OBJECT_TYPE_GENERIC:
1981		if (bp->object_info_tbl.revision.minor < 3)
1982			return NULL;
1983		offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset);
1984		break;
1985
1986	default:
1987		return NULL;
1988	}
1989
1990	offset += bp->object_info_tbl_offset;
1991
1992	tbl = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base, offset,
1993				struct_size(tbl, asObjects, 1)));
1994	if (!tbl)
1995		return NULL;
1996
1997	for (i = 0; i < tbl->ucNumberOfObjects; i++)
1998		if (dal_graphics_object_id_is_equal(id,
1999				object_id_from_bios_object_id(
2000						le16_to_cpu(tbl->asObjects[i].usObjectID))))
2001			return &tbl->asObjects[i];
2002
2003	return NULL;
2004}
2005
2006static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
2007	uint16_t **id_list)
2008{
2009	uint32_t offset;
2010	uint8_t *number;
2011
2012	if (!object) {
2013		BREAK_TO_DEBUGGER(); /* Invalid object id */
2014		return 0;
2015	}
2016
2017	offset = le16_to_cpu(object->usSrcDstTableOffset)
2018					+ bp->object_info_tbl_offset;
2019
2020	number = GET_IMAGE(uint8_t, offset);
2021	if (!number)
2022		return 0;
2023
2024	offset += sizeof(uint8_t);
2025	*id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t));
2026
2027	if (!*id_list)
2028		return 0;
2029
2030	return *number;
2031}
2032
2033static struct device_id device_type_from_device_id(uint16_t device_id)
2034{
2035
2036	struct device_id result_device_id = {0};
2037
2038	switch (device_id) {
2039	case ATOM_DEVICE_LCD1_SUPPORT:
2040		result_device_id.device_type = DEVICE_TYPE_LCD;
2041		result_device_id.enum_id = 1;
2042		break;
2043
2044	case ATOM_DEVICE_LCD2_SUPPORT:
2045		result_device_id.device_type = DEVICE_TYPE_LCD;
2046		result_device_id.enum_id = 2;
2047		break;
2048
2049	case ATOM_DEVICE_CRT1_SUPPORT:
2050		result_device_id.device_type = DEVICE_TYPE_CRT;
2051		result_device_id.enum_id = 1;
2052		break;
2053
2054	case ATOM_DEVICE_CRT2_SUPPORT:
2055		result_device_id.device_type = DEVICE_TYPE_CRT;
2056		result_device_id.enum_id = 2;
2057		break;
2058
2059	case ATOM_DEVICE_DFP1_SUPPORT:
2060		result_device_id.device_type = DEVICE_TYPE_DFP;
2061		result_device_id.enum_id = 1;
2062		break;
2063
2064	case ATOM_DEVICE_DFP2_SUPPORT:
2065		result_device_id.device_type = DEVICE_TYPE_DFP;
2066		result_device_id.enum_id = 2;
2067		break;
2068
2069	case ATOM_DEVICE_DFP3_SUPPORT:
2070		result_device_id.device_type = DEVICE_TYPE_DFP;
2071		result_device_id.enum_id = 3;
2072		break;
2073
2074	case ATOM_DEVICE_DFP4_SUPPORT:
2075		result_device_id.device_type = DEVICE_TYPE_DFP;
2076		result_device_id.enum_id = 4;
2077		break;
2078
2079	case ATOM_DEVICE_DFP5_SUPPORT:
2080		result_device_id.device_type = DEVICE_TYPE_DFP;
2081		result_device_id.enum_id = 5;
2082		break;
2083
2084	case ATOM_DEVICE_DFP6_SUPPORT:
2085		result_device_id.device_type = DEVICE_TYPE_DFP;
2086		result_device_id.enum_id = 6;
2087		break;
2088
2089	default:
2090		BREAK_TO_DEBUGGER(); /* Invalid device Id */
2091		result_device_id.device_type = DEVICE_TYPE_UNKNOWN;
2092		result_device_id.enum_id = 0;
2093	}
2094	return result_device_id;
2095}
2096
2097static void get_atom_data_table_revision(
2098	ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
2099	struct atom_data_revision *tbl_revision)
2100{
2101	if (!tbl_revision)
2102		return;
2103
2104	/* initialize the revision to 0 which is invalid revision */
2105	tbl_revision->major = 0;
2106	tbl_revision->minor = 0;
2107
2108	if (!atom_data_tbl)
2109		return;
2110
2111	tbl_revision->major =
2112			(uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl);
2113	tbl_revision->minor =
2114			(uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl);
2115}
2116
2117static uint32_t signal_to_ss_id(enum as_signal_type signal)
2118{
2119	uint32_t clk_id_ss = 0;
2120
2121	switch (signal) {
2122	case AS_SIGNAL_TYPE_DVI:
2123		clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS;
2124		break;
2125	case AS_SIGNAL_TYPE_HDMI:
2126		clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI;
2127		break;
2128	case AS_SIGNAL_TYPE_LVDS:
2129		clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS;
2130		break;
2131	case AS_SIGNAL_TYPE_DISPLAY_PORT:
2132		clk_id_ss = ASIC_INTERNAL_SS_ON_DP;
2133		break;
2134	case AS_SIGNAL_TYPE_GPU_PLL:
2135		clk_id_ss = ASIC_INTERNAL_GPUPLL_SS;
2136		break;
2137	default:
2138		break;
2139	}
2140	return clk_id_ss;
2141}
2142
2143static uint32_t get_support_mask_for_device_id(struct device_id device_id)
2144{
2145	enum dal_device_type device_type = device_id.device_type;
2146	uint32_t enum_id = device_id.enum_id;
2147
2148	switch (device_type) {
2149	case DEVICE_TYPE_LCD:
2150		switch (enum_id) {
2151		case 1:
2152			return ATOM_DEVICE_LCD1_SUPPORT;
2153		case 2:
2154			return ATOM_DEVICE_LCD2_SUPPORT;
2155		default:
2156			break;
2157		}
2158		break;
2159	case DEVICE_TYPE_CRT:
2160		switch (enum_id) {
2161		case 1:
2162			return ATOM_DEVICE_CRT1_SUPPORT;
2163		case 2:
2164			return ATOM_DEVICE_CRT2_SUPPORT;
2165		default:
2166			break;
2167		}
2168		break;
2169	case DEVICE_TYPE_DFP:
2170		switch (enum_id) {
2171		case 1:
2172			return ATOM_DEVICE_DFP1_SUPPORT;
2173		case 2:
2174			return ATOM_DEVICE_DFP2_SUPPORT;
2175		case 3:
2176			return ATOM_DEVICE_DFP3_SUPPORT;
2177		case 4:
2178			return ATOM_DEVICE_DFP4_SUPPORT;
2179		case 5:
2180			return ATOM_DEVICE_DFP5_SUPPORT;
2181		case 6:
2182			return ATOM_DEVICE_DFP6_SUPPORT;
2183		default:
2184			break;
2185		}
2186		break;
2187	case DEVICE_TYPE_CV:
2188		switch (enum_id) {
2189		case 1:
2190			return ATOM_DEVICE_CV_SUPPORT;
2191		default:
2192			break;
2193		}
2194		break;
2195	case DEVICE_TYPE_TV:
2196		switch (enum_id) {
2197		case 1:
2198			return ATOM_DEVICE_TV1_SUPPORT;
2199		default:
2200			break;
2201		}
2202		break;
2203	default:
2204		break;
2205	}
2206
2207	/* Unidentified device ID, return empty support mask. */
2208	return 0;
2209}
2210
2211/**
2212 * bios_parser_set_scratch_critical_state - update critical state
2213 *                                          bit in VBIOS scratch register
2214 * @dcb:    pointer to the DC BIOS
2215 * @state:  set or reset state
2216 */
2217static void bios_parser_set_scratch_critical_state(
2218	struct dc_bios *dcb,
2219	bool state)
2220{
2221	bios_set_scratch_critical_state(dcb, state);
2222}
2223
2224/*
2225 * get_integrated_info_v8
2226 *
2227 * @brief
2228 * Get V8 integrated BIOS information
2229 *
2230 * @param
2231 * bios_parser *bp - [in]BIOS parser handler to get master data table
2232 * integrated_info *info - [out] store and output integrated info
2233 *
2234 * return:
2235 * enum bp_result - BP_RESULT_OK if information is available,
2236 *                  BP_RESULT_BADBIOSTABLE otherwise.
2237 */
2238static enum bp_result get_integrated_info_v8(
2239	struct bios_parser *bp,
2240	struct integrated_info *info)
2241{
2242	ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8;
2243	uint32_t i;
2244
2245	info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8,
2246			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
2247
2248	if (info_v8 == NULL)
2249		return BP_RESULT_BADBIOSTABLE;
2250	info->boot_up_engine_clock = le32_to_cpu(info_v8->ulBootUpEngineClock) * 10;
2251	info->dentist_vco_freq = le32_to_cpu(info_v8->ulDentistVCOFreq) * 10;
2252	info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
2253
2254	for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2255		/* Convert [10KHz] into [KHz] */
2256		info->disp_clk_voltage[i].max_supported_clk =
2257			le32_to_cpu(info_v8->sDISPCLK_Voltage[i].
2258				    ulMaximumSupportedCLK) * 10;
2259		info->disp_clk_voltage[i].voltage_index =
2260			le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex);
2261	}
2262
2263	info->boot_up_req_display_vector =
2264		le32_to_cpu(info_v8->ulBootUpReqDisplayVector);
2265	info->gpu_cap_info =
2266		le32_to_cpu(info_v8->ulGPUCapInfo);
2267
2268	/*
2269	 * system_config: Bit[0] = 0 : PCIE power gating disabled
2270	 *                       = 1 : PCIE power gating enabled
2271	 *                Bit[1] = 0 : DDR-PLL shut down disabled
2272	 *                       = 1 : DDR-PLL shut down enabled
2273	 *                Bit[2] = 0 : DDR-PLL power down disabled
2274	 *                       = 1 : DDR-PLL power down enabled
2275	 */
2276	info->system_config = le32_to_cpu(info_v8->ulSystemConfig);
2277	info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo);
2278	info->boot_up_nb_voltage =
2279		le16_to_cpu(info_v8->usBootUpNBVoltage);
2280	info->ext_disp_conn_info_offset =
2281		le16_to_cpu(info_v8->usExtDispConnInfoOffset);
2282	info->memory_type = info_v8->ucMemoryType;
2283	info->ma_channel_number = info_v8->ucUMAChannelNumber;
2284	info->gmc_restore_reset_time =
2285		le32_to_cpu(info_v8->ulGMCRestoreResetTime);
2286
2287	info->minimum_n_clk =
2288		le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]);
2289	for (i = 1; i < 4; ++i)
2290		info->minimum_n_clk =
2291			info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ?
2292			info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]);
2293
2294	info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk);
2295	info->ddr_dll_power_up_time =
2296		le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime);
2297	info->ddr_pll_power_up_time =
2298		le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime);
2299	info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType);
2300	info->lvds_ss_percentage =
2301		le16_to_cpu(info_v8->usLvdsSSPercentage);
2302	info->lvds_sspread_rate_in_10hz =
2303		le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz);
2304	info->hdmi_ss_percentage =
2305		le16_to_cpu(info_v8->usHDMISSPercentage);
2306	info->hdmi_sspread_rate_in_10hz =
2307		le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz);
2308	info->dvi_ss_percentage =
2309		le16_to_cpu(info_v8->usDVISSPercentage);
2310	info->dvi_sspread_rate_in_10_hz =
2311		le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz);
2312
2313	info->max_lvds_pclk_freq_in_single_link =
2314		le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink);
2315	info->lvds_misc = info_v8->ucLvdsMisc;
2316	info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
2317		info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
2318	info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
2319		info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
2320	info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
2321		info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
2322	info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
2323		info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
2324	info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
2325		info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
2326	info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
2327		info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
2328	info->lvds_off_to_on_delay_in_4ms =
2329		info_v8->ucLVDSOffToOnDelay_in4Ms;
2330	info->lvds_bit_depth_control_val =
2331		le32_to_cpu(info_v8->ulLCDBitDepthControlVal);
2332
2333	for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
2334		/* Convert [10KHz] into [KHz] */
2335		info->avail_s_clk[i].supported_s_clk =
2336			le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10;
2337		info->avail_s_clk[i].voltage_index =
2338			le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex);
2339		info->avail_s_clk[i].voltage_id =
2340			le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID);
2341	}
2342
2343	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2344		info->ext_disp_conn_info.gu_id[i] =
2345			info_v8->sExtDispConnInfo.ucGuid[i];
2346	}
2347
2348	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2349		info->ext_disp_conn_info.path[i].device_connector_id =
2350			object_id_from_bios_object_id(
2351				le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector));
2352
2353		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2354			object_id_from_bios_object_id(
2355				le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
2356
2357		info->ext_disp_conn_info.path[i].device_tag =
2358			le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag);
2359		info->ext_disp_conn_info.path[i].device_acpi_enum =
2360			le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
2361		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2362			info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
2363		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2364			info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
2365		info->ext_disp_conn_info.path[i].channel_mapping.raw =
2366			info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping;
2367	}
2368	info->ext_disp_conn_info.checksum =
2369		info_v8->sExtDispConnInfo.ucChecksum;
2370
2371	return BP_RESULT_OK;
2372}
2373
2374/*
2375 * get_integrated_info_v8
2376 *
2377 * @brief
2378 * Get V8 integrated BIOS information
2379 *
2380 * @param
2381 * bios_parser *bp - [in]BIOS parser handler to get master data table
2382 * integrated_info *info - [out] store and output integrated info
2383 *
2384 * return:
2385 * enum bp_result - BP_RESULT_OK if information is available,
2386 *                  BP_RESULT_BADBIOSTABLE otherwise.
2387 */
2388static enum bp_result get_integrated_info_v9(
2389	struct bios_parser *bp,
2390	struct integrated_info *info)
2391{
2392	ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9;
2393	uint32_t i;
2394
2395	info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9,
2396			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
2397
2398	if (!info_v9)
2399		return BP_RESULT_BADBIOSTABLE;
2400
2401	info->boot_up_engine_clock = le32_to_cpu(info_v9->ulBootUpEngineClock) * 10;
2402	info->dentist_vco_freq = le32_to_cpu(info_v9->ulDentistVCOFreq) * 10;
2403	info->boot_up_uma_clock = le32_to_cpu(info_v9->ulBootUpUMAClock) * 10;
2404
2405	for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2406		/* Convert [10KHz] into [KHz] */
2407		info->disp_clk_voltage[i].max_supported_clk =
2408			le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10;
2409		info->disp_clk_voltage[i].voltage_index =
2410			le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex);
2411	}
2412
2413	info->boot_up_req_display_vector =
2414		le32_to_cpu(info_v9->ulBootUpReqDisplayVector);
2415	info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo);
2416
2417	/*
2418	 * system_config: Bit[0] = 0 : PCIE power gating disabled
2419	 *                       = 1 : PCIE power gating enabled
2420	 *                Bit[1] = 0 : DDR-PLL shut down disabled
2421	 *                       = 1 : DDR-PLL shut down enabled
2422	 *                Bit[2] = 0 : DDR-PLL power down disabled
2423	 *                       = 1 : DDR-PLL power down enabled
2424	 */
2425	info->system_config = le32_to_cpu(info_v9->ulSystemConfig);
2426	info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo);
2427	info->boot_up_nb_voltage = le16_to_cpu(info_v9->usBootUpNBVoltage);
2428	info->ext_disp_conn_info_offset = le16_to_cpu(info_v9->usExtDispConnInfoOffset);
2429	info->memory_type = info_v9->ucMemoryType;
2430	info->ma_channel_number = info_v9->ucUMAChannelNumber;
2431	info->gmc_restore_reset_time = le32_to_cpu(info_v9->ulGMCRestoreResetTime);
2432
2433	info->minimum_n_clk = le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]);
2434	for (i = 1; i < 4; ++i)
2435		info->minimum_n_clk =
2436			info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ?
2437			info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]);
2438
2439	info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk);
2440	info->ddr_dll_power_up_time = le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime);
2441	info->ddr_pll_power_up_time = le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime);
2442	info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType);
2443	info->lvds_ss_percentage = le16_to_cpu(info_v9->usLvdsSSPercentage);
2444	info->lvds_sspread_rate_in_10hz = le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz);
2445	info->hdmi_ss_percentage = le16_to_cpu(info_v9->usHDMISSPercentage);
2446	info->hdmi_sspread_rate_in_10hz = le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz);
2447	info->dvi_ss_percentage = le16_to_cpu(info_v9->usDVISSPercentage);
2448	info->dvi_sspread_rate_in_10_hz = le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz);
2449
2450	info->max_lvds_pclk_freq_in_single_link =
2451		le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink);
2452	info->lvds_misc = info_v9->ucLvdsMisc;
2453	info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
2454		info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
2455	info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
2456		info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
2457	info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
2458		info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
2459	info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
2460		info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
2461	info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
2462		info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
2463	info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
2464		info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
2465	info->lvds_off_to_on_delay_in_4ms =
2466		info_v9->ucLVDSOffToOnDelay_in4Ms;
2467	info->lvds_bit_depth_control_val =
2468		le32_to_cpu(info_v9->ulLCDBitDepthControlVal);
2469
2470	for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
2471		/* Convert [10KHz] into [KHz] */
2472		info->avail_s_clk[i].supported_s_clk =
2473			le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10;
2474		info->avail_s_clk[i].voltage_index =
2475			le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex);
2476		info->avail_s_clk[i].voltage_id =
2477			le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID);
2478	}
2479
2480	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2481		info->ext_disp_conn_info.gu_id[i] =
2482			info_v9->sExtDispConnInfo.ucGuid[i];
2483	}
2484
2485	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2486		info->ext_disp_conn_info.path[i].device_connector_id =
2487			object_id_from_bios_object_id(
2488				le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector));
2489
2490		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2491			object_id_from_bios_object_id(
2492				le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
2493
2494		info->ext_disp_conn_info.path[i].device_tag =
2495			le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag);
2496		info->ext_disp_conn_info.path[i].device_acpi_enum =
2497			le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
2498		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2499			info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
2500		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2501			info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
2502		info->ext_disp_conn_info.path[i].channel_mapping.raw =
2503			info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping;
2504	}
2505	info->ext_disp_conn_info.checksum =
2506		info_v9->sExtDispConnInfo.ucChecksum;
2507
2508	return BP_RESULT_OK;
2509}
2510
2511/*
2512 * construct_integrated_info
2513 *
2514 * @brief
2515 * Get integrated BIOS information based on table revision
2516 *
2517 * @param
2518 * bios_parser *bp - [in]BIOS parser handler to get master data table
2519 * integrated_info *info - [out] store and output integrated info
2520 *
2521 * return:
2522 * enum bp_result - BP_RESULT_OK if information is available,
2523 *                  BP_RESULT_BADBIOSTABLE otherwise.
2524 */
2525static enum bp_result construct_integrated_info(
2526	struct bios_parser *bp,
2527	struct integrated_info *info)
2528{
2529	enum bp_result result = BP_RESULT_BADBIOSTABLE;
2530
2531	ATOM_COMMON_TABLE_HEADER *header;
2532	struct atom_data_revision revision;
2533
2534	if (bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) {
2535		header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
2536				bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
2537
2538		get_atom_data_table_revision(header, &revision);
2539
2540		/* Don't need to check major revision as they are all 1 */
2541		switch (revision.minor) {
2542		case 8:
2543			result = get_integrated_info_v8(bp, info);
2544			break;
2545		case 9:
2546			result = get_integrated_info_v9(bp, info);
2547			break;
2548		default:
2549			return result;
2550
2551		}
2552	}
2553
2554	/* Sort voltage table from low to high*/
2555	if (result == BP_RESULT_OK) {
2556		uint32_t i;
2557		uint32_t j;
2558
2559		for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2560			for (j = i; j > 0; --j) {
2561				if (
2562						info->disp_clk_voltage[j].max_supported_clk <
2563						info->disp_clk_voltage[j-1].max_supported_clk) {
2564					/* swap j and j - 1*/
2565					swap(info->disp_clk_voltage[j - 1],
2566					     info->disp_clk_voltage[j]);
2567				}
2568			}
2569		}
2570
2571	}
2572
2573	return result;
2574}
2575
2576static struct integrated_info *bios_parser_create_integrated_info(
2577	struct dc_bios *dcb)
2578{
2579	struct bios_parser *bp = BP_FROM_DCB(dcb);
2580	struct integrated_info *info = NULL;
2581
2582	info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL);
2583
2584	if (info == NULL) {
2585		ASSERT_CRITICAL(0);
2586		return NULL;
2587	}
2588
2589	if (construct_integrated_info(bp, info) == BP_RESULT_OK)
2590		return info;
2591
2592	kfree(info);
2593
2594	return NULL;
2595}
2596
2597static enum bp_result update_slot_layout_info(
2598	struct dc_bios *dcb,
2599	unsigned int i,
2600	struct slot_layout_info *slot_layout_info,
2601	unsigned int record_offset)
2602{
2603	unsigned int j;
2604	struct bios_parser *bp;
2605	ATOM_BRACKET_LAYOUT_RECORD *record;
2606	ATOM_COMMON_RECORD_HEADER *record_header;
2607	enum bp_result result = BP_RESULT_NORECORD;
2608
2609	bp = BP_FROM_DCB(dcb);
2610	record = NULL;
2611	record_header = NULL;
2612
2613	for (;;) {
2614
2615		record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);
2616		if (record_header == NULL) {
2617			result = BP_RESULT_BADBIOSTABLE;
2618			break;
2619		}
2620
2621		/* the end of the list */
2622		if (record_header->ucRecordType == 0xff ||
2623			record_header->ucRecordSize == 0)	{
2624			break;
2625		}
2626
2627		if (record_header->ucRecordType ==
2628			ATOM_BRACKET_LAYOUT_RECORD_TYPE &&
2629			struct_size(record, asConnInfo, 1)
2630			<= record_header->ucRecordSize) {
2631			record = (ATOM_BRACKET_LAYOUT_RECORD *)
2632				(record_header);
2633			result = BP_RESULT_OK;
2634			break;
2635		}
2636
2637		record_offset += record_header->ucRecordSize;
2638	}
2639
2640	/* return if the record not found */
2641	if (result != BP_RESULT_OK)
2642		return result;
2643
2644	/* get slot sizes */
2645	slot_layout_info->length = record->ucLength;
2646	slot_layout_info->width = record->ucWidth;
2647
2648	/* get info for each connector in the slot */
2649	slot_layout_info->num_of_connectors = record->ucConnNum;
2650	for (j = 0; j < slot_layout_info->num_of_connectors; ++j) {
2651		slot_layout_info->connectors[j].connector_type =
2652			(enum connector_layout_type)
2653			(record->asConnInfo[j].ucConnectorType);
2654		switch (record->asConnInfo[j].ucConnectorType) {
2655		case CONNECTOR_TYPE_DVI_D:
2656			slot_layout_info->connectors[j].connector_type =
2657				CONNECTOR_LAYOUT_TYPE_DVI_D;
2658			slot_layout_info->connectors[j].length =
2659				CONNECTOR_SIZE_DVI;
2660			break;
2661
2662		case CONNECTOR_TYPE_HDMI:
2663			slot_layout_info->connectors[j].connector_type =
2664				CONNECTOR_LAYOUT_TYPE_HDMI;
2665			slot_layout_info->connectors[j].length =
2666				CONNECTOR_SIZE_HDMI;
2667			break;
2668
2669		case CONNECTOR_TYPE_DISPLAY_PORT:
2670			slot_layout_info->connectors[j].connector_type =
2671				CONNECTOR_LAYOUT_TYPE_DP;
2672			slot_layout_info->connectors[j].length =
2673				CONNECTOR_SIZE_DP;
2674			break;
2675
2676		case CONNECTOR_TYPE_MINI_DISPLAY_PORT:
2677			slot_layout_info->connectors[j].connector_type =
2678				CONNECTOR_LAYOUT_TYPE_MINI_DP;
2679			slot_layout_info->connectors[j].length =
2680				CONNECTOR_SIZE_MINI_DP;
2681			break;
2682
2683		default:
2684			slot_layout_info->connectors[j].connector_type =
2685				CONNECTOR_LAYOUT_TYPE_UNKNOWN;
2686			slot_layout_info->connectors[j].length =
2687				CONNECTOR_SIZE_UNKNOWN;
2688		}
2689
2690		slot_layout_info->connectors[j].position =
2691			record->asConnInfo[j].ucPosition;
2692		slot_layout_info->connectors[j].connector_id =
2693			object_id_from_bios_object_id(
2694				record->asConnInfo[j].usConnectorObjectId);
2695	}
2696	return result;
2697}
2698
2699
2700static enum bp_result get_bracket_layout_record(
2701	struct dc_bios *dcb,
2702	unsigned int bracket_layout_id,
2703	struct slot_layout_info *slot_layout_info)
2704{
2705	unsigned int i;
2706	unsigned int record_offset;
2707	struct bios_parser *bp;
2708	enum bp_result result;
2709	ATOM_OBJECT *object;
2710	ATOM_OBJECT_TABLE *object_table;
2711	unsigned int genericTableOffset;
2712
2713	bp = BP_FROM_DCB(dcb);
2714	object = NULL;
2715	if (slot_layout_info == NULL) {
2716		DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");
2717		return BP_RESULT_BADINPUT;
2718	}
2719
2720
2721	genericTableOffset = bp->object_info_tbl_offset +
2722		bp->object_info_tbl.v1_3->usMiscObjectTableOffset;
2723	object_table = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base,
2724				genericTableOffset,
2725				struct_size(object_table, asObjects, 1)));
2726	if (!object_table)
2727		return BP_RESULT_FAILURE;
2728
2729	result = BP_RESULT_NORECORD;
2730	for (i = 0; i < object_table->ucNumberOfObjects; ++i) {
2731
2732		if (bracket_layout_id ==
2733			object_table->asObjects[i].usObjectID) {
2734
2735			object = &object_table->asObjects[i];
2736			record_offset = object->usRecordOffset +
2737				bp->object_info_tbl_offset;
2738
2739			result = update_slot_layout_info(dcb, i,
2740				slot_layout_info, record_offset);
2741			break;
2742		}
2743	}
2744	return result;
2745}
2746
2747static enum bp_result bios_get_board_layout_info(
2748	struct dc_bios *dcb,
2749	struct board_layout_info *board_layout_info)
2750{
2751	unsigned int i;
 
2752	enum bp_result record_result;
2753
2754	const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {
2755		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1,
2756		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2,
2757		0, 0
2758	};
 
 
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/******************************************************************************/