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