Linux Audio

Check our new training course

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