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