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