xref: /linux/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c (revision d36771a03412454a0c7f1c81746426958008a2bb)
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 static enum bp_result bios_parser_get_encoder_cap_info(
2207 	struct dc_bios *dcb,
2208 	struct graphics_object_id object_id,
2209 	struct bp_encoder_cap_info *info)
2210 {
2211 	struct bios_parser *bp = BP_FROM_DCB(dcb);
2212 	struct atom_display_object_path_v2 *object;
2213 	struct atom_encoder_caps_record *record = NULL;
2214 
2215 	if (!info)
2216 		return BP_RESULT_BADINPUT;
2217 
2218 #if defined(CONFIG_DRM_AMD_DC_FP)
2219 	/* encoder cap record not available in v1_5 */
2220 	if (bp->object_info_tbl.revision.minor == 5)
2221 		return BP_RESULT_NORECORD;
2222 #endif
2223 
2224 	object = get_bios_object(bp, object_id);
2225 
2226 	if (!object)
2227 		return BP_RESULT_BADINPUT;
2228 
2229 	record = get_encoder_cap_record(bp, object);
2230 	if (!record)
2231 		return BP_RESULT_NORECORD;
2232 	DC_LOG_BIOS("record->encodercaps 0x%x for object_id 0x%x", record->encodercaps, object_id.id);
2233 
2234 	info->DP_HBR2_CAP = (record->encodercaps &
2235 			ATOM_ENCODER_CAP_RECORD_HBR2) ? 1 : 0;
2236 	info->DP_HBR2_EN = (record->encodercaps &
2237 			ATOM_ENCODER_CAP_RECORD_HBR2_EN) ? 1 : 0;
2238 	info->DP_HBR3_EN = (record->encodercaps &
2239 			ATOM_ENCODER_CAP_RECORD_HBR3_EN) ? 1 : 0;
2240 	info->HDMI_6GB_EN = (record->encodercaps &
2241 			ATOM_ENCODER_CAP_RECORD_HDMI6Gbps_EN) ? 1 : 0;
2242 	info->IS_DP2_CAPABLE = (record->encodercaps &
2243 			ATOM_ENCODER_CAP_RECORD_DP2) ? 1 : 0;
2244 	info->DP_UHBR10_EN = (record->encodercaps &
2245 			ATOM_ENCODER_CAP_RECORD_UHBR10_EN) ? 1 : 0;
2246 	info->DP_UHBR13_5_EN = (record->encodercaps &
2247 			ATOM_ENCODER_CAP_RECORD_UHBR13_5_EN) ? 1 : 0;
2248 	info->DP_UHBR20_EN = (record->encodercaps &
2249 			ATOM_ENCODER_CAP_RECORD_UHBR20_EN) ? 1 : 0;
2250 	info->DP_IS_USB_C = (record->encodercaps &
2251 			ATOM_ENCODER_CAP_RECORD_USB_C_TYPE) ? 1 : 0;
2252 	DC_LOG_BIOS("\t info->DP_IS_USB_C %d", info->DP_IS_USB_C);
2253 
2254 	return BP_RESULT_OK;
2255 }
2256 
2257 
2258 static struct atom_encoder_caps_record *get_encoder_cap_record(
2259 	struct bios_parser *bp,
2260 	struct atom_display_object_path_v2 *object)
2261 {
2262 	struct atom_common_record_header *header;
2263 	uint32_t offset;
2264 	int i;
2265 
2266 	if (!object) {
2267 		BREAK_TO_DEBUGGER(); /* Invalid object */
2268 		return NULL;
2269 	}
2270 
2271 	offset = object->encoder_recordoffset + bp->object_info_tbl_offset;
2272 
2273 	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
2274 		header = GET_IMAGE(struct atom_common_record_header, offset);
2275 
2276 		if (!header)
2277 			return NULL;
2278 
2279 		offset += header->record_size;
2280 
2281 		if (header->record_type == LAST_RECORD_TYPE ||
2282 				!header->record_size)
2283 			break;
2284 
2285 		if (header->record_type != ATOM_ENCODER_CAP_RECORD_TYPE)
2286 			continue;
2287 
2288 		if (sizeof(struct atom_encoder_caps_record) <=
2289 							header->record_size)
2290 			return (struct atom_encoder_caps_record *)header;
2291 	}
2292 
2293 	return NULL;
2294 }
2295 
2296 static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
2297 	struct bios_parser *bp,
2298 	struct atom_display_object_path_v2 *object)
2299 {
2300 	struct atom_common_record_header *header;
2301 	uint32_t offset;
2302 	int i;
2303 
2304 	if (!object) {
2305 		BREAK_TO_DEBUGGER(); /* Invalid object */
2306 		return NULL;
2307 	}
2308 
2309 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
2310 
2311 	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
2312 		header = GET_IMAGE(struct atom_common_record_header, offset);
2313 
2314 		if (!header)
2315 			return NULL;
2316 
2317 		offset += header->record_size;
2318 
2319 		if (header->record_type == LAST_RECORD_TYPE ||
2320 				!header->record_size)
2321 			break;
2322 
2323 		if (header->record_type != ATOM_DISP_CONNECTOR_CAPS_RECORD_TYPE)
2324 			continue;
2325 
2326 		if (sizeof(struct atom_disp_connector_caps_record) <=
2327 							header->record_size)
2328 			return (struct atom_disp_connector_caps_record *)header;
2329 	}
2330 
2331 	return NULL;
2332 }
2333 
2334 static struct atom_connector_caps_record *get_connector_caps_record(struct bios_parser *bp,
2335 								    struct atom_display_object_path_v3 *object)
2336 {
2337 	struct atom_common_record_header *header;
2338 	uint32_t offset;
2339 	int i;
2340 
2341 	if (!object) {
2342 		BREAK_TO_DEBUGGER(); /* Invalid object */
2343 		return NULL;
2344 	}
2345 
2346 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
2347 
2348 	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
2349 		header = GET_IMAGE(struct atom_common_record_header, offset);
2350 
2351 		if (!header)
2352 			return NULL;
2353 
2354 		offset += header->record_size;
2355 
2356 		if (header->record_type == ATOM_RECORD_END_TYPE ||
2357 				!header->record_size)
2358 			break;
2359 
2360 		if (header->record_type != ATOM_CONNECTOR_CAP_RECORD_TYPE)
2361 			continue;
2362 
2363 		if (sizeof(struct atom_connector_caps_record) <= header->record_size)
2364 			return (struct atom_connector_caps_record *)header;
2365 	}
2366 
2367 	return NULL;
2368 }
2369 
2370 static enum bp_result bios_parser_get_disp_connector_caps_info(
2371 	struct dc_bios *dcb,
2372 	struct graphics_object_id object_id,
2373 	struct bp_disp_connector_caps_info *info)
2374 {
2375 	struct bios_parser *bp = BP_FROM_DCB(dcb);
2376 	struct atom_display_object_path_v2 *object;
2377 	struct atom_display_object_path_v3 *object_path_v3;
2378 	struct atom_connector_caps_record *record_path_v3;
2379 	struct atom_disp_connector_caps_record *record = NULL;
2380 
2381 	if (!info)
2382 		return BP_RESULT_BADINPUT;
2383 
2384 	switch (bp->object_info_tbl.revision.minor) {
2385 	case 4:
2386 		default:
2387 			object = get_bios_object(bp, object_id);
2388 
2389 			if (!object)
2390 				return BP_RESULT_BADINPUT;
2391 
2392 			record = get_disp_connector_caps_record(bp, object);
2393 			if (!record)
2394 				return BP_RESULT_NORECORD;
2395 
2396 			info->INTERNAL_DISPLAY =
2397 				(record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY) ? 1 : 0;
2398 			info->INTERNAL_DISPLAY_BL =
2399 				(record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL) ? 1 : 0;
2400 			break;
2401 	case 5:
2402 		object_path_v3 = get_bios_object_from_path_v3(bp, object_id);
2403 
2404 		if (!object_path_v3)
2405 			return BP_RESULT_BADINPUT;
2406 
2407 		record_path_v3 = get_connector_caps_record(bp, object_path_v3);
2408 		if (!record_path_v3)
2409 			return BP_RESULT_NORECORD;
2410 
2411 		info->INTERNAL_DISPLAY = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY)
2412 									? 1 : 0;
2413 		info->INTERNAL_DISPLAY_BL = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL)
2414 										? 1 : 0;
2415 		// All aux transactions for this connector should rely only on aux instance, not on ddc instance
2416 		info->NO_DDC_PIN = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_DP_PLUS_PLUS_TYPE2_ONLY) ? 1 : 0;
2417 
2418 		break;
2419 	}
2420 
2421 	return BP_RESULT_OK;
2422 }
2423 
2424 static struct atom_connector_speed_record *get_connector_speed_cap_record(struct bios_parser *bp,
2425 									  struct atom_display_object_path_v3 *object)
2426 {
2427 	struct atom_common_record_header *header;
2428 	uint32_t offset;
2429 	int i;
2430 
2431 	if (!object) {
2432 		BREAK_TO_DEBUGGER(); /* Invalid object */
2433 		return NULL;
2434 	}
2435 
2436 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
2437 
2438 	for (i = 0; i < BIOS_MAX_NUM_RECORD; i++) {
2439 		header = GET_IMAGE(struct atom_common_record_header, offset);
2440 
2441 		if (!header)
2442 			return NULL;
2443 
2444 		offset += header->record_size;
2445 
2446 		if (header->record_type == ATOM_RECORD_END_TYPE ||
2447 				!header->record_size)
2448 			break;
2449 
2450 		if (header->record_type != ATOM_CONNECTOR_SPEED_UPTO)
2451 			continue;
2452 
2453 		if (sizeof(struct atom_connector_speed_record) <= header->record_size)
2454 			return (struct atom_connector_speed_record *)header;
2455 	}
2456 
2457 	return NULL;
2458 }
2459 
2460 static enum bp_result bios_parser_get_connector_speed_cap_info(
2461 	struct dc_bios *dcb,
2462 	struct graphics_object_id object_id,
2463 	struct bp_connector_speed_cap_info *info)
2464 {
2465 	struct bios_parser *bp = BP_FROM_DCB(dcb);
2466 	struct atom_display_object_path_v3 *object_path_v3;
2467 	//struct atom_connector_speed_record *record = NULL;
2468 	struct atom_connector_speed_record *record;
2469 
2470 	if (!info)
2471 		return BP_RESULT_BADINPUT;
2472 
2473 	object_path_v3 = get_bios_object_from_path_v3(bp, object_id);
2474 
2475 	if (!object_path_v3)
2476 		return BP_RESULT_BADINPUT;
2477 
2478 	record = get_connector_speed_cap_record(bp, object_path_v3);
2479 	if (!record)
2480 		return BP_RESULT_NORECORD;
2481 
2482 	info->DP_HBR2_EN = (record->connector_max_speed >= 5400) ? 1 : 0;
2483 	info->DP_HBR3_EN = (record->connector_max_speed >= 8100) ? 1 : 0;
2484 	info->HDMI_6GB_EN = (record->connector_max_speed >= 5940) ? 1 : 0;
2485 	info->DP_UHBR10_EN = (record->connector_max_speed >= 10000) ? 1 : 0;
2486 	info->DP_UHBR13_5_EN = (record->connector_max_speed >= 13500) ? 1 : 0;
2487 	info->DP_UHBR20_EN = (record->connector_max_speed >= 20000) ? 1 : 0;
2488 	return BP_RESULT_OK;
2489 }
2490 
2491 static enum bp_result get_vram_info_v23(
2492 	struct bios_parser *bp,
2493 	struct dc_vram_info *info)
2494 {
2495 	struct atom_vram_info_header_v2_3 *info_v23;
2496 	static enum bp_result result = BP_RESULT_OK;
2497 
2498 	info_v23 = GET_IMAGE(struct atom_vram_info_header_v2_3,
2499 						DATA_TABLES(vram_info));
2500 
2501 	if (info_v23 == NULL)
2502 		return BP_RESULT_BADBIOSTABLE;
2503 
2504 	info->num_chans = info_v23->vram_module[0].channel_num;
2505 	info->dram_channel_width_bytes = (1 << info_v23->vram_module[0].channel_width) / 8;
2506 
2507 	return result;
2508 }
2509 
2510 static enum bp_result get_vram_info_v24(
2511 	struct bios_parser *bp,
2512 	struct dc_vram_info *info)
2513 {
2514 	struct atom_vram_info_header_v2_4 *info_v24;
2515 	static enum bp_result result = BP_RESULT_OK;
2516 
2517 	info_v24 = GET_IMAGE(struct atom_vram_info_header_v2_4,
2518 						DATA_TABLES(vram_info));
2519 
2520 	if (info_v24 == NULL)
2521 		return BP_RESULT_BADBIOSTABLE;
2522 
2523 	info->num_chans = info_v24->vram_module[0].channel_num;
2524 	info->dram_channel_width_bytes = (1 << info_v24->vram_module[0].channel_width) / 8;
2525 
2526 	return result;
2527 }
2528 
2529 static enum bp_result get_vram_info_v25(
2530 	struct bios_parser *bp,
2531 	struct dc_vram_info *info)
2532 {
2533 	struct atom_vram_info_header_v2_5 *info_v25;
2534 	static enum bp_result result = BP_RESULT_OK;
2535 
2536 	info_v25 = GET_IMAGE(struct atom_vram_info_header_v2_5,
2537 						DATA_TABLES(vram_info));
2538 
2539 	if (info_v25 == NULL)
2540 		return BP_RESULT_BADBIOSTABLE;
2541 
2542 	info->num_chans = info_v25->vram_module[0].channel_num;
2543 	info->dram_channel_width_bytes = (1 << info_v25->vram_module[0].channel_width) / 8;
2544 
2545 	return result;
2546 }
2547 
2548 static enum bp_result get_vram_info_v30(
2549 	struct bios_parser *bp,
2550 	struct dc_vram_info *info)
2551 {
2552 	struct atom_vram_info_header_v3_0 *info_v30;
2553 	enum bp_result result = BP_RESULT_OK;
2554 
2555 	info_v30 = GET_IMAGE(struct atom_vram_info_header_v3_0,
2556 						DATA_TABLES(vram_info));
2557 
2558 	if (info_v30 == NULL)
2559 		return BP_RESULT_BADBIOSTABLE;
2560 
2561 	info->num_chans = info_v30->channel_num;
2562 	info->dram_channel_width_bytes = (1 << info_v30->channel_width) / 8;
2563 
2564 	return result;
2565 }
2566 
2567 static enum bp_result get_vram_info_from_umc_info_v40(
2568 		struct bios_parser *bp,
2569 		struct dc_vram_info *info)
2570 {
2571 	struct atom_umc_info_v4_0 *info_v40;
2572 	enum bp_result result = BP_RESULT_OK;
2573 
2574 	info_v40 = GET_IMAGE(struct atom_umc_info_v4_0,
2575 						DATA_TABLES(umc_info));
2576 
2577 	if (info_v40 == NULL)
2578 		return BP_RESULT_BADBIOSTABLE;
2579 
2580 	info->num_chans = info_v40->channel_num;
2581 	info->dram_channel_width_bytes = (1 << info_v40->channel_width) / 8;
2582 
2583 	return result;
2584 }
2585 
2586 /*
2587  * get_integrated_info_v11
2588  *
2589  * @brief
2590  * Get V8 integrated BIOS information
2591  *
2592  * @param
2593  * bios_parser *bp - [in]BIOS parser handler to get master data table
2594  * integrated_info *info - [out] store and output integrated info
2595  *
2596  * @return
2597  * static enum bp_result - BP_RESULT_OK if information is available,
2598  *                  BP_RESULT_BADBIOSTABLE otherwise.
2599  */
2600 static enum bp_result get_integrated_info_v11(
2601 	struct bios_parser *bp,
2602 	struct integrated_info *info)
2603 {
2604 	struct atom_integrated_system_info_v1_11 *info_v11;
2605 	uint32_t i;
2606 
2607 	info_v11 = GET_IMAGE(struct atom_integrated_system_info_v1_11,
2608 					DATA_TABLES(integratedsysteminfo));
2609 
2610 	if (info_v11 == NULL)
2611 		return BP_RESULT_BADBIOSTABLE;
2612 
2613 	DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v11->gpuclk_ss_percentage);
2614 
2615 	info->gpu_cap_info =
2616 	le32_to_cpu(info_v11->gpucapinfo);
2617 	/*
2618 	* system_config: Bit[0] = 0 : PCIE power gating disabled
2619 	*                       = 1 : PCIE power gating enabled
2620 	*                Bit[1] = 0 : DDR-PLL shut down disabled
2621 	*                       = 1 : DDR-PLL shut down enabled
2622 	*                Bit[2] = 0 : DDR-PLL power down disabled
2623 	*                       = 1 : DDR-PLL power down enabled
2624 	*/
2625 	info->system_config = le32_to_cpu(info_v11->system_config);
2626 	info->cpu_cap_info = le32_to_cpu(info_v11->cpucapinfo);
2627 	info->memory_type = info_v11->memorytype;
2628 	info->ma_channel_number = info_v11->umachannelnumber;
2629 	info->lvds_ss_percentage =
2630 	le16_to_cpu(info_v11->lvds_ss_percentage);
2631 	info->dp_ss_control =
2632 	le16_to_cpu(info_v11->reserved1);
2633 	info->lvds_sspread_rate_in_10hz =
2634 	le16_to_cpu(info_v11->lvds_ss_rate_10hz);
2635 	info->hdmi_ss_percentage =
2636 	le16_to_cpu(info_v11->hdmi_ss_percentage);
2637 	info->hdmi_sspread_rate_in_10hz =
2638 	le16_to_cpu(info_v11->hdmi_ss_rate_10hz);
2639 	info->dvi_ss_percentage =
2640 	le16_to_cpu(info_v11->dvi_ss_percentage);
2641 	info->dvi_sspread_rate_in_10_hz =
2642 	le16_to_cpu(info_v11->dvi_ss_rate_10hz);
2643 	info->lvds_misc = info_v11->lvds_misc;
2644 	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2645 		info->ext_disp_conn_info.gu_id[i] =
2646 				info_v11->extdispconninfo.guid[i];
2647 	}
2648 
2649 	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2650 		info->ext_disp_conn_info.path[i].device_connector_id =
2651 		object_id_from_bios_object_id(
2652 		le16_to_cpu(info_v11->extdispconninfo.path[i].connectorobjid));
2653 
2654 		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2655 		object_id_from_bios_object_id(
2656 			le16_to_cpu(
2657 			info_v11->extdispconninfo.path[i].ext_encoder_objid));
2658 
2659 		info->ext_disp_conn_info.path[i].device_tag =
2660 			le16_to_cpu(
2661 				info_v11->extdispconninfo.path[i].device_tag);
2662 		info->ext_disp_conn_info.path[i].device_acpi_enum =
2663 		le16_to_cpu(
2664 			info_v11->extdispconninfo.path[i].device_acpi_enum);
2665 		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2666 			info_v11->extdispconninfo.path[i].auxddclut_index;
2667 		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2668 			info_v11->extdispconninfo.path[i].hpdlut_index;
2669 		info->ext_disp_conn_info.path[i].channel_mapping.raw =
2670 			info_v11->extdispconninfo.path[i].channelmapping;
2671 		info->ext_disp_conn_info.path[i].caps =
2672 				(unsigned short)le16_to_cpu(info_v11->extdispconninfo.path[i].caps);
2673 	}
2674 	info->ext_disp_conn_info.checksum =
2675 	info_v11->extdispconninfo.checksum;
2676 
2677 	info->dp0_ext_hdmi_slv_addr = info_v11->dp0_retimer_set.HdmiSlvAddr;
2678 	info->dp0_ext_hdmi_reg_num = min_t(u8, info_v11->dp0_retimer_set.HdmiRegNum,
2679 					    ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings));
2680 	for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
2681 		info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
2682 				info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2683 		info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
2684 				info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2685 	}
2686 	info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp0_retimer_set.Hdmi6GRegNum,
2687 					       ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings));
2688 	for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
2689 		info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2690 				info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2691 		info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2692 				info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2693 	}
2694 
2695 	info->dp1_ext_hdmi_slv_addr = info_v11->dp1_retimer_set.HdmiSlvAddr;
2696 	info->dp1_ext_hdmi_reg_num = min_t(u8, info_v11->dp1_retimer_set.HdmiRegNum,
2697 					    ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings));
2698 	for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
2699 		info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
2700 				info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2701 		info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
2702 				info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2703 	}
2704 	info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp1_retimer_set.Hdmi6GRegNum,
2705 					       ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings));
2706 	for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
2707 		info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2708 				info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2709 		info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2710 				info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2711 	}
2712 
2713 	info->dp2_ext_hdmi_slv_addr = info_v11->dp2_retimer_set.HdmiSlvAddr;
2714 	info->dp2_ext_hdmi_reg_num = min_t(u8, info_v11->dp2_retimer_set.HdmiRegNum,
2715 					    ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings));
2716 	for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
2717 		info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
2718 				info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2719 		info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
2720 				info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2721 	}
2722 	info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp2_retimer_set.Hdmi6GRegNum,
2723 					       ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings));
2724 	for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
2725 		info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2726 				info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2727 		info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2728 				info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2729 	}
2730 
2731 	info->dp3_ext_hdmi_slv_addr = info_v11->dp3_retimer_set.HdmiSlvAddr;
2732 	info->dp3_ext_hdmi_reg_num = min_t(u8, info_v11->dp3_retimer_set.HdmiRegNum,
2733 					    ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings));
2734 	for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
2735 		info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
2736 				info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2737 		info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
2738 				info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2739 	}
2740 	info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v11->dp3_retimer_set.Hdmi6GRegNum,
2741 					       ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings));
2742 	for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
2743 		info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2744 				info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2745 		info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2746 				info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2747 	}
2748 
2749 
2750 	/** TODO - review **/
2751 	#if 0
2752 	info->boot_up_engine_clock = le32_to_cpu(info_v11->ulBootUpEngineClock)
2753 									* 10;
2754 	info->dentist_vco_freq = le32_to_cpu(info_v11->ulDentistVCOFreq) * 10;
2755 	info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
2756 
2757 	info->boot_up_req_display_vector =
2758 			le32_to_cpu(info_v11->ulBootUpReqDisplayVector);
2759 	info->boot_up_nb_voltage =
2760 			le16_to_cpu(info_v11->usBootUpNBVoltage);
2761 	info->ext_disp_conn_info_offset =
2762 			le16_to_cpu(info_v11->usExtDispConnInfoOffset);
2763 	info->gmc_restore_reset_time =
2764 			le32_to_cpu(info_v11->ulGMCRestoreResetTime);
2765 	info->minimum_n_clk =
2766 			le32_to_cpu(info_v11->ulNbpStateNClkFreq[0]);
2767 	for (i = 1; i < 4; ++i)
2768 		info->minimum_n_clk =
2769 				info->minimum_n_clk <
2770 				le32_to_cpu(info_v11->ulNbpStateNClkFreq[i]) ?
2771 				info->minimum_n_clk : le32_to_cpu(
2772 					info_v11->ulNbpStateNClkFreq[i]);
2773 
2774 	info->idle_n_clk = le32_to_cpu(info_v11->ulIdleNClk);
2775 	info->ddr_dll_power_up_time =
2776 	    le32_to_cpu(info_v11->ulDDR_DLL_PowerUpTime);
2777 	info->ddr_pll_power_up_time =
2778 		le32_to_cpu(info_v11->ulDDR_PLL_PowerUpTime);
2779 	info->pcie_clk_ss_type = le16_to_cpu(info_v11->usPCIEClkSSType);
2780 	info->max_lvds_pclk_freq_in_single_link =
2781 		le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink);
2782 	info->max_lvds_pclk_freq_in_single_link =
2783 		le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink);
2784 	info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
2785 		info_v11->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
2786 	info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
2787 		info_v11->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
2788 	info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
2789 		info_v11->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
2790 	info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
2791 		info_v11->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
2792 	info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
2793 		info_v11->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
2794 	info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
2795 		info_v11->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
2796 	info->lvds_off_to_on_delay_in_4ms =
2797 		info_v11->ucLVDSOffToOnDelay_in4Ms;
2798 	info->lvds_bit_depth_control_val =
2799 		le32_to_cpu(info_v11->ulLCDBitDepthControlVal);
2800 
2801 	for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
2802 		/* Convert [10KHz] into [KHz] */
2803 		info->avail_s_clk[i].supported_s_clk =
2804 			le32_to_cpu(info_v11->sAvail_SCLK[i].ulSupportedSCLK)
2805 									* 10;
2806 		info->avail_s_clk[i].voltage_index =
2807 			le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageIndex);
2808 		info->avail_s_clk[i].voltage_id =
2809 			le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageID);
2810 	}
2811 	#endif /* TODO*/
2812 
2813 	return BP_RESULT_OK;
2814 }
2815 
2816 static enum bp_result get_integrated_info_v2_1(
2817 	struct bios_parser *bp,
2818 	struct integrated_info *info)
2819 {
2820 	struct atom_integrated_system_info_v2_1 *info_v2_1;
2821 	uint32_t i;
2822 
2823 	info_v2_1 = GET_IMAGE(struct atom_integrated_system_info_v2_1,
2824 					DATA_TABLES(integratedsysteminfo));
2825 
2826 	if (info_v2_1 == NULL)
2827 		return BP_RESULT_BADBIOSTABLE;
2828 
2829 	DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_1->gpuclk_ss_percentage);
2830 
2831 	info->gpu_cap_info =
2832 	le32_to_cpu(info_v2_1->gpucapinfo);
2833 	/*
2834 	* system_config: Bit[0] = 0 : PCIE power gating disabled
2835 	*                       = 1 : PCIE power gating enabled
2836 	*                Bit[1] = 0 : DDR-PLL shut down disabled
2837 	*                       = 1 : DDR-PLL shut down enabled
2838 	*                Bit[2] = 0 : DDR-PLL power down disabled
2839 	*                       = 1 : DDR-PLL power down enabled
2840 	*/
2841 	info->system_config = le32_to_cpu(info_v2_1->system_config);
2842 	info->cpu_cap_info = le32_to_cpu(info_v2_1->cpucapinfo);
2843 	info->memory_type = info_v2_1->memorytype;
2844 	info->ma_channel_number = info_v2_1->umachannelnumber;
2845 	info->dp_ss_control =
2846 		le16_to_cpu(info_v2_1->reserved1);
2847 
2848 	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2849 		info->ext_disp_conn_info.gu_id[i] =
2850 				info_v2_1->extdispconninfo.guid[i];
2851 	}
2852 
2853 	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2854 		info->ext_disp_conn_info.path[i].device_connector_id =
2855 		object_id_from_bios_object_id(
2856 		le16_to_cpu(info_v2_1->extdispconninfo.path[i].connectorobjid));
2857 
2858 		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2859 		object_id_from_bios_object_id(
2860 			le16_to_cpu(
2861 			info_v2_1->extdispconninfo.path[i].ext_encoder_objid));
2862 
2863 		info->ext_disp_conn_info.path[i].device_tag =
2864 			le16_to_cpu(
2865 				info_v2_1->extdispconninfo.path[i].device_tag);
2866 		info->ext_disp_conn_info.path[i].device_acpi_enum =
2867 		le16_to_cpu(
2868 			info_v2_1->extdispconninfo.path[i].device_acpi_enum);
2869 		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2870 			info_v2_1->extdispconninfo.path[i].auxddclut_index;
2871 		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2872 			info_v2_1->extdispconninfo.path[i].hpdlut_index;
2873 		info->ext_disp_conn_info.path[i].channel_mapping.raw =
2874 			info_v2_1->extdispconninfo.path[i].channelmapping;
2875 		info->ext_disp_conn_info.path[i].caps =
2876 				(unsigned short)le16_to_cpu(info_v2_1->extdispconninfo.path[i].caps);
2877 	}
2878 
2879 	info->ext_disp_conn_info.checksum =
2880 		info_v2_1->extdispconninfo.checksum;
2881 	info->dp0_ext_hdmi_slv_addr = info_v2_1->dp0_retimer_set.HdmiSlvAddr;
2882 	info->dp0_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.HdmiRegNum,
2883 					    ARRAY_SIZE(info->dp0_ext_hdmi_reg_settings));
2884 	for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
2885 		info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
2886 				info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2887 		info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
2888 				info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2889 	}
2890 	info->dp0_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp0_retimer_set.Hdmi6GRegNum,
2891 					       ARRAY_SIZE(info->dp0_ext_hdmi_6g_reg_settings));
2892 	for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
2893 		info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2894 				info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2895 		info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2896 				info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2897 	}
2898 	info->dp1_ext_hdmi_slv_addr = info_v2_1->dp1_retimer_set.HdmiSlvAddr;
2899 	info->dp1_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.HdmiRegNum,
2900 					    ARRAY_SIZE(info->dp1_ext_hdmi_reg_settings));
2901 	for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
2902 		info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
2903 				info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2904 		info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
2905 				info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2906 	}
2907 	info->dp1_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp1_retimer_set.Hdmi6GRegNum,
2908 					       ARRAY_SIZE(info->dp1_ext_hdmi_6g_reg_settings));
2909 	for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
2910 		info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2911 				info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2912 		info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2913 				info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2914 	}
2915 	info->dp2_ext_hdmi_slv_addr = info_v2_1->dp2_retimer_set.HdmiSlvAddr;
2916 	info->dp2_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.HdmiRegNum,
2917 					    ARRAY_SIZE(info->dp2_ext_hdmi_reg_settings));
2918 	for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
2919 		info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
2920 				info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2921 		info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
2922 				info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2923 	}
2924 	info->dp2_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp2_retimer_set.Hdmi6GRegNum,
2925 					       ARRAY_SIZE(info->dp2_ext_hdmi_6g_reg_settings));
2926 	for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
2927 		info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2928 				info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2929 		info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2930 				info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2931 	}
2932 	info->dp3_ext_hdmi_slv_addr = info_v2_1->dp3_retimer_set.HdmiSlvAddr;
2933 	info->dp3_ext_hdmi_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.HdmiRegNum,
2934 					    ARRAY_SIZE(info->dp3_ext_hdmi_reg_settings));
2935 	for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
2936 		info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
2937 				info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2938 		info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
2939 				info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2940 	}
2941 	info->dp3_ext_hdmi_6g_reg_num = min_t(u8, info_v2_1->dp3_retimer_set.Hdmi6GRegNum,
2942 					       ARRAY_SIZE(info->dp3_ext_hdmi_6g_reg_settings));
2943 	for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
2944 		info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2945 				info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2946 		info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2947 				info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2948 	}
2949 
2950 	info->edp1_info.edp_backlight_pwm_hz =
2951 	le16_to_cpu(info_v2_1->edp1_info.edp_backlight_pwm_hz);
2952 	info->edp1_info.edp_ss_percentage =
2953 	le16_to_cpu(info_v2_1->edp1_info.edp_ss_percentage);
2954 	info->edp1_info.edp_ss_rate_10hz =
2955 	le16_to_cpu(info_v2_1->edp1_info.edp_ss_rate_10hz);
2956 	info->edp1_info.edp_pwr_on_off_delay =
2957 		info_v2_1->edp1_info.edp_pwr_on_off_delay;
2958 	info->edp1_info.edp_pwr_on_vary_bl_to_blon =
2959 		info_v2_1->edp1_info.edp_pwr_on_vary_bl_to_blon;
2960 	info->edp1_info.edp_pwr_down_bloff_to_vary_bloff =
2961 		info_v2_1->edp1_info.edp_pwr_down_bloff_to_vary_bloff;
2962 	info->edp1_info.edp_panel_bpc =
2963 		info_v2_1->edp1_info.edp_panel_bpc;
2964 	info->edp1_info.edp_bootup_bl_level = info_v2_1->edp1_info.edp_bootup_bl_level;
2965 
2966 	info->edp2_info.edp_backlight_pwm_hz =
2967 	le16_to_cpu(info_v2_1->edp2_info.edp_backlight_pwm_hz);
2968 	info->edp2_info.edp_ss_percentage =
2969 	le16_to_cpu(info_v2_1->edp2_info.edp_ss_percentage);
2970 	info->edp2_info.edp_ss_rate_10hz =
2971 	le16_to_cpu(info_v2_1->edp2_info.edp_ss_rate_10hz);
2972 	info->edp2_info.edp_pwr_on_off_delay =
2973 		info_v2_1->edp2_info.edp_pwr_on_off_delay;
2974 	info->edp2_info.edp_pwr_on_vary_bl_to_blon =
2975 		info_v2_1->edp2_info.edp_pwr_on_vary_bl_to_blon;
2976 	info->edp2_info.edp_pwr_down_bloff_to_vary_bloff =
2977 		info_v2_1->edp2_info.edp_pwr_down_bloff_to_vary_bloff;
2978 	info->edp2_info.edp_panel_bpc =
2979 		info_v2_1->edp2_info.edp_panel_bpc;
2980 	info->edp2_info.edp_bootup_bl_level =
2981 		info_v2_1->edp2_info.edp_bootup_bl_level;
2982 
2983 	return BP_RESULT_OK;
2984 }
2985 
2986 static enum bp_result get_integrated_info_v2_2(
2987 	struct bios_parser *bp,
2988 	struct integrated_info *info)
2989 {
2990 	struct atom_integrated_system_info_v2_2 *info_v2_2;
2991 	uint32_t i;
2992 
2993 	info_v2_2 = GET_IMAGE(struct atom_integrated_system_info_v2_2,
2994 					DATA_TABLES(integratedsysteminfo));
2995 
2996 	if (info_v2_2 == NULL)
2997 		return BP_RESULT_BADBIOSTABLE;
2998 
2999 	DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_2->gpuclk_ss_percentage);
3000 
3001 	info->gpu_cap_info =
3002 	le32_to_cpu(info_v2_2->gpucapinfo);
3003 	/*
3004 	* system_config: Bit[0] = 0 : PCIE power gating disabled
3005 	*                       = 1 : PCIE power gating enabled
3006 	*                Bit[1] = 0 : DDR-PLL shut down disabled
3007 	*                       = 1 : DDR-PLL shut down enabled
3008 	*                Bit[2] = 0 : DDR-PLL power down disabled
3009 	*                       = 1 : DDR-PLL power down enabled
3010 	*/
3011 	info->system_config = le32_to_cpu(info_v2_2->system_config);
3012 	info->cpu_cap_info = le32_to_cpu(info_v2_2->cpucapinfo);
3013 	info->memory_type = info_v2_2->memorytype;
3014 	info->ma_channel_number = info_v2_2->umachannelnumber;
3015 	info->dp_ss_control =
3016 		le16_to_cpu(info_v2_2->reserved1);
3017 	info->gpuclk_ss_percentage = info_v2_2->gpuclk_ss_percentage;
3018 	info->gpuclk_ss_type = info_v2_2->gpuclk_ss_type;
3019 
3020 	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
3021 		info->ext_disp_conn_info.gu_id[i] =
3022 				info_v2_2->extdispconninfo.guid[i];
3023 	}
3024 
3025 	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
3026 		info->ext_disp_conn_info.path[i].device_connector_id =
3027 		object_id_from_bios_object_id(
3028 		le16_to_cpu(info_v2_2->extdispconninfo.path[i].connectorobjid));
3029 
3030 		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
3031 		object_id_from_bios_object_id(
3032 			le16_to_cpu(
3033 			info_v2_2->extdispconninfo.path[i].ext_encoder_objid));
3034 
3035 		info->ext_disp_conn_info.path[i].device_tag =
3036 			le16_to_cpu(
3037 				info_v2_2->extdispconninfo.path[i].device_tag);
3038 		info->ext_disp_conn_info.path[i].device_acpi_enum =
3039 		le16_to_cpu(
3040 			info_v2_2->extdispconninfo.path[i].device_acpi_enum);
3041 		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
3042 			info_v2_2->extdispconninfo.path[i].auxddclut_index;
3043 		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
3044 			info_v2_2->extdispconninfo.path[i].hpdlut_index;
3045 		info->ext_disp_conn_info.path[i].channel_mapping.raw =
3046 			info_v2_2->extdispconninfo.path[i].channelmapping;
3047 		info->ext_disp_conn_info.path[i].caps =
3048 				(unsigned short)le16_to_cpu(info_v2_2->extdispconninfo.path[i].caps);
3049 	}
3050 
3051 	info->ext_disp_conn_info.checksum =
3052 		info_v2_2->extdispconninfo.checksum;
3053 	info->ext_disp_conn_info.fixdpvoltageswing =
3054 		info_v2_2->extdispconninfo.fixdpvoltageswing;
3055 
3056 	info->edp1_info.edp_backlight_pwm_hz =
3057 	le16_to_cpu(info_v2_2->edp1_info.edp_backlight_pwm_hz);
3058 	info->edp1_info.edp_ss_percentage =
3059 	le16_to_cpu(info_v2_2->edp1_info.edp_ss_percentage);
3060 	info->edp1_info.edp_ss_rate_10hz =
3061 	le16_to_cpu(info_v2_2->edp1_info.edp_ss_rate_10hz);
3062 	info->edp1_info.edp_pwr_on_off_delay =
3063 		info_v2_2->edp1_info.edp_pwr_on_off_delay;
3064 	info->edp1_info.edp_pwr_on_vary_bl_to_blon =
3065 		info_v2_2->edp1_info.edp_pwr_on_vary_bl_to_blon;
3066 	info->edp1_info.edp_pwr_down_bloff_to_vary_bloff =
3067 		info_v2_2->edp1_info.edp_pwr_down_bloff_to_vary_bloff;
3068 	info->edp1_info.edp_panel_bpc =
3069 		info_v2_2->edp1_info.edp_panel_bpc;
3070 	info->edp1_info.edp_bootup_bl_level =
3071 		info_v2_2->edp1_info.edp_bootup_bl_level;
3072 
3073 	info->edp2_info.edp_backlight_pwm_hz =
3074 	le16_to_cpu(info_v2_2->edp2_info.edp_backlight_pwm_hz);
3075 	info->edp2_info.edp_ss_percentage =
3076 	le16_to_cpu(info_v2_2->edp2_info.edp_ss_percentage);
3077 	info->edp2_info.edp_ss_rate_10hz =
3078 	le16_to_cpu(info_v2_2->edp2_info.edp_ss_rate_10hz);
3079 	info->edp2_info.edp_pwr_on_off_delay =
3080 		info_v2_2->edp2_info.edp_pwr_on_off_delay;
3081 	info->edp2_info.edp_pwr_on_vary_bl_to_blon =
3082 		info_v2_2->edp2_info.edp_pwr_on_vary_bl_to_blon;
3083 	info->edp2_info.edp_pwr_down_bloff_to_vary_bloff =
3084 		info_v2_2->edp2_info.edp_pwr_down_bloff_to_vary_bloff;
3085 	info->edp2_info.edp_panel_bpc =
3086 		info_v2_2->edp2_info.edp_panel_bpc;
3087 	info->edp2_info.edp_bootup_bl_level =
3088 		info_v2_2->edp2_info.edp_bootup_bl_level;
3089 
3090 	return BP_RESULT_OK;
3091 }
3092 
3093 /*
3094  * construct_integrated_info
3095  *
3096  * @brief
3097  * Get integrated BIOS information based on table revision
3098  *
3099  * @param
3100  * bios_parser *bp - [in]BIOS parser handler to get master data table
3101  * integrated_info *info - [out] store and output integrated info
3102  *
3103  * @return
3104  * static enum bp_result - BP_RESULT_OK if information is available,
3105  *                  BP_RESULT_BADBIOSTABLE otherwise.
3106  */
3107 static enum bp_result construct_integrated_info(
3108 	struct bios_parser *bp,
3109 	struct integrated_info *info)
3110 {
3111 	static enum bp_result result = BP_RESULT_BADBIOSTABLE;
3112 
3113 	struct atom_common_table_header *header;
3114 	struct atom_data_revision revision;
3115 
3116 	int32_t i;
3117 
3118 	if (!info)
3119 		return result;
3120 
3121 	if (info && DATA_TABLES(integratedsysteminfo)) {
3122 		header = GET_IMAGE(struct atom_common_table_header,
3123 					DATA_TABLES(integratedsysteminfo));
3124 
3125 		get_atom_data_table_revision(header, &revision);
3126 
3127 		switch (revision.major) {
3128 		case 1:
3129 			switch (revision.minor) {
3130 			case 11:
3131 			case 12:
3132 				result = get_integrated_info_v11(bp, info);
3133 				break;
3134 			default:
3135 				return result;
3136 			}
3137 			break;
3138 		case 2:
3139 			switch (revision.minor) {
3140 			case 1:
3141 				result = get_integrated_info_v2_1(bp, info);
3142 				break;
3143 			case 2:
3144 			case 3:
3145 				result = get_integrated_info_v2_2(bp, info);
3146 				break;
3147 			default:
3148 				return result;
3149 			}
3150 			break;
3151 		default:
3152 			return result;
3153 		}
3154 		if (result == BP_RESULT_OK) {
3155 
3156 			DC_LOG_BIOS("edp1:\n"
3157 						"\tedp_pwr_on_off_delay = %d\n"
3158 						"\tedp_pwr_on_vary_bl_to_blon = %d\n"
3159 						"\tedp_pwr_down_bloff_to_vary_bloff = %d\n"
3160 						"\tedp_bootup_bl_level = %d\n",
3161 						info->edp1_info.edp_pwr_on_off_delay,
3162 						info->edp1_info.edp_pwr_on_vary_bl_to_blon,
3163 						info->edp1_info.edp_pwr_down_bloff_to_vary_bloff,
3164 						info->edp1_info.edp_bootup_bl_level);
3165 			DC_LOG_BIOS("edp2:\n"
3166 						"\tedp_pwr_on_off_delayv = %d\n"
3167 						"\tedp_pwr_on_vary_bl_to_blon = %d\n"
3168 						"\tedp_pwr_down_bloff_to_vary_bloff = %d\n"
3169 						"\tedp_bootup_bl_level = %d\n",
3170 						info->edp2_info.edp_pwr_on_off_delay,
3171 						info->edp2_info.edp_pwr_on_vary_bl_to_blon,
3172 						info->edp2_info.edp_pwr_down_bloff_to_vary_bloff,
3173 						info->edp2_info.edp_bootup_bl_level);
3174 		}
3175 	}
3176 
3177 	if (result != BP_RESULT_OK)
3178 		return result;
3179 	else {
3180 		// Log each external path
3181 		for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {
3182 			if (info->ext_disp_conn_info.path[i].device_tag != 0)
3183 				DC_LOG_BIOS("integrated_info:For EXTERNAL DISPLAY PATH %d --------------\n"
3184 						"DEVICE_TAG: 0x%x\n"
3185 						"DEVICE_ACPI_ENUM: 0x%x\n"
3186 						"DEVICE_CONNECTOR_ID: 0x%x\n"
3187 						"EXT_AUX_DDC_LUT_INDEX: %d\n"
3188 						"EXT_HPD_PIN_LUT_INDEX: %d\n"
3189 						"EXT_ENCODER_OBJ_ID: 0x%x\n"
3190 						"Encoder CAPS: 0x%x\n",
3191 						i,
3192 						info->ext_disp_conn_info.path[i].device_tag,
3193 						info->ext_disp_conn_info.path[i].device_acpi_enum,
3194 						info->ext_disp_conn_info.path[i].device_connector_id.id,
3195 						info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index,
3196 						info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index,
3197 						info->ext_disp_conn_info.path[i].ext_encoder_obj_id.id,
3198 						info->ext_disp_conn_info.path[i].caps
3199 						);
3200 			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)
3201 				DC_LOG_BIOS("BIOS AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);
3202 			else if (bp->base.ctx->dc->config.force_bios_fixed_vs) {
3203 				info->ext_disp_conn_info.path[i].caps &= ~AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK;
3204 				info->ext_disp_conn_info.path[i].caps |= AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN;
3205 				DC_LOG_BIOS("driver forced AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);
3206 			}
3207 		}
3208 		// Log the Checksum and Voltage Swing
3209 		DC_LOG_BIOS("Integrated info table CHECKSUM: %d\n"
3210 					"Integrated info table FIX_DP_VOLTAGE_SWING: %d\n",
3211 					info->ext_disp_conn_info.checksum,
3212 					info->ext_disp_conn_info.fixdpvoltageswing);
3213 		if (bp->base.ctx->dc->config.force_bios_fixed_vs && info->ext_disp_conn_info.fixdpvoltageswing == 0) {
3214 			info->ext_disp_conn_info.fixdpvoltageswing = bp->base.ctx->dc->config.force_bios_fixed_vs & 0xF;
3215 			DC_LOG_BIOS("driver forced fixdpvoltageswing = %d\n", info->ext_disp_conn_info.fixdpvoltageswing);
3216 		}
3217 	}
3218 
3219 	return result;
3220 }
3221 
3222 static enum bp_result bios_parser_get_vram_info(
3223 		struct dc_bios *dcb,
3224 		struct dc_vram_info *info)
3225 {
3226 	struct bios_parser *bp = BP_FROM_DCB(dcb);
3227 	enum bp_result result = BP_RESULT_BADBIOSTABLE;
3228 	struct atom_common_table_header *header;
3229 	struct atom_data_revision revision;
3230 
3231 	// vram info moved to umc_info for DCN4x
3232 	if (info && DATA_TABLES(umc_info)) {
3233 		header = GET_IMAGE(struct atom_common_table_header,
3234 					DATA_TABLES(umc_info));
3235 
3236 		get_atom_data_table_revision(header, &revision);
3237 
3238 		switch (revision.major) {
3239 		case 4:
3240 			switch (revision.minor) {
3241 			case 0:
3242 				result = get_vram_info_from_umc_info_v40(bp, info);
3243 				break;
3244 			default:
3245 				break;
3246 			}
3247 			break;
3248 		default:
3249 			break;
3250 		}
3251 	}
3252 
3253 	if (result != BP_RESULT_OK && info && DATA_TABLES(vram_info)) {
3254 		header = GET_IMAGE(struct atom_common_table_header,
3255 					DATA_TABLES(vram_info));
3256 
3257 		get_atom_data_table_revision(header, &revision);
3258 
3259 		switch (revision.major) {
3260 		case 2:
3261 			switch (revision.minor) {
3262 			case 3:
3263 				result = get_vram_info_v23(bp, info);
3264 				break;
3265 			case 4:
3266 				result = get_vram_info_v24(bp, info);
3267 				break;
3268 			case 5:
3269 				result = get_vram_info_v25(bp, info);
3270 				break;
3271 			default:
3272 				break;
3273 			}
3274 			break;
3275 
3276 		case 3:
3277 			switch (revision.minor) {
3278 			case 0:
3279 				result = get_vram_info_v30(bp, info);
3280 				break;
3281 			default:
3282 				break;
3283 			}
3284 			break;
3285 
3286 		default:
3287 			return result;
3288 		}
3289 
3290 	}
3291 	return result;
3292 }
3293 
3294 static struct integrated_info *bios_parser_create_integrated_info(
3295 	struct dc_bios *dcb)
3296 {
3297 	struct bios_parser *bp = BP_FROM_DCB(dcb);
3298 	struct integrated_info *info;
3299 
3300 	info = kzalloc_obj(struct integrated_info);
3301 
3302 	if (info == NULL) {
3303 		ASSERT_CRITICAL(0);
3304 		return NULL;
3305 	}
3306 
3307 	if (construct_integrated_info(bp, info) == BP_RESULT_OK)
3308 		return info;
3309 
3310 	kfree(info);
3311 
3312 	return NULL;
3313 }
3314 
3315 static enum bp_result update_slot_layout_info(
3316 	struct dc_bios *dcb,
3317 	unsigned int i,
3318 	struct slot_layout_info *slot_layout_info)
3319 {
3320 	unsigned int record_offset;
3321 	unsigned int j;
3322 	unsigned int n;
3323 	struct atom_display_object_path_v2 *object;
3324 	struct atom_bracket_layout_record *record;
3325 	struct atom_common_record_header *record_header;
3326 	static enum bp_result result;
3327 	struct bios_parser *bp;
3328 	struct object_info_table *tbl;
3329 	struct display_object_info_table_v1_4 *v1_4;
3330 
3331 	record = NULL;
3332 	record_header = NULL;
3333 	result = BP_RESULT_NORECORD;
3334 
3335 	bp = BP_FROM_DCB(dcb);
3336 	tbl = &bp->object_info_tbl;
3337 	v1_4 = tbl->v1_4;
3338 
3339 	object = &v1_4->display_path[i];
3340 	record_offset = (unsigned int)
3341 		(object->disp_recordoffset) +
3342 		(unsigned int)(bp->object_info_tbl_offset);
3343 
3344 	for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
3345 
3346 		record_header = (struct atom_common_record_header *)
3347 			GET_IMAGE(struct atom_common_record_header,
3348 			record_offset);
3349 		if (record_header == NULL) {
3350 			result = BP_RESULT_BADBIOSTABLE;
3351 			break;
3352 		}
3353 
3354 		/* the end of the list */
3355 		if (record_header->record_type == 0xff ||
3356 			record_header->record_size == 0)	{
3357 			break;
3358 		}
3359 
3360 		if (record_header->record_type ==
3361 			ATOM_BRACKET_LAYOUT_RECORD_TYPE &&
3362 			sizeof(struct atom_bracket_layout_record)
3363 			<= record_header->record_size) {
3364 			record = (struct atom_bracket_layout_record *)
3365 				(record_header);
3366 			result = BP_RESULT_OK;
3367 			break;
3368 		}
3369 
3370 		record_offset += record_header->record_size;
3371 	}
3372 
3373 	/* return if the record not found */
3374 	if (result != BP_RESULT_OK)
3375 		return result;
3376 
3377 	/* get slot sizes */
3378 	slot_layout_info->length = record->bracketlen;
3379 	slot_layout_info->width = record->bracketwidth;
3380 
3381 	/* get info for each connector in the slot */
3382 	slot_layout_info->num_of_connectors = record->conn_num;
3383 	for (j = 0; j < slot_layout_info->num_of_connectors; ++j) {
3384 		slot_layout_info->connectors[j].connector_type =
3385 			(enum connector_layout_type)
3386 			(record->conn_info[j].connector_type);
3387 		switch (record->conn_info[j].connector_type) {
3388 		case CONNECTOR_TYPE_DVI_D:
3389 			slot_layout_info->connectors[j].connector_type =
3390 				CONNECTOR_LAYOUT_TYPE_DVI_D;
3391 			slot_layout_info->connectors[j].length =
3392 				CONNECTOR_SIZE_DVI;
3393 			break;
3394 
3395 		case CONNECTOR_TYPE_HDMI:
3396 			slot_layout_info->connectors[j].connector_type =
3397 				CONNECTOR_LAYOUT_TYPE_HDMI;
3398 			slot_layout_info->connectors[j].length =
3399 				CONNECTOR_SIZE_HDMI;
3400 			break;
3401 
3402 		case CONNECTOR_TYPE_DISPLAY_PORT:
3403 			slot_layout_info->connectors[j].connector_type =
3404 				CONNECTOR_LAYOUT_TYPE_DP;
3405 			slot_layout_info->connectors[j].length =
3406 				CONNECTOR_SIZE_DP;
3407 			break;
3408 
3409 		case CONNECTOR_TYPE_MINI_DISPLAY_PORT:
3410 			slot_layout_info->connectors[j].connector_type =
3411 				CONNECTOR_LAYOUT_TYPE_MINI_DP;
3412 			slot_layout_info->connectors[j].length =
3413 				CONNECTOR_SIZE_MINI_DP;
3414 			break;
3415 
3416 		default:
3417 			slot_layout_info->connectors[j].connector_type =
3418 				CONNECTOR_LAYOUT_TYPE_UNKNOWN;
3419 			slot_layout_info->connectors[j].length =
3420 				CONNECTOR_SIZE_UNKNOWN;
3421 		}
3422 
3423 		slot_layout_info->connectors[j].position =
3424 			record->conn_info[j].position;
3425 		slot_layout_info->connectors[j].connector_id =
3426 			object_id_from_bios_object_id(
3427 				record->conn_info[j].connectorobjid);
3428 	}
3429 	return result;
3430 }
3431 
3432 static enum bp_result update_slot_layout_info_v2(
3433 	struct dc_bios *dcb,
3434 	unsigned int i,
3435 	struct slot_layout_info *slot_layout_info)
3436 {
3437 	unsigned int record_offset;
3438 	unsigned int n;
3439 	struct atom_display_object_path_v3 *object;
3440 	struct atom_bracket_layout_record_v2 *record;
3441 	struct atom_common_record_header *record_header;
3442 	static enum bp_result result;
3443 	struct bios_parser *bp;
3444 	struct object_info_table *tbl;
3445 	struct display_object_info_table_v1_5 *v1_5;
3446 	struct graphics_object_id connector_id;
3447 
3448 	record = NULL;
3449 	record_header = NULL;
3450 	result = BP_RESULT_NORECORD;
3451 
3452 	bp = BP_FROM_DCB(dcb);
3453 	tbl = &bp->object_info_tbl;
3454 	v1_5 = tbl->v1_5;
3455 
3456 	object = &v1_5->display_path[i];
3457 	record_offset = (unsigned int)
3458 		(object->disp_recordoffset) +
3459 		(unsigned int)(bp->object_info_tbl_offset);
3460 
3461 	for (n = 0; n < BIOS_MAX_NUM_RECORD; n++) {
3462 
3463 		record_header = (struct atom_common_record_header *)
3464 			GET_IMAGE(struct atom_common_record_header,
3465 			record_offset);
3466 		if (record_header == NULL) {
3467 			result = BP_RESULT_BADBIOSTABLE;
3468 			break;
3469 		}
3470 
3471 		/* the end of the list */
3472 		if (record_header->record_type == ATOM_RECORD_END_TYPE ||
3473 			record_header->record_size == 0)	{
3474 			break;
3475 		}
3476 
3477 		if (record_header->record_type ==
3478 			ATOM_BRACKET_LAYOUT_V2_RECORD_TYPE &&
3479 			sizeof(struct atom_bracket_layout_record_v2)
3480 			<= record_header->record_size) {
3481 			record = (struct atom_bracket_layout_record_v2 *)
3482 				(record_header);
3483 			result = BP_RESULT_OK;
3484 			break;
3485 		}
3486 
3487 		record_offset += record_header->record_size;
3488 	}
3489 
3490 	/* return if the record not found */
3491 	if (result != BP_RESULT_OK)
3492 		return result;
3493 
3494 	/* get slot sizes */
3495 	connector_id = object_id_from_bios_object_id(object->display_objid);
3496 
3497 	slot_layout_info->length = record->bracketlen;
3498 	slot_layout_info->width = record->bracketwidth;
3499 	slot_layout_info->num_of_connectors = v1_5->number_of_path;
3500 	slot_layout_info->connectors[i].position = record->conn_num;
3501 	slot_layout_info->connectors[i].connector_id = connector_id;
3502 
3503 	switch (connector_id.id) {
3504 	case CONNECTOR_ID_SINGLE_LINK_DVID:
3505 	case CONNECTOR_ID_DUAL_LINK_DVID:
3506 		slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_DVI_D;
3507 		slot_layout_info->connectors[i].length = CONNECTOR_SIZE_DVI;
3508 		break;
3509 
3510 	case CONNECTOR_ID_HDMI_TYPE_A:
3511 		slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_HDMI;
3512 		slot_layout_info->connectors[i].length = CONNECTOR_SIZE_HDMI;
3513 		break;
3514 
3515 	case CONNECTOR_ID_DISPLAY_PORT:
3516 	case CONNECTOR_ID_USBC:
3517 		if (record->mini_type == MINI_TYPE_NORMAL) {
3518 			slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_DP;
3519 			slot_layout_info->connectors[i].length = CONNECTOR_SIZE_DP;
3520 		} else {
3521 			slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_MINI_DP;
3522 			slot_layout_info->connectors[i].length = CONNECTOR_SIZE_MINI_DP;
3523 		}
3524 		break;
3525 
3526 	default:
3527 		slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_UNKNOWN;
3528 		slot_layout_info->connectors[i].length = CONNECTOR_SIZE_UNKNOWN;
3529 	}
3530 	return result;
3531 }
3532 
3533 static enum bp_result get_bracket_layout_record(
3534 	struct dc_bios *dcb,
3535 	unsigned int bracket_layout_id,
3536 	struct slot_layout_info *slot_layout_info)
3537 {
3538 	unsigned int i;
3539 	struct bios_parser *bp = BP_FROM_DCB(dcb);
3540 	static enum bp_result result;
3541 	struct object_info_table *tbl;
3542 	struct display_object_info_table_v1_4 *v1_4;
3543 	struct display_object_info_table_v1_5 *v1_5;
3544 
3545 	if (slot_layout_info == NULL) {
3546 		DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");
3547 		return BP_RESULT_BADINPUT;
3548 	}
3549 
3550 	tbl = &bp->object_info_tbl;
3551 	v1_4 = tbl->v1_4;
3552 	v1_5 = tbl->v1_5;
3553 
3554 	result = BP_RESULT_NORECORD;
3555 	switch (bp->object_info_tbl.revision.minor) {
3556 	case 4:
3557 	default:
3558 		for (i = 0; i < v1_4->number_of_path; ++i) {
3559 			if (bracket_layout_id == v1_4->display_path[i].display_objid) {
3560 				result = update_slot_layout_info(dcb, i, slot_layout_info);
3561 				break;
3562 			}
3563 		}
3564 		break;
3565 	case 5:
3566 		for (i = 0; i < v1_5->number_of_path; ++i)
3567 			result = update_slot_layout_info_v2(dcb, i, slot_layout_info);
3568 		break;
3569 	}
3570 
3571 	return result;
3572 }
3573 
3574 static enum bp_result bios_get_board_layout_info(
3575 	struct dc_bios *dcb,
3576 	struct board_layout_info *board_layout_info)
3577 {
3578 	unsigned int i;
3579 	struct bios_parser *bp;
3580 	static enum bp_result record_result;
3581 	unsigned int max_slots;
3582 
3583 	const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {
3584 		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1,
3585 		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2,
3586 		0, 0
3587 	};
3588 
3589 	bp = BP_FROM_DCB(dcb);
3590 
3591 	if (board_layout_info == NULL) {
3592 		DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");
3593 		return BP_RESULT_BADINPUT;
3594 	}
3595 
3596 	board_layout_info->num_of_slots = 0;
3597 	max_slots = MAX_BOARD_SLOTS;
3598 
3599 	// Assume single slot on v1_5
3600 	if (bp->object_info_tbl.revision.minor == 5) {
3601 		max_slots = 1;
3602 	}
3603 
3604 	for (i = 0; i < max_slots; ++i) {
3605 		record_result = get_bracket_layout_record(dcb,
3606 			slot_index_to_vbios_id[i],
3607 			&board_layout_info->slots[i]);
3608 
3609 		if (record_result == BP_RESULT_NORECORD && i > 0)
3610 			break; /* no more slots present in bios */
3611 		else if (record_result != BP_RESULT_OK)
3612 			return record_result;  /* fail */
3613 
3614 		++board_layout_info->num_of_slots;
3615 	}
3616 
3617 	/* all data is valid */
3618 	board_layout_info->is_number_of_slots_valid = 1;
3619 	board_layout_info->is_slots_size_valid = 1;
3620 	board_layout_info->is_connector_offsets_valid = 1;
3621 	board_layout_info->is_connector_lengths_valid = 1;
3622 
3623 	return BP_RESULT_OK;
3624 }
3625 
3626 
3627 static uint16_t bios_parser_pack_data_tables(
3628 	struct dc_bios *dcb,
3629 	void *dst)
3630 {
3631 	(void)dcb;
3632 	(void)dst;
3633 	// TODO: There is data bytes alignment issue, disable it for now.
3634 	return 0;
3635 }
3636 
3637 static struct atom_dc_golden_table_v1 *bios_get_golden_table(
3638 		struct bios_parser *bp,
3639 		uint32_t rev_major,
3640 		uint32_t rev_minor,
3641 		uint16_t *dc_golden_table_ver)
3642 {
3643 	struct atom_display_controller_info_v4_4 *disp_cntl_tbl_4_4 = NULL;
3644 	uint32_t dc_golden_offset = 0;
3645 	*dc_golden_table_ver = 0;
3646 
3647 	if (!DATA_TABLES(dce_info))
3648 		return NULL;
3649 
3650 	/* ver.4.4 or higher */
3651 	switch (rev_major) {
3652 	case 4:
3653 		switch (rev_minor) {
3654 		case 4:
3655 			disp_cntl_tbl_4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,
3656 									DATA_TABLES(dce_info));
3657 			if (!disp_cntl_tbl_4_4)
3658 				return NULL;
3659 			dc_golden_offset = DATA_TABLES(dce_info) + disp_cntl_tbl_4_4->dc_golden_table_offset;
3660 			*dc_golden_table_ver = disp_cntl_tbl_4_4->dc_golden_table_ver;
3661 			break;
3662 		case 5:
3663 		default:
3664 			/* For atom_display_controller_info_v4_5 there is no need to get golden table from
3665 			 * dc_golden_table_offset as all these fields previously in golden table used for AUX
3666 			 * pre-charge settings are now available directly in atom_display_controller_info_v4_5.
3667 			 */
3668 			break;
3669 		}
3670 		break;
3671 	}
3672 
3673 	if (!dc_golden_offset)
3674 		return NULL;
3675 
3676 	if (*dc_golden_table_ver != 1)
3677 		return NULL;
3678 
3679 	return GET_IMAGE(struct atom_dc_golden_table_v1,
3680 			dc_golden_offset);
3681 }
3682 
3683 static enum bp_result bios_get_atom_dc_golden_table(
3684 	struct dc_bios *dcb)
3685 {
3686 	struct bios_parser *bp = BP_FROM_DCB(dcb);
3687 	enum bp_result result = BP_RESULT_OK;
3688 	struct atom_dc_golden_table_v1 *atom_dc_golden_table = NULL;
3689 	struct atom_common_table_header *header;
3690 	struct atom_data_revision tbl_revision;
3691 	uint16_t dc_golden_table_ver = 0;
3692 
3693 	header = GET_IMAGE(struct atom_common_table_header,
3694 							DATA_TABLES(dce_info));
3695 	if (!header)
3696 		return BP_RESULT_UNSUPPORTED;
3697 
3698 	get_atom_data_table_revision(header, &tbl_revision);
3699 
3700 	atom_dc_golden_table = bios_get_golden_table(bp,
3701 			tbl_revision.major,
3702 			tbl_revision.minor,
3703 			&dc_golden_table_ver);
3704 
3705 	if (!atom_dc_golden_table)
3706 		return BP_RESULT_UNSUPPORTED;
3707 
3708 	dcb->golden_table.dc_golden_table_ver = dc_golden_table_ver;
3709 	dcb->golden_table.aux_dphy_rx_control0_val = atom_dc_golden_table->aux_dphy_rx_control0_val;
3710 	dcb->golden_table.aux_dphy_rx_control1_val = atom_dc_golden_table->aux_dphy_rx_control1_val;
3711 	dcb->golden_table.aux_dphy_tx_control_val = atom_dc_golden_table->aux_dphy_tx_control_val;
3712 	dcb->golden_table.dc_gpio_aux_ctrl_0_val = atom_dc_golden_table->dc_gpio_aux_ctrl_0_val;
3713 	dcb->golden_table.dc_gpio_aux_ctrl_1_val = atom_dc_golden_table->dc_gpio_aux_ctrl_1_val;
3714 	dcb->golden_table.dc_gpio_aux_ctrl_2_val = atom_dc_golden_table->dc_gpio_aux_ctrl_2_val;
3715 	dcb->golden_table.dc_gpio_aux_ctrl_3_val = atom_dc_golden_table->dc_gpio_aux_ctrl_3_val;
3716 	dcb->golden_table.dc_gpio_aux_ctrl_4_val = atom_dc_golden_table->dc_gpio_aux_ctrl_4_val;
3717 	dcb->golden_table.dc_gpio_aux_ctrl_5_val = atom_dc_golden_table->dc_gpio_aux_ctrl_5_val;
3718 
3719 	return result;
3720 }
3721 
3722 
3723 static const struct dc_vbios_funcs vbios_funcs = {
3724 	.get_connectors_number = bios_parser_get_connectors_number,
3725 
3726 	.get_connector_id = bios_parser_get_connector_id,
3727 
3728 	.get_src_obj = bios_parser_get_src_obj,
3729 
3730 	.get_i2c_info = bios_parser_get_i2c_info,
3731 
3732 	.get_hpd_info = bios_parser_get_hpd_info,
3733 
3734 	.get_device_tag = bios_parser_get_device_tag,
3735 
3736 	.get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
3737 
3738 	.get_ss_entry_number = bios_parser_get_ss_entry_number,
3739 
3740 	.get_embedded_panel_info = bios_parser_get_embedded_panel_info,
3741 
3742 	.get_gpio_pin_info = bios_parser_get_gpio_pin_info,
3743 
3744 	.get_encoder_cap_info = bios_parser_get_encoder_cap_info,
3745 
3746 	.is_device_id_supported = bios_parser_is_device_id_supported,
3747 
3748 	.is_accelerated_mode = bios_parser_is_accelerated_mode,
3749 
3750 	.set_scratch_critical_state = bios_parser_set_scratch_critical_state,
3751 
3752 
3753 /*	 COMMANDS */
3754 	.encoder_control = bios_parser_encoder_control,
3755 
3756 	.transmitter_control = bios_parser_transmitter_control,
3757 
3758 	.enable_crtc = bios_parser_enable_crtc,
3759 
3760 	.set_pixel_clock = bios_parser_set_pixel_clock,
3761 
3762 	.set_dce_clock = bios_parser_set_dce_clock,
3763 
3764 	.program_crtc_timing = bios_parser_program_crtc_timing,
3765 
3766 	.enable_disp_power_gating = bios_parser_enable_disp_power_gating,
3767 
3768 	.bios_parser_destroy = firmware_parser_destroy,
3769 
3770 	.get_board_layout_info = bios_get_board_layout_info,
3771 	.pack_data_tables = bios_parser_pack_data_tables,
3772 
3773 	.get_atom_dc_golden_table = bios_get_atom_dc_golden_table,
3774 
3775 	.enable_lvtma_control = bios_parser_enable_lvtma_control,
3776 
3777 	.get_soc_bb_info = bios_parser_get_soc_bb_info,
3778 
3779 	.get_disp_connector_caps_info = bios_parser_get_disp_connector_caps_info,
3780 
3781 	.get_lttpr_caps = bios_parser_get_lttpr_caps,
3782 
3783 	.get_lttpr_interop = bios_parser_get_lttpr_interop,
3784 
3785 	.get_connector_speed_cap_info = bios_parser_get_connector_speed_cap_info,
3786 	.get_connector_aux_info = bios_parser_get_connector_aux_info,
3787 };
3788 
3789 static bool bios_parser2_construct(
3790 	struct bios_parser *bp,
3791 	struct bp_init_data *init,
3792 	enum dce_version dce_version)
3793 {
3794 	uint16_t *rom_header_offset = NULL;
3795 	struct atom_rom_header_v2_2 *rom_header = NULL;
3796 	struct display_object_info_table_v1_4 *object_info_tbl;
3797 	struct atom_data_revision tbl_rev = {0};
3798 
3799 	if (!init)
3800 		return false;
3801 
3802 	if (!init->bios)
3803 		return false;
3804 
3805 	bp->base.funcs = &vbios_funcs;
3806 	bp->base.bios = init->bios;
3807 	bp->base.bios_size = bp->base.bios[OFFSET_TO_ATOM_ROM_IMAGE_SIZE] * BIOS_IMAGE_SIZE_UNIT;
3808 
3809 	bp->base.ctx = init->ctx;
3810 
3811 	bp->base.bios_local_image = NULL;
3812 
3813 	rom_header_offset =
3814 			GET_IMAGE(uint16_t, OFFSET_TO_ATOM_ROM_HEADER_POINTER);
3815 
3816 	if (!rom_header_offset)
3817 		return false;
3818 
3819 	rom_header = GET_IMAGE(struct atom_rom_header_v2_2, *rom_header_offset);
3820 
3821 	if (!rom_header)
3822 		return false;
3823 
3824 	get_atom_data_table_revision(&rom_header->table_header, &tbl_rev);
3825 	if (!(tbl_rev.major >= 2 && tbl_rev.minor >= 2))
3826 		return false;
3827 
3828 	bp->master_data_tbl =
3829 		GET_IMAGE(struct atom_master_data_table_v2_1,
3830 				rom_header->masterdatatable_offset);
3831 
3832 	if (!bp->master_data_tbl)
3833 		return false;
3834 
3835 	bp->object_info_tbl_offset = DATA_TABLES(displayobjectinfo);
3836 
3837 	if (!bp->object_info_tbl_offset)
3838 		return false;
3839 
3840 	object_info_tbl =
3841 			GET_IMAGE(struct display_object_info_table_v1_4,
3842 						bp->object_info_tbl_offset);
3843 
3844 	if (!object_info_tbl)
3845 		return false;
3846 
3847 	get_atom_data_table_revision(&object_info_tbl->table_header,
3848 		&bp->object_info_tbl.revision);
3849 
3850 	if (bp->object_info_tbl.revision.major == 1
3851 		&& bp->object_info_tbl.revision.minor == 4) {
3852 		struct display_object_info_table_v1_4 *tbl_v1_4;
3853 
3854 		tbl_v1_4 = GET_IMAGE(struct display_object_info_table_v1_4,
3855 			bp->object_info_tbl_offset);
3856 		if (!tbl_v1_4)
3857 			return false;
3858 
3859 		bp->object_info_tbl.v1_4 = tbl_v1_4;
3860 	} else if (bp->object_info_tbl.revision.major == 1
3861 		&& bp->object_info_tbl.revision.minor == 5) {
3862 		struct display_object_info_table_v1_5 *tbl_v1_5;
3863 
3864 		tbl_v1_5 = GET_IMAGE(struct display_object_info_table_v1_5,
3865 			bp->object_info_tbl_offset);
3866 		if (!tbl_v1_5)
3867 			return false;
3868 
3869 		bp->object_info_tbl.v1_5 = tbl_v1_5;
3870 	} else {
3871 		ASSERT(0);
3872 		return false;
3873 	}
3874 
3875 	dal_firmware_parser_init_cmd_tbl(bp);
3876 	dal_bios_parser_init_cmd_tbl_helper2(&bp->cmd_helper, dce_version);
3877 
3878 	bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);
3879 	bp->base.fw_info_valid = bios_parser_get_firmware_info(&bp->base, &bp->base.fw_info) == BP_RESULT_OK;
3880 	bios_parser_get_vram_info(&bp->base, &bp->base.vram_info);
3881 	bios_parser_get_soc_bb_info(&bp->base, &bp->base.bb_info);
3882 	return true;
3883 }
3884 
3885 struct dc_bios *firmware_parser_create(
3886 	struct bp_init_data *init,
3887 	enum dce_version dce_version)
3888 {
3889 	struct bios_parser *bp;
3890 
3891 	bp = kzalloc_obj(struct bios_parser);
3892 	if (!bp)
3893 		return NULL;
3894 
3895 	if (bios_parser2_construct(bp, init, dce_version))
3896 		return &bp->base;
3897 
3898 	kfree(bp);
3899 	return NULL;
3900 }
3901 
3902 
3903