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