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