xref: /linux/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c (revision fdaf63d9a83aeff2f165b45e7073767bbe62f2fc)
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 #include "core_types.h"
28 
29 #include "ObjectID.h"
30 #include "atomfirmware.h"
31 
32 #include "dc_bios_types.h"
33 #include "include/grph_object_ctrl_defs.h"
34 #include "include/bios_parser_interface.h"
35 #include "include/logger_interface.h"
36 
37 #include "command_table2.h"
38 
39 #include "bios_parser_helper.h"
40 #include "command_table_helper2.h"
41 #include "bios_parser2.h"
42 #include "bios_parser_types_internal2.h"
43 #include "bios_parser_interface.h"
44 
45 #include "bios_parser_common.h"
46 
47 #define DC_LOGGER \
48 	bp->base.ctx->logger
49 
50 #define LAST_RECORD_TYPE 0xff
51 #define SMU9_SYSPLL0_ID  0
52 
53 static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
54 	struct atom_i2c_record *record,
55 	struct graphics_object_i2c_info *info);
56 
57 static enum bp_result bios_parser_get_firmware_info(
58 	struct dc_bios *dcb,
59 	struct dc_firmware_info *info);
60 
61 static enum bp_result bios_parser_get_encoder_cap_info(
62 	struct dc_bios *dcb,
63 	struct graphics_object_id object_id,
64 	struct bp_encoder_cap_info *info);
65 
66 static enum bp_result get_firmware_info_v3_1(
67 	struct bios_parser *bp,
68 	struct dc_firmware_info *info);
69 
70 static enum bp_result get_firmware_info_v3_2(
71 	struct bios_parser *bp,
72 	struct dc_firmware_info *info);
73 
74 static enum bp_result get_firmware_info_v3_4(
75 	struct bios_parser *bp,
76 	struct dc_firmware_info *info);
77 
78 static enum bp_result get_firmware_info_v3_5(
79 	struct bios_parser *bp,
80 	struct dc_firmware_info *info);
81 
82 static struct atom_hpd_int_record *get_hpd_record(struct bios_parser *bp,
83 		struct atom_display_object_path_v2 *object);
84 
85 static struct atom_encoder_caps_record *get_encoder_cap_record(
86 	struct bios_parser *bp,
87 	struct atom_display_object_path_v2 *object);
88 
89 #define BIOS_IMAGE_SIZE_OFFSET 2
90 #define BIOS_IMAGE_SIZE_UNIT 512
91 
92 #define DATA_TABLES(table) (bp->master_data_tbl->listOfdatatables.table)
93 
94 static void bios_parser2_destruct(struct bios_parser *bp)
95 {
96 	kfree(bp->base.bios_local_image);
97 	kfree(bp->base.integrated_info);
98 }
99 
100 static void firmware_parser_destroy(struct dc_bios **dcb)
101 {
102 	struct bios_parser *bp = BP_FROM_DCB(*dcb);
103 
104 	if (!bp) {
105 		BREAK_TO_DEBUGGER();
106 		return;
107 	}
108 
109 	bios_parser2_destruct(bp);
110 
111 	kfree(bp);
112 	*dcb = NULL;
113 }
114 
115 static void get_atom_data_table_revision(
116 	struct atom_common_table_header *atom_data_tbl,
117 	struct atom_data_revision *tbl_revision)
118 {
119 	if (!tbl_revision)
120 		return;
121 
122 	/* initialize the revision to 0 which is invalid revision */
123 	tbl_revision->major = 0;
124 	tbl_revision->minor = 0;
125 
126 	if (!atom_data_tbl)
127 		return;
128 
129 	tbl_revision->major =
130 			(uint32_t) atom_data_tbl->format_revision & 0x3f;
131 	tbl_revision->minor =
132 			(uint32_t) atom_data_tbl->content_revision & 0x3f;
133 }
134 
135 /* BIOS oject table displaypath is per connector.
136  * There is extra path not for connector. BIOS fill its encoderid as 0
137  */
138 static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)
139 {
140 	struct bios_parser *bp = BP_FROM_DCB(dcb);
141 	unsigned int count = 0;
142 	unsigned int i;
143 
144 	switch (bp->object_info_tbl.revision.minor) {
145 	default:
146 	case 4:
147 		for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++)
148 			if (bp->object_info_tbl.v1_4->display_path[i].encoderobjid != 0)
149 				count++;
150 
151 		break;
152 
153 	case 5:
154 		for (i = 0; i < bp->object_info_tbl.v1_5->number_of_path; i++)
155 			if (bp->object_info_tbl.v1_5->display_path[i].encoderobjid != 0)
156 				count++;
157 
158 		break;
159 	}
160 	return (uint8_t)count;
161 }
162 
163 static struct graphics_object_id bios_parser_get_connector_id(
164 	struct dc_bios *dcb,
165 	uint8_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 	struct object_info_table *tbl = &bp->object_info_tbl;
171 	struct display_object_info_table_v1_4 *v1_4 = tbl->v1_4;
172 
173 	struct display_object_info_table_v1_5 *v1_5 = tbl->v1_5;
174 
175 	switch (bp->object_info_tbl.revision.minor) {
176 	default:
177 	case 4:
178 		if (v1_4->number_of_path > i) {
179 			/* If display_objid is generic object id,  the encoderObj
180 			 * /extencoderobjId should be 0
181 			 */
182 			if (v1_4->display_path[i].encoderobjid != 0 &&
183 			    v1_4->display_path[i].display_objid != 0)
184 				object_id = object_id_from_bios_object_id(
185 					v1_4->display_path[i].display_objid);
186 		}
187 		break;
188 
189 	case 5:
190 		if (v1_5->number_of_path > i) {
191 			/* If display_objid is generic object id,  the encoderObjId
192 		 * should be 0
193 		 */
194 			if (v1_5->display_path[i].encoderobjid != 0 &&
195 			    v1_5->display_path[i].display_objid != 0)
196 				object_id = object_id_from_bios_object_id(
197 					v1_5->display_path[i].display_objid);
198 		}
199 		break;
200 	}
201 	return object_id;
202 }
203 
204 static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
205 	struct graphics_object_id object_id, uint32_t index,
206 	struct graphics_object_id *src_object_id)
207 {
208 	(void)index;
209 	struct bios_parser *bp = BP_FROM_DCB(dcb);
210 	unsigned int i;
211 	enum bp_result bp_result = BP_RESULT_BADINPUT;
212 	struct graphics_object_id obj_id = { 0 };
213 	struct object_info_table *tbl = &bp->object_info_tbl;
214 
215 	if (!src_object_id)
216 		return bp_result;
217 
218 	switch (object_id.type) {
219 	/* Encoder's Source is GPU.  BIOS does not provide GPU, since all
220 	 * displaypaths point to same GPU (0x1100).  Hardcode GPU object type
221 	 */
222 	case OBJECT_TYPE_ENCODER:
223 		/* TODO: since num of src must be less than 2.
224 		 * If found in for loop, should break.
225 		 * DAL2 implementation may be changed too
226 		 */
227 		switch (bp->object_info_tbl.revision.minor) {
228 		default:
229 		case 4:
230 			for (i = 0; i < tbl->v1_4->number_of_path; i++) {
231 				obj_id = object_id_from_bios_object_id(
232 					tbl->v1_4->display_path[i].encoderobjid);
233 				if (object_id.type == obj_id.type &&
234 				    object_id.id == obj_id.id &&
235 				    object_id.enum_id == obj_id.enum_id) {
236 					*src_object_id =
237 						object_id_from_bios_object_id(
238 							0x1100);
239 					/* break; */
240 				}
241 			}
242 			bp_result = BP_RESULT_OK;
243 			break;
244 
245 		case 5:
246 			for (i = 0; i < tbl->v1_5->number_of_path; i++) {
247 				obj_id = object_id_from_bios_object_id(
248 					tbl->v1_5->display_path[i].encoderobjid);
249 				if (object_id.type == obj_id.type &&
250 				    object_id.id == obj_id.id &&
251 				    object_id.enum_id == obj_id.enum_id) {
252 					*src_object_id =
253 						object_id_from_bios_object_id(
254 							0x1100);
255 					/* break; */
256 				}
257 			}
258 			bp_result = BP_RESULT_OK;
259 			break;
260 		}
261 		break;
262 	case OBJECT_TYPE_CONNECTOR:
263 		switch (bp->object_info_tbl.revision.minor) {
264 		default:
265 		case 4:
266 			for (i = 0; i < tbl->v1_4->number_of_path; i++) {
267 				obj_id = object_id_from_bios_object_id(
268 					tbl->v1_4->display_path[i]
269 						.display_objid);
270 
271 				if (object_id.type == obj_id.type &&
272 				    object_id.id == obj_id.id &&
273 				    object_id.enum_id == obj_id.enum_id) {
274 					*src_object_id =
275 						object_id_from_bios_object_id(
276 							tbl->v1_4
277 								->display_path[i]
278 								.encoderobjid);
279 					/* break; */
280 				}
281 			}
282 			bp_result = BP_RESULT_OK;
283 			break;
284 		}
285 		bp_result = BP_RESULT_OK;
286 		break;
287 		case 5:
288 			for (i = 0; i < tbl->v1_5->number_of_path; i++) {
289 				obj_id = object_id_from_bios_object_id(
290 								       tbl->v1_5->display_path[i].display_objid);
291 
292 				if (object_id.type == obj_id.type &&
293 				    object_id.id == obj_id.id &&
294 				    object_id.enum_id == obj_id.enum_id) {
295 					*src_object_id = object_id_from_bios_object_id(
296 										       tbl->v1_5->display_path[i].encoderobjid);
297 					/* break; */
298 				}
299 			}
300 		bp_result = BP_RESULT_OK;
301 		break;
302 
303 	default:
304 		bp_result = BP_RESULT_OK;
305 		break;
306 	}
307 
308 	return bp_result;
309 }
310 
311 /* from graphics_object_id, find display path which includes the object_id */
312 static struct atom_display_object_path_v2 *get_bios_object(
313 		struct bios_parser *bp,
314 		struct graphics_object_id id)
315 {
316 	unsigned int i;
317 	struct graphics_object_id obj_id = {0};
318 
319 	switch (id.type) {
320 	case OBJECT_TYPE_ENCODER:
321 		for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) {
322 			obj_id = object_id_from_bios_object_id(
323 					bp->object_info_tbl.v1_4->display_path[i].encoderobjid);
324 			if (id.type == obj_id.type && id.id == obj_id.id
325 					&& id.enum_id == obj_id.enum_id)
326 				return &bp->object_info_tbl.v1_4->display_path[i];
327 		}
328 		fallthrough;
329 	case OBJECT_TYPE_CONNECTOR:
330 	case OBJECT_TYPE_GENERIC:
331 		/* Both Generic and Connector Object ID
332 		 * will be stored on display_objid
333 		 */
334 		for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) {
335 			obj_id = object_id_from_bios_object_id(
336 					bp->object_info_tbl.v1_4->display_path[i].display_objid);
337 			if (id.type == obj_id.type && id.id == obj_id.id
338 					&& id.enum_id == obj_id.enum_id)
339 				return &bp->object_info_tbl.v1_4->display_path[i];
340 		}
341 		fallthrough;
342 	default:
343 		return NULL;
344 	}
345 }
346 
347 /* from graphics_object_id, find display path which includes the object_id */
348 static struct atom_display_object_path_v3 *get_bios_object_from_path_v3(struct bios_parser *bp,
349 									struct graphics_object_id id)
350 {
351 	unsigned int i;
352 	struct graphics_object_id obj_id = {0};
353 
354 	switch (id.type) {
355 	case OBJECT_TYPE_ENCODER:
356 		for (i = 0; i < bp->object_info_tbl.v1_5->number_of_path; i++) {
357 			obj_id = object_id_from_bios_object_id(
358 					bp->object_info_tbl.v1_5->display_path[i].encoderobjid);
359 			if (id.type == obj_id.type && id.id == obj_id.id
360 					&& id.enum_id == obj_id.enum_id)
361 				return &bp->object_info_tbl.v1_5->display_path[i];
362 		}
363 	break;
364 
365 	case OBJECT_TYPE_CONNECTOR:
366 	case OBJECT_TYPE_GENERIC:
367 		/* Both Generic and Connector Object ID
368 		 * will be stored on display_objid
369 		 */
370 		for (i = 0; i < bp->object_info_tbl.v1_5->number_of_path; i++) {
371 			obj_id = object_id_from_bios_object_id(
372 					bp->object_info_tbl.v1_5->display_path[i].display_objid);
373 			if (id.type == obj_id.type && id.id == obj_id.id
374 					&& id.enum_id == obj_id.enum_id)
375 				return &bp->object_info_tbl.v1_5->display_path[i];
376 		}
377 	break;
378 
379 	default:
380 		return NULL;
381 	}
382 
383 	return NULL;
384 }
385 
386 static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
387 	struct graphics_object_id id,
388 	struct graphics_object_i2c_info *info)
389 {
390 	uint32_t offset;
391 	struct atom_display_object_path_v2 *object;
392 
393 	struct atom_display_object_path_v3 *object_path_v3;
394 
395 	struct atom_common_record_header *header;
396 	struct atom_i2c_record *record;
397 	struct atom_i2c_record dummy_record = {0};
398 	struct bios_parser *bp = BP_FROM_DCB(dcb);
399 	int i;
400 
401 	if (!info)
402 		return BP_RESULT_BADINPUT;
403 
404 	if (id.type == OBJECT_TYPE_GENERIC) {
405 		dummy_record.i2c_id = (uint8_t)id.id;
406 
407 		if (get_gpio_i2c_info(bp, &dummy_record, info) == BP_RESULT_OK)
408 			return BP_RESULT_OK;
409 		else
410 			return BP_RESULT_NORECORD;
411 	}
412 
413 	switch (bp->object_info_tbl.revision.minor) {
414 	case 4:
415 	default:
416 		object = get_bios_object(bp, id);
417 
418 		if (!object)
419 			return BP_RESULT_BADINPUT;
420 
421 		offset = object->disp_recordoffset + bp->object_info_tbl_offset;
422 		break;
423 	case 5:
424 		object_path_v3 = get_bios_object_from_path_v3(bp, id);
425 
426 		if (!object_path_v3)
427 			return BP_RESULT_BADINPUT;
428 
429 		offset = object_path_v3->disp_recordoffset + bp->object_info_tbl_offset;
430 		break;
431 	}
432 
433 	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
434 		header = GET_IMAGE(struct atom_common_record_header, offset);
435 
436 		if (!header)
437 			return BP_RESULT_BADBIOSTABLE;
438 
439 		if (header->record_type == LAST_RECORD_TYPE ||
440 			!header->record_size)
441 			break;
442 
443 		if (header->record_type == ATOM_I2C_RECORD_TYPE
444 			&& sizeof(struct atom_i2c_record) <=
445 							header->record_size) {
446 			/* get the I2C info */
447 			record = (struct atom_i2c_record *) header;
448 
449 			if (get_gpio_i2c_info(bp, record, info) ==
450 								BP_RESULT_OK)
451 				return BP_RESULT_OK;
452 		}
453 
454 		offset += header->record_size;
455 	}
456 
457 	return BP_RESULT_NORECORD;
458 }
459 
460 static enum bp_result get_gpio_i2c_info(
461 	struct bios_parser *bp,
462 	struct atom_i2c_record *record,
463 	struct graphics_object_i2c_info *info)
464 {
465 	struct atom_gpio_pin_lut_v2_1 *header;
466 	uint32_t count = 0;
467 	unsigned int table_index = 0;
468 	bool find_valid = false;
469 	struct atom_gpio_pin_assignment *pin;
470 
471 	if (!info)
472 		return BP_RESULT_BADINPUT;
473 
474 	/* get the GPIO_I2C info */
475 	if (!DATA_TABLES(gpio_pin_lut))
476 		return BP_RESULT_BADBIOSTABLE;
477 
478 	header = GET_IMAGE(struct atom_gpio_pin_lut_v2_1,
479 					DATA_TABLES(gpio_pin_lut));
480 	if (!header)
481 		return BP_RESULT_BADBIOSTABLE;
482 
483 	if (sizeof(struct atom_common_table_header) +
484 			sizeof(struct atom_gpio_pin_assignment)	>
485 			le16_to_cpu(header->table_header.structuresize))
486 		return BP_RESULT_BADBIOSTABLE;
487 
488 	/* TODO: is version change? */
489 	if (header->table_header.content_revision != 1)
490 		return BP_RESULT_UNSUPPORTED;
491 
492 	/* get data count */
493 	count = (le16_to_cpu(header->table_header.structuresize)
494 			- sizeof(struct atom_common_table_header))
495 				/ sizeof(struct atom_gpio_pin_assignment);
496 
497 	if (!bios_get_image(&bp->base, DATA_TABLES(gpio_pin_lut),
498 			    le16_to_cpu(header->table_header.structuresize)))
499 		return BP_RESULT_BADBIOSTABLE;
500 
501 	pin = (struct atom_gpio_pin_assignment *) header->gpio_pin;
502 
503 	for (table_index = 0; table_index < count; table_index++) {
504 		if (((record->i2c_id & I2C_HW_CAP) 				== (pin->gpio_id & I2C_HW_CAP)) &&
505 		    ((record->i2c_id & I2C_HW_ENGINE_ID_MASK)	== (pin->gpio_id & I2C_HW_ENGINE_ID_MASK)) &&
506 		    ((record->i2c_id & I2C_HW_LANE_MUX) 		== (pin->gpio_id & I2C_HW_LANE_MUX))) {
507 			/* still valid */
508 			find_valid = true;
509 			break;
510 		}
511 		pin = (struct atom_gpio_pin_assignment *)((uint8_t *)pin + sizeof(struct atom_gpio_pin_assignment));
512 	}
513 
514 	/* If we don't find the entry that we are looking for then
515 	 *  we will return BP_Result_BadBiosTable.
516 	 */
517 	if (find_valid == false)
518 		return BP_RESULT_BADBIOSTABLE;
519 
520 	/* get the GPIO_I2C_INFO */
521 	info->i2c_hw_assist = (record->i2c_id & I2C_HW_CAP) ? true : false;
522 	info->i2c_line = record->i2c_id & I2C_HW_LANE_MUX;
523 	info->i2c_engine_id = (record->i2c_id & I2C_HW_ENGINE_ID_MASK) >> 4;
524 	info->i2c_slave_address = record->i2c_slave_addr;
525 
526 	/* TODO: check how to get register offset for en, Y, etc. */
527 	info->gpio_info.clk_a_register_index = le16_to_cpu(pin->data_a_reg_index);
528 	info->gpio_info.clk_a_shift = pin->gpio_bitshift;
529 
530 	return BP_RESULT_OK;
531 }
532 
533 static struct atom_hpd_int_record *get_hpd_record_for_path_v3(struct bios_parser *bp,
534 							      struct atom_display_object_path_v3 *object)
535 {
536 	struct atom_common_record_header *header;
537 	uint32_t offset;
538 	int i;
539 
540 	if (!object) {
541 		BREAK_TO_DEBUGGER(); /* Invalid object */
542 		return NULL;
543 	}
544 
545 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
546 
547 	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
548 		header = GET_IMAGE(struct atom_common_record_header, offset);
549 
550 		if (!header)
551 			return NULL;
552 
553 		if (header->record_type == ATOM_RECORD_END_TYPE ||
554 			!header->record_size)
555 			break;
556 
557 		if (header->record_type == ATOM_HPD_INT_RECORD_TYPE
558 			&& sizeof(struct atom_hpd_int_record) <=
559 							header->record_size)
560 			return (struct atom_hpd_int_record *) header;
561 
562 		offset += header->record_size;
563 	}
564 
565 	return NULL;
566 }
567 
568 static enum bp_result bios_parser_get_hpd_info(
569 	struct dc_bios *dcb,
570 	struct graphics_object_id id,
571 	struct graphics_object_hpd_info *info)
572 {
573 	struct bios_parser *bp = BP_FROM_DCB(dcb);
574 	struct atom_display_object_path_v2 *object;
575 	struct atom_display_object_path_v3 *object_path_v3;
576 	struct atom_hpd_int_record *record = NULL;
577 
578 	if (!info)
579 		return BP_RESULT_BADINPUT;
580 
581 	switch (bp->object_info_tbl.revision.minor) {
582 	case 4:
583 	default:
584 		object = get_bios_object(bp, id);
585 
586 		if (!object)
587 			return BP_RESULT_BADINPUT;
588 
589 		record = get_hpd_record(bp, object);
590 		break;
591 	case 5:
592 		object_path_v3 = get_bios_object_from_path_v3(bp, id);
593 
594 		if (!object_path_v3)
595 			return BP_RESULT_BADINPUT;
596 
597 		record = get_hpd_record_for_path_v3(bp, object_path_v3);
598 		break;
599 	}
600 
601 	if (record != NULL) {
602 		info->hpd_int_gpio_uid = record->pin_id;
603 		info->hpd_active = record->plugin_pin_state;
604 		return BP_RESULT_OK;
605 	}
606 
607 	return BP_RESULT_NORECORD;
608 }
609 
610 static struct atom_hpd_int_record *get_hpd_record(
611 	struct bios_parser *bp,
612 	struct atom_display_object_path_v2 *object)
613 {
614 	struct atom_common_record_header *header;
615 	uint32_t offset;
616 	int i;
617 
618 	if (!object) {
619 		BREAK_TO_DEBUGGER(); /* Invalid object */
620 		return NULL;
621 	}
622 
623 	offset = le16_to_cpu(object->disp_recordoffset)
624 			+ bp->object_info_tbl_offset;
625 
626 	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
627 		header = GET_IMAGE(struct atom_common_record_header, offset);
628 
629 		if (!header)
630 			return NULL;
631 
632 		if (header->record_type == LAST_RECORD_TYPE ||
633 			!header->record_size)
634 			break;
635 
636 		if (header->record_type == ATOM_HPD_INT_RECORD_TYPE
637 			&& sizeof(struct atom_hpd_int_record) <=
638 							header->record_size)
639 			return (struct atom_hpd_int_record *) header;
640 
641 		offset += header->record_size;
642 	}
643 
644 	return NULL;
645 }
646 
647 /**
648  * bios_parser_get_gpio_pin_info
649  * Get GpioPin information of input gpio id
650  *
651  * @dcb:     pointer to the DC BIOS
652  * @gpio_id: GPIO ID
653  * @info:    GpioPin information structure
654  * return: Bios parser result code
655  * note:
656  *  to get the GPIO PIN INFO, we need:
657  *  1. get the GPIO_ID from other object table, see GetHPDInfo()
658  *  2. in DATA_TABLE.GPIO_Pin_LUT, search all records,
659  *	to get the registerA  offset/mask
660  */
661 static enum bp_result bios_parser_get_gpio_pin_info(
662 	struct dc_bios *dcb,
663 	uint32_t gpio_id,
664 	struct gpio_pin_info *info)
665 {
666 	struct bios_parser *bp = BP_FROM_DCB(dcb);
667 	struct atom_gpio_pin_lut_v2_1 *header;
668 	uint32_t count = 0;
669 	uint32_t i = 0;
670 
671 	if (!DATA_TABLES(gpio_pin_lut))
672 		return BP_RESULT_BADBIOSTABLE;
673 
674 	header = GET_IMAGE(struct atom_gpio_pin_lut_v2_1,
675 						DATA_TABLES(gpio_pin_lut));
676 	if (!header)
677 		return BP_RESULT_BADBIOSTABLE;
678 
679 	if (sizeof(struct atom_common_table_header) +
680 			sizeof(struct atom_gpio_pin_assignment)
681 			> le16_to_cpu(header->table_header.structuresize))
682 		return BP_RESULT_BADBIOSTABLE;
683 
684 	if (header->table_header.content_revision != 1)
685 		return BP_RESULT_UNSUPPORTED;
686 
687 	/* Temporary hard code gpio pin info */
688 	count = (le16_to_cpu(header->table_header.structuresize)
689 			- sizeof(struct atom_common_table_header))
690 				/ sizeof(struct atom_gpio_pin_assignment);
691 
692 	if (!bios_get_image(&bp->base, DATA_TABLES(gpio_pin_lut),
693 			    le16_to_cpu(header->table_header.structuresize)))
694 		return BP_RESULT_BADBIOSTABLE;
695 
696 	for (i = 0; i < count; ++i) {
697 		if (header->gpio_pin[i].gpio_id != gpio_id)
698 			continue;
699 
700 		info->offset =
701 			(uint32_t) le16_to_cpu(
702 					header->gpio_pin[i].data_a_reg_index);
703 		info->offset_y = info->offset + 2;
704 		info->offset_en = info->offset + 1;
705 		info->offset_mask = info->offset - 1;
706 
707 		if (header->gpio_pin[i].gpio_bitshift >= 32)
708 			return BP_RESULT_BADBIOSTABLE;
709 
710 		info->mask = 1u << header->gpio_pin[i].gpio_bitshift;
711 		info->mask_y = info->mask + 2;
712 		info->mask_en = info->mask + 1;
713 		info->mask_mask = info->mask - 1;
714 
715 		return BP_RESULT_OK;
716 	}
717 
718 	return BP_RESULT_NORECORD;
719 }
720 
721 static enum bp_result bios_parser_get_connector_aux_info(struct dc_bios *dcb,
722 	struct graphics_object_id id,
723 	struct graphics_object_i2c_info *info)
724 {
725 	uint32_t offset;
726 	struct atom_display_object_path_v2 *object;
727 	struct atom_display_object_path_v3 *object_path_v3;
728 	struct atom_common_record_header *header;
729 	struct atom_i2c_record *record;
730 	struct bios_parser *bp = BP_FROM_DCB(dcb);
731 
732 	if (!info)
733 		return BP_RESULT_BADINPUT;
734 
735 	switch (bp->object_info_tbl.revision.minor) {
736 	case 4:
737 	default:
738 		object = get_bios_object(bp, id);
739 
740 		if (!object)
741 			return BP_RESULT_BADINPUT;
742 
743 		offset = object->disp_recordoffset + bp->object_info_tbl_offset;
744 		break;
745 	case 5:
746 		object_path_v3 = get_bios_object_from_path_v3(bp, id);
747 
748 		if (!object_path_v3)
749 			return BP_RESULT_BADINPUT;
750 
751 		offset = object_path_v3->disp_recordoffset + bp->object_info_tbl_offset;
752 		break;
753 	}
754 
755 	for (;;) {
756 		header = GET_IMAGE(struct atom_common_record_header, offset);
757 
758 		if (!header)
759 			return BP_RESULT_BADBIOSTABLE;
760 
761 		if (header->record_type == LAST_RECORD_TYPE ||
762 			!header->record_size)
763 			break;
764 
765 		if (header->record_type == ATOM_I2C_RECORD_TYPE
766 			&& sizeof(struct atom_i2c_record) <=
767 			header->record_size) {
768 			/* get_connector_aux_info - which aux instance is used it is based
769 			 * on record->i2c_id field only, does not need GPIO DDC
770 			 */
771 			record = (struct atom_i2c_record *)header;
772 
773 			info->i2c_line = record->i2c_id & I2C_HW_LANE_MUX;
774 
775 			return BP_RESULT_OK;
776 		}
777 
778 		offset += header->record_size;
779 	}
780 
781 	return BP_RESULT_NORECORD;
782 }
783 
784 static struct device_id device_type_from_device_id(uint16_t device_id)
785 {
786 
787 	struct device_id result_device_id;
788 
789 	result_device_id.raw_device_tag = device_id;
790 
791 	switch (device_id) {
792 	case ATOM_DISPLAY_LCD1_SUPPORT:
793 		result_device_id.device_type = DEVICE_TYPE_LCD;
794 		result_device_id.enum_id = 1;
795 		break;
796 
797 	case ATOM_DISPLAY_LCD2_SUPPORT:
798 		result_device_id.device_type = DEVICE_TYPE_LCD;
799 		result_device_id.enum_id = 2;
800 		break;
801 
802 	case ATOM_DISPLAY_DFP1_SUPPORT:
803 		result_device_id.device_type = DEVICE_TYPE_DFP;
804 		result_device_id.enum_id = 1;
805 		break;
806 
807 	case ATOM_DISPLAY_DFP2_SUPPORT:
808 		result_device_id.device_type = DEVICE_TYPE_DFP;
809 		result_device_id.enum_id = 2;
810 		break;
811 
812 	case ATOM_DISPLAY_DFP3_SUPPORT:
813 		result_device_id.device_type = DEVICE_TYPE_DFP;
814 		result_device_id.enum_id = 3;
815 		break;
816 
817 	case ATOM_DISPLAY_DFP4_SUPPORT:
818 		result_device_id.device_type = DEVICE_TYPE_DFP;
819 		result_device_id.enum_id = 4;
820 		break;
821 
822 	case ATOM_DISPLAY_DFP5_SUPPORT:
823 		result_device_id.device_type = DEVICE_TYPE_DFP;
824 		result_device_id.enum_id = 5;
825 		break;
826 
827 	case ATOM_DISPLAY_DFP6_SUPPORT:
828 		result_device_id.device_type = DEVICE_TYPE_DFP;
829 		result_device_id.enum_id = 6;
830 		break;
831 
832 	default:
833 		BREAK_TO_DEBUGGER(); /* Invalid device Id */
834 		result_device_id.device_type = DEVICE_TYPE_UNKNOWN;
835 		result_device_id.enum_id = 0;
836 	}
837 	return result_device_id;
838 }
839 
840 static enum bp_result bios_parser_get_device_tag(
841 	struct dc_bios *dcb,
842 	struct graphics_object_id connector_object_id,
843 	uint32_t device_tag_index,
844 	struct connector_device_tag_info *info)
845 {
846 	(void)device_tag_index;
847 	struct bios_parser *bp = BP_FROM_DCB(dcb);
848 	struct atom_display_object_path_v2 *object;
849 
850 	struct atom_display_object_path_v3 *object_path_v3;
851 
852 
853 	if (!info)
854 		return BP_RESULT_BADINPUT;
855 
856 	switch (bp->object_info_tbl.revision.minor) {
857 	case 4:
858 	default:
859 	        /* getBiosObject will return MXM object */
860 		object = get_bios_object(bp, connector_object_id);
861 
862 		if (!object) {
863 			BREAK_TO_DEBUGGER(); /* Invalid object id */
864 			return BP_RESULT_BADINPUT;
865 		}
866 
867 		info->acpi_device = 0; /* BIOS no longer provides this */
868 		info->dev_id = device_type_from_device_id(object->device_tag);
869 		break;
870 	case 5:
871 		object_path_v3 = get_bios_object_from_path_v3(bp, connector_object_id);
872 
873 		if (!object_path_v3) {
874 			BREAK_TO_DEBUGGER(); /* Invalid object id */
875 			return BP_RESULT_BADINPUT;
876 		}
877 		info->acpi_device = 0; /* BIOS no longer provides this */
878 		info->dev_id = device_type_from_device_id(object_path_v3->device_tag);
879 		break;
880 	}
881 
882 	return BP_RESULT_OK;
883 }
884 
885 static enum bp_result get_ss_info_v4_1(
886 	struct bios_parser *bp,
887 	uint32_t id,
888 	uint32_t index,
889 	struct spread_spectrum_info *ss_info)
890 {
891 	(void)index;
892 	enum bp_result result = BP_RESULT_OK;
893 	struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL;
894 	struct atom_smu_info_v3_3 *smu_info = NULL;
895 
896 	if (!ss_info)
897 		return BP_RESULT_BADINPUT;
898 
899 	if (!DATA_TABLES(dce_info))
900 		return BP_RESULT_BADBIOSTABLE;
901 
902 	disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_1,
903 							DATA_TABLES(dce_info));
904 	if (!disp_cntl_tbl)
905 		return BP_RESULT_BADBIOSTABLE;
906 
907 
908 	ss_info->type.STEP_AND_DELAY_INFO = false;
909 	ss_info->spread_percentage_divider = 1000;
910 	/* BIOS no longer uses target clock.  Always enable for now */
911 	ss_info->target_clock_range = 0xffffffff;
912 
913 	switch (id) {
914 	case AS_SIGNAL_TYPE_DVI:
915 		ss_info->spread_spectrum_percentage =
916 				disp_cntl_tbl->dvi_ss_percentage;
917 		ss_info->spread_spectrum_range =
918 				disp_cntl_tbl->dvi_ss_rate_10hz * 10;
919 		if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
920 			ss_info->type.CENTER_MODE = true;
921 
922 		DC_LOG_BIOS("AS_SIGNAL_TYPE_DVI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
923 		break;
924 	case AS_SIGNAL_TYPE_HDMI:
925 		ss_info->spread_spectrum_percentage =
926 				disp_cntl_tbl->hdmi_ss_percentage;
927 		ss_info->spread_spectrum_range =
928 				disp_cntl_tbl->hdmi_ss_rate_10hz * 10;
929 		if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
930 			ss_info->type.CENTER_MODE = true;
931 
932 		DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
933 		break;
934 	/* TODO LVDS not support anymore? */
935 	case AS_SIGNAL_TYPE_DISPLAY_PORT:
936 		ss_info->spread_spectrum_percentage =
937 				disp_cntl_tbl->dp_ss_percentage;
938 		ss_info->spread_spectrum_range =
939 				disp_cntl_tbl->dp_ss_rate_10hz * 10;
940 		if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
941 			ss_info->type.CENTER_MODE = true;
942 
943 		DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
944 		break;
945 	case AS_SIGNAL_TYPE_GPU_PLL:
946 		/* atom_firmware: DAL only get data from dce_info table.
947 		 * if data within smu_info is needed for DAL, VBIOS should
948 		 * copy it into dce_info
949 		 */
950 		result = BP_RESULT_UNSUPPORTED;
951 		break;
952 	case AS_SIGNAL_TYPE_XGMI:
953 		smu_info =  GET_IMAGE(struct atom_smu_info_v3_3,
954 				      DATA_TABLES(smu_info));
955 		if (!smu_info)
956 			return BP_RESULT_BADBIOSTABLE;
957 		DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info->gpuclk_ss_percentage);
958 		ss_info->spread_spectrum_percentage =
959 				smu_info->waflclk_ss_percentage;
960 		ss_info->spread_spectrum_range =
961 				smu_info->gpuclk_ss_rate_10hz * 10;
962 		if (smu_info->waflclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
963 			ss_info->type.CENTER_MODE = true;
964 
965 		DC_LOG_BIOS("AS_SIGNAL_TYPE_XGMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
966 		break;
967 	default:
968 		result = BP_RESULT_UNSUPPORTED;
969 	}
970 
971 	return result;
972 }
973 
974 static enum bp_result get_ss_info_v4_2(
975 	struct bios_parser *bp,
976 	uint32_t id,
977 	uint32_t index,
978 	struct spread_spectrum_info *ss_info)
979 {
980 	(void)index;
981 	enum bp_result result = BP_RESULT_OK;
982 	struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL;
983 	struct atom_smu_info_v3_1 *smu_info = NULL;
984 
985 	if (!ss_info)
986 		return BP_RESULT_BADINPUT;
987 
988 	if (!DATA_TABLES(dce_info))
989 		return BP_RESULT_BADBIOSTABLE;
990 
991 	if (!DATA_TABLES(smu_info))
992 		return BP_RESULT_BADBIOSTABLE;
993 
994 	disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_2,
995 							DATA_TABLES(dce_info));
996 	if (!disp_cntl_tbl)
997 		return BP_RESULT_BADBIOSTABLE;
998 
999 	smu_info =  GET_IMAGE(struct atom_smu_info_v3_1, DATA_TABLES(smu_info));
1000 	if (!smu_info)
1001 		return BP_RESULT_BADBIOSTABLE;
1002 
1003 	DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info->gpuclk_ss_percentage);
1004 	ss_info->type.STEP_AND_DELAY_INFO = false;
1005 	ss_info->spread_percentage_divider = 1000;
1006 	/* BIOS no longer uses target clock.  Always enable for now */
1007 	ss_info->target_clock_range = 0xffffffff;
1008 
1009 	switch (id) {
1010 	case AS_SIGNAL_TYPE_DVI:
1011 		ss_info->spread_spectrum_percentage =
1012 				disp_cntl_tbl->dvi_ss_percentage;
1013 		ss_info->spread_spectrum_range =
1014 				disp_cntl_tbl->dvi_ss_rate_10hz * 10;
1015 		if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
1016 			ss_info->type.CENTER_MODE = true;
1017 
1018 		DC_LOG_BIOS("AS_SIGNAL_TYPE_DVI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
1019 		break;
1020 	case AS_SIGNAL_TYPE_HDMI:
1021 		ss_info->spread_spectrum_percentage =
1022 				disp_cntl_tbl->hdmi_ss_percentage;
1023 		ss_info->spread_spectrum_range =
1024 				disp_cntl_tbl->hdmi_ss_rate_10hz * 10;
1025 		if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
1026 			ss_info->type.CENTER_MODE = true;
1027 
1028 		DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
1029 		break;
1030 	/* TODO LVDS not support anymore? */
1031 	case AS_SIGNAL_TYPE_DISPLAY_PORT:
1032 		ss_info->spread_spectrum_percentage =
1033 				smu_info->gpuclk_ss_percentage;
1034 		ss_info->spread_spectrum_range =
1035 				smu_info->gpuclk_ss_rate_10hz * 10;
1036 		if (smu_info->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
1037 			ss_info->type.CENTER_MODE = true;
1038 
1039 		DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
1040 		break;
1041 	case AS_SIGNAL_TYPE_GPU_PLL:
1042 		/* atom_firmware: DAL only get data from dce_info table.
1043 		 * if data within smu_info is needed for DAL, VBIOS should
1044 		 * copy it into dce_info
1045 		 */
1046 		result = BP_RESULT_UNSUPPORTED;
1047 		break;
1048 	default:
1049 		result = BP_RESULT_UNSUPPORTED;
1050 	}
1051 
1052 	return result;
1053 }
1054 
1055 static enum bp_result get_ss_info_v4_5(
1056 	struct bios_parser *bp,
1057 	uint32_t id,
1058 	uint32_t index,
1059 	struct spread_spectrum_info *ss_info)
1060 {
1061 	(void)index;
1062 	enum bp_result result = BP_RESULT_OK;
1063 	struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
1064 
1065 	if (!ss_info)
1066 		return BP_RESULT_BADINPUT;
1067 
1068 	if (!DATA_TABLES(dce_info))
1069 		return BP_RESULT_BADBIOSTABLE;
1070 
1071 	disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_5,
1072 							DATA_TABLES(dce_info));
1073 	if (!disp_cntl_tbl)
1074 		return BP_RESULT_BADBIOSTABLE;
1075 
1076 	ss_info->type.STEP_AND_DELAY_INFO = false;
1077 	ss_info->spread_percentage_divider = 1000;
1078 	/* BIOS no longer uses target clock.  Always enable for now */
1079 	ss_info->target_clock_range = 0xffffffff;
1080 
1081 	switch (id) {
1082 	case AS_SIGNAL_TYPE_DVI:
1083 		ss_info->spread_spectrum_percentage =
1084 				disp_cntl_tbl->dvi_ss_percentage;
1085 		ss_info->spread_spectrum_range =
1086 				disp_cntl_tbl->dvi_ss_rate_10hz * 10;
1087 		if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
1088 			ss_info->type.CENTER_MODE = true;
1089 
1090 		DC_LOG_BIOS("AS_SIGNAL_TYPE_DVI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
1091 		break;
1092 	case AS_SIGNAL_TYPE_HDMI:
1093 		ss_info->spread_spectrum_percentage =
1094 				disp_cntl_tbl->hdmi_ss_percentage;
1095 		ss_info->spread_spectrum_range =
1096 				disp_cntl_tbl->hdmi_ss_rate_10hz * 10;
1097 		if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
1098 			ss_info->type.CENTER_MODE = true;
1099 
1100 		DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
1101 		break;
1102 	case AS_SIGNAL_TYPE_DISPLAY_PORT:
1103 		if (bp->base.integrated_info) {
1104 			DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", bp->base.integrated_info->gpuclk_ss_percentage);
1105 			ss_info->spread_spectrum_percentage =
1106 					bp->base.integrated_info->gpuclk_ss_percentage;
1107 			ss_info->type.CENTER_MODE =
1108 					bp->base.integrated_info->gpuclk_ss_type;
1109 		} else {
1110 			ss_info->spread_spectrum_percentage =
1111 				disp_cntl_tbl->dp_ss_percentage;
1112 			ss_info->spread_spectrum_range =
1113 				disp_cntl_tbl->dp_ss_rate_10hz * 10;
1114 			if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
1115 				ss_info->type.CENTER_MODE = true;
1116 		}
1117 		DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
1118 		break;
1119 	case AS_SIGNAL_TYPE_GPU_PLL:
1120 		/* atom_smu_info_v4_0 does not have fields for SS for SMU Display PLL anymore.
1121 		 * SMU Display PLL supposed to be without spread.
1122 		 * Better place for it would be in atom_display_controller_info_v4_5 table.
1123 		 */
1124 		result = BP_RESULT_UNSUPPORTED;
1125 		break;
1126 	default:
1127 		result = BP_RESULT_UNSUPPORTED;
1128 		break;
1129 	}
1130 
1131 	return result;
1132 }
1133 
1134 /**
1135  * bios_parser_get_spread_spectrum_info
1136  * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or
1137  * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info
1138  * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info
1139  * ver 3.1,
1140  * there is only one entry for each signal /ss id.  However, there is
1141  * no planning of supporting multiple spread Sprectum entry for EverGreen
1142  * @dcb:     pointer to the DC BIOS
1143  * @signal:  ASSignalType to be converted to info index
1144  * @index:   number of entries that match the converted info index
1145  * @ss_info: sprectrum information structure,
1146  * return: Bios parser result code
1147  */
1148 static enum bp_result bios_parser_get_spread_spectrum_info(
1149 	struct dc_bios *dcb,
1150 	enum as_signal_type signal,
1151 	uint32_t index,
1152 	struct spread_spectrum_info *ss_info)
1153 {
1154 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1155 	enum bp_result result = BP_RESULT_UNSUPPORTED;
1156 	struct atom_common_table_header *header;
1157 	struct atom_data_revision tbl_revision;
1158 
1159 	if (!ss_info) /* check for bad input */
1160 		return BP_RESULT_BADINPUT;
1161 
1162 	if (!DATA_TABLES(dce_info))
1163 		return BP_RESULT_UNSUPPORTED;
1164 
1165 	header = GET_IMAGE(struct atom_common_table_header,
1166 						DATA_TABLES(dce_info));
1167 	get_atom_data_table_revision(header, &tbl_revision);
1168 
1169 	switch (tbl_revision.major) {
1170 	case 4:
1171 		switch (tbl_revision.minor) {
1172 		case 1:
1173 			return get_ss_info_v4_1(bp, signal, index, ss_info);
1174 		case 2:
1175 		case 3:
1176 		case 4:
1177 			return get_ss_info_v4_2(bp, signal, index, ss_info);
1178 		case 5:
1179 			return get_ss_info_v4_5(bp, signal, index, ss_info);
1180 
1181 		default:
1182 			ASSERT(0);
1183 			break;
1184 		}
1185 		break;
1186 	default:
1187 		break;
1188 	}
1189 	/* there can not be more then one entry for SS Info table */
1190 	return result;
1191 }
1192 
1193 static enum bp_result get_soc_bb_info_v4_4(
1194 	struct bios_parser *bp,
1195 	struct bp_soc_bb_info *soc_bb_info)
1196 {
1197 	enum bp_result result = BP_RESULT_OK;
1198 	struct atom_display_controller_info_v4_4 *disp_cntl_tbl = NULL;
1199 
1200 	if (!soc_bb_info)
1201 		return BP_RESULT_BADINPUT;
1202 
1203 	if (!DATA_TABLES(dce_info))
1204 		return BP_RESULT_BADBIOSTABLE;
1205 
1206 	if (!DATA_TABLES(smu_info))
1207 		return BP_RESULT_BADBIOSTABLE;
1208 
1209 	disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_4,
1210 							DATA_TABLES(dce_info));
1211 	if (!disp_cntl_tbl)
1212 		return BP_RESULT_BADBIOSTABLE;
1213 
1214 	soc_bb_info->dram_clock_change_latency_100ns = disp_cntl_tbl->max_mclk_chg_lat;
1215 	soc_bb_info->dram_sr_enter_exit_latency_100ns = disp_cntl_tbl->max_sr_enter_exit_lat;
1216 	soc_bb_info->dram_sr_exit_latency_100ns = disp_cntl_tbl->max_sr_exit_lat;
1217 
1218 	return result;
1219 }
1220 
1221 static enum bp_result get_soc_bb_info_v4_5(
1222 	struct bios_parser *bp,
1223 	struct bp_soc_bb_info *soc_bb_info)
1224 {
1225 	enum bp_result result = BP_RESULT_OK;
1226 	struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
1227 
1228 	if (!soc_bb_info)
1229 		return BP_RESULT_BADINPUT;
1230 
1231 	if (!DATA_TABLES(dce_info))
1232 		return BP_RESULT_BADBIOSTABLE;
1233 
1234 	disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_5,
1235 							DATA_TABLES(dce_info));
1236 	if (!disp_cntl_tbl)
1237 		return BP_RESULT_BADBIOSTABLE;
1238 
1239 	soc_bb_info->dram_clock_change_latency_100ns = disp_cntl_tbl->max_mclk_chg_lat;
1240 	soc_bb_info->dram_sr_enter_exit_latency_100ns = disp_cntl_tbl->max_sr_enter_exit_lat;
1241 	soc_bb_info->dram_sr_exit_latency_100ns = disp_cntl_tbl->max_sr_exit_lat;
1242 
1243 	return result;
1244 }
1245 
1246 static enum bp_result bios_parser_get_soc_bb_info(
1247 	struct dc_bios *dcb,
1248 	struct bp_soc_bb_info *soc_bb_info)
1249 {
1250 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1251 	enum bp_result result = BP_RESULT_UNSUPPORTED;
1252 	struct atom_common_table_header *header;
1253 	struct atom_data_revision tbl_revision;
1254 
1255 	if (!soc_bb_info) /* check for bad input */
1256 		return BP_RESULT_BADINPUT;
1257 
1258 	if (!DATA_TABLES(dce_info))
1259 		return BP_RESULT_UNSUPPORTED;
1260 
1261 	header = GET_IMAGE(struct atom_common_table_header,
1262 						DATA_TABLES(dce_info));
1263 	get_atom_data_table_revision(header, &tbl_revision);
1264 
1265 	switch (tbl_revision.major) {
1266 	case 4:
1267 		switch (tbl_revision.minor) {
1268 		case 1:
1269 		case 2:
1270 		case 3:
1271 			break;
1272 		case 4:
1273 			result = get_soc_bb_info_v4_4(bp, soc_bb_info);
1274 			break;
1275 		case 5:
1276 			result = get_soc_bb_info_v4_5(bp, soc_bb_info);
1277 			break;
1278 		default:
1279 			break;
1280 		}
1281 		break;
1282 	default:
1283 		break;
1284 	}
1285 
1286 	return result;
1287 }
1288 
1289 static enum bp_result get_disp_caps_v4_1(
1290 	struct bios_parser *bp,
1291 	uint8_t *dce_caps)
1292 {
1293 	enum bp_result result = BP_RESULT_OK;
1294 	struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL;
1295 
1296 	if (!dce_caps)
1297 		return BP_RESULT_BADINPUT;
1298 
1299 	if (!DATA_TABLES(dce_info))
1300 		return BP_RESULT_BADBIOSTABLE;
1301 
1302 	disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_1,
1303 							DATA_TABLES(dce_info));
1304 
1305 	if (!disp_cntl_tbl)
1306 		return BP_RESULT_BADBIOSTABLE;
1307 
1308 	*dce_caps = (uint8_t)disp_cntl_tbl->display_caps;
1309 
1310 	return result;
1311 }
1312 
1313 static enum bp_result get_disp_caps_v4_2(
1314 	struct bios_parser *bp,
1315 	uint8_t *dce_caps)
1316 {
1317 	enum bp_result result = BP_RESULT_OK;
1318 	struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL;
1319 
1320 	if (!dce_caps)
1321 		return BP_RESULT_BADINPUT;
1322 
1323 	if (!DATA_TABLES(dce_info))
1324 		return BP_RESULT_BADBIOSTABLE;
1325 
1326 	disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_2,
1327 							DATA_TABLES(dce_info));
1328 
1329 	if (!disp_cntl_tbl)
1330 		return BP_RESULT_BADBIOSTABLE;
1331 
1332 	*dce_caps = (uint8_t)disp_cntl_tbl->display_caps;
1333 
1334 	return result;
1335 }
1336 
1337 static enum bp_result get_disp_caps_v4_3(
1338 	struct bios_parser *bp,
1339 	uint8_t *dce_caps)
1340 {
1341 	enum bp_result result = BP_RESULT_OK;
1342 	struct atom_display_controller_info_v4_3 *disp_cntl_tbl = NULL;
1343 
1344 	if (!dce_caps)
1345 		return BP_RESULT_BADINPUT;
1346 
1347 	if (!DATA_TABLES(dce_info))
1348 		return BP_RESULT_BADBIOSTABLE;
1349 
1350 	disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_3,
1351 							DATA_TABLES(dce_info));
1352 
1353 	if (!disp_cntl_tbl)
1354 		return BP_RESULT_BADBIOSTABLE;
1355 
1356 	*dce_caps = (uint8_t)disp_cntl_tbl->display_caps;
1357 
1358 	return result;
1359 }
1360 
1361 static enum bp_result get_disp_caps_v4_4(
1362 	struct bios_parser *bp,
1363 	uint8_t *dce_caps)
1364 {
1365 	enum bp_result result = BP_RESULT_OK;
1366 	struct atom_display_controller_info_v4_4 *disp_cntl_tbl = NULL;
1367 
1368 	if (!dce_caps)
1369 		return BP_RESULT_BADINPUT;
1370 
1371 	if (!DATA_TABLES(dce_info))
1372 		return BP_RESULT_BADBIOSTABLE;
1373 
1374 	disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_4,
1375 							DATA_TABLES(dce_info));
1376 
1377 	if (!disp_cntl_tbl)
1378 		return BP_RESULT_BADBIOSTABLE;
1379 
1380 	*dce_caps = (uint8_t)disp_cntl_tbl->display_caps;
1381 
1382 	return result;
1383 }
1384 
1385 static enum bp_result get_disp_caps_v4_5(
1386 	struct bios_parser *bp,
1387 	uint8_t *dce_caps)
1388 {
1389 	enum bp_result result = BP_RESULT_OK;
1390 	struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
1391 
1392 	if (!dce_caps)
1393 		return BP_RESULT_BADINPUT;
1394 
1395 	if (!DATA_TABLES(dce_info))
1396 		return BP_RESULT_BADBIOSTABLE;
1397 
1398 	disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_5,
1399 							DATA_TABLES(dce_info));
1400 
1401 	if (!disp_cntl_tbl)
1402 		return BP_RESULT_BADBIOSTABLE;
1403 
1404 	*dce_caps = (uint8_t)disp_cntl_tbl->display_caps;
1405 
1406 	return result;
1407 }
1408 
1409 static enum bp_result bios_parser_get_lttpr_interop(
1410 	struct dc_bios *dcb,
1411 	uint8_t *dce_caps)
1412 {
1413 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1414 	enum bp_result result = BP_RESULT_UNSUPPORTED;
1415 	struct atom_common_table_header *header;
1416 	struct atom_data_revision tbl_revision;
1417 
1418 	if (!DATA_TABLES(dce_info))
1419 		return BP_RESULT_UNSUPPORTED;
1420 
1421 	header = GET_IMAGE(struct atom_common_table_header,
1422 						DATA_TABLES(dce_info));
1423 	get_atom_data_table_revision(header, &tbl_revision);
1424 	switch (tbl_revision.major) {
1425 	case 4:
1426 		switch (tbl_revision.minor) {
1427 		case 1:
1428 			result = get_disp_caps_v4_1(bp, dce_caps);
1429 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
1430 			break;
1431 		case 2:
1432 			result = get_disp_caps_v4_2(bp, dce_caps);
1433 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
1434 			break;
1435 		case 3:
1436 			result = get_disp_caps_v4_3(bp, dce_caps);
1437 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
1438 			break;
1439 		case 4:
1440 			result = get_disp_caps_v4_4(bp, dce_caps);
1441 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
1442 			break;
1443 		case 5:
1444 			result = get_disp_caps_v4_5(bp, dce_caps);
1445 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
1446 			break;
1447 
1448 		default:
1449 			break;
1450 		}
1451 		break;
1452 	default:
1453 		break;
1454 	}
1455 	DC_LOG_BIOS("DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE: %d tbl_revision.major = %d tbl_revision.minor = %d\n", *dce_caps, tbl_revision.major, tbl_revision.minor);
1456 	return result;
1457 }
1458 
1459 static enum bp_result bios_parser_get_lttpr_caps(
1460 	struct dc_bios *dcb,
1461 	uint8_t *dce_caps)
1462 {
1463 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1464 	enum bp_result result = BP_RESULT_UNSUPPORTED;
1465 	struct atom_common_table_header *header;
1466 	struct atom_data_revision tbl_revision;
1467 
1468 	if (!DATA_TABLES(dce_info))
1469 		return BP_RESULT_UNSUPPORTED;
1470 
1471 	*dce_caps  = 0;
1472 	header = GET_IMAGE(struct atom_common_table_header,
1473 						DATA_TABLES(dce_info));
1474 	get_atom_data_table_revision(header, &tbl_revision);
1475 	switch (tbl_revision.major) {
1476 	case 4:
1477 		switch (tbl_revision.minor) {
1478 		case 1:
1479 			result = get_disp_caps_v4_1(bp, dce_caps);
1480 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
1481 			break;
1482 		case 2:
1483 			result = get_disp_caps_v4_2(bp, dce_caps);
1484 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
1485 			break;
1486 		case 3:
1487 			result = get_disp_caps_v4_3(bp, dce_caps);
1488 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
1489 			break;
1490 		case 4:
1491 			result = get_disp_caps_v4_4(bp, dce_caps);
1492 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
1493 			break;
1494 		case 5:
1495 			result = get_disp_caps_v4_5(bp, dce_caps);
1496 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
1497 			break;
1498 		default:
1499 			break;
1500 		}
1501 		break;
1502 	default:
1503 		break;
1504 	}
1505 	DC_LOG_BIOS("DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE: %d tbl_revision.major = %d tbl_revision.minor = %d\n", *dce_caps, tbl_revision.major, tbl_revision.minor);
1506 	if (dcb->ctx->dc->config.force_bios_enable_lttpr && *dce_caps == 0) {
1507 		*dce_caps = 1;
1508 		DC_LOG_BIOS("DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE: forced enabled");
1509 	}
1510 	return result;
1511 }
1512 
1513 static enum bp_result get_embedded_panel_info_v2_1(
1514 		struct bios_parser *bp,
1515 		struct embedded_panel_info *info)
1516 {
1517 	struct lcd_info_v2_1 *lvds;
1518 
1519 	if (!info)
1520 		return BP_RESULT_BADINPUT;
1521 
1522 	if (!DATA_TABLES(lcd_info))
1523 		return BP_RESULT_UNSUPPORTED;
1524 
1525 	lvds = GET_IMAGE(struct lcd_info_v2_1, DATA_TABLES(lcd_info));
1526 
1527 	if (!lvds)
1528 		return BP_RESULT_BADBIOSTABLE;
1529 
1530 	/* TODO: previous vv1_3, should v2_1 */
1531 	if (!((lvds->table_header.format_revision == 2)
1532 			&& (lvds->table_header.content_revision >= 1)))
1533 		return BP_RESULT_UNSUPPORTED;
1534 
1535 	memset(info, 0, sizeof(struct embedded_panel_info));
1536 
1537 	/* We need to convert from 10KHz units into KHz units */
1538 	info->lcd_timing.pixel_clk = le16_to_cpu(lvds->lcd_timing.pixclk) * 10;
1539 	/* usHActive does not include borders, according to VBIOS team */
1540 	info->lcd_timing.horizontal_addressable = le16_to_cpu(lvds->lcd_timing.h_active);
1541 	/* usHBlanking_Time includes borders, so we should really be
1542 	 * subtractingborders duing this translation, but LVDS generally
1543 	 * doesn't have borders, so we should be okay leaving this as is for
1544 	 * now.  May need to revisit if we ever have LVDS with borders
1545 	 */
1546 	info->lcd_timing.horizontal_blanking_time = le16_to_cpu(lvds->lcd_timing.h_blanking_time);
1547 	/* usVActive does not include borders, according to VBIOS team*/
1548 	info->lcd_timing.vertical_addressable = le16_to_cpu(lvds->lcd_timing.v_active);
1549 	/* usVBlanking_Time includes borders, so we should really be
1550 	 * subtracting borders duing this translation, but LVDS generally
1551 	 * doesn't have borders, so we should be okay leaving this as is for
1552 	 * now. May need to revisit if we ever have LVDS with borders
1553 	 */
1554 	info->lcd_timing.vertical_blanking_time = le16_to_cpu(lvds->lcd_timing.v_blanking_time);
1555 	info->lcd_timing.horizontal_sync_offset = le16_to_cpu(lvds->lcd_timing.h_sync_offset);
1556 	info->lcd_timing.horizontal_sync_width = le16_to_cpu(lvds->lcd_timing.h_sync_width);
1557 	info->lcd_timing.vertical_sync_offset = le16_to_cpu(lvds->lcd_timing.v_sync_offset);
1558 	info->lcd_timing.vertical_sync_width = le16_to_cpu(lvds->lcd_timing.v_syncwidth);
1559 	info->lcd_timing.horizontal_border = lvds->lcd_timing.h_border;
1560 	info->lcd_timing.vertical_border = lvds->lcd_timing.v_border;
1561 
1562 	/* not provided by VBIOS */
1563 	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 0;
1564 
1565 	info->lcd_timing.misc_info.H_SYNC_POLARITY = !(lvds->lcd_timing.miscinfo &
1566 						       ATOM_HSYNC_POLARITY);
1567 	info->lcd_timing.misc_info.V_SYNC_POLARITY = !(lvds->lcd_timing.miscinfo &
1568 						       ATOM_VSYNC_POLARITY);
1569 
1570 	/* not provided by VBIOS */
1571 	info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0;
1572 
1573 	info->lcd_timing.misc_info.H_REPLICATION_BY2 = !!(lvds->lcd_timing.miscinfo
1574 			& ATOM_H_REPLICATIONBY2);
1575 	info->lcd_timing.misc_info.V_REPLICATION_BY2 = !!(lvds->lcd_timing.miscinfo
1576 			& ATOM_V_REPLICATIONBY2);
1577 	info->lcd_timing.misc_info.COMPOSITE_SYNC = !!(lvds->lcd_timing.miscinfo
1578 			& ATOM_COMPOSITESYNC);
1579 	info->lcd_timing.misc_info.INTERLACE = !!(lvds->lcd_timing.miscinfo & ATOM_INTERLACE);
1580 
1581 	/* not provided by VBIOS*/
1582 	info->lcd_timing.misc_info.DOUBLE_CLOCK = 0;
1583 	/* not provided by VBIOS*/
1584 	info->ss_id = 0;
1585 
1586 	info->realtek_eDPToLVDS = !!(lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID);
1587 
1588 	return BP_RESULT_OK;
1589 }
1590 
1591 static enum bp_result bios_parser_get_embedded_panel_info(
1592 		struct dc_bios *dcb,
1593 		struct embedded_panel_info *info)
1594 {
1595 	struct bios_parser
1596 	*bp = BP_FROM_DCB(dcb);
1597 	struct atom_common_table_header *header;
1598 	struct atom_data_revision tbl_revision;
1599 
1600 	if (!DATA_TABLES(lcd_info))
1601 		return BP_RESULT_FAILURE;
1602 
1603 	header = GET_IMAGE(struct atom_common_table_header, DATA_TABLES(lcd_info));
1604 
1605 	if (!header)
1606 		return BP_RESULT_BADBIOSTABLE;
1607 
1608 	get_atom_data_table_revision(header, &tbl_revision);
1609 
1610 	switch (tbl_revision.major) {
1611 	case 2:
1612 		switch (tbl_revision.minor) {
1613 		case 1:
1614 			return get_embedded_panel_info_v2_1(bp, info);
1615 		default:
1616 			break;
1617 		}
1618 		break;
1619 	default:
1620 		break;
1621 	}
1622 
1623 	return BP_RESULT_FAILURE;
1624 }
1625 
1626 static uint32_t get_support_mask_for_device_id(struct device_id device_id)
1627 {
1628 	enum dal_device_type device_type = device_id.device_type;
1629 	uint32_t enum_id = device_id.enum_id;
1630 
1631 	switch (device_type) {
1632 	case DEVICE_TYPE_LCD:
1633 		switch (enum_id) {
1634 		case 1:
1635 			return ATOM_DISPLAY_LCD1_SUPPORT;
1636 		default:
1637 			break;
1638 		}
1639 		break;
1640 	case DEVICE_TYPE_DFP:
1641 		switch (enum_id) {
1642 		case 1:
1643 			return ATOM_DISPLAY_DFP1_SUPPORT;
1644 		case 2:
1645 			return ATOM_DISPLAY_DFP2_SUPPORT;
1646 		case 3:
1647 			return ATOM_DISPLAY_DFP3_SUPPORT;
1648 		case 4:
1649 			return ATOM_DISPLAY_DFP4_SUPPORT;
1650 		case 5:
1651 			return ATOM_DISPLAY_DFP5_SUPPORT;
1652 		case 6:
1653 			return ATOM_DISPLAY_DFP6_SUPPORT;
1654 		default:
1655 			break;
1656 		}
1657 		break;
1658 	default:
1659 		break;
1660 	}
1661 
1662 	/* Unidentified device ID, return empty support mask. */
1663 	return 0;
1664 }
1665 
1666 static bool bios_parser_is_device_id_supported(
1667 	struct dc_bios *dcb,
1668 	struct device_id id)
1669 {
1670 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1671 
1672 	uint32_t mask = get_support_mask_for_device_id(id);
1673 
1674 	switch (bp->object_info_tbl.revision.minor) {
1675 	case 4:
1676 	default:
1677 		return (le16_to_cpu(bp->object_info_tbl.v1_4->supporteddevices) & mask) != 0;
1678 		break;
1679 	case 5:
1680 		return (le16_to_cpu(bp->object_info_tbl.v1_5->supporteddevices) & mask) != 0;
1681 		break;
1682 	}
1683 }
1684 
1685 static uint32_t bios_parser_get_ss_entry_number(
1686 	struct dc_bios *dcb,
1687 	enum as_signal_type signal)
1688 {
1689 	(void)dcb;
1690 	(void)signal;
1691 	/* TODO: DAL2 atomfirmware implementation does not need this.
1692 	 * why DAL3 need this?
1693 	 */
1694 	return 1;
1695 }
1696 
1697 static enum bp_result bios_parser_transmitter_control(
1698 	struct dc_bios *dcb,
1699 	struct bp_transmitter_control *cntl)
1700 {
1701 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1702 
1703 	if (!bp->cmd_tbl.transmitter_control)
1704 		return BP_RESULT_FAILURE;
1705 
1706 	return bp->cmd_tbl.transmitter_control(bp, cntl);
1707 }
1708 
1709 static enum bp_result bios_parser_encoder_control(
1710 	struct dc_bios *dcb,
1711 	struct bp_encoder_control *cntl)
1712 {
1713 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1714 
1715 	if (!bp->cmd_tbl.dig_encoder_control)
1716 		return BP_RESULT_FAILURE;
1717 
1718 	return bp->cmd_tbl.dig_encoder_control(bp, cntl);
1719 }
1720 
1721 static enum bp_result bios_parser_set_pixel_clock(
1722 	struct dc_bios *dcb,
1723 	struct bp_pixel_clock_parameters *bp_params)
1724 {
1725 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1726 
1727 	if (!bp->cmd_tbl.set_pixel_clock)
1728 		return BP_RESULT_FAILURE;
1729 
1730 	return bp->cmd_tbl.set_pixel_clock(bp, bp_params);
1731 }
1732 
1733 static enum bp_result bios_parser_set_dce_clock(
1734 	struct dc_bios *dcb,
1735 	struct bp_set_dce_clock_parameters *bp_params)
1736 {
1737 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1738 
1739 	if (!bp->cmd_tbl.set_dce_clock)
1740 		return BP_RESULT_FAILURE;
1741 
1742 	return bp->cmd_tbl.set_dce_clock(bp, bp_params);
1743 }
1744 
1745 static enum bp_result bios_parser_program_crtc_timing(
1746 	struct dc_bios *dcb,
1747 	struct bp_hw_crtc_timing_parameters *bp_params)
1748 {
1749 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1750 
1751 	if (!bp->cmd_tbl.set_crtc_timing)
1752 		return BP_RESULT_FAILURE;
1753 
1754 	return bp->cmd_tbl.set_crtc_timing(bp, bp_params);
1755 }
1756 
1757 static enum bp_result bios_parser_enable_crtc(
1758 	struct dc_bios *dcb,
1759 	enum controller_id id,
1760 	bool enable)
1761 {
1762 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1763 
1764 	if (!bp->cmd_tbl.enable_crtc)
1765 		return BP_RESULT_FAILURE;
1766 
1767 	return bp->cmd_tbl.enable_crtc(bp, id, enable);
1768 }
1769 
1770 static enum bp_result bios_parser_enable_disp_power_gating(
1771 	struct dc_bios *dcb,
1772 	enum controller_id controller_id,
1773 	enum bp_pipe_control_action action)
1774 {
1775 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1776 
1777 	if (!bp->cmd_tbl.enable_disp_power_gating)
1778 		return BP_RESULT_FAILURE;
1779 
1780 	return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id,
1781 		action);
1782 }
1783 
1784 static enum bp_result bios_parser_enable_lvtma_control(
1785 	struct dc_bios *dcb,
1786 	uint8_t uc_pwr_on,
1787 	uint8_t pwrseq_instance,
1788 	uint8_t bypass_panel_control_wait)
1789 {
1790 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1791 
1792 	if (!bp->cmd_tbl.enable_lvtma_control)
1793 		return BP_RESULT_FAILURE;
1794 
1795 	return bp->cmd_tbl.enable_lvtma_control(bp, uc_pwr_on, pwrseq_instance, bypass_panel_control_wait);
1796 }
1797 
1798 static bool bios_parser_is_accelerated_mode(
1799 	struct dc_bios *dcb)
1800 {
1801 	return bios_is_accelerated_mode(dcb);
1802 }
1803 
1804 /**
1805  * bios_parser_set_scratch_critical_state - update critical state bit
1806  *                                          in VBIOS scratch register
1807  *
1808  * @dcb:   pointer to the DC BIO
1809  * @state: set or reset state
1810  */
1811 static void bios_parser_set_scratch_critical_state(
1812 	struct dc_bios *dcb,
1813 	bool state)
1814 {
1815 	bios_set_scratch_critical_state(dcb, state);
1816 }
1817 
1818 static enum bp_result bios_parser_get_firmware_info(
1819 	struct dc_bios *dcb,
1820 	struct dc_firmware_info *info)
1821 {
1822 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1823 	static enum bp_result result = BP_RESULT_BADBIOSTABLE;
1824 	struct atom_common_table_header *header;
1825 
1826 	struct atom_data_revision revision;
1827 
1828 	if (info && DATA_TABLES(firmwareinfo)) {
1829 		header = GET_IMAGE(struct atom_common_table_header,
1830 				DATA_TABLES(firmwareinfo));
1831 		get_atom_data_table_revision(header, &revision);
1832 		switch (revision.major) {
1833 		case 3:
1834 			switch (revision.minor) {
1835 			case 1:
1836 				result = get_firmware_info_v3_1(bp, info);
1837 				break;
1838 			case 2:
1839 			case 3:
1840 				result = get_firmware_info_v3_2(bp, info);
1841 				break;
1842 			case 4:
1843 				result = get_firmware_info_v3_4(bp, info);
1844 				break;
1845 			case 5:
1846 				result = get_firmware_info_v3_5(bp, info);
1847 				break;
1848 			default:
1849 				break;
1850 			}
1851 			break;
1852 		default:
1853 			break;
1854 		}
1855 	}
1856 
1857 	return result;
1858 }
1859 
1860 static enum bp_result get_firmware_info_v3_1(
1861 	struct bios_parser *bp,
1862 	struct dc_firmware_info *info)
1863 {
1864 	struct atom_firmware_info_v3_1 *firmware_info;
1865 	struct atom_firmware_info_v3_2 *firmware_info32;
1866 	struct atom_display_controller_info_v4_1 *dce_info = NULL;
1867 
1868 	if (!info)
1869 		return BP_RESULT_BADINPUT;
1870 
1871 	firmware_info = GET_IMAGE(struct atom_firmware_info_v3_1,
1872 			DATA_TABLES(firmwareinfo));
1873 	firmware_info32 = GET_IMAGE(struct atom_firmware_info_v3_2,
1874 			DATA_TABLES(firmwareinfo));
1875 
1876 	dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1,
1877 			DATA_TABLES(dce_info));
1878 
1879 	if (!firmware_info || !firmware_info32 || !dce_info)
1880 		return BP_RESULT_BADBIOSTABLE;
1881 
1882 	memset(info, 0, sizeof(*info));
1883 
1884 	/* Pixel clock pll information. */
1885 	 /* We need to convert from 10KHz units into KHz units */
1886 	info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
1887 	info->default_engine_clk = firmware_info->bootup_sclk_in10khz * 10;
1888 
1889 	 /* 27MHz for Vega10: */
1890 	info->pll_info.crystal_frequency = dce_info->dce_refclk_10khz * 10;
1891 
1892 	/* Hardcode frequency if BIOS gives no DCE Ref Clk */
1893 	if (info->pll_info.crystal_frequency == 0)
1894 		info->pll_info.crystal_frequency = 27000;
1895 	/*dp_phy_ref_clk is not correct for atom_display_controller_info_v4_2, but we don't use it*/
1896 	info->dp_phy_ref_clk     = dce_info->dpphy_refclk_10khz * 10;
1897 	info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10;
1898 
1899 	/* Get GPU PLL VCO Clock */
1900 
1901 	if (bp->cmd_tbl.get_smu_clock_info != NULL) {
1902 		/* VBIOS gives in 10KHz */
1903 		info->smu_gpu_pll_output_freq =
1904 				bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;
1905 	}
1906 
1907 	/* These fields are marked as reserved in v3_1, but they appear to be populated
1908 	 * properly.
1909 	 */
1910 	if (firmware_info32 && firmware_info32->board_i2c_feature_id == 0x2) {
1911 		info->oem_i2c_present = true;
1912 		info->oem_i2c_obj_id = firmware_info32->board_i2c_feature_gpio_id;
1913 	} else {
1914 		info->oem_i2c_present = false;
1915 	}
1916 
1917 	return BP_RESULT_OK;
1918 }
1919 
1920 static enum bp_result get_firmware_info_v3_2(
1921 	struct bios_parser *bp,
1922 	struct dc_firmware_info *info)
1923 {
1924 	struct atom_firmware_info_v3_2 *firmware_info;
1925 	struct atom_display_controller_info_v4_1 *dce_info = NULL;
1926 	struct atom_common_table_header *header;
1927 	struct atom_data_revision revision;
1928 	struct atom_smu_info_v3_2 *smu_info_v3_2 = NULL;
1929 	struct atom_smu_info_v3_3 *smu_info_v3_3 = NULL;
1930 
1931 	if (!info)
1932 		return BP_RESULT_BADINPUT;
1933 
1934 	firmware_info = GET_IMAGE(struct atom_firmware_info_v3_2,
1935 			DATA_TABLES(firmwareinfo));
1936 
1937 	dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1,
1938 			DATA_TABLES(dce_info));
1939 
1940 	if (!firmware_info || !dce_info)
1941 		return BP_RESULT_BADBIOSTABLE;
1942 
1943 	memset(info, 0, sizeof(*info));
1944 
1945 	header = GET_IMAGE(struct atom_common_table_header,
1946 					DATA_TABLES(smu_info));
1947 	get_atom_data_table_revision(header, &revision);
1948 
1949 	if (revision.minor == 2) {
1950 		/* Vega12 */
1951 		smu_info_v3_2 = GET_IMAGE(struct atom_smu_info_v3_2,
1952 							DATA_TABLES(smu_info));
1953 		if (!smu_info_v3_2)
1954 			return BP_RESULT_BADBIOSTABLE;
1955 
1956 		DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_2->gpuclk_ss_percentage);
1957 
1958 		info->default_engine_clk = smu_info_v3_2->bootup_dcefclk_10khz * 10;
1959 	} else if (revision.minor == 3) {
1960 		/* Vega20 */
1961 		smu_info_v3_3 = GET_IMAGE(struct atom_smu_info_v3_3,
1962 							DATA_TABLES(smu_info));
1963 		if (!smu_info_v3_3)
1964 			return BP_RESULT_BADBIOSTABLE;
1965 
1966 		DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_3->gpuclk_ss_percentage);
1967 
1968 		info->default_engine_clk = smu_info_v3_3->bootup_dcefclk_10khz * 10;
1969 	}
1970 
1971 	 // We need to convert from 10KHz units into KHz units.
1972 	info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
1973 
1974 	 /* 27MHz for Vega10 & Vega12; 100MHz for Vega20 */
1975 	info->pll_info.crystal_frequency = dce_info->dce_refclk_10khz * 10;
1976 	/* Hardcode frequency if BIOS gives no DCE Ref Clk */
1977 	if (info->pll_info.crystal_frequency == 0) {
1978 		if (revision.minor == 2)
1979 			info->pll_info.crystal_frequency = 27000;
1980 		else if (revision.minor == 3)
1981 			info->pll_info.crystal_frequency = 100000;
1982 	}
1983 	/*dp_phy_ref_clk is not correct for atom_display_controller_info_v4_2, but we don't use it*/
1984 	info->dp_phy_ref_clk     = dce_info->dpphy_refclk_10khz * 10;
1985 	info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10;
1986 
1987 	/* Get GPU PLL VCO Clock */
1988 	if (bp->cmd_tbl.get_smu_clock_info != NULL) {
1989 		if (revision.minor == 2)
1990 			info->smu_gpu_pll_output_freq =
1991 					bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;
1992 		else if (revision.minor == 3)
1993 			info->smu_gpu_pll_output_freq =
1994 					bp->cmd_tbl.get_smu_clock_info(bp, SMU11_SYSPLL3_0_ID) * 10;
1995 	}
1996 
1997 	if (firmware_info->board_i2c_feature_id == 0x2) {
1998 		info->oem_i2c_present = true;
1999 		info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;
2000 	} else {
2001 		info->oem_i2c_present = false;
2002 	}
2003 
2004 	return BP_RESULT_OK;
2005 }
2006 
2007 static enum bp_result get_firmware_info_v3_4(
2008 	struct bios_parser *bp,
2009 	struct dc_firmware_info *info)
2010 {
2011 	struct atom_firmware_info_v3_4 *firmware_info;
2012 	struct atom_common_table_header *header;
2013 	struct atom_data_revision revision;
2014 	struct atom_display_controller_info_v4_1 *dce_info_v4_1 = NULL;
2015 	struct atom_display_controller_info_v4_4 *dce_info_v4_4 = NULL;
2016 
2017 	struct atom_smu_info_v3_5 *smu_info_v3_5 = NULL;
2018 	struct atom_display_controller_info_v4_5 *dce_info_v4_5 = NULL;
2019 	struct atom_smu_info_v4_0 *smu_info_v4_0 = NULL;
2020 
2021 	if (!info)
2022 		return BP_RESULT_BADINPUT;
2023 
2024 	firmware_info = GET_IMAGE(struct atom_firmware_info_v3_4,
2025 			DATA_TABLES(firmwareinfo));
2026 
2027 	if (!firmware_info)
2028 		return BP_RESULT_BADBIOSTABLE;
2029 
2030 	memset(info, 0, sizeof(*info));
2031 
2032 	header = GET_IMAGE(struct atom_common_table_header,
2033 					DATA_TABLES(dce_info));
2034 
2035 	get_atom_data_table_revision(header, &revision);
2036 
2037 	switch (revision.major) {
2038 	case 4:
2039 		switch (revision.minor) {
2040 		case 5:
2041 			dce_info_v4_5 = GET_IMAGE(struct atom_display_controller_info_v4_5,
2042 							DATA_TABLES(dce_info));
2043 
2044 			if (!dce_info_v4_5)
2045 				return BP_RESULT_BADBIOSTABLE;
2046 
2047 			 /* 100MHz expected */
2048 			info->pll_info.crystal_frequency = dce_info_v4_5->dce_refclk_10khz * 10;
2049 			info->dp_phy_ref_clk             = dce_info_v4_5->dpphy_refclk_10khz * 10;
2050 			 /* 50MHz expected */
2051 			info->i2c_engine_ref_clk         = dce_info_v4_5->i2c_engine_refclk_10khz * 10;
2052 
2053 			/* For DCN32/321 Display PLL VCO Frequency from dce_info_v4_5 may not be reliable */
2054 			break;
2055 
2056 		case 4:
2057 			dce_info_v4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,
2058 							DATA_TABLES(dce_info));
2059 
2060 			if (!dce_info_v4_4)
2061 				return BP_RESULT_BADBIOSTABLE;
2062 
2063 			/* 100MHz expected */
2064 			info->pll_info.crystal_frequency = dce_info_v4_4->dce_refclk_10khz * 10;
2065 			info->dp_phy_ref_clk             = dce_info_v4_4->dpphy_refclk_10khz * 10;
2066 			/* 50MHz expected */
2067 			info->i2c_engine_ref_clk         = dce_info_v4_4->i2c_engine_refclk_10khz * 10;
2068 
2069 			/* Get SMU Display PLL VCO Frequency in KHz*/
2070 			info->smu_gpu_pll_output_freq =	dce_info_v4_4->dispclk_pll_vco_freq * 10;
2071 			break;
2072 
2073 		default:
2074 			/* should not come here, keep as backup, as was before */
2075 			dce_info_v4_1 = GET_IMAGE(struct atom_display_controller_info_v4_1,
2076 							DATA_TABLES(dce_info));
2077 
2078 			if (!dce_info_v4_1)
2079 				return BP_RESULT_BADBIOSTABLE;
2080 
2081 			info->pll_info.crystal_frequency = dce_info_v4_1->dce_refclk_10khz * 10;
2082 			info->dp_phy_ref_clk             = dce_info_v4_1->dpphy_refclk_10khz * 10;
2083 			info->i2c_engine_ref_clk         = dce_info_v4_1->i2c_engine_refclk_10khz * 10;
2084 			break;
2085 		}
2086 		break;
2087 
2088 	default:
2089 		ASSERT(0);
2090 		break;
2091 	}
2092 
2093 	header = GET_IMAGE(struct atom_common_table_header,
2094 					DATA_TABLES(smu_info));
2095 	get_atom_data_table_revision(header, &revision);
2096 
2097 	switch (revision.major) {
2098 	case 3:
2099 		switch (revision.minor) {
2100 		case 5:
2101 			smu_info_v3_5 = GET_IMAGE(struct atom_smu_info_v3_5,
2102 							DATA_TABLES(smu_info));
2103 
2104 			if (!smu_info_v3_5)
2105 				return BP_RESULT_BADBIOSTABLE;
2106 			DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_5->gpuclk_ss_percentage);
2107 			info->default_engine_clk = smu_info_v3_5->bootup_dcefclk_10khz * 10;
2108 			break;
2109 
2110 		default:
2111 			break;
2112 		}
2113 		break;
2114 
2115 	case 4:
2116 		switch (revision.minor) {
2117 		case 0:
2118 			smu_info_v4_0 = GET_IMAGE(struct atom_smu_info_v4_0,
2119 							DATA_TABLES(smu_info));
2120 
2121 			if (!smu_info_v4_0)
2122 				return BP_RESULT_BADBIOSTABLE;
2123 
2124 			/* For DCN32/321 bootup DCFCLK from smu_info_v4_0 may not be reliable */
2125 			break;
2126 
2127 		default:
2128 			break;
2129 		}
2130 		break;
2131 
2132 	default:
2133 		break;
2134 	}
2135 
2136 	 // We need to convert from 10KHz units into KHz units.
2137 	info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
2138 
2139 	if (firmware_info->board_i2c_feature_id == 0x2) {
2140 		info->oem_i2c_present = true;
2141 		info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;
2142 	} else {
2143 		info->oem_i2c_present = false;
2144 	}
2145 
2146 	return BP_RESULT_OK;
2147 }
2148 
2149 static enum bp_result get_firmware_info_v3_5(
2150 	struct bios_parser *bp,
2151 	struct dc_firmware_info *info)
2152 {
2153 	struct atom_firmware_info_v3_5 *firmware_info;
2154 	struct atom_common_table_header *header;
2155 	struct atom_data_revision revision;
2156 	struct atom_display_controller_info_v4_5 *dce_info_v4_5 = NULL;
2157 
2158 	if (!info)
2159 		return BP_RESULT_BADINPUT;
2160 
2161 	firmware_info = GET_IMAGE(struct atom_firmware_info_v3_5,
2162 			DATA_TABLES(firmwareinfo));
2163 
2164 	if (!firmware_info)
2165 		return BP_RESULT_BADBIOSTABLE;
2166 
2167 	memset(info, 0, sizeof(*info));
2168 
2169 	if (firmware_info->board_i2c_feature_id == 0x2) {
2170 		info->oem_i2c_present = true;
2171 		info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;
2172 	} else {
2173 		info->oem_i2c_present = false;
2174 	}
2175 
2176 	header = GET_IMAGE(struct atom_common_table_header,
2177 					DATA_TABLES(dce_info));
2178 
2179 	get_atom_data_table_revision(header, &revision);
2180 
2181 	switch (revision.major) {
2182 	case 4:
2183 		switch (revision.minor) {
2184 		case 5:
2185 			dce_info_v4_5 = GET_IMAGE(struct atom_display_controller_info_v4_5,
2186 							DATA_TABLES(dce_info));
2187 
2188 			if (!dce_info_v4_5)
2189 				return BP_RESULT_BADBIOSTABLE;
2190 
2191 			 /* 100MHz expected */
2192 			info->pll_info.crystal_frequency = dce_info_v4_5->dce_refclk_10khz * 10;
2193 			break;
2194 		default:
2195 			break;
2196 		}
2197 		break;
2198 	default:
2199 		break;
2200 	}
2201 
2202 
2203 	return BP_RESULT_OK;
2204 }
2205 
2206 /* TODO: Remove this temp define after atomfirmware.h is updated */
2207 #define ATOM_ENCODER_CAP_RECORD_HDMI_FRL_TEMP  0x200
2208 #define ATOM_ENCODER_CAP_RECORD_HDMI_FRL_8GbEn_TEMP 0x400        // HDMI FRL 8Gb support
2209 #define ATOM_ENCODER_CAP_RECORD_HDMI_FRL_10GbEn_TEMP 0x800        // HDMI FRL 10Gb support
2210 #define ATOM_ENCODER_CAP_RECORD_HDMI_FRL_12GbEn_TEMP 0x1000       // HDMI FRL 12Gb support
2211 
2212 static enum bp_result bios_parser_get_encoder_cap_info(
2213 	struct dc_bios *dcb,
2214 	struct graphics_object_id object_id,
2215 	struct bp_encoder_cap_info *info)
2216 {
2217 	struct bios_parser *bp = BP_FROM_DCB(dcb);
2218 	struct atom_display_object_path_v2 *object;
2219 	struct atom_encoder_caps_record *record = NULL;
2220 
2221 	if (!info)
2222 		return BP_RESULT_BADINPUT;
2223 
2224 #if defined(CONFIG_DRM_AMD_DC_FP)
2225 	/* encoder cap record not available in v1_5 */
2226 	if (bp->object_info_tbl.revision.minor == 5)
2227 		return BP_RESULT_NORECORD;
2228 #endif
2229 
2230 	object = get_bios_object(bp, object_id);
2231 
2232 	if (!object)
2233 		return BP_RESULT_BADINPUT;
2234 
2235 	record = get_encoder_cap_record(bp, object);
2236 	if (!record)
2237 		return BP_RESULT_NORECORD;
2238 	DC_LOG_BIOS("record->encodercaps 0x%x for object_id 0x%x", record->encodercaps, object_id.id);
2239 
2240 	info->DP_HBR2_CAP = (record->encodercaps &
2241 			ATOM_ENCODER_CAP_RECORD_HBR2) ? 1 : 0;
2242 	info->DP_HBR2_EN = (record->encodercaps &
2243 			ATOM_ENCODER_CAP_RECORD_HBR2_EN) ? 1 : 0;
2244 	info->DP_HBR3_EN = (record->encodercaps &
2245 			ATOM_ENCODER_CAP_RECORD_HBR3_EN) ? 1 : 0;
2246 	info->HDMI_6GB_EN = (record->encodercaps &
2247 			ATOM_ENCODER_CAP_RECORD_HDMI6Gbps_EN) ? 1 : 0;
2248 	info->IS_DP2_CAPABLE = (record->encodercaps &
2249 			ATOM_ENCODER_CAP_RECORD_DP2) ? 1 : 0;
2250 	info->DP_UHBR10_EN = (record->encodercaps &
2251 			ATOM_ENCODER_CAP_RECORD_UHBR10_EN) ? 1 : 0;
2252 	info->DP_UHBR13_5_EN = (record->encodercaps &
2253 			ATOM_ENCODER_CAP_RECORD_UHBR13_5_EN) ? 1 : 0;
2254 	info->DP_UHBR20_EN = (record->encodercaps &
2255 			ATOM_ENCODER_CAP_RECORD_UHBR20_EN) ? 1 : 0;
2256 	info->DP_IS_USB_C = (record->encodercaps &
2257 			ATOM_ENCODER_CAP_RECORD_USB_C_TYPE) ? 1 : 0;
2258 	DC_LOG_BIOS("\t info->DP_IS_USB_C %d", info->DP_IS_USB_C);
2259 	info->IS_HDMI_FRL_CAPABLE = (record->encodercaps &
2260 			ATOM_ENCODER_CAP_RECORD_HDMI_FRL_TEMP) ? 1 : 0;
2261 	info->FRL_8G_EN = (record->encodercaps &
2262 			ATOM_ENCODER_CAP_RECORD_HDMI_FRL_8GbEn_TEMP) ? 1 : 0;
2263 	info->FRL_10G_EN = (record->encodercaps &
2264 			ATOM_ENCODER_CAP_RECORD_HDMI_FRL_10GbEn_TEMP) ? 1 : 0;
2265 	info->FRL_12G_EN = (record->encodercaps &
2266 			ATOM_ENCODER_CAP_RECORD_HDMI_FRL_12GbEn_TEMP) ? 1 : 0;
2267 	DC_LOG_BIOS("\t info->IS_HDMI_FRL_CAPABLE %d\n", info->IS_HDMI_FRL_CAPABLE);
2268 
2269 	return BP_RESULT_OK;
2270 }
2271 
2272 
2273 static struct atom_encoder_caps_record *get_encoder_cap_record(
2274 	struct bios_parser *bp,
2275 	struct atom_display_object_path_v2 *object)
2276 {
2277 	struct atom_common_record_header *header;
2278 	uint32_t offset;
2279 	int i;
2280 
2281 	if (!object) {
2282 		BREAK_TO_DEBUGGER(); /* Invalid object */
2283 		return NULL;
2284 	}
2285 
2286 	offset = object->encoder_recordoffset + bp->object_info_tbl_offset;
2287 
2288 	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
2289 		header = GET_IMAGE(struct atom_common_record_header, offset);
2290 
2291 		if (!header)
2292 			return NULL;
2293 
2294 		offset += header->record_size;
2295 
2296 		if (header->record_type == LAST_RECORD_TYPE ||
2297 				!header->record_size)
2298 			break;
2299 
2300 		if (header->record_type != ATOM_ENCODER_CAP_RECORD_TYPE)
2301 			continue;
2302 
2303 		if (sizeof(struct atom_encoder_caps_record) <=
2304 							header->record_size)
2305 			return (struct atom_encoder_caps_record *)header;
2306 	}
2307 
2308 	return NULL;
2309 }
2310 
2311 static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
2312 	struct bios_parser *bp,
2313 	struct atom_display_object_path_v2 *object)
2314 {
2315 	struct atom_common_record_header *header;
2316 	uint32_t offset;
2317 	int i;
2318 
2319 	if (!object) {
2320 		BREAK_TO_DEBUGGER(); /* Invalid object */
2321 		return NULL;
2322 	}
2323 
2324 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
2325 
2326 	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
2327 		header = GET_IMAGE(struct atom_common_record_header, offset);
2328 
2329 		if (!header)
2330 			return NULL;
2331 
2332 		offset += header->record_size;
2333 
2334 		if (header->record_type == LAST_RECORD_TYPE ||
2335 				!header->record_size)
2336 			break;
2337 
2338 		if (header->record_type != ATOM_DISP_CONNECTOR_CAPS_RECORD_TYPE)
2339 			continue;
2340 
2341 		if (sizeof(struct atom_disp_connector_caps_record) <=
2342 							header->record_size)
2343 			return (struct atom_disp_connector_caps_record *)header;
2344 	}
2345 
2346 	return NULL;
2347 }
2348 
2349 static struct atom_connector_caps_record *get_connector_caps_record(struct bios_parser *bp,
2350 								    struct atom_display_object_path_v3 *object)
2351 {
2352 	struct atom_common_record_header *header;
2353 	uint32_t offset;
2354 	int i;
2355 
2356 	if (!object) {
2357 		BREAK_TO_DEBUGGER(); /* Invalid object */
2358 		return NULL;
2359 	}
2360 
2361 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
2362 
2363 	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
2364 		header = GET_IMAGE(struct atom_common_record_header, offset);
2365 
2366 		if (!header)
2367 			return NULL;
2368 
2369 		offset += header->record_size;
2370 
2371 		if (header->record_type == ATOM_RECORD_END_TYPE ||
2372 				!header->record_size)
2373 			break;
2374 
2375 		if (header->record_type != ATOM_CONNECTOR_CAP_RECORD_TYPE)
2376 			continue;
2377 
2378 		if (sizeof(struct atom_connector_caps_record) <= header->record_size)
2379 			return (struct atom_connector_caps_record *)header;
2380 	}
2381 
2382 	return NULL;
2383 }
2384 
2385 static enum bp_result bios_parser_get_disp_connector_caps_info(
2386 	struct dc_bios *dcb,
2387 	struct graphics_object_id object_id,
2388 	struct bp_disp_connector_caps_info *info)
2389 {
2390 	struct bios_parser *bp = BP_FROM_DCB(dcb);
2391 	struct atom_display_object_path_v2 *object;
2392 	struct atom_display_object_path_v3 *object_path_v3;
2393 	struct atom_connector_caps_record *record_path_v3;
2394 	struct atom_disp_connector_caps_record *record = NULL;
2395 
2396 	if (!info)
2397 		return BP_RESULT_BADINPUT;
2398 
2399 	switch (bp->object_info_tbl.revision.minor) {
2400 	case 4:
2401 		default:
2402 			object = get_bios_object(bp, object_id);
2403 
2404 			if (!object)
2405 				return BP_RESULT_BADINPUT;
2406 
2407 			record = get_disp_connector_caps_record(bp, object);
2408 			if (!record)
2409 				return BP_RESULT_NORECORD;
2410 
2411 			info->INTERNAL_DISPLAY =
2412 				(record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY) ? 1 : 0;
2413 			info->INTERNAL_DISPLAY_BL =
2414 				(record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL) ? 1 : 0;
2415 			break;
2416 	case 5:
2417 		object_path_v3 = get_bios_object_from_path_v3(bp, object_id);
2418 
2419 		if (!object_path_v3)
2420 			return BP_RESULT_BADINPUT;
2421 
2422 		record_path_v3 = get_connector_caps_record(bp, object_path_v3);
2423 		if (!record_path_v3)
2424 			return BP_RESULT_NORECORD;
2425 
2426 		info->INTERNAL_DISPLAY = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY)
2427 									? 1 : 0;
2428 		info->INTERNAL_DISPLAY_BL = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL)
2429 										? 1 : 0;
2430 		// All aux transactions for this connector should rely only on aux instance, not on ddc instance
2431 		info->NO_DDC_PIN = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_DP_PLUS_PLUS_TYPE2_ONLY) ? 1 : 0;
2432 
2433 		break;
2434 	}
2435 
2436 	return BP_RESULT_OK;
2437 }
2438 
2439 static struct atom_connector_speed_record *get_connector_speed_cap_record(struct bios_parser *bp,
2440 									  struct atom_display_object_path_v3 *object)
2441 {
2442 	struct atom_common_record_header *header;
2443 	uint32_t offset;
2444 	int i;
2445 
2446 	if (!object) {
2447 		BREAK_TO_DEBUGGER(); /* Invalid object */
2448 		return NULL;
2449 	}
2450 
2451 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
2452 
2453 	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
2454 		header = GET_IMAGE(struct atom_common_record_header, offset);
2455 
2456 		if (!header)
2457 			return NULL;
2458 
2459 		offset += header->record_size;
2460 
2461 		if (header->record_type == ATOM_RECORD_END_TYPE ||
2462 				!header->record_size)
2463 			break;
2464 
2465 		if (header->record_type != ATOM_CONNECTOR_SPEED_UPTO)
2466 			continue;
2467 
2468 		if (sizeof(struct atom_connector_speed_record) <= header->record_size)
2469 			return (struct atom_connector_speed_record *)header;
2470 	}
2471 
2472 	return NULL;
2473 }
2474 
2475 static enum bp_result bios_parser_get_connector_speed_cap_info(
2476 	struct dc_bios *dcb,
2477 	struct graphics_object_id object_id,
2478 	struct bp_connector_speed_cap_info *info)
2479 {
2480 	struct bios_parser *bp = BP_FROM_DCB(dcb);
2481 	struct atom_display_object_path_v3 *object_path_v3;
2482 	//struct atom_connector_speed_record *record = NULL;
2483 	struct atom_connector_speed_record *record;
2484 
2485 	if (!info)
2486 		return BP_RESULT_BADINPUT;
2487 
2488 	object_path_v3 = get_bios_object_from_path_v3(bp, object_id);
2489 
2490 	if (!object_path_v3)
2491 		return BP_RESULT_BADINPUT;
2492 
2493 	record = get_connector_speed_cap_record(bp, object_path_v3);
2494 	if (!record)
2495 		return BP_RESULT_NORECORD;
2496 
2497 	info->DP_HBR2_EN = (record->connector_max_speed >= 5400) ? 1 : 0;
2498 	info->DP_HBR3_EN = (record->connector_max_speed >= 8100) ? 1 : 0;
2499 	info->HDMI_6GB_EN = (record->connector_max_speed >= 5940) ? 1 : 0;
2500 	info->DP_UHBR10_EN = (record->connector_max_speed >= 10000) ? 1 : 0;
2501 	info->DP_UHBR13_5_EN = (record->connector_max_speed >= 13500) ? 1 : 0;
2502 	info->DP_UHBR20_EN = (record->connector_max_speed >= 20000) ? 1 : 0;
2503 	info->FRL_8G_EN = (record->connector_max_speed >= 8000) ? 1 : 0;
2504 	info->FRL_10G_EN = (record->connector_max_speed >= 10000) ? 1 : 0;
2505 	info->FRL_12G_EN = (record->connector_max_speed >= 12000) ? 1 : 0;
2506 	info->FRL_16G_EN = (record->connector_max_speed >= 16000) ? 1 : 0;
2507 	info->FRL_20G_EN = (record->connector_max_speed >= 20000) ? 1 : 0;
2508 	info->FRL_24G_EN = (record->connector_max_speed >= 24000) ? 1 : 0;
2509 	return BP_RESULT_OK;
2510 }
2511 
2512 static enum bp_result get_vram_info_v23(
2513 	struct bios_parser *bp,
2514 	struct dc_vram_info *info)
2515 {
2516 	struct atom_vram_info_header_v2_3 *info_v23;
2517 	static enum bp_result result = BP_RESULT_OK;
2518 
2519 	info_v23 = GET_IMAGE(struct atom_vram_info_header_v2_3,
2520 						DATA_TABLES(vram_info));
2521 
2522 	if (info_v23 == NULL)
2523 		return BP_RESULT_BADBIOSTABLE;
2524 
2525 	info->num_chans = info_v23->vram_module[0].channel_num;
2526 	info->dram_channel_width_bytes = (1 << info_v23->vram_module[0].channel_width) / 8;
2527 
2528 	return result;
2529 }
2530 
2531 static enum bp_result get_vram_info_v24(
2532 	struct bios_parser *bp,
2533 	struct dc_vram_info *info)
2534 {
2535 	struct atom_vram_info_header_v2_4 *info_v24;
2536 	static enum bp_result result = BP_RESULT_OK;
2537 
2538 	info_v24 = GET_IMAGE(struct atom_vram_info_header_v2_4,
2539 						DATA_TABLES(vram_info));
2540 
2541 	if (info_v24 == NULL)
2542 		return BP_RESULT_BADBIOSTABLE;
2543 
2544 	info->num_chans = info_v24->vram_module[0].channel_num;
2545 	info->dram_channel_width_bytes = (1 << info_v24->vram_module[0].channel_width) / 8;
2546 
2547 	return result;
2548 }
2549 
2550 static enum bp_result get_vram_info_v25(
2551 	struct bios_parser *bp,
2552 	struct dc_vram_info *info)
2553 {
2554 	struct atom_vram_info_header_v2_5 *info_v25;
2555 	static enum bp_result result = BP_RESULT_OK;
2556 
2557 	info_v25 = GET_IMAGE(struct atom_vram_info_header_v2_5,
2558 						DATA_TABLES(vram_info));
2559 
2560 	if (info_v25 == NULL)
2561 		return BP_RESULT_BADBIOSTABLE;
2562 
2563 	info->num_chans = info_v25->vram_module[0].channel_num;
2564 	info->dram_channel_width_bytes = (1 << info_v25->vram_module[0].channel_width) / 8;
2565 
2566 	return result;
2567 }
2568 
2569 static enum bp_result get_vram_info_v30(
2570 	struct bios_parser *bp,
2571 	struct dc_vram_info *info)
2572 {
2573 	struct atom_vram_info_header_v3_0 *info_v30;
2574 	enum bp_result result = BP_RESULT_OK;
2575 
2576 	info_v30 = GET_IMAGE(struct atom_vram_info_header_v3_0,
2577 						DATA_TABLES(vram_info));
2578 
2579 	if (info_v30 == NULL)
2580 		return BP_RESULT_BADBIOSTABLE;
2581 
2582 	info->num_chans = info_v30->channel_num;
2583 	info->dram_channel_width_bytes = (1 << info_v30->channel_width) / 8;
2584 
2585 	return result;
2586 }
2587 
2588 static enum bp_result get_vram_info_from_umc_info_v40(
2589 		struct bios_parser *bp,
2590 		struct dc_vram_info *info)
2591 {
2592 	struct atom_umc_info_v4_0 *info_v40;
2593 	enum bp_result result = BP_RESULT_OK;
2594 
2595 	info_v40 = GET_IMAGE(struct atom_umc_info_v4_0,
2596 						DATA_TABLES(umc_info));
2597 
2598 	if (info_v40 == NULL)
2599 		return BP_RESULT_BADBIOSTABLE;
2600 
2601 	info->num_chans = info_v40->channel_num;
2602 	info->dram_channel_width_bytes = (1 << info_v40->channel_width) / 8;
2603 
2604 	return result;
2605 }
2606 
2607 /*
2608  * get_integrated_info_v11
2609  *
2610  * @brief
2611  * Get V8 integrated BIOS information
2612  *
2613  * @param
2614  * bios_parser *bp - [in]BIOS parser handler to get master data table
2615  * integrated_info *info - [out] store and output integrated info
2616  *
2617  * @return
2618  * static enum bp_result - BP_RESULT_OK if information is available,
2619  *                  BP_RESULT_BADBIOSTABLE otherwise.
2620  */
2621 static enum bp_result get_integrated_info_v11(
2622 	struct bios_parser *bp,
2623 	struct integrated_info *info)
2624 {
2625 	struct atom_integrated_system_info_v1_11 *info_v11;
2626 	uint32_t i;
2627 
2628 	info_v11 = GET_IMAGE(struct atom_integrated_system_info_v1_11,
2629 					DATA_TABLES(integratedsysteminfo));
2630 
2631 	if (info_v11 == NULL)
2632 		return BP_RESULT_BADBIOSTABLE;
2633 
2634 	DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v11->gpuclk_ss_percentage);
2635 
2636 	info->gpu_cap_info =
2637 	le32_to_cpu(info_v11->gpucapinfo);
2638 	/*
2639 	* system_config: Bit[0] = 0 : PCIE power gating disabled
2640 	*                       = 1 : PCIE power gating enabled
2641 	*                Bit[1] = 0 : DDR-PLL shut down disabled
2642 	*                       = 1 : DDR-PLL shut down enabled
2643 	*                Bit[2] = 0 : DDR-PLL power down disabled
2644 	*                       = 1 : DDR-PLL power down enabled
2645 	*/
2646 	info->system_config = le32_to_cpu(info_v11->system_config);
2647 	info->cpu_cap_info = le32_to_cpu(info_v11->cpucapinfo);
2648 	info->memory_type = info_v11->memorytype;
2649 	info->ma_channel_number = info_v11->umachannelnumber;
2650 	info->lvds_ss_percentage =
2651 	le16_to_cpu(info_v11->lvds_ss_percentage);
2652 	info->dp_ss_control =
2653 	le16_to_cpu(info_v11->reserved1);
2654 	info->lvds_sspread_rate_in_10hz =
2655 	le16_to_cpu(info_v11->lvds_ss_rate_10hz);
2656 	info->hdmi_ss_percentage =
2657 	le16_to_cpu(info_v11->hdmi_ss_percentage);
2658 	info->hdmi_sspread_rate_in_10hz =
2659 	le16_to_cpu(info_v11->hdmi_ss_rate_10hz);
2660 	info->dvi_ss_percentage =
2661 	le16_to_cpu(info_v11->dvi_ss_percentage);
2662 	info->dvi_sspread_rate_in_10_hz =
2663 	le16_to_cpu(info_v11->dvi_ss_rate_10hz);
2664 	info->lvds_misc = info_v11->lvds_misc;
2665 	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2666 		info->ext_disp_conn_info.gu_id[i] =
2667 				info_v11->extdispconninfo.guid[i];
2668 	}
2669 
2670 	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2671 		info->ext_disp_conn_info.path[i].device_connector_id =
2672 		object_id_from_bios_object_id(
2673 		le16_to_cpu(info_v11->extdispconninfo.path[i].connectorobjid));
2674 
2675 		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2676 		object_id_from_bios_object_id(
2677 			le16_to_cpu(
2678 			info_v11->extdispconninfo.path[i].ext_encoder_objid));
2679 
2680 		info->ext_disp_conn_info.path[i].device_tag =
2681 			le16_to_cpu(
2682 				info_v11->extdispconninfo.path[i].device_tag);
2683 		info->ext_disp_conn_info.path[i].device_acpi_enum =
2684 		le16_to_cpu(
2685 			info_v11->extdispconninfo.path[i].device_acpi_enum);
2686 		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2687 			info_v11->extdispconninfo.path[i].auxddclut_index;
2688 		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2689 			info_v11->extdispconninfo.path[i].hpdlut_index;
2690 		info->ext_disp_conn_info.path[i].channel_mapping.raw =
2691 			info_v11->extdispconninfo.path[i].channelmapping;
2692 		info->ext_disp_conn_info.path[i].caps =
2693 				(unsigned short)le16_to_cpu(info_v11->extdispconninfo.path[i].caps);
2694 	}
2695 	info->ext_disp_conn_info.checksum =
2696 	info_v11->extdispconninfo.checksum;
2697 
2698 	info->dp0_ext_hdmi_slv_addr = info_v11->dp0_retimer_set.HdmiSlvAddr;
2699 	info->dp0_ext_hdmi_reg_num = min_t(u8, info_v11->dp0_retimer_set.HdmiRegNum,
2700 					    ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings));
2701 	for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
2702 		info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
2703 				info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2704 		info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
2705 				info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2706 	}
2707 	info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp0_retimer_set.Hdmi6GRegNum,
2708 					       ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings));
2709 	for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
2710 		info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2711 				info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2712 		info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2713 				info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2714 	}
2715 
2716 	info->dp1_ext_hdmi_slv_addr = info_v11->dp1_retimer_set.HdmiSlvAddr;
2717 	info->dp1_ext_hdmi_reg_num = min_t(u8, info_v11->dp1_retimer_set.HdmiRegNum,
2718 					    ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings));
2719 	for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
2720 		info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
2721 				info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2722 		info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
2723 				info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2724 	}
2725 	info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp1_retimer_set.Hdmi6GRegNum,
2726 					       ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings));
2727 	for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
2728 		info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2729 				info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2730 		info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2731 				info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2732 	}
2733 
2734 	info->dp2_ext_hdmi_slv_addr = info_v11->dp2_retimer_set.HdmiSlvAddr;
2735 	info->dp2_ext_hdmi_reg_num = min_t(u8, info_v11->dp2_retimer_set.HdmiRegNum,
2736 					    ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings));
2737 	for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
2738 		info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
2739 				info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2740 		info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
2741 				info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2742 	}
2743 	info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp2_retimer_set.Hdmi6GRegNum,
2744 					       ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings));
2745 	for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
2746 		info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2747 				info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2748 		info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2749 				info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2750 	}
2751 
2752 	info->dp3_ext_hdmi_slv_addr = info_v11->dp3_retimer_set.HdmiSlvAddr;
2753 	info->dp3_ext_hdmi_reg_num = min_t(u8, info_v11->dp3_retimer_set.HdmiRegNum,
2754 					    ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings));
2755 	for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
2756 		info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
2757 				info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2758 		info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
2759 				info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2760 	}
2761 	info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp3_retimer_set.Hdmi6GRegNum,
2762 					       ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings));
2763 	for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
2764 		info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2765 				info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2766 		info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2767 				info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2768 	}
2769 
2770 
2771 	/** TODO - review **/
2772 	#if 0
2773 	info->boot_up_engine_clock = le32_to_cpu(info_v11->ulBootUpEngineClock)
2774 									* 10;
2775 	info->dentist_vco_freq = le32_to_cpu(info_v11->ulDentistVCOFreq) * 10;
2776 	info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
2777 
2778 	info->boot_up_req_display_vector =
2779 			le32_to_cpu(info_v11->ulBootUpReqDisplayVector);
2780 	info->boot_up_nb_voltage =
2781 			le16_to_cpu(info_v11->usBootUpNBVoltage);
2782 	info->ext_disp_conn_info_offset =
2783 			le16_to_cpu(info_v11->usExtDispConnInfoOffset);
2784 	info->gmc_restore_reset_time =
2785 			le32_to_cpu(info_v11->ulGMCRestoreResetTime);
2786 	info->minimum_n_clk =
2787 			le32_to_cpu(info_v11->ulNbpStateNClkFreq[0]);
2788 	for (i = 1; i < 4; ++i)
2789 		info->minimum_n_clk =
2790 				info->minimum_n_clk <
2791 				le32_to_cpu(info_v11->ulNbpStateNClkFreq[i]) ?
2792 				info->minimum_n_clk : le32_to_cpu(
2793 					info_v11->ulNbpStateNClkFreq[i]);
2794 
2795 	info->idle_n_clk = le32_to_cpu(info_v11->ulIdleNClk);
2796 	info->ddr_dll_power_up_time =
2797 	    le32_to_cpu(info_v11->ulDDR_DLL_PowerUpTime);
2798 	info->ddr_pll_power_up_time =
2799 		le32_to_cpu(info_v11->ulDDR_PLL_PowerUpTime);
2800 	info->pcie_clk_ss_type = le16_to_cpu(info_v11->usPCIEClkSSType);
2801 	info->max_lvds_pclk_freq_in_single_link =
2802 		le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink);
2803 	info->max_lvds_pclk_freq_in_single_link =
2804 		le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink);
2805 	info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
2806 		info_v11->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
2807 	info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
2808 		info_v11->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
2809 	info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
2810 		info_v11->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
2811 	info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
2812 		info_v11->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
2813 	info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
2814 		info_v11->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
2815 	info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
2816 		info_v11->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
2817 	info->lvds_off_to_on_delay_in_4ms =
2818 		info_v11->ucLVDSOffToOnDelay_in4Ms;
2819 	info->lvds_bit_depth_control_val =
2820 		le32_to_cpu(info_v11->ulLCDBitDepthControlVal);
2821 
2822 	for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
2823 		/* Convert [10KHz] into [KHz] */
2824 		info->avail_s_clk[i].supported_s_clk =
2825 			le32_to_cpu(info_v11->sAvail_SCLK[i].ulSupportedSCLK)
2826 									* 10;
2827 		info->avail_s_clk[i].voltage_index =
2828 			le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageIndex);
2829 		info->avail_s_clk[i].voltage_id =
2830 			le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageID);
2831 	}
2832 	#endif /* TODO*/
2833 
2834 	return BP_RESULT_OK;
2835 }
2836 
2837 static enum bp_result get_integrated_info_v2_1(
2838 	struct bios_parser *bp,
2839 	struct integrated_info *info)
2840 {
2841 	struct atom_integrated_system_info_v2_1 *info_v2_1;
2842 	uint32_t i;
2843 
2844 	info_v2_1 = GET_IMAGE(struct atom_integrated_system_info_v2_1,
2845 					DATA_TABLES(integratedsysteminfo));
2846 
2847 	if (info_v2_1 == NULL)
2848 		return BP_RESULT_BADBIOSTABLE;
2849 
2850 	DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_1->gpuclk_ss_percentage);
2851 
2852 	info->gpu_cap_info =
2853 	le32_to_cpu(info_v2_1->gpucapinfo);
2854 	/*
2855 	* system_config: Bit[0] = 0 : PCIE power gating disabled
2856 	*                       = 1 : PCIE power gating enabled
2857 	*                Bit[1] = 0 : DDR-PLL shut down disabled
2858 	*                       = 1 : DDR-PLL shut down enabled
2859 	*                Bit[2] = 0 : DDR-PLL power down disabled
2860 	*                       = 1 : DDR-PLL power down enabled
2861 	*/
2862 	info->system_config = le32_to_cpu(info_v2_1->system_config);
2863 	info->cpu_cap_info = le32_to_cpu(info_v2_1->cpucapinfo);
2864 	info->memory_type = info_v2_1->memorytype;
2865 	info->ma_channel_number = info_v2_1->umachannelnumber;
2866 	info->dp_ss_control =
2867 		le16_to_cpu(info_v2_1->reserved1);
2868 
2869 	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2870 		info->ext_disp_conn_info.gu_id[i] =
2871 				info_v2_1->extdispconninfo.guid[i];
2872 	}
2873 
2874 	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2875 		info->ext_disp_conn_info.path[i].device_connector_id =
2876 		object_id_from_bios_object_id(
2877 		le16_to_cpu(info_v2_1->extdispconninfo.path[i].connectorobjid));
2878 
2879 		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2880 		object_id_from_bios_object_id(
2881 			le16_to_cpu(
2882 			info_v2_1->extdispconninfo.path[i].ext_encoder_objid));
2883 
2884 		info->ext_disp_conn_info.path[i].device_tag =
2885 			le16_to_cpu(
2886 				info_v2_1->extdispconninfo.path[i].device_tag);
2887 		info->ext_disp_conn_info.path[i].device_acpi_enum =
2888 		le16_to_cpu(
2889 			info_v2_1->extdispconninfo.path[i].device_acpi_enum);
2890 		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2891 			info_v2_1->extdispconninfo.path[i].auxddclut_index;
2892 		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2893 			info_v2_1->extdispconninfo.path[i].hpdlut_index;
2894 		info->ext_disp_conn_info.path[i].channel_mapping.raw =
2895 			info_v2_1->extdispconninfo.path[i].channelmapping;
2896 		info->ext_disp_conn_info.path[i].caps =
2897 				(unsigned short)le16_to_cpu(info_v2_1->extdispconninfo.path[i].caps);
2898 	}
2899 
2900 	info->ext_disp_conn_info.checksum =
2901 		info_v2_1->extdispconninfo.checksum;
2902 	info->dp0_ext_hdmi_slv_addr = info_v2_1->dp0_retimer_set.HdmiSlvAddr;
2903 	info->dp0_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.HdmiRegNum,
2904 					    ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings));
2905 	for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
2906 		info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
2907 				info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2908 		info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
2909 				info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2910 	}
2911 	info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.Hdmi6GRegNum,
2912 					       ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings));
2913 	for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
2914 		info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2915 				info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2916 		info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2917 				info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2918 	}
2919 	info->dp1_ext_hdmi_slv_addr = info_v2_1->dp1_retimer_set.HdmiSlvAddr;
2920 	info->dp1_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.HdmiRegNum,
2921 					    ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings));
2922 	for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
2923 		info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
2924 				info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2925 		info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
2926 				info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2927 	}
2928 	info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.Hdmi6GRegNum,
2929 					       ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings));
2930 	for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
2931 		info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2932 				info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2933 		info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2934 				info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2935 	}
2936 	info->dp2_ext_hdmi_slv_addr = info_v2_1->dp2_retimer_set.HdmiSlvAddr;
2937 	info->dp2_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.HdmiRegNum,
2938 					    ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings));
2939 	for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
2940 		info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
2941 				info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2942 		info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
2943 				info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2944 	}
2945 	info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.Hdmi6GRegNum,
2946 					       ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings));
2947 	for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
2948 		info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2949 				info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2950 		info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2951 				info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2952 	}
2953 	info->dp3_ext_hdmi_slv_addr = info_v2_1->dp3_retimer_set.HdmiSlvAddr;
2954 	info->dp3_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.HdmiRegNum,
2955 					    ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings));
2956 	for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
2957 		info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
2958 				info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2959 		info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
2960 				info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2961 	}
2962 	info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.Hdmi6GRegNum,
2963 					       ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings));
2964 	for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
2965 		info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2966 				info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2967 		info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2968 				info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2969 	}
2970 
2971 	info->edp1_info.edp_backlight_pwm_hz =
2972 	le16_to_cpu(info_v2_1->edp1_info.edp_backlight_pwm_hz);
2973 	info->edp1_info.edp_ss_percentage =
2974 	le16_to_cpu(info_v2_1->edp1_info.edp_ss_percentage);
2975 	info->edp1_info.edp_ss_rate_10hz =
2976 	le16_to_cpu(info_v2_1->edp1_info.edp_ss_rate_10hz);
2977 	info->edp1_info.edp_pwr_on_off_delay =
2978 		info_v2_1->edp1_info.edp_pwr_on_off_delay;
2979 	info->edp1_info.edp_pwr_on_vary_bl_to_blon =
2980 		info_v2_1->edp1_info.edp_pwr_on_vary_bl_to_blon;
2981 	info->edp1_info.edp_pwr_down_bloff_to_vary_bloff =
2982 		info_v2_1->edp1_info.edp_pwr_down_bloff_to_vary_bloff;
2983 	info->edp1_info.edp_panel_bpc =
2984 		info_v2_1->edp1_info.edp_panel_bpc;
2985 	info->edp1_info.edp_bootup_bl_level = info_v2_1->edp1_info.edp_bootup_bl_level;
2986 
2987 	info->edp2_info.edp_backlight_pwm_hz =
2988 	le16_to_cpu(info_v2_1->edp2_info.edp_backlight_pwm_hz);
2989 	info->edp2_info.edp_ss_percentage =
2990 	le16_to_cpu(info_v2_1->edp2_info.edp_ss_percentage);
2991 	info->edp2_info.edp_ss_rate_10hz =
2992 	le16_to_cpu(info_v2_1->edp2_info.edp_ss_rate_10hz);
2993 	info->edp2_info.edp_pwr_on_off_delay =
2994 		info_v2_1->edp2_info.edp_pwr_on_off_delay;
2995 	info->edp2_info.edp_pwr_on_vary_bl_to_blon =
2996 		info_v2_1->edp2_info.edp_pwr_on_vary_bl_to_blon;
2997 	info->edp2_info.edp_pwr_down_bloff_to_vary_bloff =
2998 		info_v2_1->edp2_info.edp_pwr_down_bloff_to_vary_bloff;
2999 	info->edp2_info.edp_panel_bpc =
3000 		info_v2_1->edp2_info.edp_panel_bpc;
3001 	info->edp2_info.edp_bootup_bl_level =
3002 		info_v2_1->edp2_info.edp_bootup_bl_level;
3003 
3004 	return BP_RESULT_OK;
3005 }
3006 
3007 static enum bp_result get_integrated_info_v2_2(
3008 	struct bios_parser *bp,
3009 	struct integrated_info *info)
3010 {
3011 	struct atom_integrated_system_info_v2_2 *info_v2_2;
3012 	uint32_t i;
3013 
3014 	info_v2_2 = GET_IMAGE(struct atom_integrated_system_info_v2_2,
3015 					DATA_TABLES(integratedsysteminfo));
3016 
3017 	if (info_v2_2 == NULL)
3018 		return BP_RESULT_BADBIOSTABLE;
3019 
3020 	DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_2->gpuclk_ss_percentage);
3021 
3022 	info->gpu_cap_info =
3023 	le32_to_cpu(info_v2_2->gpucapinfo);
3024 	/*
3025 	* system_config: Bit[0] = 0 : PCIE power gating disabled
3026 	*                       = 1 : PCIE power gating enabled
3027 	*                Bit[1] = 0 : DDR-PLL shut down disabled
3028 	*                       = 1 : DDR-PLL shut down enabled
3029 	*                Bit[2] = 0 : DDR-PLL power down disabled
3030 	*                       = 1 : DDR-PLL power down enabled
3031 	*/
3032 	info->system_config = le32_to_cpu(info_v2_2->system_config);
3033 	info->cpu_cap_info = le32_to_cpu(info_v2_2->cpucapinfo);
3034 	info->memory_type = info_v2_2->memorytype;
3035 	info->ma_channel_number = info_v2_2->umachannelnumber;
3036 	info->dp_ss_control =
3037 		le16_to_cpu(info_v2_2->reserved1);
3038 	info->gpuclk_ss_percentage = info_v2_2->gpuclk_ss_percentage;
3039 	info->gpuclk_ss_type = info_v2_2->gpuclk_ss_type;
3040 
3041 	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
3042 		info->ext_disp_conn_info.gu_id[i] =
3043 				info_v2_2->extdispconninfo.guid[i];
3044 	}
3045 
3046 	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
3047 		info->ext_disp_conn_info.path[i].device_connector_id =
3048 		object_id_from_bios_object_id(
3049 		le16_to_cpu(info_v2_2->extdispconninfo.path[i].connectorobjid));
3050 
3051 		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
3052 		object_id_from_bios_object_id(
3053 			le16_to_cpu(
3054 			info_v2_2->extdispconninfo.path[i].ext_encoder_objid));
3055 
3056 		info->ext_disp_conn_info.path[i].device_tag =
3057 			le16_to_cpu(
3058 				info_v2_2->extdispconninfo.path[i].device_tag);
3059 		info->ext_disp_conn_info.path[i].device_acpi_enum =
3060 		le16_to_cpu(
3061 			info_v2_2->extdispconninfo.path[i].device_acpi_enum);
3062 		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
3063 			info_v2_2->extdispconninfo.path[i].auxddclut_index;
3064 		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
3065 			info_v2_2->extdispconninfo.path[i].hpdlut_index;
3066 		info->ext_disp_conn_info.path[i].channel_mapping.raw =
3067 			info_v2_2->extdispconninfo.path[i].channelmapping;
3068 		info->ext_disp_conn_info.path[i].caps =
3069 				(unsigned short)le16_to_cpu(info_v2_2->extdispconninfo.path[i].caps);
3070 	}
3071 
3072 	info->ext_disp_conn_info.checksum =
3073 		info_v2_2->extdispconninfo.checksum;
3074 	info->ext_disp_conn_info.fixdpvoltageswing =
3075 		info_v2_2->extdispconninfo.fixdpvoltageswing;
3076 
3077 	info->edp1_info.edp_backlight_pwm_hz =
3078 	le16_to_cpu(info_v2_2->edp1_info.edp_backlight_pwm_hz);
3079 	info->edp1_info.edp_ss_percentage =
3080 	le16_to_cpu(info_v2_2->edp1_info.edp_ss_percentage);
3081 	info->edp1_info.edp_ss_rate_10hz =
3082 	le16_to_cpu(info_v2_2->edp1_info.edp_ss_rate_10hz);
3083 	info->edp1_info.edp_pwr_on_off_delay =
3084 		info_v2_2->edp1_info.edp_pwr_on_off_delay;
3085 	info->edp1_info.edp_pwr_on_vary_bl_to_blon =
3086 		info_v2_2->edp1_info.edp_pwr_on_vary_bl_to_blon;
3087 	info->edp1_info.edp_pwr_down_bloff_to_vary_bloff =
3088 		info_v2_2->edp1_info.edp_pwr_down_bloff_to_vary_bloff;
3089 	info->edp1_info.edp_panel_bpc =
3090 		info_v2_2->edp1_info.edp_panel_bpc;
3091 	info->edp1_info.edp_bootup_bl_level =
3092 		info_v2_2->edp1_info.edp_bootup_bl_level;
3093 
3094 	info->edp2_info.edp_backlight_pwm_hz =
3095 	le16_to_cpu(info_v2_2->edp2_info.edp_backlight_pwm_hz);
3096 	info->edp2_info.edp_ss_percentage =
3097 	le16_to_cpu(info_v2_2->edp2_info.edp_ss_percentage);
3098 	info->edp2_info.edp_ss_rate_10hz =
3099 	le16_to_cpu(info_v2_2->edp2_info.edp_ss_rate_10hz);
3100 	info->edp2_info.edp_pwr_on_off_delay =
3101 		info_v2_2->edp2_info.edp_pwr_on_off_delay;
3102 	info->edp2_info.edp_pwr_on_vary_bl_to_blon =
3103 		info_v2_2->edp2_info.edp_pwr_on_vary_bl_to_blon;
3104 	info->edp2_info.edp_pwr_down_bloff_to_vary_bloff =
3105 		info_v2_2->edp2_info.edp_pwr_down_bloff_to_vary_bloff;
3106 	info->edp2_info.edp_panel_bpc =
3107 		info_v2_2->edp2_info.edp_panel_bpc;
3108 	info->edp2_info.edp_bootup_bl_level =
3109 		info_v2_2->edp2_info.edp_bootup_bl_level;
3110 
3111 	return BP_RESULT_OK;
3112 }
3113 
3114 /*
3115  * construct_integrated_info
3116  *
3117  * @brief
3118  * Get integrated BIOS information based on table revision
3119  *
3120  * @param
3121  * bios_parser *bp - [in]BIOS parser handler to get master data table
3122  * integrated_info *info - [out] store and output integrated info
3123  *
3124  * @return
3125  * static enum bp_result - BP_RESULT_OK if information is available,
3126  *                  BP_RESULT_BADBIOSTABLE otherwise.
3127  */
3128 static enum bp_result construct_integrated_info(
3129 	struct bios_parser *bp,
3130 	struct integrated_info *info)
3131 {
3132 	static enum bp_result result = BP_RESULT_BADBIOSTABLE;
3133 
3134 	struct atom_common_table_header *header;
3135 	struct atom_data_revision revision;
3136 
3137 	int32_t i;
3138 
3139 	if (!info)
3140 		return result;
3141 
3142 	if (info && DATA_TABLES(integratedsysteminfo)) {
3143 		header = GET_IMAGE(struct atom_common_table_header,
3144 					DATA_TABLES(integratedsysteminfo));
3145 
3146 		get_atom_data_table_revision(header, &revision);
3147 
3148 		switch (revision.major) {
3149 		case 1:
3150 			switch (revision.minor) {
3151 			case 11:
3152 			case 12:
3153 				result = get_integrated_info_v11(bp, info);
3154 				break;
3155 			default:
3156 				return result;
3157 			}
3158 			break;
3159 		case 2:
3160 			switch (revision.minor) {
3161 			case 1:
3162 				result = get_integrated_info_v2_1(bp, info);
3163 				break;
3164 			case 2:
3165 			case 3:
3166 				result = get_integrated_info_v2_2(bp, info);
3167 				break;
3168 			default:
3169 				return result;
3170 			}
3171 			break;
3172 		default:
3173 			return result;
3174 		}
3175 		if (result == BP_RESULT_OK) {
3176 
3177 			DC_LOG_BIOS("edp1:\n"
3178 						"\tedp_pwr_on_off_delay = %d\n"
3179 						"\tedp_pwr_on_vary_bl_to_blon = %d\n"
3180 						"\tedp_pwr_down_bloff_to_vary_bloff = %d\n"
3181 						"\tedp_bootup_bl_level = %d\n",
3182 						info->edp1_info.edp_pwr_on_off_delay,
3183 						info->edp1_info.edp_pwr_on_vary_bl_to_blon,
3184 						info->edp1_info.edp_pwr_down_bloff_to_vary_bloff,
3185 						info->edp1_info.edp_bootup_bl_level);
3186 			DC_LOG_BIOS("edp2:\n"
3187 						"\tedp_pwr_on_off_delayv = %d\n"
3188 						"\tedp_pwr_on_vary_bl_to_blon = %d\n"
3189 						"\tedp_pwr_down_bloff_to_vary_bloff = %d\n"
3190 						"\tedp_bootup_bl_level = %d\n",
3191 						info->edp2_info.edp_pwr_on_off_delay,
3192 						info->edp2_info.edp_pwr_on_vary_bl_to_blon,
3193 						info->edp2_info.edp_pwr_down_bloff_to_vary_bloff,
3194 						info->edp2_info.edp_bootup_bl_level);
3195 		}
3196 	}
3197 
3198 	if (result != BP_RESULT_OK)
3199 		return result;
3200 	else {
3201 		// Log each external path
3202 		for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {
3203 			if (info->ext_disp_conn_info.path[i].device_tag != 0)
3204 				DC_LOG_BIOS("integrated_info:For EXTERNAL DISPLAY PATH %d --------------\n"
3205 						"DEVICE_TAG: 0x%x\n"
3206 						"DEVICE_ACPI_ENUM: 0x%x\n"
3207 						"DEVICE_CONNECTOR_ID: 0x%x\n"
3208 						"EXT_AUX_DDC_LUT_INDEX: %d\n"
3209 						"EXT_HPD_PIN_LUT_INDEX: %d\n"
3210 						"EXT_ENCODER_OBJ_ID: 0x%x\n"
3211 						"Encoder CAPS: 0x%x\n",
3212 						i,
3213 						info->ext_disp_conn_info.path[i].device_tag,
3214 						info->ext_disp_conn_info.path[i].device_acpi_enum,
3215 						info->ext_disp_conn_info.path[i].device_connector_id.id,
3216 						info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index,
3217 						info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index,
3218 						info->ext_disp_conn_info.path[i].ext_encoder_obj_id.id,
3219 						info->ext_disp_conn_info.path[i].caps
3220 						);
3221 			if ((info->ext_disp_conn_info.path[i].caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN)
3222 				DC_LOG_BIOS("BIOS AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);
3223 			else if (bp->base.ctx->dc->config.force_bios_fixed_vs) {
3224 				info->ext_disp_conn_info.path[i].caps &= ~AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK;
3225 				info->ext_disp_conn_info.path[i].caps |= AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN;
3226 				DC_LOG_BIOS("driver forced AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);
3227 			}
3228 		}
3229 		// Log the Checksum and Voltage Swing
3230 		DC_LOG_BIOS("Integrated info table CHECKSUM: %d\n"
3231 					"Integrated info table FIX_DP_VOLTAGE_SWING: %d\n",
3232 					info->ext_disp_conn_info.checksum,
3233 					info->ext_disp_conn_info.fixdpvoltageswing);
3234 		if (bp->base.ctx->dc->config.force_bios_fixed_vs && info->ext_disp_conn_info.fixdpvoltageswing == 0) {
3235 			info->ext_disp_conn_info.fixdpvoltageswing = bp->base.ctx->dc->config.force_bios_fixed_vs & 0xF;
3236 			DC_LOG_BIOS("driver forced fixdpvoltageswing = %d\n", info->ext_disp_conn_info.fixdpvoltageswing);
3237 		}
3238 	}
3239 
3240 	return result;
3241 }
3242 
3243 static enum bp_result bios_parser_get_vram_info(
3244 		struct dc_bios *dcb,
3245 		struct dc_vram_info *info)
3246 {
3247 	struct bios_parser *bp = BP_FROM_DCB(dcb);
3248 	enum bp_result result = BP_RESULT_BADBIOSTABLE;
3249 	struct atom_common_table_header *header;
3250 	struct atom_data_revision revision;
3251 
3252 	// vram info moved to umc_info for DCN4x
3253 	if (info && DATA_TABLES(umc_info)) {
3254 		header = GET_IMAGE(struct atom_common_table_header,
3255 					DATA_TABLES(umc_info));
3256 
3257 		get_atom_data_table_revision(header, &revision);
3258 
3259 		switch (revision.major) {
3260 		case 4:
3261 			switch (revision.minor) {
3262 			case 0:
3263 				result = get_vram_info_from_umc_info_v40(bp, info);
3264 				break;
3265 			default:
3266 				break;
3267 			}
3268 			break;
3269 		default:
3270 			break;
3271 		}
3272 	}
3273 
3274 	if (result != BP_RESULT_OK && info && DATA_TABLES(vram_info)) {
3275 		header = GET_IMAGE(struct atom_common_table_header,
3276 					DATA_TABLES(vram_info));
3277 
3278 		get_atom_data_table_revision(header, &revision);
3279 
3280 		switch (revision.major) {
3281 		case 2:
3282 			switch (revision.minor) {
3283 			case 3:
3284 				result = get_vram_info_v23(bp, info);
3285 				break;
3286 			case 4:
3287 				result = get_vram_info_v24(bp, info);
3288 				break;
3289 			case 5:
3290 				result = get_vram_info_v25(bp, info);
3291 				break;
3292 			default:
3293 				break;
3294 			}
3295 			break;
3296 
3297 		case 3:
3298 			switch (revision.minor) {
3299 			case 0:
3300 				result = get_vram_info_v30(bp, info);
3301 				break;
3302 			default:
3303 				break;
3304 			}
3305 			break;
3306 
3307 		default:
3308 			return result;
3309 		}
3310 
3311 	}
3312 	return result;
3313 }
3314 
3315 static struct integrated_info *bios_parser_create_integrated_info(
3316 	struct dc_bios *dcb)
3317 {
3318 	struct bios_parser *bp = BP_FROM_DCB(dcb);
3319 	struct integrated_info *info;
3320 
3321 	info = kzalloc_obj(struct integrated_info);
3322 
3323 	if (info == NULL) {
3324 		ASSERT_CRITICAL(0);
3325 		return NULL;
3326 	}
3327 
3328 	if (construct_integrated_info(bp, info) == BP_RESULT_OK)
3329 		return info;
3330 
3331 	kfree(info);
3332 
3333 	return NULL;
3334 }
3335 
3336 static enum bp_result update_slot_layout_info(
3337 	struct dc_bios *dcb,
3338 	unsigned int i,
3339 	struct slot_layout_info *slot_layout_info)
3340 {
3341 	unsigned int record_offset;
3342 	unsigned int j;
3343 	unsigned int n;
3344 	struct atom_display_object_path_v2 *object;
3345 	struct atom_bracket_layout_record *record;
3346 	struct atom_common_record_header *record_header;
3347 	static enum bp_result result;
3348 	struct bios_parser *bp;
3349 	struct object_info_table *tbl;
3350 	struct display_object_info_table_v1_4 *v1_4;
3351 
3352 	record = NULL;
3353 	record_header = NULL;
3354 	result = BP_RESULT_NORECORD;
3355 
3356 	bp = BP_FROM_DCB(dcb);
3357 	tbl = &bp->object_info_tbl;
3358 	v1_4 = tbl->v1_4;
3359 
3360 	object = &v1_4->display_path[i];
3361 	record_offset = (unsigned int)
3362 		(object->disp_recordoffset) +
3363 		(unsigned int)(bp->object_info_tbl_offset);
3364 
3365 	for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
3366 
3367 		record_header = (struct atom_common_record_header *)
3368 			GET_IMAGE(struct atom_common_record_header,
3369 			record_offset);
3370 		if (record_header == NULL) {
3371 			result = BP_RESULT_BADBIOSTABLE;
3372 			break;
3373 		}
3374 
3375 		/* the end of the list */
3376 		if (record_header->record_type == 0xff ||
3377 			record_header->record_size == 0)	{
3378 			break;
3379 		}
3380 
3381 		if (record_header->record_type ==
3382 			ATOM_BRACKET_LAYOUT_RECORD_TYPE &&
3383 			sizeof(struct atom_bracket_layout_record)
3384 			<= record_header->record_size) {
3385 			record = (struct atom_bracket_layout_record *)
3386 				(record_header);
3387 			result = BP_RESULT_OK;
3388 			break;
3389 		}
3390 
3391 		record_offset += record_header->record_size;
3392 	}
3393 
3394 	/* return if the record not found */
3395 	if (result != BP_RESULT_OK)
3396 		return result;
3397 
3398 	/* get slot sizes */
3399 	slot_layout_info->length = record->bracketlen;
3400 	slot_layout_info->width = record->bracketwidth;
3401 
3402 	/* get info for each connector in the slot */
3403 	slot_layout_info->num_of_connectors = record->conn_num;
3404 	for (j = 0; j < slot_layout_info->num_of_connectors; ++j) {
3405 		slot_layout_info->connectors[j].connector_type =
3406 			(enum connector_layout_type)
3407 			(record->conn_info[j].connector_type);
3408 		switch (record->conn_info[j].connector_type) {
3409 		case CONNECTOR_TYPE_DVI_D:
3410 			slot_layout_info->connectors[j].connector_type =
3411 				CONNECTOR_LAYOUT_TYPE_DVI_D;
3412 			slot_layout_info->connectors[j].length =
3413 				CONNECTOR_SIZE_DVI;
3414 			break;
3415 
3416 		case CONNECTOR_TYPE_HDMI:
3417 			slot_layout_info->connectors[j].connector_type =
3418 				CONNECTOR_LAYOUT_TYPE_HDMI;
3419 			slot_layout_info->connectors[j].length =
3420 				CONNECTOR_SIZE_HDMI;
3421 			break;
3422 
3423 		case CONNECTOR_TYPE_DISPLAY_PORT:
3424 			slot_layout_info->connectors[j].connector_type =
3425 				CONNECTOR_LAYOUT_TYPE_DP;
3426 			slot_layout_info->connectors[j].length =
3427 				CONNECTOR_SIZE_DP;
3428 			break;
3429 
3430 		case CONNECTOR_TYPE_MINI_DISPLAY_PORT:
3431 			slot_layout_info->connectors[j].connector_type =
3432 				CONNECTOR_LAYOUT_TYPE_MINI_DP;
3433 			slot_layout_info->connectors[j].length =
3434 				CONNECTOR_SIZE_MINI_DP;
3435 			break;
3436 
3437 		default:
3438 			slot_layout_info->connectors[j].connector_type =
3439 				CONNECTOR_LAYOUT_TYPE_UNKNOWN;
3440 			slot_layout_info->connectors[j].length =
3441 				CONNECTOR_SIZE_UNKNOWN;
3442 		}
3443 
3444 		slot_layout_info->connectors[j].position =
3445 			record->conn_info[j].position;
3446 		slot_layout_info->connectors[j].connector_id =
3447 			object_id_from_bios_object_id(
3448 				record->conn_info[j].connectorobjid);
3449 	}
3450 	return result;
3451 }
3452 
3453 static enum bp_result update_slot_layout_info_v2(
3454 	struct dc_bios *dcb,
3455 	unsigned int i,
3456 	struct slot_layout_info *slot_layout_info)
3457 {
3458 	unsigned int record_offset;
3459 	unsigned int n;
3460 	struct atom_display_object_path_v3 *object;
3461 	struct atom_bracket_layout_record_v2 *record;
3462 	struct atom_common_record_header *record_header;
3463 	static enum bp_result result;
3464 	struct bios_parser *bp;
3465 	struct object_info_table *tbl;
3466 	struct display_object_info_table_v1_5 *v1_5;
3467 	struct graphics_object_id connector_id;
3468 
3469 	record = NULL;
3470 	record_header = NULL;
3471 	result = BP_RESULT_NORECORD;
3472 
3473 	bp = BP_FROM_DCB(dcb);
3474 	tbl = &bp->object_info_tbl;
3475 	v1_5 = tbl->v1_5;
3476 
3477 	object = &v1_5->display_path[i];
3478 	record_offset = (unsigned int)
3479 		(object->disp_recordoffset) +
3480 		(unsigned int)(bp->object_info_tbl_offset);
3481 
3482 	for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
3483 
3484 		record_header = (struct atom_common_record_header *)
3485 			GET_IMAGE(struct atom_common_record_header,
3486 			record_offset);
3487 		if (record_header == NULL) {
3488 			result = BP_RESULT_BADBIOSTABLE;
3489 			break;
3490 		}
3491 
3492 		/* the end of the list */
3493 		if (record_header->record_type == ATOM_RECORD_END_TYPE ||
3494 			record_header->record_size == 0)	{
3495 			break;
3496 		}
3497 
3498 		if (record_header->record_type ==
3499 			ATOM_BRACKET_LAYOUT_V2_RECORD_TYPE &&
3500 			sizeof(struct atom_bracket_layout_record_v2)
3501 			<= record_header->record_size) {
3502 			record = (struct atom_bracket_layout_record_v2 *)
3503 				(record_header);
3504 			result = BP_RESULT_OK;
3505 			break;
3506 		}
3507 
3508 		record_offset += record_header->record_size;
3509 	}
3510 
3511 	/* return if the record not found */
3512 	if (result != BP_RESULT_OK)
3513 		return result;
3514 
3515 	/* get slot sizes */
3516 	connector_id = object_id_from_bios_object_id(object->display_objid);
3517 
3518 	slot_layout_info->length = record->bracketlen;
3519 	slot_layout_info->width = record->bracketwidth;
3520 	slot_layout_info->num_of_connectors = v1_5->number_of_path;
3521 	slot_layout_info->connectors[i].position = record->conn_num;
3522 	slot_layout_info->connectors[i].connector_id = connector_id;
3523 
3524 	switch (connector_id.id) {
3525 	case CONNECTOR_ID_SINGLE_LINK_DVID:
3526 	case CONNECTOR_ID_DUAL_LINK_DVID:
3527 		slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_DVI_D;
3528 		slot_layout_info->connectors[i].length = CONNECTOR_SIZE_DVI;
3529 		break;
3530 
3531 	case CONNECTOR_ID_HDMI_TYPE_A:
3532 		slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_HDMI;
3533 		slot_layout_info->connectors[i].length = CONNECTOR_SIZE_HDMI;
3534 		break;
3535 
3536 	case CONNECTOR_ID_DISPLAY_PORT:
3537 	case CONNECTOR_ID_USBC:
3538 		if (record->mini_type == MINI_TYPE_NORMAL) {
3539 			slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_DP;
3540 			slot_layout_info->connectors[i].length = CONNECTOR_SIZE_DP;
3541 		} else {
3542 			slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_MINI_DP;
3543 			slot_layout_info->connectors[i].length = CONNECTOR_SIZE_MINI_DP;
3544 		}
3545 		break;
3546 
3547 	default:
3548 		slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_UNKNOWN;
3549 		slot_layout_info->connectors[i].length = CONNECTOR_SIZE_UNKNOWN;
3550 	}
3551 	return result;
3552 }
3553 
3554 static enum bp_result get_bracket_layout_record(
3555 	struct dc_bios *dcb,
3556 	unsigned int bracket_layout_id,
3557 	struct slot_layout_info *slot_layout_info)
3558 {
3559 	unsigned int i;
3560 	struct bios_parser *bp = BP_FROM_DCB(dcb);
3561 	static enum bp_result result;
3562 	struct object_info_table *tbl;
3563 	struct display_object_info_table_v1_4 *v1_4;
3564 	struct display_object_info_table_v1_5 *v1_5;
3565 
3566 	if (slot_layout_info == NULL) {
3567 		DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");
3568 		return BP_RESULT_BADINPUT;
3569 	}
3570 
3571 	tbl = &bp->object_info_tbl;
3572 	v1_4 = tbl->v1_4;
3573 	v1_5 = tbl->v1_5;
3574 
3575 	result = BP_RESULT_NORECORD;
3576 	switch (bp->object_info_tbl.revision.minor) {
3577 	case 4:
3578 	default:
3579 		for (i = 0; i < v1_4->number_of_path; ++i) {
3580 			if (bracket_layout_id == v1_4->display_path[i].display_objid) {
3581 				result = update_slot_layout_info(dcb, i, slot_layout_info);
3582 				break;
3583 			}
3584 		}
3585 		break;
3586 	case 5:
3587 		for (i = 0; i < v1_5->number_of_path; ++i)
3588 			result = update_slot_layout_info_v2(dcb, i, slot_layout_info);
3589 		break;
3590 	}
3591 
3592 	return result;
3593 }
3594 
3595 static enum bp_result bios_get_board_layout_info(
3596 	struct dc_bios *dcb,
3597 	struct board_layout_info *board_layout_info)
3598 {
3599 	unsigned int i;
3600 	struct bios_parser *bp;
3601 	static enum bp_result record_result;
3602 	unsigned int max_slots;
3603 
3604 	const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {
3605 		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1,
3606 		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2,
3607 		0, 0
3608 	};
3609 
3610 	bp = BP_FROM_DCB(dcb);
3611 
3612 	if (board_layout_info == NULL) {
3613 		DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");
3614 		return BP_RESULT_BADINPUT;
3615 	}
3616 
3617 	board_layout_info->num_of_slots = 0;
3618 	max_slots = MAX_BOARD_SLOTS;
3619 
3620 	// Assume single slot on v1_5
3621 	if (bp->object_info_tbl.revision.minor == 5) {
3622 		max_slots = 1;
3623 	}
3624 
3625 	for (i = 0; i < max_slots; ++i) {
3626 		record_result = get_bracket_layout_record(dcb,
3627 			slot_index_to_vbios_id[i],
3628 			&board_layout_info->slots[i]);
3629 
3630 		if (record_result == BP_RESULT_NORECORD && i > 0)
3631 			break; /* no more slots present in bios */
3632 		else if (record_result != BP_RESULT_OK)
3633 			return record_result;  /* fail */
3634 
3635 		++board_layout_info->num_of_slots;
3636 	}
3637 
3638 	/* all data is valid */
3639 	board_layout_info->is_number_of_slots_valid = 1;
3640 	board_layout_info->is_slots_size_valid = 1;
3641 	board_layout_info->is_connector_offsets_valid = 1;
3642 	board_layout_info->is_connector_lengths_valid = 1;
3643 
3644 	return BP_RESULT_OK;
3645 }
3646 
3647 
3648 static uint16_t bios_parser_pack_data_tables(
3649 	struct dc_bios *dcb,
3650 	void *dst)
3651 {
3652 	(void)dcb;
3653 	(void)dst;
3654 	// TODO: There is data bytes alignment issue, disable it for now.
3655 	return 0;
3656 }
3657 
3658 static struct atom_dc_golden_table_v1 *bios_get_golden_table(
3659 		struct bios_parser *bp,
3660 		uint32_t rev_major,
3661 		uint32_t rev_minor,
3662 		uint16_t *dc_golden_table_ver)
3663 {
3664 	struct atom_display_controller_info_v4_4 *disp_cntl_tbl_4_4 = NULL;
3665 	uint32_t dc_golden_offset = 0;
3666 	*dc_golden_table_ver = 0;
3667 
3668 	if (!DATA_TABLES(dce_info))
3669 		return NULL;
3670 
3671 	/* ver.4.4 or higher */
3672 	switch (rev_major) {
3673 	case 4:
3674 		switch (rev_minor) {
3675 		case 4:
3676 			disp_cntl_tbl_4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,
3677 									DATA_TABLES(dce_info));
3678 			if (!disp_cntl_tbl_4_4)
3679 				return NULL;
3680 			dc_golden_offset = DATA_TABLES(dce_info) + disp_cntl_tbl_4_4->dc_golden_table_offset;
3681 			*dc_golden_table_ver = disp_cntl_tbl_4_4->dc_golden_table_ver;
3682 			break;
3683 		case 5:
3684 		default:
3685 			/* For atom_display_controller_info_v4_5 there is no need to get golden table from
3686 			 * dc_golden_table_offset as all these fields previously in golden table used for AUX
3687 			 * pre-charge settings are now available directly in atom_display_controller_info_v4_5.
3688 			 */
3689 			break;
3690 		}
3691 		break;
3692 	}
3693 
3694 	if (!dc_golden_offset)
3695 		return NULL;
3696 
3697 	if (*dc_golden_table_ver != 1)
3698 		return NULL;
3699 
3700 	return GET_IMAGE(struct atom_dc_golden_table_v1,
3701 			dc_golden_offset);
3702 }
3703 
3704 static enum bp_result bios_get_atom_dc_golden_table(
3705 	struct dc_bios *dcb)
3706 {
3707 	struct bios_parser *bp = BP_FROM_DCB(dcb);
3708 	enum bp_result result = BP_RESULT_OK;
3709 	struct atom_dc_golden_table_v1 *atom_dc_golden_table = NULL;
3710 	struct atom_common_table_header *header;
3711 	struct atom_data_revision tbl_revision;
3712 	uint16_t dc_golden_table_ver = 0;
3713 
3714 	header = GET_IMAGE(struct atom_common_table_header,
3715 							DATA_TABLES(dce_info));
3716 	if (!header)
3717 		return BP_RESULT_UNSUPPORTED;
3718 
3719 	get_atom_data_table_revision(header, &tbl_revision);
3720 
3721 	atom_dc_golden_table = bios_get_golden_table(bp,
3722 			tbl_revision.major,
3723 			tbl_revision.minor,
3724 			&dc_golden_table_ver);
3725 
3726 	if (!atom_dc_golden_table)
3727 		return BP_RESULT_UNSUPPORTED;
3728 
3729 	dcb->golden_table.dc_golden_table_ver = dc_golden_table_ver;
3730 	dcb->golden_table.aux_dphy_rx_control0_val = atom_dc_golden_table->aux_dphy_rx_control0_val;
3731 	dcb->golden_table.aux_dphy_rx_control1_val = atom_dc_golden_table->aux_dphy_rx_control1_val;
3732 	dcb->golden_table.aux_dphy_tx_control_val = atom_dc_golden_table->aux_dphy_tx_control_val;
3733 	dcb->golden_table.dc_gpio_aux_ctrl_0_val = atom_dc_golden_table->dc_gpio_aux_ctrl_0_val;
3734 	dcb->golden_table.dc_gpio_aux_ctrl_1_val = atom_dc_golden_table->dc_gpio_aux_ctrl_1_val;
3735 	dcb->golden_table.dc_gpio_aux_ctrl_2_val = atom_dc_golden_table->dc_gpio_aux_ctrl_2_val;
3736 	dcb->golden_table.dc_gpio_aux_ctrl_3_val = atom_dc_golden_table->dc_gpio_aux_ctrl_3_val;
3737 	dcb->golden_table.dc_gpio_aux_ctrl_4_val = atom_dc_golden_table->dc_gpio_aux_ctrl_4_val;
3738 	dcb->golden_table.dc_gpio_aux_ctrl_5_val = atom_dc_golden_table->dc_gpio_aux_ctrl_5_val;
3739 
3740 	return result;
3741 }
3742 
3743 
3744 static const struct dc_vbios_funcs vbios_funcs = {
3745 	.get_connectors_number = bios_parser_get_connectors_number,
3746 
3747 	.get_connector_id = bios_parser_get_connector_id,
3748 
3749 	.get_src_obj = bios_parser_get_src_obj,
3750 
3751 	.get_i2c_info = bios_parser_get_i2c_info,
3752 
3753 	.get_hpd_info = bios_parser_get_hpd_info,
3754 
3755 	.get_device_tag = bios_parser_get_device_tag,
3756 
3757 	.get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
3758 
3759 	.get_ss_entry_number = bios_parser_get_ss_entry_number,
3760 
3761 	.get_embedded_panel_info = bios_parser_get_embedded_panel_info,
3762 
3763 	.get_gpio_pin_info = bios_parser_get_gpio_pin_info,
3764 
3765 	.get_encoder_cap_info = bios_parser_get_encoder_cap_info,
3766 
3767 	.is_device_id_supported = bios_parser_is_device_id_supported,
3768 
3769 	.is_accelerated_mode = bios_parser_is_accelerated_mode,
3770 
3771 	.set_scratch_critical_state = bios_parser_set_scratch_critical_state,
3772 
3773 
3774 /*	 COMMANDS */
3775 	.encoder_control = bios_parser_encoder_control,
3776 
3777 	.transmitter_control = bios_parser_transmitter_control,
3778 
3779 	.enable_crtc = bios_parser_enable_crtc,
3780 
3781 	.set_pixel_clock = bios_parser_set_pixel_clock,
3782 
3783 	.set_dce_clock = bios_parser_set_dce_clock,
3784 
3785 	.program_crtc_timing = bios_parser_program_crtc_timing,
3786 
3787 	.enable_disp_power_gating = bios_parser_enable_disp_power_gating,
3788 
3789 	.bios_parser_destroy = firmware_parser_destroy,
3790 
3791 	.get_board_layout_info = bios_get_board_layout_info,
3792 	.pack_data_tables = bios_parser_pack_data_tables,
3793 
3794 	.get_atom_dc_golden_table = bios_get_atom_dc_golden_table,
3795 
3796 	.enable_lvtma_control = bios_parser_enable_lvtma_control,
3797 
3798 	.get_soc_bb_info = bios_parser_get_soc_bb_info,
3799 
3800 	.get_disp_connector_caps_info = bios_parser_get_disp_connector_caps_info,
3801 
3802 	.get_lttpr_caps = bios_parser_get_lttpr_caps,
3803 
3804 	.get_lttpr_interop = bios_parser_get_lttpr_interop,
3805 
3806 	.get_connector_speed_cap_info = bios_parser_get_connector_speed_cap_info,
3807 	.get_connector_aux_info = bios_parser_get_connector_aux_info,
3808 };
3809 
3810 static bool bios_parser2_construct(
3811 	struct bios_parser *bp,
3812 	struct bp_init_data *init,
3813 	enum dce_version dce_version)
3814 {
3815 	uint16_t *rom_header_offset = NULL;
3816 	struct atom_rom_header_v2_2 *rom_header = NULL;
3817 	struct display_object_info_table_v1_4 *object_info_tbl;
3818 	struct atom_data_revision tbl_rev = {0};
3819 
3820 	if (!init)
3821 		return false;
3822 
3823 	if (!init->bios)
3824 		return false;
3825 
3826 	bp->base.funcs = &vbios_funcs;
3827 	bp->base.bios = init->bios;
3828 	bp->base.bios_size = bp->base.bios[OFFSET_TO_ATOM_ROM_IMAGE_SIZE] * BIOS_IMAGE_SIZE_UNIT;
3829 
3830 	bp->base.ctx = init->ctx;
3831 
3832 	bp->base.bios_local_image = NULL;
3833 
3834 	rom_header_offset =
3835 			GET_IMAGE(uint16_t, OFFSET_TO_ATOM_ROM_HEADER_POINTER);
3836 
3837 	if (!rom_header_offset)
3838 		return false;
3839 
3840 	rom_header = GET_IMAGE(struct atom_rom_header_v2_2, *rom_header_offset);
3841 
3842 	if (!rom_header)
3843 		return false;
3844 
3845 	get_atom_data_table_revision(&rom_header->table_header, &tbl_rev);
3846 	if (!(tbl_rev.major >= 2 && tbl_rev.minor >= 2))
3847 		return false;
3848 
3849 	bp->master_data_tbl =
3850 		GET_IMAGE(struct atom_master_data_table_v2_1,
3851 				rom_header->masterdatatable_offset);
3852 
3853 	if (!bp->master_data_tbl)
3854 		return false;
3855 
3856 	bp->object_info_tbl_offset = DATA_TABLES(displayobjectinfo);
3857 
3858 	if (!bp->object_info_tbl_offset)
3859 		return false;
3860 
3861 	object_info_tbl =
3862 			GET_IMAGE(struct display_object_info_table_v1_4,
3863 						bp->object_info_tbl_offset);
3864 
3865 	if (!object_info_tbl)
3866 		return false;
3867 
3868 	get_atom_data_table_revision(&object_info_tbl->table_header,
3869 		&bp->object_info_tbl.revision);
3870 
3871 	if (bp->object_info_tbl.revision.major == 1
3872 		&& bp->object_info_tbl.revision.minor == 4) {
3873 		struct display_object_info_table_v1_4 *tbl_v1_4;
3874 
3875 		tbl_v1_4 = GET_IMAGE(struct display_object_info_table_v1_4,
3876 			bp->object_info_tbl_offset);
3877 		if (!tbl_v1_4)
3878 			return false;
3879 
3880 		bp->object_info_tbl.v1_4 = tbl_v1_4;
3881 	} else if (bp->object_info_tbl.revision.major == 1
3882 		&& bp->object_info_tbl.revision.minor == 5) {
3883 		struct display_object_info_table_v1_5 *tbl_v1_5;
3884 
3885 		tbl_v1_5 = GET_IMAGE(struct display_object_info_table_v1_5,
3886 			bp->object_info_tbl_offset);
3887 		if (!tbl_v1_5)
3888 			return false;
3889 
3890 		bp->object_info_tbl.v1_5 = tbl_v1_5;
3891 	} else {
3892 		ASSERT(0);
3893 		return false;
3894 	}
3895 
3896 	dal_firmware_parser_init_cmd_tbl(bp);
3897 	dal_bios_parser_init_cmd_tbl_helper2(&bp->cmd_helper, dce_version);
3898 
3899 	bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);
3900 	bp->base.fw_info_valid = bios_parser_get_firmware_info(&bp->base, &bp->base.fw_info) == BP_RESULT_OK;
3901 	bios_parser_get_vram_info(&bp->base, &bp->base.vram_info);
3902 	bios_parser_get_soc_bb_info(&bp->base, &bp->base.bb_info);
3903 	return true;
3904 }
3905 
3906 struct dc_bios *firmware_parser_create(
3907 	struct bp_init_data *init,
3908 	enum dce_version dce_version)
3909 {
3910 	struct bios_parser *bp;
3911 
3912 	bp = kzalloc_obj(struct bios_parser);
3913 	if (!bp)
3914 		return NULL;
3915 
3916 	if (bios_parser2_construct(bp, init, dce_version))
3917 		return &bp->base;
3918 
3919 	kfree(bp);
3920 	return NULL;
3921 }
3922 
3923 
3924