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