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 "dm_services.h"
27 
28 #include "atom.h"
29 
30 #include "dc_bios_types.h"
31 #include "include/gpio_service_interface.h"
32 #include "include/grph_object_ctrl_defs.h"
33 #include "include/bios_parser_interface.h"
34 #include "include/i2caux_interface.h"
35 #include "include/logger_interface.h"
36 
37 #include "command_table.h"
38 #include "bios_parser_helper.h"
39 #include "command_table_helper.h"
40 #include "bios_parser.h"
41 #include "bios_parser_types_internal.h"
42 #include "bios_parser_interface.h"
43 
44 #include "bios_parser_common.h"
45 /* TODO remove - only needed for default i2c speed */
46 #include "dc.h"
47 
48 #define THREE_PERCENT_OF_10000 300
49 
50 #define LAST_RECORD_TYPE 0xff
51 
52 #define DC_LOGGER \
53 	bp->base.ctx->logger
54 
55 /* GUID to validate external display connection info table (aka OPM module) */
56 static const uint8_t ext_display_connection_guid[NUMBER_OF_UCHAR_FOR_GUID] = {
57 	0x91, 0x6E, 0x57, 0x09,
58 	0x3F, 0x6D, 0xD2, 0x11,
59 	0x39, 0x8E, 0x00, 0xA0,
60 	0xC9, 0x69, 0x72, 0x3B};
61 
62 #define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table)
63 
64 static void get_atom_data_table_revision(
65 	ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
66 	struct atom_data_revision *tbl_revision);
67 static uint32_t get_dst_number_from_object(struct bios_parser *bp,
68 	ATOM_OBJECT *object);
69 static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
70 	uint16_t **id_list);
71 static uint32_t get_dest_obj_list(struct bios_parser *bp,
72 	ATOM_OBJECT *object, uint16_t **id_list);
73 static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
74 	struct graphics_object_id id);
75 static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
76 	ATOM_I2C_RECORD *record,
77 	struct graphics_object_i2c_info *info);
78 static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
79 	ATOM_OBJECT *object);
80 static struct device_id device_type_from_device_id(uint16_t device_id);
81 static uint32_t signal_to_ss_id(enum as_signal_type signal);
82 static uint32_t get_support_mask_for_device_id(struct device_id device_id);
83 static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
84 	struct bios_parser *bp,
85 	ATOM_OBJECT *object);
86 
87 #define BIOS_IMAGE_SIZE_OFFSET 2
88 #define BIOS_IMAGE_SIZE_UNIT 512
89 
90 /*****************************************************************************/
91 static bool bios_parser_construct(
92 	struct bios_parser *bp,
93 	struct bp_init_data *init,
94 	enum dce_version dce_version);
95 
96 static uint8_t bios_parser_get_connectors_number(
97 	struct dc_bios *dcb);
98 
99 static enum bp_result bios_parser_get_embedded_panel_info(
100 	struct dc_bios *dcb,
101 	struct embedded_panel_info *info);
102 
103 /*****************************************************************************/
104 
105 struct dc_bios *bios_parser_create(
106 	struct bp_init_data *init,
107 	enum dce_version dce_version)
108 {
109 	struct bios_parser *bp = NULL;
110 
111 	bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL);
112 	if (!bp)
113 		return NULL;
114 
115 	if (bios_parser_construct(bp, init, dce_version))
116 		return &bp->base;
117 
118 	kfree(bp);
119 	BREAK_TO_DEBUGGER();
120 	return NULL;
121 }
122 
123 static void destruct(struct bios_parser *bp)
124 {
125 	kfree(bp->base.bios_local_image);
126 	kfree(bp->base.integrated_info);
127 }
128 
129 static void bios_parser_destroy(struct dc_bios **dcb)
130 {
131 	struct bios_parser *bp = BP_FROM_DCB(*dcb);
132 
133 	if (!bp) {
134 		BREAK_TO_DEBUGGER();
135 		return;
136 	}
137 
138 	destruct(bp);
139 
140 	kfree(bp);
141 	*dcb = NULL;
142 }
143 
144 static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset)
145 {
146 	ATOM_OBJECT_TABLE *table;
147 
148 	uint32_t object_table_offset = bp->object_info_tbl_offset + offset;
149 
150 	table = GET_IMAGE(ATOM_OBJECT_TABLE, object_table_offset);
151 
152 	if (!table)
153 		return 0;
154 	else
155 		return table->ucNumberOfObjects;
156 }
157 
158 static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)
159 {
160 	struct bios_parser *bp = BP_FROM_DCB(dcb);
161 
162 	return get_number_of_objects(bp,
163 		le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset));
164 }
165 
166 static struct graphics_object_id bios_parser_get_encoder_id(
167 	struct dc_bios *dcb,
168 	uint32_t i)
169 {
170 	struct bios_parser *bp = BP_FROM_DCB(dcb);
171 	struct graphics_object_id object_id = dal_graphics_object_id_init(
172 		0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
173 
174 	uint32_t encoder_table_offset = bp->object_info_tbl_offset
175 		+ le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
176 
177 	ATOM_OBJECT_TABLE *tbl =
178 		GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset);
179 
180 	if (tbl && tbl->ucNumberOfObjects > i) {
181 		const uint16_t id = le16_to_cpu(tbl->asObjects[i].usObjectID);
182 
183 		object_id = object_id_from_bios_object_id(id);
184 	}
185 
186 	return object_id;
187 }
188 
189 static struct graphics_object_id bios_parser_get_connector_id(
190 	struct dc_bios *dcb,
191 	uint8_t i)
192 {
193 	struct bios_parser *bp = BP_FROM_DCB(dcb);
194 	struct graphics_object_id object_id = dal_graphics_object_id_init(
195 		0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
196 	uint16_t id;
197 
198 	uint32_t connector_table_offset = bp->object_info_tbl_offset
199 		+ le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
200 
201 	ATOM_OBJECT_TABLE *tbl =
202 		GET_IMAGE(ATOM_OBJECT_TABLE, connector_table_offset);
203 
204 	if (!tbl) {
205 		dm_error("Can't get connector table from atom bios.\n");
206 		return object_id;
207 	}
208 
209 	if (tbl->ucNumberOfObjects <= i) {
210 		dm_error("Can't find connector id %d in connector table of size %d.\n",
211 			 i, tbl->ucNumberOfObjects);
212 		return object_id;
213 	}
214 
215 	id = le16_to_cpu(tbl->asObjects[i].usObjectID);
216 	object_id = object_id_from_bios_object_id(id);
217 	return object_id;
218 }
219 
220 static uint32_t bios_parser_get_dst_number(struct dc_bios *dcb,
221 	struct graphics_object_id id)
222 {
223 	struct bios_parser *bp = BP_FROM_DCB(dcb);
224 	ATOM_OBJECT *object = get_bios_object(bp, id);
225 
226 	return get_dst_number_from_object(bp, object);
227 }
228 
229 static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
230 	struct graphics_object_id object_id, uint32_t index,
231 	struct graphics_object_id *src_object_id)
232 {
233 	uint32_t number;
234 	uint16_t *id;
235 	ATOM_OBJECT *object;
236 	struct bios_parser *bp = BP_FROM_DCB(dcb);
237 
238 	if (!src_object_id)
239 		return BP_RESULT_BADINPUT;
240 
241 	object = get_bios_object(bp, object_id);
242 
243 	if (!object) {
244 		BREAK_TO_DEBUGGER(); /* Invalid object id */
245 		return BP_RESULT_BADINPUT;
246 	}
247 
248 	number = get_src_obj_list(bp, object, &id);
249 
250 	if (number <= index)
251 		return BP_RESULT_BADINPUT;
252 
253 	*src_object_id = object_id_from_bios_object_id(id[index]);
254 
255 	return BP_RESULT_OK;
256 }
257 
258 static enum bp_result bios_parser_get_dst_obj(struct dc_bios *dcb,
259 	struct graphics_object_id object_id, uint32_t index,
260 	struct graphics_object_id *dest_object_id)
261 {
262 	uint32_t number;
263 	uint16_t *id = NULL;
264 	ATOM_OBJECT *object;
265 	struct bios_parser *bp = BP_FROM_DCB(dcb);
266 
267 	if (!dest_object_id)
268 		return BP_RESULT_BADINPUT;
269 
270 	object = get_bios_object(bp, object_id);
271 
272 	number = get_dest_obj_list(bp, object, &id);
273 
274 	if (number <= index || !id)
275 		return BP_RESULT_BADINPUT;
276 
277 	*dest_object_id = object_id_from_bios_object_id(id[index]);
278 
279 	return BP_RESULT_OK;
280 }
281 
282 static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
283 	struct graphics_object_id id,
284 	struct graphics_object_i2c_info *info)
285 {
286 	uint32_t offset;
287 	ATOM_OBJECT *object;
288 	ATOM_COMMON_RECORD_HEADER *header;
289 	ATOM_I2C_RECORD *record;
290 	struct bios_parser *bp = BP_FROM_DCB(dcb);
291 
292 	if (!info)
293 		return BP_RESULT_BADINPUT;
294 
295 	object = get_bios_object(bp, id);
296 
297 	if (!object)
298 		return BP_RESULT_BADINPUT;
299 
300 	offset = le16_to_cpu(object->usRecordOffset)
301 			+ bp->object_info_tbl_offset;
302 
303 	for (;;) {
304 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
305 
306 		if (!header)
307 			return BP_RESULT_BADBIOSTABLE;
308 
309 		if (LAST_RECORD_TYPE == header->ucRecordType ||
310 			!header->ucRecordSize)
311 			break;
312 
313 		if (ATOM_I2C_RECORD_TYPE == header->ucRecordType
314 			&& sizeof(ATOM_I2C_RECORD) <= header->ucRecordSize) {
315 			/* get the I2C info */
316 			record = (ATOM_I2C_RECORD *) header;
317 
318 			if (get_gpio_i2c_info(bp, record, info) == BP_RESULT_OK)
319 				return BP_RESULT_OK;
320 		}
321 
322 		offset += header->ucRecordSize;
323 	}
324 
325 	return BP_RESULT_NORECORD;
326 }
327 
328 static enum bp_result get_voltage_ddc_info_v1(uint8_t *i2c_line,
329 	ATOM_COMMON_TABLE_HEADER *header,
330 	uint8_t *address)
331 {
332 	enum bp_result result = BP_RESULT_NORECORD;
333 	ATOM_VOLTAGE_OBJECT_INFO *info =
334 		(ATOM_VOLTAGE_OBJECT_INFO *) address;
335 
336 	uint8_t *voltage_current_object = (uint8_t *) &info->asVoltageObj[0];
337 
338 	while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) {
339 		ATOM_VOLTAGE_OBJECT *object =
340 			(ATOM_VOLTAGE_OBJECT *) voltage_current_object;
341 
342 		if ((object->ucVoltageType == SET_VOLTAGE_INIT_MODE) &&
343 			(object->ucVoltageType &
344 				VOLTAGE_CONTROLLED_BY_I2C_MASK)) {
345 
346 			*i2c_line = object->asControl.ucVoltageControlI2cLine
347 					^ 0x90;
348 			result = BP_RESULT_OK;
349 			break;
350 		}
351 
352 		voltage_current_object += object->ucSize;
353 	}
354 	return result;
355 }
356 
357 static enum bp_result get_voltage_ddc_info_v3(uint8_t *i2c_line,
358 	uint32_t index,
359 	ATOM_COMMON_TABLE_HEADER *header,
360 	uint8_t *address)
361 {
362 	enum bp_result result = BP_RESULT_NORECORD;
363 	ATOM_VOLTAGE_OBJECT_INFO_V3_1 *info =
364 		(ATOM_VOLTAGE_OBJECT_INFO_V3_1 *) address;
365 
366 	uint8_t *voltage_current_object =
367 		(uint8_t *) (&(info->asVoltageObj[0]));
368 
369 	while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) {
370 		ATOM_I2C_VOLTAGE_OBJECT_V3 *object =
371 			(ATOM_I2C_VOLTAGE_OBJECT_V3 *) voltage_current_object;
372 
373 		if (object->sHeader.ucVoltageMode ==
374 			ATOM_INIT_VOLTAGE_REGULATOR) {
375 			if (object->sHeader.ucVoltageType == index) {
376 				*i2c_line = object->ucVoltageControlI2cLine
377 						^ 0x90;
378 				result = BP_RESULT_OK;
379 				break;
380 			}
381 		}
382 
383 		voltage_current_object += le16_to_cpu(object->sHeader.usSize);
384 	}
385 	return result;
386 }
387 
388 static enum bp_result bios_parser_get_thermal_ddc_info(
389 	struct dc_bios *dcb,
390 	uint32_t i2c_channel_id,
391 	struct graphics_object_i2c_info *info)
392 {
393 	struct bios_parser *bp = BP_FROM_DCB(dcb);
394 	ATOM_I2C_ID_CONFIG_ACCESS *config;
395 	ATOM_I2C_RECORD record;
396 
397 	if (!info)
398 		return BP_RESULT_BADINPUT;
399 
400 	config = (ATOM_I2C_ID_CONFIG_ACCESS *) &i2c_channel_id;
401 
402 	record.sucI2cId.bfHW_Capable = config->sbfAccess.bfHW_Capable;
403 	record.sucI2cId.bfI2C_LineMux = config->sbfAccess.bfI2C_LineMux;
404 	record.sucI2cId.bfHW_EngineID = config->sbfAccess.bfHW_EngineID;
405 
406 	return get_gpio_i2c_info(bp, &record, info);
407 }
408 
409 static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb,
410 	uint32_t index,
411 	struct graphics_object_i2c_info *info)
412 {
413 	uint8_t i2c_line = 0;
414 	enum bp_result result = BP_RESULT_NORECORD;
415 	uint8_t *voltage_info_address;
416 	ATOM_COMMON_TABLE_HEADER *header;
417 	struct atom_data_revision revision = {0};
418 	struct bios_parser *bp = BP_FROM_DCB(dcb);
419 
420 	if (!DATA_TABLES(VoltageObjectInfo))
421 		return result;
422 
423 	voltage_info_address = bios_get_image(&bp->base, DATA_TABLES(VoltageObjectInfo), sizeof(ATOM_COMMON_TABLE_HEADER));
424 
425 	header = (ATOM_COMMON_TABLE_HEADER *) voltage_info_address;
426 
427 	get_atom_data_table_revision(header, &revision);
428 
429 	switch (revision.major) {
430 	case 1:
431 	case 2:
432 		result = get_voltage_ddc_info_v1(&i2c_line, header,
433 			voltage_info_address);
434 		break;
435 	case 3:
436 		if (revision.minor != 1)
437 			break;
438 		result = get_voltage_ddc_info_v3(&i2c_line, index, header,
439 			voltage_info_address);
440 		break;
441 	}
442 
443 	if (result == BP_RESULT_OK)
444 		result = bios_parser_get_thermal_ddc_info(dcb,
445 			i2c_line, info);
446 
447 	return result;
448 }
449 
450 /* TODO: temporary commented out to suppress 'defined but not used' warning */
451 #if 0
452 static enum bp_result bios_parser_get_ddc_info_for_i2c_line(
453 	struct bios_parser *bp,
454 	uint8_t i2c_line, struct graphics_object_i2c_info *info)
455 {
456 	uint32_t offset;
457 	ATOM_OBJECT *object;
458 	ATOM_OBJECT_TABLE *table;
459 	uint32_t i;
460 
461 	if (!info)
462 		return BP_RESULT_BADINPUT;
463 
464 	offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
465 
466 	offset += bp->object_info_tbl_offset;
467 
468 	table = GET_IMAGE(ATOM_OBJECT_TABLE, offset);
469 
470 	if (!table)
471 		return BP_RESULT_BADBIOSTABLE;
472 
473 	for (i = 0; i < table->ucNumberOfObjects; i++) {
474 		object = &table->asObjects[i];
475 
476 		if (!object) {
477 			BREAK_TO_DEBUGGER(); /* Invalid object id */
478 			return BP_RESULT_BADINPUT;
479 		}
480 
481 		offset = le16_to_cpu(object->usRecordOffset)
482 				+ bp->object_info_tbl_offset;
483 
484 		for (;;) {
485 			ATOM_COMMON_RECORD_HEADER *header =
486 				GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
487 
488 			if (!header)
489 				return BP_RESULT_BADBIOSTABLE;
490 
491 			offset += header->ucRecordSize;
492 
493 			if (LAST_RECORD_TYPE == header->ucRecordType ||
494 				!header->ucRecordSize)
495 				break;
496 
497 			if (ATOM_I2C_RECORD_TYPE == header->ucRecordType
498 				&& sizeof(ATOM_I2C_RECORD) <=
499 				header->ucRecordSize) {
500 				ATOM_I2C_RECORD *record =
501 					(ATOM_I2C_RECORD *) header;
502 
503 				if (i2c_line != record->sucI2cId.bfI2C_LineMux)
504 					continue;
505 
506 				/* get the I2C info */
507 				if (get_gpio_i2c_info(bp, record, info) ==
508 					BP_RESULT_OK)
509 					return BP_RESULT_OK;
510 			}
511 		}
512 	}
513 
514 	return BP_RESULT_NORECORD;
515 }
516 #endif
517 
518 static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb,
519 	struct graphics_object_id id,
520 	struct graphics_object_hpd_info *info)
521 {
522 	struct bios_parser *bp = BP_FROM_DCB(dcb);
523 	ATOM_OBJECT *object;
524 	ATOM_HPD_INT_RECORD *record = NULL;
525 
526 	if (!info)
527 		return BP_RESULT_BADINPUT;
528 
529 	object = get_bios_object(bp, id);
530 
531 	if (!object)
532 		return BP_RESULT_BADINPUT;
533 
534 	record = get_hpd_record(bp, object);
535 
536 	if (record != NULL) {
537 		info->hpd_int_gpio_uid = record->ucHPDIntGPIOID;
538 		info->hpd_active = record->ucPlugged_PinState;
539 		return BP_RESULT_OK;
540 	}
541 
542 	return BP_RESULT_NORECORD;
543 }
544 
545 static enum bp_result bios_parser_get_device_tag_record(
546 	struct bios_parser *bp,
547 	ATOM_OBJECT *object,
548 	ATOM_CONNECTOR_DEVICE_TAG_RECORD **record)
549 {
550 	ATOM_COMMON_RECORD_HEADER *header;
551 	uint32_t offset;
552 
553 	offset = le16_to_cpu(object->usRecordOffset)
554 			+ bp->object_info_tbl_offset;
555 
556 	for (;;) {
557 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
558 
559 		if (!header)
560 			return BP_RESULT_BADBIOSTABLE;
561 
562 		offset += header->ucRecordSize;
563 
564 		if (LAST_RECORD_TYPE == header->ucRecordType ||
565 			!header->ucRecordSize)
566 			break;
567 
568 		if (ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE !=
569 			header->ucRecordType)
570 			continue;
571 
572 		if (sizeof(ATOM_CONNECTOR_DEVICE_TAG) > header->ucRecordSize)
573 			continue;
574 
575 		*record = (ATOM_CONNECTOR_DEVICE_TAG_RECORD *) header;
576 		return BP_RESULT_OK;
577 	}
578 
579 	return BP_RESULT_NORECORD;
580 }
581 
582 static enum bp_result bios_parser_get_device_tag(
583 	struct dc_bios *dcb,
584 	struct graphics_object_id connector_object_id,
585 	uint32_t device_tag_index,
586 	struct connector_device_tag_info *info)
587 {
588 	struct bios_parser *bp = BP_FROM_DCB(dcb);
589 	ATOM_OBJECT *object;
590 	ATOM_CONNECTOR_DEVICE_TAG_RECORD *record = NULL;
591 	ATOM_CONNECTOR_DEVICE_TAG *device_tag;
592 
593 	if (!info)
594 		return BP_RESULT_BADINPUT;
595 
596 	/* getBiosObject will return MXM object */
597 	object = get_bios_object(bp, connector_object_id);
598 
599 	if (!object) {
600 		BREAK_TO_DEBUGGER(); /* Invalid object id */
601 		return BP_RESULT_BADINPUT;
602 	}
603 
604 	if (bios_parser_get_device_tag_record(bp, object, &record)
605 		!= BP_RESULT_OK)
606 		return BP_RESULT_NORECORD;
607 
608 	if (device_tag_index >= record->ucNumberOfDevice)
609 		return BP_RESULT_NORECORD;
610 
611 	device_tag = &record->asDeviceTag[device_tag_index];
612 
613 	info->acpi_device = le32_to_cpu(device_tag->ulACPIDeviceEnum);
614 	info->dev_id =
615 		device_type_from_device_id(le16_to_cpu(device_tag->usDeviceID));
616 
617 	return BP_RESULT_OK;
618 }
619 
620 static enum bp_result get_firmware_info_v1_4(
621 	struct bios_parser *bp,
622 	struct dc_firmware_info *info);
623 static enum bp_result get_firmware_info_v2_1(
624 	struct bios_parser *bp,
625 	struct dc_firmware_info *info);
626 static enum bp_result get_firmware_info_v2_2(
627 	struct bios_parser *bp,
628 	struct dc_firmware_info *info);
629 
630 static enum bp_result bios_parser_get_firmware_info(
631 	struct dc_bios *dcb,
632 	struct dc_firmware_info *info)
633 {
634 	struct bios_parser *bp = BP_FROM_DCB(dcb);
635 	enum bp_result result = BP_RESULT_BADBIOSTABLE;
636 	ATOM_COMMON_TABLE_HEADER *header;
637 	struct atom_data_revision revision;
638 
639 	if (info && DATA_TABLES(FirmwareInfo)) {
640 		header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
641 			DATA_TABLES(FirmwareInfo));
642 		get_atom_data_table_revision(header, &revision);
643 		switch (revision.major) {
644 		case 1:
645 			switch (revision.minor) {
646 			case 4:
647 				result = get_firmware_info_v1_4(bp, info);
648 				break;
649 			default:
650 				break;
651 			}
652 			break;
653 
654 		case 2:
655 			switch (revision.minor) {
656 			case 1:
657 				result = get_firmware_info_v2_1(bp, info);
658 				break;
659 			case 2:
660 				result = get_firmware_info_v2_2(bp, info);
661 				break;
662 			default:
663 				break;
664 			}
665 			break;
666 		default:
667 			break;
668 		}
669 	}
670 
671 	return result;
672 }
673 
674 static enum bp_result get_firmware_info_v1_4(
675 	struct bios_parser *bp,
676 	struct dc_firmware_info *info)
677 {
678 	ATOM_FIRMWARE_INFO_V1_4 *firmware_info =
679 		GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4,
680 			DATA_TABLES(FirmwareInfo));
681 
682 	if (!info)
683 		return BP_RESULT_BADINPUT;
684 
685 	if (!firmware_info)
686 		return BP_RESULT_BADBIOSTABLE;
687 
688 	memset(info, 0, sizeof(*info));
689 
690 	/* Pixel clock pll information. We need to convert from 10KHz units into
691 	 * KHz units */
692 	info->pll_info.crystal_frequency =
693 		le16_to_cpu(firmware_info->usReferenceClock) * 10;
694 	info->pll_info.min_input_pxl_clk_pll_frequency =
695 		le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
696 	info->pll_info.max_input_pxl_clk_pll_frequency =
697 		le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
698 	info->pll_info.min_output_pxl_clk_pll_frequency =
699 		le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
700 	info->pll_info.max_output_pxl_clk_pll_frequency =
701 		le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
702 
703 	if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
704 		/* Since there is no information on the SS, report conservative
705 		 * value 3% for bandwidth calculation */
706 		/* unit of 0.01% */
707 		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
708 
709 	if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
710 		/* Since there is no information on the SS,report conservative
711 		 * value 3% for bandwidth calculation */
712 		/* unit of 0.01% */
713 		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
714 
715 	return BP_RESULT_OK;
716 }
717 
718 static enum bp_result get_ss_info_v3_1(
719 	struct bios_parser *bp,
720 	uint32_t id,
721 	uint32_t index,
722 	struct spread_spectrum_info *ss_info);
723 
724 static enum bp_result get_firmware_info_v2_1(
725 	struct bios_parser *bp,
726 	struct dc_firmware_info *info)
727 {
728 	ATOM_FIRMWARE_INFO_V2_1 *firmwareInfo =
729 		GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1, DATA_TABLES(FirmwareInfo));
730 	struct spread_spectrum_info internalSS;
731 	uint32_t index;
732 
733 	if (!info)
734 		return BP_RESULT_BADINPUT;
735 
736 	if (!firmwareInfo)
737 		return BP_RESULT_BADBIOSTABLE;
738 
739 	memset(info, 0, sizeof(*info));
740 
741 	/* Pixel clock pll information. We need to convert from 10KHz units into
742 	 * KHz units */
743 	info->pll_info.crystal_frequency =
744 		le16_to_cpu(firmwareInfo->usCoreReferenceClock) * 10;
745 	info->pll_info.min_input_pxl_clk_pll_frequency =
746 		le16_to_cpu(firmwareInfo->usMinPixelClockPLL_Input) * 10;
747 	info->pll_info.max_input_pxl_clk_pll_frequency =
748 		le16_to_cpu(firmwareInfo->usMaxPixelClockPLL_Input) * 10;
749 	info->pll_info.min_output_pxl_clk_pll_frequency =
750 		le32_to_cpu(firmwareInfo->ulMinPixelClockPLL_Output) * 10;
751 	info->pll_info.max_output_pxl_clk_pll_frequency =
752 		le32_to_cpu(firmwareInfo->ulMaxPixelClockPLL_Output) * 10;
753 	info->default_display_engine_pll_frequency =
754 		le32_to_cpu(firmwareInfo->ulDefaultDispEngineClkFreq) * 10;
755 	info->external_clock_source_frequency_for_dp =
756 		le16_to_cpu(firmwareInfo->usUniphyDPModeExtClkFreq) * 10;
757 	info->min_allowed_bl_level = firmwareInfo->ucMinAllowedBL_Level;
758 
759 	/* There should be only one entry in the SS info table for Memory Clock
760 	 */
761 	index = 0;
762 	if (firmwareInfo->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
763 		/* Since there is no information for external SS, report
764 		 *  conservative value 3% for bandwidth calculation */
765 		/* unit of 0.01% */
766 		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
767 	else if (get_ss_info_v3_1(bp,
768 		ASIC_INTERNAL_MEMORY_SS, index, &internalSS) == BP_RESULT_OK) {
769 		if (internalSS.spread_spectrum_percentage) {
770 			info->feature.memory_clk_ss_percentage =
771 				internalSS.spread_spectrum_percentage;
772 			if (internalSS.type.CENTER_MODE) {
773 				/* if it is centermode, the exact SS Percentage
774 				 * will be round up of half of the percentage
775 				 * reported in the SS table */
776 				++info->feature.memory_clk_ss_percentage;
777 				info->feature.memory_clk_ss_percentage /= 2;
778 			}
779 		}
780 	}
781 
782 	/* There should be only one entry in the SS info table for Engine Clock
783 	 */
784 	index = 1;
785 	if (firmwareInfo->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
786 		/* Since there is no information for external SS, report
787 		 * conservative value 3% for bandwidth calculation */
788 		/* unit of 0.01% */
789 		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
790 	else if (get_ss_info_v3_1(bp,
791 		ASIC_INTERNAL_ENGINE_SS, index, &internalSS) == BP_RESULT_OK) {
792 		if (internalSS.spread_spectrum_percentage) {
793 			info->feature.engine_clk_ss_percentage =
794 				internalSS.spread_spectrum_percentage;
795 			if (internalSS.type.CENTER_MODE) {
796 				/* if it is centermode, the exact SS Percentage
797 				 * will be round up of half of the percentage
798 				 * reported in the SS table */
799 				++info->feature.engine_clk_ss_percentage;
800 				info->feature.engine_clk_ss_percentage /= 2;
801 			}
802 		}
803 	}
804 
805 	return BP_RESULT_OK;
806 }
807 
808 static enum bp_result get_firmware_info_v2_2(
809 	struct bios_parser *bp,
810 	struct dc_firmware_info *info)
811 {
812 	ATOM_FIRMWARE_INFO_V2_2 *firmware_info;
813 	struct spread_spectrum_info internal_ss;
814 	uint32_t index;
815 
816 	if (!info)
817 		return BP_RESULT_BADINPUT;
818 
819 	firmware_info = GET_IMAGE(ATOM_FIRMWARE_INFO_V2_2,
820 		DATA_TABLES(FirmwareInfo));
821 
822 	if (!firmware_info)
823 		return BP_RESULT_BADBIOSTABLE;
824 
825 	memset(info, 0, sizeof(*info));
826 
827 	/* Pixel clock pll information. We need to convert from 10KHz units into
828 	 * KHz units */
829 	info->pll_info.crystal_frequency =
830 		le16_to_cpu(firmware_info->usCoreReferenceClock) * 10;
831 	info->pll_info.min_input_pxl_clk_pll_frequency =
832 		le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
833 	info->pll_info.max_input_pxl_clk_pll_frequency =
834 		le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
835 	info->pll_info.min_output_pxl_clk_pll_frequency =
836 		le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
837 	info->pll_info.max_output_pxl_clk_pll_frequency =
838 		le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
839 	info->default_display_engine_pll_frequency =
840 		le32_to_cpu(firmware_info->ulDefaultDispEngineClkFreq) * 10;
841 	info->external_clock_source_frequency_for_dp =
842 		le16_to_cpu(firmware_info->usUniphyDPModeExtClkFreq) * 10;
843 
844 	/* There should be only one entry in the SS info table for Memory Clock
845 	 */
846 	index = 0;
847 	if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
848 		/* Since there is no information for external SS, report
849 		 *  conservative value 3% for bandwidth calculation */
850 		/* unit of 0.01% */
851 		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
852 	else if (get_ss_info_v3_1(bp,
853 			ASIC_INTERNAL_MEMORY_SS, index, &internal_ss) == BP_RESULT_OK) {
854 		if (internal_ss.spread_spectrum_percentage) {
855 			info->feature.memory_clk_ss_percentage =
856 					internal_ss.spread_spectrum_percentage;
857 			if (internal_ss.type.CENTER_MODE) {
858 				/* if it is centermode, the exact SS Percentage
859 				 * will be round up of half of the percentage
860 				 * reported in the SS table */
861 				++info->feature.memory_clk_ss_percentage;
862 				info->feature.memory_clk_ss_percentage /= 2;
863 			}
864 		}
865 	}
866 
867 	/* There should be only one entry in the SS info table for Engine Clock
868 	 */
869 	index = 1;
870 	if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
871 		/* Since there is no information for external SS, report
872 		 * conservative value 3% for bandwidth calculation */
873 		/* unit of 0.01% */
874 		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
875 	else if (get_ss_info_v3_1(bp,
876 			ASIC_INTERNAL_ENGINE_SS, index, &internal_ss) == BP_RESULT_OK) {
877 		if (internal_ss.spread_spectrum_percentage) {
878 			info->feature.engine_clk_ss_percentage =
879 					internal_ss.spread_spectrum_percentage;
880 			if (internal_ss.type.CENTER_MODE) {
881 				/* if it is centermode, the exact SS Percentage
882 				 * will be round up of half of the percentage
883 				 * reported in the SS table */
884 				++info->feature.engine_clk_ss_percentage;
885 				info->feature.engine_clk_ss_percentage /= 2;
886 			}
887 		}
888 	}
889 
890 	/* Remote Display */
891 	info->remote_display_config = firmware_info->ucRemoteDisplayConfig;
892 
893 	/* Is allowed minimum BL level */
894 	info->min_allowed_bl_level = firmware_info->ucMinAllowedBL_Level;
895 	/* Used starting from CI */
896 	info->smu_gpu_pll_output_freq =
897 			(uint32_t) (le32_to_cpu(firmware_info->ulGPUPLL_OutputFreq) * 10);
898 
899 	return BP_RESULT_OK;
900 }
901 
902 static enum bp_result get_ss_info_v3_1(
903 	struct bios_parser *bp,
904 	uint32_t id,
905 	uint32_t index,
906 	struct spread_spectrum_info *ss_info)
907 {
908 	ATOM_ASIC_INTERNAL_SS_INFO_V3 *ss_table_header_include;
909 	ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
910 	uint32_t table_size;
911 	uint32_t i;
912 	uint32_t table_index = 0;
913 
914 	if (!ss_info)
915 		return BP_RESULT_BADINPUT;
916 
917 	if (!DATA_TABLES(ASIC_InternalSS_Info))
918 		return BP_RESULT_UNSUPPORTED;
919 
920 	ss_table_header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
921 		DATA_TABLES(ASIC_InternalSS_Info));
922 	table_size =
923 		(le16_to_cpu(ss_table_header_include->sHeader.usStructureSize)
924 				- sizeof(ATOM_COMMON_TABLE_HEADER))
925 				/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
926 
927 	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
928 				&ss_table_header_include->asSpreadSpectrum[0];
929 
930 	memset(ss_info, 0, sizeof(struct spread_spectrum_info));
931 
932 	for (i = 0; i < table_size; i++) {
933 		if (tbl[i].ucClockIndication != (uint8_t) id)
934 			continue;
935 
936 		if (table_index != index) {
937 			table_index++;
938 			continue;
939 		}
940 		/* VBIOS introduced new defines for Version 3, same values as
941 		 *  before, so now use these new ones for Version 3.
942 		 * Shouldn't affect field VBIOS's V3 as define values are still
943 		 *  same.
944 		 * #define SS_MODE_V3_CENTRE_SPREAD_MASK                0x01
945 		 * #define SS_MODE_V3_EXTERNAL_SS_MASK                  0x02
946 
947 		 * Old VBIOS defines:
948 		 * #define ATOM_SS_CENTRE_SPREAD_MODE_MASK        0x00000001
949 		 * #define ATOM_EXTERNAL_SS_MASK                  0x00000002
950 		 */
951 
952 		if (SS_MODE_V3_EXTERNAL_SS_MASK & tbl[i].ucSpreadSpectrumMode)
953 			ss_info->type.EXTERNAL = true;
954 
955 		if (SS_MODE_V3_CENTRE_SPREAD_MASK & tbl[i].ucSpreadSpectrumMode)
956 			ss_info->type.CENTER_MODE = true;
957 
958 		/* Older VBIOS (in field) always provides SS percentage in 0.01%
959 		 * units set Divider to 100 */
960 		ss_info->spread_percentage_divider = 100;
961 
962 		/* #define SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 0x10 */
963 		if (SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK
964 				& tbl[i].ucSpreadSpectrumMode)
965 			ss_info->spread_percentage_divider = 1000;
966 
967 		ss_info->type.STEP_AND_DELAY_INFO = false;
968 		/* convert [10KHz] into [KHz] */
969 		ss_info->target_clock_range =
970 				le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
971 		ss_info->spread_spectrum_percentage =
972 				(uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
973 		ss_info->spread_spectrum_range =
974 				(uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
975 
976 		return BP_RESULT_OK;
977 	}
978 	return BP_RESULT_NORECORD;
979 }
980 
981 static enum bp_result bios_parser_transmitter_control(
982 	struct dc_bios *dcb,
983 	struct bp_transmitter_control *cntl)
984 {
985 	struct bios_parser *bp = BP_FROM_DCB(dcb);
986 
987 	if (!bp->cmd_tbl.transmitter_control)
988 		return BP_RESULT_FAILURE;
989 
990 	return bp->cmd_tbl.transmitter_control(bp, cntl);
991 }
992 
993 static enum bp_result bios_parser_encoder_control(
994 	struct dc_bios *dcb,
995 	struct bp_encoder_control *cntl)
996 {
997 	struct bios_parser *bp = BP_FROM_DCB(dcb);
998 
999 	if (!bp->cmd_tbl.dig_encoder_control)
1000 		return BP_RESULT_FAILURE;
1001 
1002 	return bp->cmd_tbl.dig_encoder_control(bp, cntl);
1003 }
1004 
1005 static enum bp_result bios_parser_adjust_pixel_clock(
1006 	struct dc_bios *dcb,
1007 	struct bp_adjust_pixel_clock_parameters *bp_params)
1008 {
1009 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1010 
1011 	if (!bp->cmd_tbl.adjust_display_pll)
1012 		return BP_RESULT_FAILURE;
1013 
1014 	return bp->cmd_tbl.adjust_display_pll(bp, bp_params);
1015 }
1016 
1017 static enum bp_result bios_parser_set_pixel_clock(
1018 	struct dc_bios *dcb,
1019 	struct bp_pixel_clock_parameters *bp_params)
1020 {
1021 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1022 
1023 	if (!bp->cmd_tbl.set_pixel_clock)
1024 		return BP_RESULT_FAILURE;
1025 
1026 	return bp->cmd_tbl.set_pixel_clock(bp, bp_params);
1027 }
1028 
1029 static enum bp_result bios_parser_set_dce_clock(
1030 	struct dc_bios *dcb,
1031 	struct bp_set_dce_clock_parameters *bp_params)
1032 {
1033 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1034 
1035 	if (!bp->cmd_tbl.set_dce_clock)
1036 		return BP_RESULT_FAILURE;
1037 
1038 	return bp->cmd_tbl.set_dce_clock(bp, bp_params);
1039 }
1040 
1041 static enum bp_result bios_parser_enable_spread_spectrum_on_ppll(
1042 	struct dc_bios *dcb,
1043 	struct bp_spread_spectrum_parameters *bp_params,
1044 	bool enable)
1045 {
1046 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1047 
1048 	if (!bp->cmd_tbl.enable_spread_spectrum_on_ppll)
1049 		return BP_RESULT_FAILURE;
1050 
1051 	return bp->cmd_tbl.enable_spread_spectrum_on_ppll(
1052 			bp, bp_params, enable);
1053 
1054 }
1055 
1056 static enum bp_result bios_parser_program_crtc_timing(
1057 	struct dc_bios *dcb,
1058 	struct bp_hw_crtc_timing_parameters *bp_params)
1059 {
1060 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1061 
1062 	if (!bp->cmd_tbl.set_crtc_timing)
1063 		return BP_RESULT_FAILURE;
1064 
1065 	return bp->cmd_tbl.set_crtc_timing(bp, bp_params);
1066 }
1067 
1068 static enum bp_result bios_parser_program_display_engine_pll(
1069 	struct dc_bios *dcb,
1070 	struct bp_pixel_clock_parameters *bp_params)
1071 {
1072 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1073 
1074 	if (!bp->cmd_tbl.program_clock)
1075 		return BP_RESULT_FAILURE;
1076 
1077 	return bp->cmd_tbl.program_clock(bp, bp_params);
1078 
1079 }
1080 
1081 
1082 static enum bp_result bios_parser_enable_crtc(
1083 	struct dc_bios *dcb,
1084 	enum controller_id id,
1085 	bool enable)
1086 {
1087 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1088 
1089 	if (!bp->cmd_tbl.enable_crtc)
1090 		return BP_RESULT_FAILURE;
1091 
1092 	return bp->cmd_tbl.enable_crtc(bp, id, enable);
1093 }
1094 
1095 static enum bp_result bios_parser_crtc_source_select(
1096 	struct dc_bios *dcb,
1097 	struct bp_crtc_source_select *bp_params)
1098 {
1099 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1100 
1101 	if (!bp->cmd_tbl.select_crtc_source)
1102 		return BP_RESULT_FAILURE;
1103 
1104 	return bp->cmd_tbl.select_crtc_source(bp, bp_params);
1105 }
1106 
1107 static enum bp_result bios_parser_enable_disp_power_gating(
1108 	struct dc_bios *dcb,
1109 	enum controller_id controller_id,
1110 	enum bp_pipe_control_action action)
1111 {
1112 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1113 
1114 	if (!bp->cmd_tbl.enable_disp_power_gating)
1115 		return BP_RESULT_FAILURE;
1116 
1117 	return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id,
1118 		action);
1119 }
1120 
1121 static bool bios_parser_is_device_id_supported(
1122 	struct dc_bios *dcb,
1123 	struct device_id id)
1124 {
1125 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1126 
1127 	uint32_t mask = get_support_mask_for_device_id(id);
1128 
1129 	return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0;
1130 }
1131 
1132 static enum bp_result bios_parser_crt_control(
1133 	struct dc_bios *dcb,
1134 	enum engine_id engine_id,
1135 	bool enable,
1136 	uint32_t pixel_clock)
1137 {
1138 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1139 	uint8_t standard;
1140 
1141 	if (!bp->cmd_tbl.dac1_encoder_control &&
1142 		engine_id == ENGINE_ID_DACA)
1143 		return BP_RESULT_FAILURE;
1144 	if (!bp->cmd_tbl.dac2_encoder_control &&
1145 		engine_id == ENGINE_ID_DACB)
1146 		return BP_RESULT_FAILURE;
1147 	/* validate params */
1148 	switch (engine_id) {
1149 	case ENGINE_ID_DACA:
1150 	case ENGINE_ID_DACB:
1151 		break;
1152 	default:
1153 		/* unsupported engine */
1154 		return BP_RESULT_FAILURE;
1155 	}
1156 
1157 	standard = ATOM_DAC1_PS2; /* == ATOM_DAC2_PS2 */
1158 
1159 	if (enable) {
1160 		if (engine_id == ENGINE_ID_DACA) {
1161 			bp->cmd_tbl.dac1_encoder_control(bp, enable,
1162 				pixel_clock, standard);
1163 			if (bp->cmd_tbl.dac1_output_control != NULL)
1164 				bp->cmd_tbl.dac1_output_control(bp, enable);
1165 		} else {
1166 			bp->cmd_tbl.dac2_encoder_control(bp, enable,
1167 				pixel_clock, standard);
1168 			if (bp->cmd_tbl.dac2_output_control != NULL)
1169 				bp->cmd_tbl.dac2_output_control(bp, enable);
1170 		}
1171 	} else {
1172 		if (engine_id == ENGINE_ID_DACA) {
1173 			if (bp->cmd_tbl.dac1_output_control != NULL)
1174 				bp->cmd_tbl.dac1_output_control(bp, enable);
1175 			bp->cmd_tbl.dac1_encoder_control(bp, enable,
1176 				pixel_clock, standard);
1177 		} else {
1178 			if (bp->cmd_tbl.dac2_output_control != NULL)
1179 				bp->cmd_tbl.dac2_output_control(bp, enable);
1180 			bp->cmd_tbl.dac2_encoder_control(bp, enable,
1181 				pixel_clock, standard);
1182 		}
1183 	}
1184 
1185 	return BP_RESULT_OK;
1186 }
1187 
1188 static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
1189 	ATOM_OBJECT *object)
1190 {
1191 	ATOM_COMMON_RECORD_HEADER *header;
1192 	uint32_t offset;
1193 
1194 	if (!object) {
1195 		BREAK_TO_DEBUGGER(); /* Invalid object */
1196 		return NULL;
1197 	}
1198 
1199 	offset = le16_to_cpu(object->usRecordOffset)
1200 			+ bp->object_info_tbl_offset;
1201 
1202 	for (;;) {
1203 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
1204 
1205 		if (!header)
1206 			return NULL;
1207 
1208 		if (LAST_RECORD_TYPE == header->ucRecordType ||
1209 			!header->ucRecordSize)
1210 			break;
1211 
1212 		if (ATOM_HPD_INT_RECORD_TYPE == header->ucRecordType
1213 			&& sizeof(ATOM_HPD_INT_RECORD) <= header->ucRecordSize)
1214 			return (ATOM_HPD_INT_RECORD *) header;
1215 
1216 		offset += header->ucRecordSize;
1217 	}
1218 
1219 	return NULL;
1220 }
1221 
1222 /**
1223  * Get I2C information of input object id
1224  *
1225  * search all records to find the ATOM_I2C_RECORD_TYPE record IR
1226  */
1227 static ATOM_I2C_RECORD *get_i2c_record(
1228 	struct bios_parser *bp,
1229 	ATOM_OBJECT *object)
1230 {
1231 	uint32_t offset;
1232 	ATOM_COMMON_RECORD_HEADER *record_header;
1233 
1234 	if (!object) {
1235 		BREAK_TO_DEBUGGER();
1236 		/* Invalid object */
1237 		return NULL;
1238 	}
1239 
1240 	offset = le16_to_cpu(object->usRecordOffset)
1241 			+ bp->object_info_tbl_offset;
1242 
1243 	for (;;) {
1244 		record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
1245 
1246 		if (!record_header)
1247 			return NULL;
1248 
1249 		if (LAST_RECORD_TYPE == record_header->ucRecordType ||
1250 			0 == record_header->ucRecordSize)
1251 			break;
1252 
1253 		if (ATOM_I2C_RECORD_TYPE == record_header->ucRecordType &&
1254 			sizeof(ATOM_I2C_RECORD) <=
1255 			record_header->ucRecordSize) {
1256 			return (ATOM_I2C_RECORD *)record_header;
1257 		}
1258 
1259 		offset += record_header->ucRecordSize;
1260 	}
1261 
1262 	return NULL;
1263 }
1264 
1265 static enum bp_result get_ss_info_from_ss_info_table(
1266 	struct bios_parser *bp,
1267 	uint32_t id,
1268 	struct spread_spectrum_info *ss_info);
1269 static enum bp_result get_ss_info_from_tbl(
1270 	struct bios_parser *bp,
1271 	uint32_t id,
1272 	struct spread_spectrum_info *ss_info);
1273 /**
1274  * bios_parser_get_spread_spectrum_info
1275  * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or
1276  * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info
1277  * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info ver 3.1,
1278  * there is only one entry for each signal /ss id.  However, there is
1279  * no planning of supporting multiple spread Sprectum entry for EverGreen
1280  * @param [in] this
1281  * @param [in] signal, ASSignalType to be converted to info index
1282  * @param [in] index, number of entries that match the converted info index
1283  * @param [out] ss_info, sprectrum information structure,
1284  * @return Bios parser result code
1285  */
1286 static enum bp_result bios_parser_get_spread_spectrum_info(
1287 	struct dc_bios *dcb,
1288 	enum as_signal_type signal,
1289 	uint32_t index,
1290 	struct spread_spectrum_info *ss_info)
1291 {
1292 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1293 	enum bp_result result = BP_RESULT_UNSUPPORTED;
1294 	uint32_t clk_id_ss = 0;
1295 	ATOM_COMMON_TABLE_HEADER *header;
1296 	struct atom_data_revision tbl_revision;
1297 
1298 	if (!ss_info) /* check for bad input */
1299 		return BP_RESULT_BADINPUT;
1300 	/* signal translation */
1301 	clk_id_ss = signal_to_ss_id(signal);
1302 
1303 	if (!DATA_TABLES(ASIC_InternalSS_Info))
1304 		if (!index)
1305 			return get_ss_info_from_ss_info_table(bp, clk_id_ss,
1306 				ss_info);
1307 
1308 	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
1309 		DATA_TABLES(ASIC_InternalSS_Info));
1310 	get_atom_data_table_revision(header, &tbl_revision);
1311 
1312 	switch (tbl_revision.major) {
1313 	case 2:
1314 		switch (tbl_revision.minor) {
1315 		case 1:
1316 			/* there can not be more then one entry for Internal
1317 			 * SS Info table version 2.1 */
1318 			if (!index)
1319 				return get_ss_info_from_tbl(bp, clk_id_ss,
1320 						ss_info);
1321 			break;
1322 		default:
1323 			break;
1324 		}
1325 		break;
1326 
1327 	case 3:
1328 		switch (tbl_revision.minor) {
1329 		case 1:
1330 			return get_ss_info_v3_1(bp, clk_id_ss, index, ss_info);
1331 		default:
1332 			break;
1333 		}
1334 		break;
1335 	default:
1336 		break;
1337 	}
1338 	/* there can not be more then one entry for SS Info table */
1339 	return result;
1340 }
1341 
1342 static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
1343 	struct bios_parser *bp,
1344 	uint32_t id,
1345 	struct spread_spectrum_info *info);
1346 
1347 /**
1348  * get_ss_info_from_table
1349  * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
1350  * SS_Info table from the VBIOS
1351  * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or
1352  * SS_Info.
1353  *
1354  * @param this
1355  * @param id, spread sprectrum info index
1356  * @param pSSinfo, sprectrum information structure,
1357  * @return Bios parser result code
1358  */
1359 static enum bp_result get_ss_info_from_tbl(
1360 	struct bios_parser *bp,
1361 	uint32_t id,
1362 	struct spread_spectrum_info *ss_info)
1363 {
1364 	if (!ss_info) /* check for bad input, if ss_info is not NULL */
1365 		return BP_RESULT_BADINPUT;
1366 	/* for SS_Info table only support DP and LVDS */
1367 	if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
1368 		return get_ss_info_from_ss_info_table(bp, id, ss_info);
1369 	else
1370 		return get_ss_info_from_internal_ss_info_tbl_V2_1(bp, id,
1371 			ss_info);
1372 }
1373 
1374 /**
1375  * get_ss_info_from_internal_ss_info_tbl_V2_1
1376  * Get spread sprectrum information from the ASIC_InternalSS_Info table Ver 2.1
1377  * from the VBIOS
1378  * There will not be multiple entry for Ver 2.1
1379  *
1380  * @param id, spread sprectrum info index
1381  * @param pSSinfo, sprectrum information structure,
1382  * @return Bios parser result code
1383  */
1384 static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
1385 	struct bios_parser *bp,
1386 	uint32_t id,
1387 	struct spread_spectrum_info *info)
1388 {
1389 	enum bp_result result = BP_RESULT_UNSUPPORTED;
1390 	ATOM_ASIC_INTERNAL_SS_INFO_V2 *header;
1391 	ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
1392 	uint32_t tbl_size, i;
1393 
1394 	if (!DATA_TABLES(ASIC_InternalSS_Info))
1395 		return result;
1396 
1397 	header = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
1398 		DATA_TABLES(ASIC_InternalSS_Info));
1399 
1400 	memset(info, 0, sizeof(struct spread_spectrum_info));
1401 
1402 	tbl_size = (le16_to_cpu(header->sHeader.usStructureSize)
1403 			- sizeof(ATOM_COMMON_TABLE_HEADER))
1404 					/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
1405 
1406 	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
1407 					&(header->asSpreadSpectrum[0]);
1408 	for (i = 0; i < tbl_size; i++) {
1409 		result = BP_RESULT_NORECORD;
1410 
1411 		if (tbl[i].ucClockIndication != (uint8_t)id)
1412 			continue;
1413 
1414 		if (ATOM_EXTERNAL_SS_MASK
1415 			& tbl[i].ucSpreadSpectrumMode) {
1416 			info->type.EXTERNAL = true;
1417 		}
1418 		if (ATOM_SS_CENTRE_SPREAD_MODE_MASK
1419 			& tbl[i].ucSpreadSpectrumMode) {
1420 			info->type.CENTER_MODE = true;
1421 		}
1422 		info->type.STEP_AND_DELAY_INFO = false;
1423 		/* convert [10KHz] into [KHz] */
1424 		info->target_clock_range =
1425 			le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
1426 		info->spread_spectrum_percentage =
1427 			(uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
1428 		info->spread_spectrum_range =
1429 			(uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
1430 		result = BP_RESULT_OK;
1431 		break;
1432 	}
1433 
1434 	return result;
1435 
1436 }
1437 
1438 /**
1439  * get_ss_info_from_ss_info_table
1440  * Get spread sprectrum information from the SS_Info table from the VBIOS
1441  * if the pointer to info is NULL, indicate the caller what to know the number
1442  * of entries that matches the id
1443  * for, the SS_Info table, there should not be more than 1 entry match.
1444  *
1445  * @param [in] id, spread sprectrum id
1446  * @param [out] pSSinfo, sprectrum information structure,
1447  * @return Bios parser result code
1448  */
1449 static enum bp_result get_ss_info_from_ss_info_table(
1450 	struct bios_parser *bp,
1451 	uint32_t id,
1452 	struct spread_spectrum_info *ss_info)
1453 {
1454 	enum bp_result result = BP_RESULT_UNSUPPORTED;
1455 	ATOM_SPREAD_SPECTRUM_INFO *tbl;
1456 	ATOM_COMMON_TABLE_HEADER *header;
1457 	uint32_t table_size;
1458 	uint32_t i;
1459 	uint32_t id_local = SS_ID_UNKNOWN;
1460 	struct atom_data_revision revision;
1461 
1462 	/* exist of the SS_Info table */
1463 	/* check for bad input, pSSinfo can not be NULL */
1464 	if (!DATA_TABLES(SS_Info) || !ss_info)
1465 		return result;
1466 
1467 	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(SS_Info));
1468 	get_atom_data_table_revision(header, &revision);
1469 
1470 	tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, DATA_TABLES(SS_Info));
1471 
1472 	if (1 != revision.major || 2 > revision.minor)
1473 		return result;
1474 
1475 	/* have to convert from Internal_SS format to SS_Info format */
1476 	switch (id) {
1477 	case ASIC_INTERNAL_SS_ON_DP:
1478 		id_local = SS_ID_DP1;
1479 		break;
1480 	case ASIC_INTERNAL_SS_ON_LVDS:
1481 	{
1482 		struct embedded_panel_info panel_info;
1483 
1484 		if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
1485 				== BP_RESULT_OK)
1486 			id_local = panel_info.ss_id;
1487 		break;
1488 	}
1489 	default:
1490 		break;
1491 	}
1492 
1493 	if (id_local == SS_ID_UNKNOWN)
1494 		return result;
1495 
1496 	table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
1497 			sizeof(ATOM_COMMON_TABLE_HEADER)) /
1498 					sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
1499 
1500 	for (i = 0; i < table_size; i++) {
1501 		if (id_local != (uint32_t)tbl->asSS_Info[i].ucSS_Id)
1502 			continue;
1503 
1504 		memset(ss_info, 0, sizeof(struct spread_spectrum_info));
1505 
1506 		if (ATOM_EXTERNAL_SS_MASK &
1507 				tbl->asSS_Info[i].ucSpreadSpectrumType)
1508 			ss_info->type.EXTERNAL = true;
1509 
1510 		if (ATOM_SS_CENTRE_SPREAD_MODE_MASK &
1511 				tbl->asSS_Info[i].ucSpreadSpectrumType)
1512 			ss_info->type.CENTER_MODE = true;
1513 
1514 		ss_info->type.STEP_AND_DELAY_INFO = true;
1515 		ss_info->spread_spectrum_percentage =
1516 			(uint32_t)le16_to_cpu(tbl->asSS_Info[i].usSpreadSpectrumPercentage);
1517 		ss_info->step_and_delay_info.step = tbl->asSS_Info[i].ucSS_Step;
1518 		ss_info->step_and_delay_info.delay =
1519 			tbl->asSS_Info[i].ucSS_Delay;
1520 		ss_info->step_and_delay_info.recommended_ref_div =
1521 			tbl->asSS_Info[i].ucRecommendedRef_Div;
1522 		ss_info->spread_spectrum_range =
1523 			(uint32_t)tbl->asSS_Info[i].ucSS_Range * 10000;
1524 
1525 		/* there will be only one entry for each display type in SS_info
1526 		 * table */
1527 		result = BP_RESULT_OK;
1528 		break;
1529 	}
1530 
1531 	return result;
1532 }
1533 static enum bp_result get_embedded_panel_info_v1_2(
1534 	struct bios_parser *bp,
1535 	struct embedded_panel_info *info);
1536 static enum bp_result get_embedded_panel_info_v1_3(
1537 	struct bios_parser *bp,
1538 	struct embedded_panel_info *info);
1539 
1540 static enum bp_result bios_parser_get_embedded_panel_info(
1541 	struct dc_bios *dcb,
1542 	struct embedded_panel_info *info)
1543 {
1544 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1545 	ATOM_COMMON_TABLE_HEADER *hdr;
1546 
1547 	if (!DATA_TABLES(LCD_Info))
1548 		return BP_RESULT_FAILURE;
1549 
1550 	hdr = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(LCD_Info));
1551 
1552 	if (!hdr)
1553 		return BP_RESULT_BADBIOSTABLE;
1554 
1555 	switch (hdr->ucTableFormatRevision) {
1556 	case 1:
1557 		switch (hdr->ucTableContentRevision) {
1558 		case 0:
1559 		case 1:
1560 		case 2:
1561 			return get_embedded_panel_info_v1_2(bp, info);
1562 		case 3:
1563 			return get_embedded_panel_info_v1_3(bp, info);
1564 		default:
1565 			break;
1566 		}
1567 	default:
1568 		break;
1569 	}
1570 
1571 	return BP_RESULT_FAILURE;
1572 }
1573 
1574 static enum bp_result get_embedded_panel_info_v1_2(
1575 	struct bios_parser *bp,
1576 	struct embedded_panel_info *info)
1577 {
1578 	ATOM_LVDS_INFO_V12 *lvds;
1579 
1580 	if (!info)
1581 		return BP_RESULT_BADINPUT;
1582 
1583 	if (!DATA_TABLES(LVDS_Info))
1584 		return BP_RESULT_UNSUPPORTED;
1585 
1586 	lvds =
1587 		GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info));
1588 
1589 	if (!lvds)
1590 		return BP_RESULT_BADBIOSTABLE;
1591 
1592 	if (1 != lvds->sHeader.ucTableFormatRevision
1593 		|| 2 > lvds->sHeader.ucTableContentRevision)
1594 		return BP_RESULT_UNSUPPORTED;
1595 
1596 	memset(info, 0, sizeof(struct embedded_panel_info));
1597 
1598 	/* We need to convert from 10KHz units into KHz units*/
1599 	info->lcd_timing.pixel_clk =
1600 		le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
1601 	/* usHActive does not include borders, according to VBIOS team*/
1602 	info->lcd_timing.horizontal_addressable =
1603 		le16_to_cpu(lvds->sLCDTiming.usHActive);
1604 	/* usHBlanking_Time includes borders, so we should really be subtracting
1605 	 * borders duing this translation, but LVDS generally*/
1606 	/* doesn't have borders, so we should be okay leaving this as is for
1607 	 * now.  May need to revisit if we ever have LVDS with borders*/
1608 	info->lcd_timing.horizontal_blanking_time =
1609 			le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
1610 	/* usVActive does not include borders, according to VBIOS team*/
1611 	info->lcd_timing.vertical_addressable =
1612 			le16_to_cpu(lvds->sLCDTiming.usVActive);
1613 	/* usVBlanking_Time includes borders, so we should really be subtracting
1614 	 * borders duing this translation, but LVDS generally*/
1615 	/* doesn't have borders, so we should be okay leaving this as is for
1616 	 * now. May need to revisit if we ever have LVDS with borders*/
1617 	info->lcd_timing.vertical_blanking_time =
1618 		le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
1619 	info->lcd_timing.horizontal_sync_offset =
1620 		le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
1621 	info->lcd_timing.horizontal_sync_width =
1622 		le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
1623 	info->lcd_timing.vertical_sync_offset =
1624 		le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
1625 	info->lcd_timing.vertical_sync_width =
1626 		le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
1627 	info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
1628 	info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
1629 	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
1630 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
1631 	info->lcd_timing.misc_info.H_SYNC_POLARITY =
1632 		~(uint32_t)
1633 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
1634 	info->lcd_timing.misc_info.V_SYNC_POLARITY =
1635 		~(uint32_t)
1636 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
1637 	info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
1638 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
1639 	info->lcd_timing.misc_info.H_REPLICATION_BY2 =
1640 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
1641 	info->lcd_timing.misc_info.V_REPLICATION_BY2 =
1642 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
1643 	info->lcd_timing.misc_info.COMPOSITE_SYNC =
1644 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
1645 	info->lcd_timing.misc_info.INTERLACE =
1646 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
1647 	info->lcd_timing.misc_info.DOUBLE_CLOCK =
1648 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
1649 	info->ss_id = lvds->ucSS_Id;
1650 
1651 	{
1652 		uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate);
1653 		/* Get minimum supported refresh rate*/
1654 		if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
1655 			info->supported_rr.REFRESH_RATE_30HZ = 1;
1656 		else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
1657 			info->supported_rr.REFRESH_RATE_40HZ = 1;
1658 		else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
1659 			info->supported_rr.REFRESH_RATE_48HZ = 1;
1660 		else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
1661 			info->supported_rr.REFRESH_RATE_50HZ = 1;
1662 		else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
1663 			info->supported_rr.REFRESH_RATE_60HZ = 1;
1664 	}
1665 
1666 	/*Drr panel support can be reported by VBIOS*/
1667 	if (LCDPANEL_CAP_DRR_SUPPORTED
1668 			& lvds->ucLCDPanel_SpecialHandlingCap)
1669 		info->drr_enabled = 1;
1670 
1671 	if (ATOM_PANEL_MISC_DUAL & lvds->ucLVDS_Misc)
1672 		info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
1673 
1674 	if (ATOM_PANEL_MISC_888RGB & lvds->ucLVDS_Misc)
1675 		info->lcd_timing.misc_info.RGB888 = true;
1676 
1677 	info->lcd_timing.misc_info.GREY_LEVEL =
1678 		(uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL &
1679 			lvds->ucLVDS_Misc) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT;
1680 
1681 	if (ATOM_PANEL_MISC_SPATIAL & lvds->ucLVDS_Misc)
1682 		info->lcd_timing.misc_info.SPATIAL = true;
1683 
1684 	if (ATOM_PANEL_MISC_TEMPORAL & lvds->ucLVDS_Misc)
1685 		info->lcd_timing.misc_info.TEMPORAL = true;
1686 
1687 	if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc)
1688 		info->lcd_timing.misc_info.API_ENABLED = true;
1689 
1690 	return BP_RESULT_OK;
1691 }
1692 
1693 static enum bp_result get_embedded_panel_info_v1_3(
1694 	struct bios_parser *bp,
1695 	struct embedded_panel_info *info)
1696 {
1697 	ATOM_LCD_INFO_V13 *lvds;
1698 
1699 	if (!info)
1700 		return BP_RESULT_BADINPUT;
1701 
1702 	if (!DATA_TABLES(LCD_Info))
1703 		return BP_RESULT_UNSUPPORTED;
1704 
1705 	lvds = GET_IMAGE(ATOM_LCD_INFO_V13, DATA_TABLES(LCD_Info));
1706 
1707 	if (!lvds)
1708 		return BP_RESULT_BADBIOSTABLE;
1709 
1710 	if (!((1 == lvds->sHeader.ucTableFormatRevision)
1711 			&& (3 <= lvds->sHeader.ucTableContentRevision)))
1712 		return BP_RESULT_UNSUPPORTED;
1713 
1714 	memset(info, 0, sizeof(struct embedded_panel_info));
1715 
1716 	/* We need to convert from 10KHz units into KHz units */
1717 	info->lcd_timing.pixel_clk =
1718 			le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
1719 	/* usHActive does not include borders, according to VBIOS team */
1720 	info->lcd_timing.horizontal_addressable =
1721 			le16_to_cpu(lvds->sLCDTiming.usHActive);
1722 	/* usHBlanking_Time includes borders, so we should really be subtracting
1723 	 * borders duing this translation, but LVDS generally*/
1724 	/* doesn't have borders, so we should be okay leaving this as is for
1725 	 * now.  May need to revisit if we ever have LVDS with borders*/
1726 	info->lcd_timing.horizontal_blanking_time =
1727 		le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
1728 	/* usVActive does not include borders, according to VBIOS team*/
1729 	info->lcd_timing.vertical_addressable =
1730 		le16_to_cpu(lvds->sLCDTiming.usVActive);
1731 	/* usVBlanking_Time includes borders, so we should really be subtracting
1732 	 * borders duing this translation, but LVDS generally*/
1733 	/* doesn't have borders, so we should be okay leaving this as is for
1734 	 * now. May need to revisit if we ever have LVDS with borders*/
1735 	info->lcd_timing.vertical_blanking_time =
1736 		le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
1737 	info->lcd_timing.horizontal_sync_offset =
1738 		le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
1739 	info->lcd_timing.horizontal_sync_width =
1740 		le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
1741 	info->lcd_timing.vertical_sync_offset =
1742 		le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
1743 	info->lcd_timing.vertical_sync_width =
1744 		le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
1745 	info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
1746 	info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
1747 	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
1748 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
1749 	info->lcd_timing.misc_info.H_SYNC_POLARITY =
1750 		~(uint32_t)
1751 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
1752 	info->lcd_timing.misc_info.V_SYNC_POLARITY =
1753 		~(uint32_t)
1754 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
1755 	info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
1756 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
1757 	info->lcd_timing.misc_info.H_REPLICATION_BY2 =
1758 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
1759 	info->lcd_timing.misc_info.V_REPLICATION_BY2 =
1760 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
1761 	info->lcd_timing.misc_info.COMPOSITE_SYNC =
1762 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
1763 	info->lcd_timing.misc_info.INTERLACE =
1764 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
1765 	info->lcd_timing.misc_info.DOUBLE_CLOCK =
1766 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
1767 	info->ss_id = lvds->ucSS_Id;
1768 
1769 	/* Drr panel support can be reported by VBIOS*/
1770 	if (LCDPANEL_CAP_V13_DRR_SUPPORTED
1771 			& lvds->ucLCDPanel_SpecialHandlingCap)
1772 		info->drr_enabled = 1;
1773 
1774 	/* Get supported refresh rate*/
1775 	if (info->drr_enabled == 1) {
1776 		uint8_t min_rr =
1777 				lvds->sRefreshRateSupport.ucMinRefreshRateForDRR;
1778 		uint8_t rr = lvds->sRefreshRateSupport.ucSupportedRefreshRate;
1779 
1780 		if (min_rr != 0) {
1781 			if (SUPPORTED_LCD_REFRESHRATE_30Hz & min_rr)
1782 				info->supported_rr.REFRESH_RATE_30HZ = 1;
1783 			else if (SUPPORTED_LCD_REFRESHRATE_40Hz & min_rr)
1784 				info->supported_rr.REFRESH_RATE_40HZ = 1;
1785 			else if (SUPPORTED_LCD_REFRESHRATE_48Hz & min_rr)
1786 				info->supported_rr.REFRESH_RATE_48HZ = 1;
1787 			else if (SUPPORTED_LCD_REFRESHRATE_50Hz & min_rr)
1788 				info->supported_rr.REFRESH_RATE_50HZ = 1;
1789 			else if (SUPPORTED_LCD_REFRESHRATE_60Hz & min_rr)
1790 				info->supported_rr.REFRESH_RATE_60HZ = 1;
1791 		} else {
1792 			if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
1793 				info->supported_rr.REFRESH_RATE_30HZ = 1;
1794 			else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
1795 				info->supported_rr.REFRESH_RATE_40HZ = 1;
1796 			else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
1797 				info->supported_rr.REFRESH_RATE_48HZ = 1;
1798 			else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
1799 				info->supported_rr.REFRESH_RATE_50HZ = 1;
1800 			else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
1801 				info->supported_rr.REFRESH_RATE_60HZ = 1;
1802 		}
1803 	}
1804 
1805 	if (ATOM_PANEL_MISC_V13_DUAL & lvds->ucLCD_Misc)
1806 		info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
1807 
1808 	if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR & lvds->ucLCD_Misc)
1809 		info->lcd_timing.misc_info.RGB888 = true;
1810 
1811 	info->lcd_timing.misc_info.GREY_LEVEL =
1812 			(uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL &
1813 				lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT;
1814 
1815 	return BP_RESULT_OK;
1816 }
1817 
1818 /**
1819  * bios_parser_get_encoder_cap_info
1820  *
1821  * @brief
1822  *  Get encoder capability information of input object id
1823  *
1824  * @param object_id, Object id
1825  * @param object_id, encoder cap information structure
1826  *
1827  * @return Bios parser result code
1828  *
1829  */
1830 static enum bp_result bios_parser_get_encoder_cap_info(
1831 	struct dc_bios *dcb,
1832 	struct graphics_object_id object_id,
1833 	struct bp_encoder_cap_info *info)
1834 {
1835 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1836 	ATOM_OBJECT *object;
1837 	ATOM_ENCODER_CAP_RECORD_V2 *record = NULL;
1838 
1839 	if (!info)
1840 		return BP_RESULT_BADINPUT;
1841 
1842 	object = get_bios_object(bp, object_id);
1843 
1844 	if (!object)
1845 		return BP_RESULT_BADINPUT;
1846 
1847 	record = get_encoder_cap_record(bp, object);
1848 	if (!record)
1849 		return BP_RESULT_NORECORD;
1850 
1851 	info->DP_HBR2_EN = record->usHBR2En;
1852 	info->DP_HBR3_EN = record->usHBR3En;
1853 	info->HDMI_6GB_EN = record->usHDMI6GEn;
1854 	return BP_RESULT_OK;
1855 }
1856 
1857 /**
1858  * get_encoder_cap_record
1859  *
1860  * @brief
1861  *  Get encoder cap record for the object
1862  *
1863  * @param object, ATOM object
1864  *
1865  * @return atom encoder cap record
1866  *
1867  * @note
1868  *  search all records to find the ATOM_ENCODER_CAP_RECORD_V2 record
1869  */
1870 static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
1871 	struct bios_parser *bp,
1872 	ATOM_OBJECT *object)
1873 {
1874 	ATOM_COMMON_RECORD_HEADER *header;
1875 	uint32_t offset;
1876 
1877 	if (!object) {
1878 		BREAK_TO_DEBUGGER(); /* Invalid object */
1879 		return NULL;
1880 	}
1881 
1882 	offset = le16_to_cpu(object->usRecordOffset)
1883 					+ bp->object_info_tbl_offset;
1884 
1885 	for (;;) {
1886 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
1887 
1888 		if (!header)
1889 			return NULL;
1890 
1891 		offset += header->ucRecordSize;
1892 
1893 		if (LAST_RECORD_TYPE == header->ucRecordType ||
1894 				!header->ucRecordSize)
1895 			break;
1896 
1897 		if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType)
1898 			continue;
1899 
1900 		if (sizeof(ATOM_ENCODER_CAP_RECORD_V2) <= header->ucRecordSize)
1901 			return (ATOM_ENCODER_CAP_RECORD_V2 *)header;
1902 	}
1903 
1904 	return NULL;
1905 }
1906 
1907 static uint32_t get_ss_entry_number(
1908 	struct bios_parser *bp,
1909 	uint32_t id);
1910 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
1911 	struct bios_parser *bp,
1912 	uint32_t id);
1913 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1914 	struct bios_parser *bp,
1915 	uint32_t id);
1916 static uint32_t get_ss_entry_number_from_ss_info_tbl(
1917 	struct bios_parser *bp,
1918 	uint32_t id);
1919 
1920 /**
1921  * BiosParserObject::GetNumberofSpreadSpectrumEntry
1922  * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from
1923  * the VBIOS that match the SSid (to be converted from signal)
1924  *
1925  * @param[in] signal, ASSignalType to be converted to SSid
1926  * @return number of SS Entry that match the signal
1927  */
1928 static uint32_t bios_parser_get_ss_entry_number(
1929 	struct dc_bios *dcb,
1930 	enum as_signal_type signal)
1931 {
1932 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1933 	uint32_t ss_id = 0;
1934 	ATOM_COMMON_TABLE_HEADER *header;
1935 	struct atom_data_revision revision;
1936 
1937 	ss_id = signal_to_ss_id(signal);
1938 
1939 	if (!DATA_TABLES(ASIC_InternalSS_Info))
1940 		return get_ss_entry_number_from_ss_info_tbl(bp, ss_id);
1941 
1942 	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
1943 			DATA_TABLES(ASIC_InternalSS_Info));
1944 	get_atom_data_table_revision(header, &revision);
1945 
1946 	switch (revision.major) {
1947 	case 2:
1948 		switch (revision.minor) {
1949 		case 1:
1950 			return get_ss_entry_number(bp, ss_id);
1951 		default:
1952 			break;
1953 		}
1954 		break;
1955 	case 3:
1956 		switch (revision.minor) {
1957 		case 1:
1958 			return
1959 				get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1960 						bp, ss_id);
1961 		default:
1962 			break;
1963 		}
1964 		break;
1965 	default:
1966 		break;
1967 	}
1968 
1969 	return 0;
1970 }
1971 
1972 /**
1973  * get_ss_entry_number_from_ss_info_tbl
1974  * Get Number of spread spectrum entry from the SS_Info table from the VBIOS.
1975  *
1976  * @note There can only be one entry for each id for SS_Info Table
1977  *
1978  * @param [in] id, spread spectrum id
1979  * @return number of SS Entry that match the id
1980  */
1981 static uint32_t get_ss_entry_number_from_ss_info_tbl(
1982 	struct bios_parser *bp,
1983 	uint32_t id)
1984 {
1985 	ATOM_SPREAD_SPECTRUM_INFO *tbl;
1986 	ATOM_COMMON_TABLE_HEADER *header;
1987 	uint32_t table_size;
1988 	uint32_t i;
1989 	uint32_t number = 0;
1990 	uint32_t id_local = SS_ID_UNKNOWN;
1991 	struct atom_data_revision revision;
1992 
1993 	/* SS_Info table exist */
1994 	if (!DATA_TABLES(SS_Info))
1995 		return number;
1996 
1997 	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
1998 			DATA_TABLES(SS_Info));
1999 	get_atom_data_table_revision(header, &revision);
2000 
2001 	tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO,
2002 			DATA_TABLES(SS_Info));
2003 
2004 	if (1 != revision.major || 2 > revision.minor)
2005 		return number;
2006 
2007 	/* have to convert from Internal_SS format to SS_Info format */
2008 	switch (id) {
2009 	case ASIC_INTERNAL_SS_ON_DP:
2010 		id_local = SS_ID_DP1;
2011 		break;
2012 	case ASIC_INTERNAL_SS_ON_LVDS: {
2013 		struct embedded_panel_info panel_info;
2014 
2015 		if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
2016 				== BP_RESULT_OK)
2017 			id_local = panel_info.ss_id;
2018 		break;
2019 	}
2020 	default:
2021 		break;
2022 	}
2023 
2024 	if (id_local == SS_ID_UNKNOWN)
2025 		return number;
2026 
2027 	table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
2028 			sizeof(ATOM_COMMON_TABLE_HEADER)) /
2029 					sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
2030 
2031 	for (i = 0; i < table_size; i++)
2032 		if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) {
2033 			number = 1;
2034 			break;
2035 		}
2036 
2037 	return number;
2038 }
2039 
2040 /**
2041  * get_ss_entry_number
2042  * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
2043  * SS_Info table from the VBIOS
2044  * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or
2045  * SS_Info.
2046  *
2047  * @param id, spread sprectrum info index
2048  * @return Bios parser result code
2049  */
2050 static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id)
2051 {
2052 	if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
2053 		return get_ss_entry_number_from_ss_info_tbl(bp, id);
2054 
2055 	return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id);
2056 }
2057 
2058 /**
2059  * get_ss_entry_number_from_internal_ss_info_tbl_v2_1
2060  * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table
2061  * Ver 2.1 from the VBIOS
2062  * There will not be multiple entry for Ver 2.1
2063  *
2064  * @param id, spread sprectrum info index
2065  * @return number of SS Entry that match the id
2066  */
2067 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
2068 	struct bios_parser *bp,
2069 	uint32_t id)
2070 {
2071 	ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include;
2072 	ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
2073 	uint32_t size;
2074 	uint32_t i;
2075 
2076 	if (!DATA_TABLES(ASIC_InternalSS_Info))
2077 		return 0;
2078 
2079 	header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
2080 			DATA_TABLES(ASIC_InternalSS_Info));
2081 
2082 	size = (le16_to_cpu(header_include->sHeader.usStructureSize)
2083 			- sizeof(ATOM_COMMON_TABLE_HEADER))
2084 						/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
2085 
2086 	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
2087 				&header_include->asSpreadSpectrum[0];
2088 	for (i = 0; i < size; i++)
2089 		if (tbl[i].ucClockIndication == (uint8_t)id)
2090 			return 1;
2091 
2092 	return 0;
2093 }
2094 /**
2095  * get_ss_entry_number_from_internal_ss_info_table_V3_1
2096  * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of
2097  * the VBIOS that matches id
2098  *
2099  * @param[in]  id, spread sprectrum id
2100  * @return number of SS Entry that match the id
2101  */
2102 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
2103 	struct bios_parser *bp,
2104 	uint32_t id)
2105 {
2106 	uint32_t number = 0;
2107 	ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include;
2108 	ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
2109 	uint32_t size;
2110 	uint32_t i;
2111 
2112 	if (!DATA_TABLES(ASIC_InternalSS_Info))
2113 		return number;
2114 
2115 	header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
2116 			DATA_TABLES(ASIC_InternalSS_Info));
2117 	size = (le16_to_cpu(header_include->sHeader.usStructureSize) -
2118 			sizeof(ATOM_COMMON_TABLE_HEADER)) /
2119 					sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
2120 
2121 	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
2122 				&header_include->asSpreadSpectrum[0];
2123 
2124 	for (i = 0; i < size; i++)
2125 		if (tbl[i].ucClockIndication == (uint8_t)id)
2126 			number++;
2127 
2128 	return number;
2129 }
2130 
2131 /**
2132  * bios_parser_get_gpio_pin_info
2133  * Get GpioPin information of input gpio id
2134  *
2135  * @param gpio_id, GPIO ID
2136  * @param info, GpioPin information structure
2137  * @return Bios parser result code
2138  * @note
2139  *  to get the GPIO PIN INFO, we need:
2140  *  1. get the GPIO_ID from other object table, see GetHPDInfo()
2141  *  2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA
2142  *  offset/mask
2143  */
2144 static enum bp_result bios_parser_get_gpio_pin_info(
2145 	struct dc_bios *dcb,
2146 	uint32_t gpio_id,
2147 	struct gpio_pin_info *info)
2148 {
2149 	struct bios_parser *bp = BP_FROM_DCB(dcb);
2150 	ATOM_GPIO_PIN_LUT *header;
2151 	uint32_t count = 0;
2152 	uint32_t i = 0;
2153 
2154 	if (!DATA_TABLES(GPIO_Pin_LUT))
2155 		return BP_RESULT_BADBIOSTABLE;
2156 
2157 	header = GET_IMAGE(ATOM_GPIO_PIN_LUT, DATA_TABLES(GPIO_Pin_LUT));
2158 	if (!header)
2159 		return BP_RESULT_BADBIOSTABLE;
2160 
2161 	if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_PIN_LUT)
2162 			> le16_to_cpu(header->sHeader.usStructureSize))
2163 		return BP_RESULT_BADBIOSTABLE;
2164 
2165 	if (1 != header->sHeader.ucTableContentRevision)
2166 		return BP_RESULT_UNSUPPORTED;
2167 
2168 	count = (le16_to_cpu(header->sHeader.usStructureSize)
2169 			- sizeof(ATOM_COMMON_TABLE_HEADER))
2170 				/ sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
2171 	for (i = 0; i < count; ++i) {
2172 		if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id)
2173 			continue;
2174 
2175 		info->offset =
2176 			(uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex);
2177 		info->offset_y = info->offset + 2;
2178 		info->offset_en = info->offset + 1;
2179 		info->offset_mask = info->offset - 1;
2180 
2181 		info->mask = (uint32_t) (1 <<
2182 			header->asGPIO_Pin[i].ucGpioPinBitShift);
2183 		info->mask_y = info->mask + 2;
2184 		info->mask_en = info->mask + 1;
2185 		info->mask_mask = info->mask - 1;
2186 
2187 		return BP_RESULT_OK;
2188 	}
2189 
2190 	return BP_RESULT_NORECORD;
2191 }
2192 
2193 static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
2194 	ATOM_I2C_RECORD *record,
2195 	struct graphics_object_i2c_info *info)
2196 {
2197 	ATOM_GPIO_I2C_INFO *header;
2198 	uint32_t count = 0;
2199 
2200 	if (!info)
2201 		return BP_RESULT_BADINPUT;
2202 
2203 	/* get the GPIO_I2C info */
2204 	if (!DATA_TABLES(GPIO_I2C_Info))
2205 		return BP_RESULT_BADBIOSTABLE;
2206 
2207 	header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info));
2208 	if (!header)
2209 		return BP_RESULT_BADBIOSTABLE;
2210 
2211 	if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT)
2212 			> le16_to_cpu(header->sHeader.usStructureSize))
2213 		return BP_RESULT_BADBIOSTABLE;
2214 
2215 	if (1 != header->sHeader.ucTableContentRevision)
2216 		return BP_RESULT_UNSUPPORTED;
2217 
2218 	/* get data count */
2219 	count = (le16_to_cpu(header->sHeader.usStructureSize)
2220 			- sizeof(ATOM_COMMON_TABLE_HEADER))
2221 				/ sizeof(ATOM_GPIO_I2C_ASSIGMENT);
2222 	if (count < record->sucI2cId.bfI2C_LineMux)
2223 		return BP_RESULT_BADBIOSTABLE;
2224 
2225 	/* get the GPIO_I2C_INFO */
2226 	info->i2c_hw_assist = record->sucI2cId.bfHW_Capable;
2227 	info->i2c_line = record->sucI2cId.bfI2C_LineMux;
2228 	info->i2c_engine_id = record->sucI2cId.bfHW_EngineID;
2229 	info->i2c_slave_address = record->ucI2CAddr;
2230 
2231 	info->gpio_info.clk_mask_register_index =
2232 			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex);
2233 	info->gpio_info.clk_en_register_index =
2234 			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex);
2235 	info->gpio_info.clk_y_register_index =
2236 			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex);
2237 	info->gpio_info.clk_a_register_index =
2238 			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex);
2239 	info->gpio_info.data_mask_register_index =
2240 			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex);
2241 	info->gpio_info.data_en_register_index =
2242 			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex);
2243 	info->gpio_info.data_y_register_index =
2244 			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex);
2245 	info->gpio_info.data_a_register_index =
2246 			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex);
2247 
2248 	info->gpio_info.clk_mask_shift =
2249 			header->asGPIO_Info[info->i2c_line].ucClkMaskShift;
2250 	info->gpio_info.clk_en_shift =
2251 			header->asGPIO_Info[info->i2c_line].ucClkEnShift;
2252 	info->gpio_info.clk_y_shift =
2253 			header->asGPIO_Info[info->i2c_line].ucClkY_Shift;
2254 	info->gpio_info.clk_a_shift =
2255 			header->asGPIO_Info[info->i2c_line].ucClkA_Shift;
2256 	info->gpio_info.data_mask_shift =
2257 			header->asGPIO_Info[info->i2c_line].ucDataMaskShift;
2258 	info->gpio_info.data_en_shift =
2259 			header->asGPIO_Info[info->i2c_line].ucDataEnShift;
2260 	info->gpio_info.data_y_shift =
2261 			header->asGPIO_Info[info->i2c_line].ucDataY_Shift;
2262 	info->gpio_info.data_a_shift =
2263 			header->asGPIO_Info[info->i2c_line].ucDataA_Shift;
2264 
2265 	return BP_RESULT_OK;
2266 }
2267 
2268 static bool dal_graphics_object_id_is_valid(struct graphics_object_id id)
2269 {
2270 	bool rc = true;
2271 
2272 	switch (id.type) {
2273 	case OBJECT_TYPE_UNKNOWN:
2274 		rc = false;
2275 		break;
2276 	case OBJECT_TYPE_GPU:
2277 	case OBJECT_TYPE_ENGINE:
2278 		/* do NOT check for id.id == 0 */
2279 		if (id.enum_id == ENUM_ID_UNKNOWN)
2280 			rc = false;
2281 		break;
2282 	default:
2283 		if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN)
2284 			rc = false;
2285 		break;
2286 	}
2287 
2288 	return rc;
2289 }
2290 
2291 static bool dal_graphics_object_id_is_equal(
2292 	struct graphics_object_id id1,
2293 	struct graphics_object_id id2)
2294 {
2295 	if (false == dal_graphics_object_id_is_valid(id1)) {
2296 		dm_output_to_console(
2297 		"%s: Warning: comparing invalid object 'id1'!\n", __func__);
2298 		return false;
2299 	}
2300 
2301 	if (false == dal_graphics_object_id_is_valid(id2)) {
2302 		dm_output_to_console(
2303 		"%s: Warning: comparing invalid object 'id2'!\n", __func__);
2304 		return false;
2305 	}
2306 
2307 	if (id1.id == id2.id && id1.enum_id == id2.enum_id
2308 		&& id1.type == id2.type)
2309 		return true;
2310 
2311 	return false;
2312 }
2313 
2314 static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
2315 	struct graphics_object_id id)
2316 {
2317 	uint32_t offset;
2318 	ATOM_OBJECT_TABLE *tbl;
2319 	uint32_t i;
2320 
2321 	switch (id.type) {
2322 	case OBJECT_TYPE_ENCODER:
2323 		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
2324 		break;
2325 
2326 	case OBJECT_TYPE_CONNECTOR:
2327 		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
2328 		break;
2329 
2330 	case OBJECT_TYPE_ROUTER:
2331 		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset);
2332 		break;
2333 
2334 	case OBJECT_TYPE_GENERIC:
2335 		if (bp->object_info_tbl.revision.minor < 3)
2336 			return NULL;
2337 		offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset);
2338 		break;
2339 
2340 	default:
2341 		return NULL;
2342 	}
2343 
2344 	offset += bp->object_info_tbl_offset;
2345 
2346 	tbl = GET_IMAGE(ATOM_OBJECT_TABLE, offset);
2347 	if (!tbl)
2348 		return NULL;
2349 
2350 	for (i = 0; i < tbl->ucNumberOfObjects; i++)
2351 		if (dal_graphics_object_id_is_equal(id,
2352 				object_id_from_bios_object_id(
2353 						le16_to_cpu(tbl->asObjects[i].usObjectID))))
2354 			return &tbl->asObjects[i];
2355 
2356 	return NULL;
2357 }
2358 
2359 static uint32_t get_dest_obj_list(struct bios_parser *bp,
2360 	ATOM_OBJECT *object, uint16_t **id_list)
2361 {
2362 	uint32_t offset;
2363 	uint8_t *number;
2364 
2365 	if (!object) {
2366 		BREAK_TO_DEBUGGER(); /* Invalid object id */
2367 		return 0;
2368 	}
2369 
2370 	offset = le16_to_cpu(object->usSrcDstTableOffset)
2371 						+ bp->object_info_tbl_offset;
2372 
2373 	number = GET_IMAGE(uint8_t, offset);
2374 	if (!number)
2375 		return 0;
2376 
2377 	offset += sizeof(uint8_t);
2378 	offset += sizeof(uint16_t) * (*number);
2379 
2380 	number = GET_IMAGE(uint8_t, offset);
2381 	if ((!number) || (!*number))
2382 		return 0;
2383 
2384 	offset += sizeof(uint8_t);
2385 	*id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t));
2386 
2387 	if (!*id_list)
2388 		return 0;
2389 
2390 	return *number;
2391 }
2392 
2393 static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
2394 	uint16_t **id_list)
2395 {
2396 	uint32_t offset;
2397 	uint8_t *number;
2398 
2399 	if (!object) {
2400 		BREAK_TO_DEBUGGER(); /* Invalid object id */
2401 		return 0;
2402 	}
2403 
2404 	offset = le16_to_cpu(object->usSrcDstTableOffset)
2405 					+ bp->object_info_tbl_offset;
2406 
2407 	number = GET_IMAGE(uint8_t, offset);
2408 	if (!number)
2409 		return 0;
2410 
2411 	offset += sizeof(uint8_t);
2412 	*id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t));
2413 
2414 	if (!*id_list)
2415 		return 0;
2416 
2417 	return *number;
2418 }
2419 
2420 static uint32_t get_dst_number_from_object(struct bios_parser *bp,
2421 	ATOM_OBJECT *object)
2422 {
2423 	uint32_t offset;
2424 	uint8_t *number;
2425 
2426 	if (!object) {
2427 		BREAK_TO_DEBUGGER(); /* Invalid encoder object id*/
2428 		return 0;
2429 	}
2430 
2431 	offset = le16_to_cpu(object->usSrcDstTableOffset)
2432 					+ bp->object_info_tbl_offset;
2433 
2434 	number = GET_IMAGE(uint8_t, offset);
2435 	if (!number)
2436 		return 0;
2437 
2438 	offset += sizeof(uint8_t);
2439 	offset += sizeof(uint16_t) * (*number);
2440 
2441 	number = GET_IMAGE(uint8_t, offset);
2442 
2443 	if (!number)
2444 		return 0;
2445 
2446 	return *number;
2447 }
2448 
2449 static struct device_id device_type_from_device_id(uint16_t device_id)
2450 {
2451 
2452 	struct device_id result_device_id;
2453 
2454 	switch (device_id) {
2455 	case ATOM_DEVICE_LCD1_SUPPORT:
2456 		result_device_id.device_type = DEVICE_TYPE_LCD;
2457 		result_device_id.enum_id = 1;
2458 		break;
2459 
2460 	case ATOM_DEVICE_LCD2_SUPPORT:
2461 		result_device_id.device_type = DEVICE_TYPE_LCD;
2462 		result_device_id.enum_id = 2;
2463 		break;
2464 
2465 	case ATOM_DEVICE_CRT1_SUPPORT:
2466 		result_device_id.device_type = DEVICE_TYPE_CRT;
2467 		result_device_id.enum_id = 1;
2468 		break;
2469 
2470 	case ATOM_DEVICE_CRT2_SUPPORT:
2471 		result_device_id.device_type = DEVICE_TYPE_CRT;
2472 		result_device_id.enum_id = 2;
2473 		break;
2474 
2475 	case ATOM_DEVICE_DFP1_SUPPORT:
2476 		result_device_id.device_type = DEVICE_TYPE_DFP;
2477 		result_device_id.enum_id = 1;
2478 		break;
2479 
2480 	case ATOM_DEVICE_DFP2_SUPPORT:
2481 		result_device_id.device_type = DEVICE_TYPE_DFP;
2482 		result_device_id.enum_id = 2;
2483 		break;
2484 
2485 	case ATOM_DEVICE_DFP3_SUPPORT:
2486 		result_device_id.device_type = DEVICE_TYPE_DFP;
2487 		result_device_id.enum_id = 3;
2488 		break;
2489 
2490 	case ATOM_DEVICE_DFP4_SUPPORT:
2491 		result_device_id.device_type = DEVICE_TYPE_DFP;
2492 		result_device_id.enum_id = 4;
2493 		break;
2494 
2495 	case ATOM_DEVICE_DFP5_SUPPORT:
2496 		result_device_id.device_type = DEVICE_TYPE_DFP;
2497 		result_device_id.enum_id = 5;
2498 		break;
2499 
2500 	case ATOM_DEVICE_DFP6_SUPPORT:
2501 		result_device_id.device_type = DEVICE_TYPE_DFP;
2502 		result_device_id.enum_id = 6;
2503 		break;
2504 
2505 	default:
2506 		BREAK_TO_DEBUGGER(); /* Invalid device Id */
2507 		result_device_id.device_type = DEVICE_TYPE_UNKNOWN;
2508 		result_device_id.enum_id = 0;
2509 	}
2510 	return result_device_id;
2511 }
2512 
2513 static void get_atom_data_table_revision(
2514 	ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
2515 	struct atom_data_revision *tbl_revision)
2516 {
2517 	if (!tbl_revision)
2518 		return;
2519 
2520 	/* initialize the revision to 0 which is invalid revision */
2521 	tbl_revision->major = 0;
2522 	tbl_revision->minor = 0;
2523 
2524 	if (!atom_data_tbl)
2525 		return;
2526 
2527 	tbl_revision->major =
2528 			(uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl);
2529 	tbl_revision->minor =
2530 			(uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl);
2531 }
2532 
2533 static uint32_t signal_to_ss_id(enum as_signal_type signal)
2534 {
2535 	uint32_t clk_id_ss = 0;
2536 
2537 	switch (signal) {
2538 	case AS_SIGNAL_TYPE_DVI:
2539 		clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS;
2540 		break;
2541 	case AS_SIGNAL_TYPE_HDMI:
2542 		clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI;
2543 		break;
2544 	case AS_SIGNAL_TYPE_LVDS:
2545 		clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS;
2546 		break;
2547 	case AS_SIGNAL_TYPE_DISPLAY_PORT:
2548 		clk_id_ss = ASIC_INTERNAL_SS_ON_DP;
2549 		break;
2550 	case AS_SIGNAL_TYPE_GPU_PLL:
2551 		clk_id_ss = ASIC_INTERNAL_GPUPLL_SS;
2552 		break;
2553 	default:
2554 		break;
2555 	}
2556 	return clk_id_ss;
2557 }
2558 
2559 static uint32_t get_support_mask_for_device_id(struct device_id device_id)
2560 {
2561 	enum dal_device_type device_type = device_id.device_type;
2562 	uint32_t enum_id = device_id.enum_id;
2563 
2564 	switch (device_type) {
2565 	case DEVICE_TYPE_LCD:
2566 		switch (enum_id) {
2567 		case 1:
2568 			return ATOM_DEVICE_LCD1_SUPPORT;
2569 		case 2:
2570 			return ATOM_DEVICE_LCD2_SUPPORT;
2571 		default:
2572 			break;
2573 		}
2574 		break;
2575 	case DEVICE_TYPE_CRT:
2576 		switch (enum_id) {
2577 		case 1:
2578 			return ATOM_DEVICE_CRT1_SUPPORT;
2579 		case 2:
2580 			return ATOM_DEVICE_CRT2_SUPPORT;
2581 		default:
2582 			break;
2583 		}
2584 		break;
2585 	case DEVICE_TYPE_DFP:
2586 		switch (enum_id) {
2587 		case 1:
2588 			return ATOM_DEVICE_DFP1_SUPPORT;
2589 		case 2:
2590 			return ATOM_DEVICE_DFP2_SUPPORT;
2591 		case 3:
2592 			return ATOM_DEVICE_DFP3_SUPPORT;
2593 		case 4:
2594 			return ATOM_DEVICE_DFP4_SUPPORT;
2595 		case 5:
2596 			return ATOM_DEVICE_DFP5_SUPPORT;
2597 		case 6:
2598 			return ATOM_DEVICE_DFP6_SUPPORT;
2599 		default:
2600 			break;
2601 		}
2602 		break;
2603 	case DEVICE_TYPE_CV:
2604 		switch (enum_id) {
2605 		case 1:
2606 			return ATOM_DEVICE_CV_SUPPORT;
2607 		default:
2608 			break;
2609 		}
2610 		break;
2611 	case DEVICE_TYPE_TV:
2612 		switch (enum_id) {
2613 		case 1:
2614 			return ATOM_DEVICE_TV1_SUPPORT;
2615 		default:
2616 			break;
2617 		}
2618 		break;
2619 	default:
2620 		break;
2621 	};
2622 
2623 	/* Unidentified device ID, return empty support mask. */
2624 	return 0;
2625 }
2626 
2627 /**
2628  *  HwContext interface for writing MM registers
2629  */
2630 
2631 static bool i2c_read(
2632 	struct bios_parser *bp,
2633 	struct graphics_object_i2c_info *i2c_info,
2634 	uint8_t *buffer,
2635 	uint32_t length)
2636 {
2637 	struct ddc *ddc;
2638 	uint8_t offset[2] = { 0, 0 };
2639 	bool result = false;
2640 	struct i2c_command cmd;
2641 	struct gpio_ddc_hw_info hw_info = {
2642 		i2c_info->i2c_hw_assist,
2643 		i2c_info->i2c_line };
2644 
2645 	ddc = dal_gpio_create_ddc(bp->base.ctx->gpio_service,
2646 		i2c_info->gpio_info.clk_a_register_index,
2647 		(1 << i2c_info->gpio_info.clk_a_shift), &hw_info);
2648 
2649 	if (!ddc)
2650 		return result;
2651 
2652 	/*Using SW engine */
2653 	cmd.engine = I2C_COMMAND_ENGINE_SW;
2654 	cmd.speed = ddc->ctx->dc->caps.i2c_speed_in_khz;
2655 
2656 	{
2657 		struct i2c_payload payloads[] = {
2658 				{
2659 						.address = i2c_info->i2c_slave_address >> 1,
2660 						.data = offset,
2661 						.length = sizeof(offset),
2662 						.write = true
2663 				},
2664 				{
2665 						.address = i2c_info->i2c_slave_address >> 1,
2666 						.data = buffer,
2667 						.length = length,
2668 						.write = false
2669 				}
2670 		};
2671 
2672 		cmd.payloads = payloads;
2673 		cmd.number_of_payloads = ARRAY_SIZE(payloads);
2674 
2675 		/* TODO route this through drm i2c_adapter */
2676 		result = dal_i2caux_submit_i2c_command(
2677 				ddc->ctx->i2caux,
2678 				ddc,
2679 				&cmd);
2680 	}
2681 
2682 	dal_gpio_destroy_ddc(&ddc);
2683 
2684 	return result;
2685 }
2686 
2687 /**
2688  * Read external display connection info table through i2c.
2689  * validate the GUID and checksum.
2690  *
2691  * @return enum bp_result whether all data was sucessfully read
2692  */
2693 static enum bp_result get_ext_display_connection_info(
2694 	struct bios_parser *bp,
2695 	ATOM_OBJECT *opm_object,
2696 	ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *ext_display_connection_info_tbl)
2697 {
2698 	bool config_tbl_present = false;
2699 	ATOM_I2C_RECORD *i2c_record = NULL;
2700 	uint32_t i = 0;
2701 
2702 	if (opm_object == NULL)
2703 		return BP_RESULT_BADINPUT;
2704 
2705 	i2c_record = get_i2c_record(bp, opm_object);
2706 
2707 	if (i2c_record != NULL) {
2708 		ATOM_GPIO_I2C_INFO *gpio_i2c_header;
2709 		struct graphics_object_i2c_info i2c_info;
2710 
2711 		gpio_i2c_header = GET_IMAGE(ATOM_GPIO_I2C_INFO,
2712 				bp->master_data_tbl->ListOfDataTables.GPIO_I2C_Info);
2713 
2714 		if (NULL == gpio_i2c_header)
2715 			return BP_RESULT_BADBIOSTABLE;
2716 
2717 		if (get_gpio_i2c_info(bp, i2c_record, &i2c_info) !=
2718 				BP_RESULT_OK)
2719 			return BP_RESULT_BADBIOSTABLE;
2720 
2721 		if (i2c_read(bp,
2722 			     &i2c_info,
2723 			     (uint8_t *)ext_display_connection_info_tbl,
2724 			     sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO))) {
2725 			config_tbl_present = true;
2726 		}
2727 	}
2728 
2729 	/* Validate GUID */
2730 	if (config_tbl_present)
2731 		for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; i++) {
2732 			if (ext_display_connection_info_tbl->ucGuid[i]
2733 			    != ext_display_connection_guid[i]) {
2734 				config_tbl_present = false;
2735 				break;
2736 			}
2737 		}
2738 
2739 	/* Validate checksum */
2740 	if (config_tbl_present) {
2741 		uint8_t check_sum = 0;
2742 		uint8_t *buf =
2743 				(uint8_t *)ext_display_connection_info_tbl;
2744 
2745 		for (i = 0; i < sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO);
2746 				i++) {
2747 			check_sum += buf[i];
2748 		}
2749 
2750 		if (check_sum != 0)
2751 			config_tbl_present = false;
2752 	}
2753 
2754 	if (config_tbl_present)
2755 		return BP_RESULT_OK;
2756 	else
2757 		return BP_RESULT_FAILURE;
2758 }
2759 
2760 /*
2761  * Gets the first device ID in the same group as the given ID for enumerating.
2762  * For instance, if any DFP device ID is passed, returns the device ID for DFP1.
2763  *
2764  * The first device ID in the same group as the passed device ID, or 0 if no
2765  * matching device group found.
2766  */
2767 static uint32_t enum_first_device_id(uint32_t dev_id)
2768 {
2769 	/* Return the first in the group that this ID belongs to. */
2770 	if (dev_id & ATOM_DEVICE_CRT_SUPPORT)
2771 		return ATOM_DEVICE_CRT1_SUPPORT;
2772 	else if (dev_id & ATOM_DEVICE_DFP_SUPPORT)
2773 		return ATOM_DEVICE_DFP1_SUPPORT;
2774 	else if (dev_id & ATOM_DEVICE_LCD_SUPPORT)
2775 		return ATOM_DEVICE_LCD1_SUPPORT;
2776 	else if (dev_id & ATOM_DEVICE_TV_SUPPORT)
2777 		return ATOM_DEVICE_TV1_SUPPORT;
2778 	else if (dev_id & ATOM_DEVICE_CV_SUPPORT)
2779 		return ATOM_DEVICE_CV_SUPPORT;
2780 
2781 	/* No group found for this device ID. */
2782 
2783 	dm_error("%s: incorrect input %d\n", __func__, dev_id);
2784 	/* No matching support flag for given device ID */
2785 	return 0;
2786 }
2787 
2788 /*
2789  * Gets the next device ID in the group for a given device ID.
2790  *
2791  * The current device ID being enumerated on.
2792  *
2793  * The next device ID in the group, or 0 if no device exists.
2794  */
2795 static uint32_t enum_next_dev_id(uint32_t dev_id)
2796 {
2797 	/* Get next device ID in the group. */
2798 	switch (dev_id) {
2799 	case ATOM_DEVICE_CRT1_SUPPORT:
2800 		return ATOM_DEVICE_CRT2_SUPPORT;
2801 	case ATOM_DEVICE_LCD1_SUPPORT:
2802 		return ATOM_DEVICE_LCD2_SUPPORT;
2803 	case ATOM_DEVICE_DFP1_SUPPORT:
2804 		return ATOM_DEVICE_DFP2_SUPPORT;
2805 	case ATOM_DEVICE_DFP2_SUPPORT:
2806 		return ATOM_DEVICE_DFP3_SUPPORT;
2807 	case ATOM_DEVICE_DFP3_SUPPORT:
2808 		return ATOM_DEVICE_DFP4_SUPPORT;
2809 	case ATOM_DEVICE_DFP4_SUPPORT:
2810 		return ATOM_DEVICE_DFP5_SUPPORT;
2811 	case ATOM_DEVICE_DFP5_SUPPORT:
2812 		return ATOM_DEVICE_DFP6_SUPPORT;
2813 	}
2814 
2815 	/* Done enumerating through devices. */
2816 	return 0;
2817 }
2818 
2819 /*
2820  * Returns the new device tag record for patched BIOS object.
2821  *
2822  * [IN] pExtDisplayPath - External display path to copy device tag from.
2823  * [IN] deviceSupport - Bit vector for device ID support flags.
2824  * [OUT] pDeviceTag - Device tag structure to fill with patched data.
2825  *
2826  * True if a compatible device ID was found, false otherwise.
2827  */
2828 static bool get_patched_device_tag(
2829 	struct bios_parser *bp,
2830 	EXT_DISPLAY_PATH *ext_display_path,
2831 	uint32_t device_support,
2832 	ATOM_CONNECTOR_DEVICE_TAG *device_tag)
2833 {
2834 	uint32_t dev_id;
2835 	/* Use fallback behaviour if not supported. */
2836 	if (!bp->remap_device_tags) {
2837 		device_tag->ulACPIDeviceEnum =
2838 				cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum));
2839 		device_tag->usDeviceID =
2840 				cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceTag));
2841 		return true;
2842 	}
2843 
2844 	/* Find the first unused in the same group. */
2845 	dev_id = enum_first_device_id(le16_to_cpu(ext_display_path->usDeviceTag));
2846 	while (dev_id != 0) {
2847 		/* Assign this device ID if supported. */
2848 		if ((device_support & dev_id) != 0) {
2849 			device_tag->ulACPIDeviceEnum =
2850 					cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum));
2851 			device_tag->usDeviceID = cpu_to_le16((USHORT) dev_id);
2852 			return true;
2853 		}
2854 
2855 		dev_id = enum_next_dev_id(dev_id);
2856 	}
2857 
2858 	/* No compatible device ID found. */
2859 	return false;
2860 }
2861 
2862 /*
2863  * Adds a device tag to a BIOS object's device tag record if there is
2864  * matching device ID supported.
2865  *
2866  * pObject - Pointer to the BIOS object to add the device tag to.
2867  * pExtDisplayPath - Display path to retrieve base device ID from.
2868  * pDeviceSupport - Pointer to bit vector for supported device IDs.
2869  */
2870 static void add_device_tag_from_ext_display_path(
2871 	struct bios_parser *bp,
2872 	ATOM_OBJECT *object,
2873 	EXT_DISPLAY_PATH *ext_display_path,
2874 	uint32_t *device_support)
2875 {
2876 	/* Get device tag record for object. */
2877 	ATOM_CONNECTOR_DEVICE_TAG *device_tag = NULL;
2878 	ATOM_CONNECTOR_DEVICE_TAG_RECORD *device_tag_record = NULL;
2879 	enum bp_result result =
2880 			bios_parser_get_device_tag_record(
2881 					bp, object, &device_tag_record);
2882 
2883 	if ((le16_to_cpu(ext_display_path->usDeviceTag) != CONNECTOR_OBJECT_ID_NONE)
2884 			&& (result == BP_RESULT_OK)) {
2885 		uint8_t index;
2886 
2887 		if ((device_tag_record->ucNumberOfDevice == 1) &&
2888 				(le16_to_cpu(device_tag_record->asDeviceTag[0].usDeviceID) == 0)) {
2889 			/*Workaround bug in current VBIOS releases where
2890 			 * ucNumberOfDevice = 1 but there is no actual device
2891 			 * tag data. This w/a is temporary until the updated
2892 			 * VBIOS is distributed. */
2893 			device_tag_record->ucNumberOfDevice =
2894 					device_tag_record->ucNumberOfDevice - 1;
2895 		}
2896 
2897 		/* Attempt to find a matching device ID. */
2898 		index = device_tag_record->ucNumberOfDevice;
2899 		device_tag = &device_tag_record->asDeviceTag[index];
2900 		if (get_patched_device_tag(
2901 				bp,
2902 				ext_display_path,
2903 				*device_support,
2904 				device_tag)) {
2905 			/* Update cached device support to remove assigned ID.
2906 			 */
2907 			*device_support &= ~le16_to_cpu(device_tag->usDeviceID);
2908 			device_tag_record->ucNumberOfDevice++;
2909 		}
2910 	}
2911 }
2912 
2913 /*
2914  * Read out a single EXT_DISPLAY_PATH from the external display connection info
2915  * table. The specific entry in the table is determined by the enum_id passed
2916  * in.
2917  *
2918  * EXT_DISPLAY_PATH describing a single Configuration table entry
2919  */
2920 
2921 #define INVALID_CONNECTOR 0xffff
2922 
2923 static EXT_DISPLAY_PATH *get_ext_display_path_entry(
2924 	ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *config_table,
2925 	uint32_t bios_object_id)
2926 {
2927 	EXT_DISPLAY_PATH *ext_display_path;
2928 	uint32_t ext_display_path_index =
2929 			((bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT) - 1;
2930 
2931 	if (ext_display_path_index >= MAX_NUMBER_OF_EXT_DISPLAY_PATH)
2932 		return NULL;
2933 
2934 	ext_display_path = &config_table->sPath[ext_display_path_index];
2935 
2936 	if (le16_to_cpu(ext_display_path->usDeviceConnector) == INVALID_CONNECTOR)
2937 		ext_display_path->usDeviceConnector = cpu_to_le16(0);
2938 
2939 	return ext_display_path;
2940 }
2941 
2942 /*
2943  * Get AUX/DDC information of input object id
2944  *
2945  * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record
2946  * IR
2947  */
2948 static ATOM_CONNECTOR_AUXDDC_LUT_RECORD *get_ext_connector_aux_ddc_lut_record(
2949 	struct bios_parser *bp,
2950 	ATOM_OBJECT *object)
2951 {
2952 	uint32_t offset;
2953 	ATOM_COMMON_RECORD_HEADER *header;
2954 
2955 	if (!object) {
2956 		BREAK_TO_DEBUGGER();
2957 		/* Invalid object */
2958 		return NULL;
2959 	}
2960 
2961 	offset = le16_to_cpu(object->usRecordOffset)
2962 					+ bp->object_info_tbl_offset;
2963 
2964 	for (;;) {
2965 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
2966 
2967 		if (!header)
2968 			return NULL;
2969 
2970 		if (LAST_RECORD_TYPE == header->ucRecordType ||
2971 				0 == header->ucRecordSize)
2972 			break;
2973 
2974 		if (ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE ==
2975 				header->ucRecordType &&
2976 				sizeof(ATOM_CONNECTOR_AUXDDC_LUT_RECORD) <=
2977 				header->ucRecordSize)
2978 			return (ATOM_CONNECTOR_AUXDDC_LUT_RECORD *)(header);
2979 
2980 		offset += header->ucRecordSize;
2981 	}
2982 
2983 	return NULL;
2984 }
2985 
2986 /*
2987  * Get AUX/DDC information of input object id
2988  *
2989  * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record
2990  * IR
2991  */
2992 static ATOM_CONNECTOR_HPDPIN_LUT_RECORD *get_ext_connector_hpd_pin_lut_record(
2993 	struct bios_parser *bp,
2994 	ATOM_OBJECT *object)
2995 {
2996 	uint32_t offset;
2997 	ATOM_COMMON_RECORD_HEADER *header;
2998 
2999 	if (!object) {
3000 		BREAK_TO_DEBUGGER();
3001 		/* Invalid object */
3002 		return NULL;
3003 	}
3004 
3005 	offset = le16_to_cpu(object->usRecordOffset)
3006 					+ bp->object_info_tbl_offset;
3007 
3008 	for (;;) {
3009 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
3010 
3011 		if (!header)
3012 			return NULL;
3013 
3014 		if (LAST_RECORD_TYPE == header->ucRecordType ||
3015 				0 == header->ucRecordSize)
3016 			break;
3017 
3018 		if (ATOM_CONNECTOR_HPDPIN_LUT_RECORD_TYPE ==
3019 				header->ucRecordType &&
3020 				sizeof(ATOM_CONNECTOR_HPDPIN_LUT_RECORD) <=
3021 				header->ucRecordSize)
3022 			return (ATOM_CONNECTOR_HPDPIN_LUT_RECORD *)header;
3023 
3024 		offset += header->ucRecordSize;
3025 	}
3026 
3027 	return NULL;
3028 }
3029 
3030 /*
3031  * Check whether we need to patch the VBIOS connector info table with
3032  * data from an external display connection info table.  This is
3033  * necessary to support MXM boards with an OPM (output personality
3034  * module).  With these designs, the VBIOS connector info table
3035  * specifies an MXM_CONNECTOR with a unique ID.  The driver retrieves
3036  * the external connection info table through i2c and then looks up the
3037  * connector ID to find the real connector type (e.g. DFP1).
3038  *
3039  */
3040 static enum bp_result patch_bios_image_from_ext_display_connection_info(
3041 	struct bios_parser *bp)
3042 {
3043 	ATOM_OBJECT_TABLE *connector_tbl;
3044 	uint32_t connector_tbl_offset;
3045 	struct graphics_object_id object_id;
3046 	ATOM_OBJECT *object;
3047 	ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO ext_display_connection_info_tbl;
3048 	EXT_DISPLAY_PATH *ext_display_path;
3049 	ATOM_CONNECTOR_AUXDDC_LUT_RECORD *aux_ddc_lut_record = NULL;
3050 	ATOM_I2C_RECORD *i2c_record = NULL;
3051 	ATOM_CONNECTOR_HPDPIN_LUT_RECORD *hpd_pin_lut_record = NULL;
3052 	ATOM_HPD_INT_RECORD *hpd_record = NULL;
3053 	ATOM_OBJECT_TABLE *encoder_table;
3054 	uint32_t encoder_table_offset;
3055 	ATOM_OBJECT *opm_object = NULL;
3056 	uint32_t i = 0;
3057 	struct graphics_object_id opm_object_id =
3058 			dal_graphics_object_id_init(
3059 					GENERIC_ID_MXM_OPM,
3060 					ENUM_ID_1,
3061 					OBJECT_TYPE_GENERIC);
3062 	ATOM_CONNECTOR_DEVICE_TAG_RECORD *dev_tag_record;
3063 	uint32_t cached_device_support =
3064 			le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport);
3065 
3066 	uint32_t dst_number;
3067 	uint16_t *dst_object_id_list;
3068 
3069 	opm_object = get_bios_object(bp, opm_object_id);
3070 	if (!opm_object)
3071 		return BP_RESULT_UNSUPPORTED;
3072 
3073 	memset(&ext_display_connection_info_tbl, 0,
3074 			sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO));
3075 
3076 	connector_tbl_offset = bp->object_info_tbl_offset
3077 			+ le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
3078 	connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset);
3079 
3080 	/* Read Connector info table from EEPROM through i2c */
3081 	if (get_ext_display_connection_info(bp,
3082 					    opm_object,
3083 					    &ext_display_connection_info_tbl) != BP_RESULT_OK) {
3084 
3085 		DC_LOG_WARNING("%s: Failed to read Connection Info Table", __func__);
3086 		return BP_RESULT_UNSUPPORTED;
3087 	}
3088 
3089 	/* Get pointer to AUX/DDC and HPD LUTs */
3090 	aux_ddc_lut_record =
3091 			get_ext_connector_aux_ddc_lut_record(bp, opm_object);
3092 	hpd_pin_lut_record =
3093 			get_ext_connector_hpd_pin_lut_record(bp, opm_object);
3094 
3095 	if ((aux_ddc_lut_record == NULL) || (hpd_pin_lut_record == NULL))
3096 		return BP_RESULT_UNSUPPORTED;
3097 
3098 	/* Cache support bits for currently unmapped device types. */
3099 	if (bp->remap_device_tags) {
3100 		for (i = 0; i < connector_tbl->ucNumberOfObjects; ++i) {
3101 			uint32_t j;
3102 			/* Remove support for all non-MXM connectors. */
3103 			object = &connector_tbl->asObjects[i];
3104 			object_id = object_id_from_bios_object_id(
3105 					le16_to_cpu(object->usObjectID));
3106 			if ((OBJECT_TYPE_CONNECTOR != object_id.type) ||
3107 					(CONNECTOR_ID_MXM == object_id.id))
3108 				continue;
3109 
3110 			/* Remove support for all device tags. */
3111 			if (bios_parser_get_device_tag_record(
3112 					bp, object, &dev_tag_record) != BP_RESULT_OK)
3113 				continue;
3114 
3115 			for (j = 0; j < dev_tag_record->ucNumberOfDevice; ++j) {
3116 				ATOM_CONNECTOR_DEVICE_TAG *device_tag =
3117 						&dev_tag_record->asDeviceTag[j];
3118 				cached_device_support &=
3119 						~le16_to_cpu(device_tag->usDeviceID);
3120 			}
3121 		}
3122 	}
3123 
3124 	/* Find all MXM connector objects and patch them with connector info
3125 	 * from the external display connection info table. */
3126 	for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) {
3127 		uint32_t j;
3128 
3129 		object = &connector_tbl->asObjects[i];
3130 		object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID));
3131 		if ((OBJECT_TYPE_CONNECTOR != object_id.type) ||
3132 				(CONNECTOR_ID_MXM != object_id.id))
3133 			continue;
3134 
3135 		/* Get the correct connection info table entry based on the enum
3136 		 * id. */
3137 		ext_display_path = get_ext_display_path_entry(
3138 				&ext_display_connection_info_tbl,
3139 				le16_to_cpu(object->usObjectID));
3140 		if (!ext_display_path)
3141 			return BP_RESULT_FAILURE;
3142 
3143 		/* Patch device connector ID */
3144 		object->usObjectID =
3145 				cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceConnector));
3146 
3147 		/* Patch device tag, ulACPIDeviceEnum. */
3148 		add_device_tag_from_ext_display_path(
3149 				bp,
3150 				object,
3151 				ext_display_path,
3152 				&cached_device_support);
3153 
3154 		/* Patch HPD info */
3155 		if (ext_display_path->ucExtHPDPINLutIndex <
3156 				MAX_NUMBER_OF_EXT_HPDPIN_LUT_ENTRIES) {
3157 			hpd_record = get_hpd_record(bp, object);
3158 			if (hpd_record) {
3159 				uint8_t index =
3160 						ext_display_path->ucExtHPDPINLutIndex;
3161 				hpd_record->ucHPDIntGPIOID =
3162 						hpd_pin_lut_record->ucHPDPINMap[index];
3163 			} else {
3164 				BREAK_TO_DEBUGGER();
3165 				/* Invalid hpd record */
3166 				return BP_RESULT_FAILURE;
3167 			}
3168 		}
3169 
3170 		/* Patch I2C/AUX info */
3171 		if (ext_display_path->ucExtHPDPINLutIndex <
3172 				MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES) {
3173 			i2c_record = get_i2c_record(bp, object);
3174 			if (i2c_record) {
3175 				uint8_t index =
3176 						ext_display_path->ucExtAUXDDCLutIndex;
3177 				i2c_record->sucI2cId =
3178 						aux_ddc_lut_record->ucAUXDDCMap[index];
3179 			} else {
3180 				BREAK_TO_DEBUGGER();
3181 				/* Invalid I2C record */
3182 				return BP_RESULT_FAILURE;
3183 			}
3184 		}
3185 
3186 		/* Merge with other MXM connectors that map to the same physical
3187 		 * connector. */
3188 		for (j = i + 1;
3189 				j < connector_tbl->ucNumberOfObjects; j++) {
3190 			ATOM_OBJECT *next_object;
3191 			struct graphics_object_id next_object_id;
3192 			EXT_DISPLAY_PATH *next_ext_display_path;
3193 
3194 			next_object = &connector_tbl->asObjects[j];
3195 			next_object_id = object_id_from_bios_object_id(
3196 					le16_to_cpu(next_object->usObjectID));
3197 
3198 			if ((OBJECT_TYPE_CONNECTOR != next_object_id.type) &&
3199 					(CONNECTOR_ID_MXM == next_object_id.id))
3200 				continue;
3201 
3202 			next_ext_display_path = get_ext_display_path_entry(
3203 					&ext_display_connection_info_tbl,
3204 					le16_to_cpu(next_object->usObjectID));
3205 
3206 			if (next_ext_display_path == NULL)
3207 				return BP_RESULT_FAILURE;
3208 
3209 			/* Merge if using same connector. */
3210 			if ((le16_to_cpu(next_ext_display_path->usDeviceConnector) ==
3211 					le16_to_cpu(ext_display_path->usDeviceConnector)) &&
3212 					(le16_to_cpu(ext_display_path->usDeviceConnector) != 0)) {
3213 				/* Clear duplicate connector from table. */
3214 				next_object->usObjectID = cpu_to_le16(0);
3215 				add_device_tag_from_ext_display_path(
3216 						bp,
3217 						object,
3218 						ext_display_path,
3219 						&cached_device_support);
3220 			}
3221 		}
3222 	}
3223 
3224 	/* Find all encoders which have an MXM object as their destination.
3225 	 *  Replace the MXM object with the real connector Id from the external
3226 	 *  display connection info table */
3227 
3228 	encoder_table_offset = bp->object_info_tbl_offset
3229 			+ le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
3230 	encoder_table = GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset);
3231 
3232 	for (i = 0; i < encoder_table->ucNumberOfObjects; i++) {
3233 		uint32_t j;
3234 
3235 		object = &encoder_table->asObjects[i];
3236 
3237 		dst_number = get_dest_obj_list(bp, object, &dst_object_id_list);
3238 
3239 		for (j = 0; j < dst_number; j++) {
3240 			object_id = object_id_from_bios_object_id(
3241 					dst_object_id_list[j]);
3242 
3243 			if ((OBJECT_TYPE_CONNECTOR != object_id.type) ||
3244 					(CONNECTOR_ID_MXM != object_id.id))
3245 				continue;
3246 
3247 			/* Get the correct connection info table entry based on
3248 			 * the enum id. */
3249 			ext_display_path =
3250 					get_ext_display_path_entry(
3251 							&ext_display_connection_info_tbl,
3252 							dst_object_id_list[j]);
3253 
3254 			if (ext_display_path == NULL)
3255 				return BP_RESULT_FAILURE;
3256 
3257 			dst_object_id_list[j] =
3258 					le16_to_cpu(ext_display_path->usDeviceConnector);
3259 		}
3260 	}
3261 
3262 	return BP_RESULT_OK;
3263 }
3264 
3265 /*
3266  * Check whether we need to patch the VBIOS connector info table with
3267  * data from an external display connection info table.  This is
3268  * necessary to support MXM boards with an OPM (output personality
3269  * module).  With these designs, the VBIOS connector info table
3270  * specifies an MXM_CONNECTOR with a unique ID.  The driver retrieves
3271  * the external connection info table through i2c and then looks up the
3272  * connector ID to find the real connector type (e.g. DFP1).
3273  *
3274  */
3275 
3276 static void process_ext_display_connection_info(struct bios_parser *bp)
3277 {
3278 	ATOM_OBJECT_TABLE *connector_tbl;
3279 	uint32_t connector_tbl_offset;
3280 	struct graphics_object_id object_id;
3281 	ATOM_OBJECT *object;
3282 	bool mxm_connector_found = false;
3283 	bool null_entry_found = false;
3284 	uint32_t i = 0;
3285 
3286 	connector_tbl_offset = bp->object_info_tbl_offset +
3287 			le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
3288 	connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset);
3289 
3290 	/* Look for MXM connectors to determine whether we need patch the VBIOS
3291 	 * connector info table. Look for null entries to determine whether we
3292 	 * need to compact connector table. */
3293 	for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) {
3294 		object = &connector_tbl->asObjects[i];
3295 		object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID));
3296 
3297 		if ((OBJECT_TYPE_CONNECTOR == object_id.type) &&
3298 				(CONNECTOR_ID_MXM == object_id.id)) {
3299 			/* Once we found MXM connector - we can break */
3300 			mxm_connector_found = true;
3301 			break;
3302 		} else if (OBJECT_TYPE_CONNECTOR != object_id.type) {
3303 			/* We need to continue looping - to check if MXM
3304 			 * connector present */
3305 			null_entry_found = true;
3306 		}
3307 	}
3308 
3309 	/* Patch BIOS image */
3310 	if (mxm_connector_found || null_entry_found) {
3311 		uint32_t connectors_num = 0;
3312 		uint8_t *original_bios;
3313 		/* Step 1: Replace bios image with the new copy which will be
3314 		 * patched */
3315 		bp->base.bios_local_image = kzalloc(bp->base.bios_size,
3316 						    GFP_KERNEL);
3317 		if (bp->base.bios_local_image == NULL) {
3318 			BREAK_TO_DEBUGGER();
3319 			/* Failed to alloc bp->base.bios_local_image */
3320 			return;
3321 		}
3322 
3323 		memmove(bp->base.bios_local_image, bp->base.bios, bp->base.bios_size);
3324 		original_bios = bp->base.bios;
3325 		bp->base.bios = bp->base.bios_local_image;
3326 		connector_tbl =
3327 				GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset);
3328 
3329 		/* Step 2: (only if MXM connector found) Patch BIOS image with
3330 		 * info from external module */
3331 		if (mxm_connector_found &&
3332 		    patch_bios_image_from_ext_display_connection_info(bp) !=
3333 						BP_RESULT_OK) {
3334 			/* Patching the bios image has failed. We will copy
3335 			 * again original image provided and afterwards
3336 			 * only remove null entries */
3337 			memmove(
3338 					bp->base.bios_local_image,
3339 					original_bios,
3340 					bp->base.bios_size);
3341 		}
3342 
3343 		/* Step 3: Compact connector table (remove null entries, valid
3344 		 * entries moved to beginning) */
3345 		for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) {
3346 			object = &connector_tbl->asObjects[i];
3347 			object_id = object_id_from_bios_object_id(
3348 					le16_to_cpu(object->usObjectID));
3349 
3350 			if (OBJECT_TYPE_CONNECTOR != object_id.type)
3351 				continue;
3352 
3353 			if (i != connectors_num) {
3354 				memmove(
3355 						&connector_tbl->
3356 						asObjects[connectors_num],
3357 						object,
3358 						sizeof(ATOM_OBJECT));
3359 			}
3360 			++connectors_num;
3361 		}
3362 		connector_tbl->ucNumberOfObjects = (uint8_t)connectors_num;
3363 	}
3364 }
3365 
3366 static void bios_parser_post_init(struct dc_bios *dcb)
3367 {
3368 	struct bios_parser *bp = BP_FROM_DCB(dcb);
3369 
3370 	process_ext_display_connection_info(bp);
3371 }
3372 
3373 /**
3374  * bios_parser_set_scratch_critical_state
3375  *
3376  * @brief
3377  *  update critical state bit in VBIOS scratch register
3378  *
3379  * @param
3380  *  bool - to set or reset state
3381  */
3382 static void bios_parser_set_scratch_critical_state(
3383 	struct dc_bios *dcb,
3384 	bool state)
3385 {
3386 	bios_set_scratch_critical_state(dcb, state);
3387 }
3388 
3389 /*
3390  * get_integrated_info_v8
3391  *
3392  * @brief
3393  * Get V8 integrated BIOS information
3394  *
3395  * @param
3396  * bios_parser *bp - [in]BIOS parser handler to get master data table
3397  * integrated_info *info - [out] store and output integrated info
3398  *
3399  * @return
3400  * enum bp_result - BP_RESULT_OK if information is available,
3401  *                  BP_RESULT_BADBIOSTABLE otherwise.
3402  */
3403 static enum bp_result get_integrated_info_v8(
3404 	struct bios_parser *bp,
3405 	struct integrated_info *info)
3406 {
3407 	ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8;
3408 	uint32_t i;
3409 
3410 	info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8,
3411 			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
3412 
3413 	if (info_v8 == NULL)
3414 		return BP_RESULT_BADBIOSTABLE;
3415 	info->boot_up_engine_clock = le32_to_cpu(info_v8->ulBootUpEngineClock) * 10;
3416 	info->dentist_vco_freq = le32_to_cpu(info_v8->ulDentistVCOFreq) * 10;
3417 	info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
3418 
3419 	for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
3420 		/* Convert [10KHz] into [KHz] */
3421 		info->disp_clk_voltage[i].max_supported_clk =
3422 			le32_to_cpu(info_v8->sDISPCLK_Voltage[i].
3423 				    ulMaximumSupportedCLK) * 10;
3424 		info->disp_clk_voltage[i].voltage_index =
3425 			le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex);
3426 	}
3427 
3428 	info->boot_up_req_display_vector =
3429 		le32_to_cpu(info_v8->ulBootUpReqDisplayVector);
3430 	info->gpu_cap_info =
3431 		le32_to_cpu(info_v8->ulGPUCapInfo);
3432 
3433 	/*
3434 	 * system_config: Bit[0] = 0 : PCIE power gating disabled
3435 	 *                       = 1 : PCIE power gating enabled
3436 	 *                Bit[1] = 0 : DDR-PLL shut down disabled
3437 	 *                       = 1 : DDR-PLL shut down enabled
3438 	 *                Bit[2] = 0 : DDR-PLL power down disabled
3439 	 *                       = 1 : DDR-PLL power down enabled
3440 	 */
3441 	info->system_config = le32_to_cpu(info_v8->ulSystemConfig);
3442 	info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo);
3443 	info->boot_up_nb_voltage =
3444 		le16_to_cpu(info_v8->usBootUpNBVoltage);
3445 	info->ext_disp_conn_info_offset =
3446 		le16_to_cpu(info_v8->usExtDispConnInfoOffset);
3447 	info->memory_type = info_v8->ucMemoryType;
3448 	info->ma_channel_number = info_v8->ucUMAChannelNumber;
3449 	info->gmc_restore_reset_time =
3450 		le32_to_cpu(info_v8->ulGMCRestoreResetTime);
3451 
3452 	info->minimum_n_clk =
3453 		le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]);
3454 	for (i = 1; i < 4; ++i)
3455 		info->minimum_n_clk =
3456 			info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ?
3457 			info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]);
3458 
3459 	info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk);
3460 	info->ddr_dll_power_up_time =
3461 		le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime);
3462 	info->ddr_pll_power_up_time =
3463 		le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime);
3464 	info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType);
3465 	info->lvds_ss_percentage =
3466 		le16_to_cpu(info_v8->usLvdsSSPercentage);
3467 	info->lvds_sspread_rate_in_10hz =
3468 		le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz);
3469 	info->hdmi_ss_percentage =
3470 		le16_to_cpu(info_v8->usHDMISSPercentage);
3471 	info->hdmi_sspread_rate_in_10hz =
3472 		le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz);
3473 	info->dvi_ss_percentage =
3474 		le16_to_cpu(info_v8->usDVISSPercentage);
3475 	info->dvi_sspread_rate_in_10_hz =
3476 		le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz);
3477 
3478 	info->max_lvds_pclk_freq_in_single_link =
3479 		le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink);
3480 	info->lvds_misc = info_v8->ucLvdsMisc;
3481 	info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
3482 		info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
3483 	info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
3484 		info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
3485 	info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
3486 		info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
3487 	info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
3488 		info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
3489 	info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
3490 		info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
3491 	info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
3492 		info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
3493 	info->lvds_off_to_on_delay_in_4ms =
3494 		info_v8->ucLVDSOffToOnDelay_in4Ms;
3495 	info->lvds_bit_depth_control_val =
3496 		le32_to_cpu(info_v8->ulLCDBitDepthControlVal);
3497 
3498 	for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
3499 		/* Convert [10KHz] into [KHz] */
3500 		info->avail_s_clk[i].supported_s_clk =
3501 			le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10;
3502 		info->avail_s_clk[i].voltage_index =
3503 			le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex);
3504 		info->avail_s_clk[i].voltage_id =
3505 			le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID);
3506 	}
3507 
3508 	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
3509 		info->ext_disp_conn_info.gu_id[i] =
3510 			info_v8->sExtDispConnInfo.ucGuid[i];
3511 	}
3512 
3513 	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
3514 		info->ext_disp_conn_info.path[i].device_connector_id =
3515 			object_id_from_bios_object_id(
3516 				le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector));
3517 
3518 		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
3519 			object_id_from_bios_object_id(
3520 				le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
3521 
3522 		info->ext_disp_conn_info.path[i].device_tag =
3523 			le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag);
3524 		info->ext_disp_conn_info.path[i].device_acpi_enum =
3525 			le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
3526 		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
3527 			info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
3528 		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
3529 			info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
3530 		info->ext_disp_conn_info.path[i].channel_mapping.raw =
3531 			info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping;
3532 	}
3533 	info->ext_disp_conn_info.checksum =
3534 		info_v8->sExtDispConnInfo.ucChecksum;
3535 
3536 	return BP_RESULT_OK;
3537 }
3538 
3539 /*
3540  * get_integrated_info_v8
3541  *
3542  * @brief
3543  * Get V8 integrated BIOS information
3544  *
3545  * @param
3546  * bios_parser *bp - [in]BIOS parser handler to get master data table
3547  * integrated_info *info - [out] store and output integrated info
3548  *
3549  * @return
3550  * enum bp_result - BP_RESULT_OK if information is available,
3551  *                  BP_RESULT_BADBIOSTABLE otherwise.
3552  */
3553 static enum bp_result get_integrated_info_v9(
3554 	struct bios_parser *bp,
3555 	struct integrated_info *info)
3556 {
3557 	ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9;
3558 	uint32_t i;
3559 
3560 	info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9,
3561 			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
3562 
3563 	if (!info_v9)
3564 		return BP_RESULT_BADBIOSTABLE;
3565 
3566 	info->boot_up_engine_clock = le32_to_cpu(info_v9->ulBootUpEngineClock) * 10;
3567 	info->dentist_vco_freq = le32_to_cpu(info_v9->ulDentistVCOFreq) * 10;
3568 	info->boot_up_uma_clock = le32_to_cpu(info_v9->ulBootUpUMAClock) * 10;
3569 
3570 	for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
3571 		/* Convert [10KHz] into [KHz] */
3572 		info->disp_clk_voltage[i].max_supported_clk =
3573 			le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10;
3574 		info->disp_clk_voltage[i].voltage_index =
3575 			le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex);
3576 	}
3577 
3578 	info->boot_up_req_display_vector =
3579 		le32_to_cpu(info_v9->ulBootUpReqDisplayVector);
3580 	info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo);
3581 
3582 	/*
3583 	 * system_config: Bit[0] = 0 : PCIE power gating disabled
3584 	 *                       = 1 : PCIE power gating enabled
3585 	 *                Bit[1] = 0 : DDR-PLL shut down disabled
3586 	 *                       = 1 : DDR-PLL shut down enabled
3587 	 *                Bit[2] = 0 : DDR-PLL power down disabled
3588 	 *                       = 1 : DDR-PLL power down enabled
3589 	 */
3590 	info->system_config = le32_to_cpu(info_v9->ulSystemConfig);
3591 	info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo);
3592 	info->boot_up_nb_voltage = le16_to_cpu(info_v9->usBootUpNBVoltage);
3593 	info->ext_disp_conn_info_offset = le16_to_cpu(info_v9->usExtDispConnInfoOffset);
3594 	info->memory_type = info_v9->ucMemoryType;
3595 	info->ma_channel_number = info_v9->ucUMAChannelNumber;
3596 	info->gmc_restore_reset_time = le32_to_cpu(info_v9->ulGMCRestoreResetTime);
3597 
3598 	info->minimum_n_clk = le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]);
3599 	for (i = 1; i < 4; ++i)
3600 		info->minimum_n_clk =
3601 			info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ?
3602 			info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]);
3603 
3604 	info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk);
3605 	info->ddr_dll_power_up_time = le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime);
3606 	info->ddr_pll_power_up_time = le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime);
3607 	info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType);
3608 	info->lvds_ss_percentage = le16_to_cpu(info_v9->usLvdsSSPercentage);
3609 	info->lvds_sspread_rate_in_10hz = le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz);
3610 	info->hdmi_ss_percentage = le16_to_cpu(info_v9->usHDMISSPercentage);
3611 	info->hdmi_sspread_rate_in_10hz = le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz);
3612 	info->dvi_ss_percentage = le16_to_cpu(info_v9->usDVISSPercentage);
3613 	info->dvi_sspread_rate_in_10_hz = le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz);
3614 
3615 	info->max_lvds_pclk_freq_in_single_link =
3616 		le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink);
3617 	info->lvds_misc = info_v9->ucLvdsMisc;
3618 	info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
3619 		info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
3620 	info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
3621 		info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
3622 	info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
3623 		info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
3624 	info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
3625 		info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
3626 	info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
3627 		info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
3628 	info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
3629 		info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
3630 	info->lvds_off_to_on_delay_in_4ms =
3631 		info_v9->ucLVDSOffToOnDelay_in4Ms;
3632 	info->lvds_bit_depth_control_val =
3633 		le32_to_cpu(info_v9->ulLCDBitDepthControlVal);
3634 
3635 	for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
3636 		/* Convert [10KHz] into [KHz] */
3637 		info->avail_s_clk[i].supported_s_clk =
3638 			le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10;
3639 		info->avail_s_clk[i].voltage_index =
3640 			le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex);
3641 		info->avail_s_clk[i].voltage_id =
3642 			le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID);
3643 	}
3644 
3645 	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
3646 		info->ext_disp_conn_info.gu_id[i] =
3647 			info_v9->sExtDispConnInfo.ucGuid[i];
3648 	}
3649 
3650 	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
3651 		info->ext_disp_conn_info.path[i].device_connector_id =
3652 			object_id_from_bios_object_id(
3653 				le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector));
3654 
3655 		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
3656 			object_id_from_bios_object_id(
3657 				le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
3658 
3659 		info->ext_disp_conn_info.path[i].device_tag =
3660 			le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag);
3661 		info->ext_disp_conn_info.path[i].device_acpi_enum =
3662 			le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
3663 		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
3664 			info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
3665 		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
3666 			info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
3667 		info->ext_disp_conn_info.path[i].channel_mapping.raw =
3668 			info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping;
3669 	}
3670 	info->ext_disp_conn_info.checksum =
3671 		info_v9->sExtDispConnInfo.ucChecksum;
3672 
3673 	return BP_RESULT_OK;
3674 }
3675 
3676 /*
3677  * construct_integrated_info
3678  *
3679  * @brief
3680  * Get integrated BIOS information based on table revision
3681  *
3682  * @param
3683  * bios_parser *bp - [in]BIOS parser handler to get master data table
3684  * integrated_info *info - [out] store and output integrated info
3685  *
3686  * @return
3687  * enum bp_result - BP_RESULT_OK if information is available,
3688  *                  BP_RESULT_BADBIOSTABLE otherwise.
3689  */
3690 static enum bp_result construct_integrated_info(
3691 	struct bios_parser *bp,
3692 	struct integrated_info *info)
3693 {
3694 	enum bp_result result = BP_RESULT_BADBIOSTABLE;
3695 
3696 	ATOM_COMMON_TABLE_HEADER *header;
3697 	struct atom_data_revision revision;
3698 
3699 	if (bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) {
3700 		header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
3701 				bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
3702 
3703 		get_atom_data_table_revision(header, &revision);
3704 
3705 		/* Don't need to check major revision as they are all 1 */
3706 		switch (revision.minor) {
3707 		case 8:
3708 			result = get_integrated_info_v8(bp, info);
3709 			break;
3710 		case 9:
3711 			result = get_integrated_info_v9(bp, info);
3712 			break;
3713 		default:
3714 			return result;
3715 
3716 		}
3717 	}
3718 
3719 	/* Sort voltage table from low to high*/
3720 	if (result == BP_RESULT_OK) {
3721 		struct clock_voltage_caps temp = {0, 0};
3722 		uint32_t i;
3723 		uint32_t j;
3724 
3725 		for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
3726 			for (j = i; j > 0; --j) {
3727 				if (
3728 						info->disp_clk_voltage[j].max_supported_clk <
3729 						info->disp_clk_voltage[j-1].max_supported_clk) {
3730 					/* swap j and j - 1*/
3731 					temp = info->disp_clk_voltage[j-1];
3732 					info->disp_clk_voltage[j-1] =
3733 							info->disp_clk_voltage[j];
3734 					info->disp_clk_voltage[j] = temp;
3735 				}
3736 			}
3737 		}
3738 
3739 	}
3740 
3741 	return result;
3742 }
3743 
3744 static struct integrated_info *bios_parser_create_integrated_info(
3745 	struct dc_bios *dcb)
3746 {
3747 	struct bios_parser *bp = BP_FROM_DCB(dcb);
3748 	struct integrated_info *info = NULL;
3749 
3750 	info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL);
3751 
3752 	if (info == NULL) {
3753 		ASSERT_CRITICAL(0);
3754 		return NULL;
3755 	}
3756 
3757 	if (construct_integrated_info(bp, info) == BP_RESULT_OK)
3758 		return info;
3759 
3760 	kfree(info);
3761 
3762 	return NULL;
3763 }
3764 
3765 static
3766 enum bp_result update_slot_layout_info(
3767 	struct dc_bios *dcb,
3768 	unsigned int i,
3769 	struct slot_layout_info *slot_layout_info,
3770 	unsigned int record_offset)
3771 {
3772 	unsigned int j;
3773 	struct bios_parser *bp;
3774 	ATOM_BRACKET_LAYOUT_RECORD *record;
3775 	ATOM_COMMON_RECORD_HEADER *record_header;
3776 	enum bp_result result = BP_RESULT_NORECORD;
3777 
3778 	bp = BP_FROM_DCB(dcb);
3779 	record = NULL;
3780 	record_header = NULL;
3781 
3782 	for (;;) {
3783 
3784 		record_header = (ATOM_COMMON_RECORD_HEADER *)
3785 			GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);
3786 		if (record_header == NULL) {
3787 			result = BP_RESULT_BADBIOSTABLE;
3788 			break;
3789 		}
3790 
3791 		/* the end of the list */
3792 		if (record_header->ucRecordType == 0xff ||
3793 			record_header->ucRecordSize == 0)	{
3794 			break;
3795 		}
3796 
3797 		if (record_header->ucRecordType ==
3798 			ATOM_BRACKET_LAYOUT_RECORD_TYPE &&
3799 			sizeof(ATOM_BRACKET_LAYOUT_RECORD)
3800 			<= record_header->ucRecordSize) {
3801 			record = (ATOM_BRACKET_LAYOUT_RECORD *)
3802 				(record_header);
3803 			result = BP_RESULT_OK;
3804 			break;
3805 		}
3806 
3807 		record_offset += record_header->ucRecordSize;
3808 	}
3809 
3810 	/* return if the record not found */
3811 	if (result != BP_RESULT_OK)
3812 		return result;
3813 
3814 	/* get slot sizes */
3815 	slot_layout_info->length = record->ucLength;
3816 	slot_layout_info->width = record->ucWidth;
3817 
3818 	/* get info for each connector in the slot */
3819 	slot_layout_info->num_of_connectors = record->ucConnNum;
3820 	for (j = 0; j < slot_layout_info->num_of_connectors; ++j) {
3821 		slot_layout_info->connectors[j].connector_type =
3822 			(enum connector_layout_type)
3823 			(record->asConnInfo[j].ucConnectorType);
3824 		switch (record->asConnInfo[j].ucConnectorType) {
3825 		case CONNECTOR_TYPE_DVI_D:
3826 			slot_layout_info->connectors[j].connector_type =
3827 				CONNECTOR_LAYOUT_TYPE_DVI_D;
3828 			slot_layout_info->connectors[j].length =
3829 				CONNECTOR_SIZE_DVI;
3830 			break;
3831 
3832 		case CONNECTOR_TYPE_HDMI:
3833 			slot_layout_info->connectors[j].connector_type =
3834 				CONNECTOR_LAYOUT_TYPE_HDMI;
3835 			slot_layout_info->connectors[j].length =
3836 				CONNECTOR_SIZE_HDMI;
3837 			break;
3838 
3839 		case CONNECTOR_TYPE_DISPLAY_PORT:
3840 			slot_layout_info->connectors[j].connector_type =
3841 				CONNECTOR_LAYOUT_TYPE_DP;
3842 			slot_layout_info->connectors[j].length =
3843 				CONNECTOR_SIZE_DP;
3844 			break;
3845 
3846 		case CONNECTOR_TYPE_MINI_DISPLAY_PORT:
3847 			slot_layout_info->connectors[j].connector_type =
3848 				CONNECTOR_LAYOUT_TYPE_MINI_DP;
3849 			slot_layout_info->connectors[j].length =
3850 				CONNECTOR_SIZE_MINI_DP;
3851 			break;
3852 
3853 		default:
3854 			slot_layout_info->connectors[j].connector_type =
3855 				CONNECTOR_LAYOUT_TYPE_UNKNOWN;
3856 			slot_layout_info->connectors[j].length =
3857 				CONNECTOR_SIZE_UNKNOWN;
3858 		}
3859 
3860 		slot_layout_info->connectors[j].position =
3861 			record->asConnInfo[j].ucPosition;
3862 		slot_layout_info->connectors[j].connector_id =
3863 			object_id_from_bios_object_id(
3864 				record->asConnInfo[j].usConnectorObjectId);
3865 	}
3866 	return result;
3867 }
3868 
3869 
3870 static
3871 enum bp_result get_bracket_layout_record(
3872 	struct dc_bios *dcb,
3873 	unsigned int bracket_layout_id,
3874 	struct slot_layout_info *slot_layout_info)
3875 {
3876 	unsigned int i;
3877 	unsigned int record_offset;
3878 	struct bios_parser *bp;
3879 	enum bp_result result;
3880 	ATOM_OBJECT *object;
3881 	ATOM_OBJECT_TABLE *object_table;
3882 	unsigned int genericTableOffset;
3883 
3884 	bp = BP_FROM_DCB(dcb);
3885 	object = NULL;
3886 	if (slot_layout_info == NULL) {
3887 		DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");
3888 		return BP_RESULT_BADINPUT;
3889 	}
3890 
3891 
3892 	genericTableOffset = bp->object_info_tbl_offset +
3893 		bp->object_info_tbl.v1_3->usMiscObjectTableOffset;
3894 	object_table = (ATOM_OBJECT_TABLE *)
3895 		GET_IMAGE(ATOM_OBJECT_TABLE, genericTableOffset);
3896 	if (!object_table)
3897 		return BP_RESULT_FAILURE;
3898 
3899 	result = BP_RESULT_NORECORD;
3900 	for (i = 0; i < object_table->ucNumberOfObjects; ++i) {
3901 
3902 		if (bracket_layout_id ==
3903 			object_table->asObjects[i].usObjectID) {
3904 
3905 			object = &object_table->asObjects[i];
3906 			record_offset = object->usRecordOffset +
3907 				bp->object_info_tbl_offset;
3908 
3909 			result = update_slot_layout_info(dcb, i,
3910 				slot_layout_info, record_offset);
3911 			break;
3912 		}
3913 	}
3914 	return result;
3915 }
3916 
3917 static enum bp_result bios_get_board_layout_info(
3918 	struct dc_bios *dcb,
3919 	struct board_layout_info *board_layout_info)
3920 {
3921 	unsigned int i;
3922 	struct bios_parser *bp;
3923 	enum bp_result record_result;
3924 
3925 	const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {
3926 		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1,
3927 		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2,
3928 		0, 0
3929 	};
3930 
3931 	bp = BP_FROM_DCB(dcb);
3932 	if (board_layout_info == NULL) {
3933 		DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");
3934 		return BP_RESULT_BADINPUT;
3935 	}
3936 
3937 	board_layout_info->num_of_slots = 0;
3938 
3939 	for (i = 0; i < MAX_BOARD_SLOTS; ++i) {
3940 		record_result = get_bracket_layout_record(dcb,
3941 			slot_index_to_vbios_id[i],
3942 			&board_layout_info->slots[i]);
3943 
3944 		if (record_result == BP_RESULT_NORECORD && i > 0)
3945 			break; /* no more slots present in bios */
3946 		else if (record_result != BP_RESULT_OK)
3947 			return record_result;  /* fail */
3948 
3949 		++board_layout_info->num_of_slots;
3950 	}
3951 
3952 	/* all data is valid */
3953 	board_layout_info->is_number_of_slots_valid = 1;
3954 	board_layout_info->is_slots_size_valid = 1;
3955 	board_layout_info->is_connector_offsets_valid = 1;
3956 	board_layout_info->is_connector_lengths_valid = 1;
3957 
3958 	return BP_RESULT_OK;
3959 }
3960 
3961 /******************************************************************************/
3962 
3963 static const struct dc_vbios_funcs vbios_funcs = {
3964 	.get_connectors_number = bios_parser_get_connectors_number,
3965 
3966 	.get_encoder_id = bios_parser_get_encoder_id,
3967 
3968 	.get_connector_id = bios_parser_get_connector_id,
3969 
3970 	.get_dst_number = bios_parser_get_dst_number,
3971 
3972 	.get_src_obj = bios_parser_get_src_obj,
3973 
3974 	.get_dst_obj = bios_parser_get_dst_obj,
3975 
3976 	.get_i2c_info = bios_parser_get_i2c_info,
3977 
3978 	.get_voltage_ddc_info = bios_parser_get_voltage_ddc_info,
3979 
3980 	.get_thermal_ddc_info = bios_parser_get_thermal_ddc_info,
3981 
3982 	.get_hpd_info = bios_parser_get_hpd_info,
3983 
3984 	.get_device_tag = bios_parser_get_device_tag,
3985 
3986 	.get_firmware_info = bios_parser_get_firmware_info,
3987 
3988 	.get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
3989 
3990 	.get_ss_entry_number = bios_parser_get_ss_entry_number,
3991 
3992 	.get_embedded_panel_info = bios_parser_get_embedded_panel_info,
3993 
3994 	.get_gpio_pin_info = bios_parser_get_gpio_pin_info,
3995 
3996 	.get_encoder_cap_info = bios_parser_get_encoder_cap_info,
3997 
3998 	/* bios scratch register communication */
3999 	.is_accelerated_mode = bios_is_accelerated_mode,
4000 	.get_vga_enabled_displays = bios_get_vga_enabled_displays,
4001 
4002 	.set_scratch_critical_state = bios_parser_set_scratch_critical_state,
4003 
4004 	.is_device_id_supported = bios_parser_is_device_id_supported,
4005 
4006 	/* COMMANDS */
4007 	.encoder_control = bios_parser_encoder_control,
4008 
4009 	.transmitter_control = bios_parser_transmitter_control,
4010 
4011 	.crt_control = bios_parser_crt_control,  /* not used in DAL3.  keep for now in case we need to support VGA on Bonaire */
4012 
4013 	.enable_crtc = bios_parser_enable_crtc,
4014 
4015 	.adjust_pixel_clock = bios_parser_adjust_pixel_clock,
4016 
4017 	.set_pixel_clock = bios_parser_set_pixel_clock,
4018 
4019 	.set_dce_clock = bios_parser_set_dce_clock,
4020 
4021 	.enable_spread_spectrum_on_ppll = bios_parser_enable_spread_spectrum_on_ppll,
4022 
4023 	.program_crtc_timing = bios_parser_program_crtc_timing, /* still use.  should probably retire and program directly */
4024 
4025 	.crtc_source_select = bios_parser_crtc_source_select,  /* still use.  should probably retire and program directly */
4026 
4027 	.program_display_engine_pll = bios_parser_program_display_engine_pll,
4028 
4029 	.enable_disp_power_gating = bios_parser_enable_disp_power_gating,
4030 
4031 	/* SW init and patch */
4032 	.post_init = bios_parser_post_init,  /* patch vbios table for mxm module by reading i2c */
4033 
4034 	.bios_parser_destroy = bios_parser_destroy,
4035 
4036 	.get_board_layout_info = bios_get_board_layout_info,
4037 };
4038 
4039 static bool bios_parser_construct(
4040 	struct bios_parser *bp,
4041 	struct bp_init_data *init,
4042 	enum dce_version dce_version)
4043 {
4044 	uint16_t *rom_header_offset = NULL;
4045 	ATOM_ROM_HEADER *rom_header = NULL;
4046 	ATOM_OBJECT_HEADER *object_info_tbl;
4047 	struct atom_data_revision tbl_rev = {0};
4048 
4049 	if (!init)
4050 		return false;
4051 
4052 	if (!init->bios)
4053 		return false;
4054 
4055 	bp->base.funcs = &vbios_funcs;
4056 	bp->base.bios = init->bios;
4057 	bp->base.bios_size = bp->base.bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT;
4058 
4059 	bp->base.ctx = init->ctx;
4060 	bp->base.bios_local_image = NULL;
4061 
4062 	rom_header_offset =
4063 	GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER);
4064 
4065 	if (!rom_header_offset)
4066 		return false;
4067 
4068 	rom_header = GET_IMAGE(ATOM_ROM_HEADER, *rom_header_offset);
4069 
4070 	if (!rom_header)
4071 		return false;
4072 
4073 	get_atom_data_table_revision(&rom_header->sHeader, &tbl_rev);
4074 	if (tbl_rev.major >= 2 && tbl_rev.minor >= 2)
4075 		return false;
4076 
4077 	bp->master_data_tbl =
4078 	GET_IMAGE(ATOM_MASTER_DATA_TABLE,
4079 		rom_header->usMasterDataTableOffset);
4080 
4081 	if (!bp->master_data_tbl)
4082 		return false;
4083 
4084 	bp->object_info_tbl_offset = DATA_TABLES(Object_Header);
4085 
4086 	if (!bp->object_info_tbl_offset)
4087 		return false;
4088 
4089 	object_info_tbl =
4090 	GET_IMAGE(ATOM_OBJECT_HEADER, bp->object_info_tbl_offset);
4091 
4092 	if (!object_info_tbl)
4093 		return false;
4094 
4095 	get_atom_data_table_revision(&object_info_tbl->sHeader,
4096 		&bp->object_info_tbl.revision);
4097 
4098 	if (bp->object_info_tbl.revision.major == 1
4099 		&& bp->object_info_tbl.revision.minor >= 3) {
4100 		ATOM_OBJECT_HEADER_V3 *tbl_v3;
4101 
4102 		tbl_v3 = GET_IMAGE(ATOM_OBJECT_HEADER_V3,
4103 			bp->object_info_tbl_offset);
4104 		if (!tbl_v3)
4105 			return false;
4106 
4107 		bp->object_info_tbl.v1_3 = tbl_v3;
4108 	} else if (bp->object_info_tbl.revision.major == 1
4109 		&& bp->object_info_tbl.revision.minor >= 1)
4110 		bp->object_info_tbl.v1_1 = object_info_tbl;
4111 	else
4112 		return false;
4113 
4114 	dal_bios_parser_init_cmd_tbl(bp);
4115 	dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version);
4116 
4117 	bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);
4118 
4119 	return true;
4120 }
4121 
4122 /******************************************************************************/
4123