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 <linux/slab.h>
27 
28 #include "dm_services.h"
29 
30 #include "atom.h"
31 
32 #include "dc_bios_types.h"
33 #include "include/gpio_service_interface.h"
34 #include "include/grph_object_ctrl_defs.h"
35 #include "include/bios_parser_interface.h"
36 #include "include/i2caux_interface.h"
37 #include "include/logger_interface.h"
38 
39 #include "command_table.h"
40 #include "bios_parser_helper.h"
41 #include "command_table_helper.h"
42 #include "bios_parser.h"
43 #include "bios_parser_types_internal.h"
44 #include "bios_parser_interface.h"
45 
46 #include "bios_parser_common.h"
47 
48 #include "dc.h"
49 
50 #define THREE_PERCENT_OF_10000 300
51 
52 #define LAST_RECORD_TYPE 0xff
53 
54 #define DC_LOGGER \
55 	bp->base.ctx->logger
56 
57 #define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table)
58 
59 static void get_atom_data_table_revision(
60 	ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
61 	struct atom_data_revision *tbl_revision);
62 static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
63 	uint16_t **id_list);
64 static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
65 	struct graphics_object_id id);
66 static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
67 	ATOM_I2C_RECORD *record,
68 	struct graphics_object_i2c_info *info);
69 static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
70 	ATOM_OBJECT *object);
71 static struct device_id device_type_from_device_id(uint16_t device_id);
72 static uint32_t signal_to_ss_id(enum as_signal_type signal);
73 static uint32_t get_support_mask_for_device_id(struct device_id device_id);
74 static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
75 	struct bios_parser *bp,
76 	ATOM_OBJECT *object);
77 
78 #define BIOS_IMAGE_SIZE_OFFSET 2
79 #define BIOS_IMAGE_SIZE_UNIT 512
80 
81 /*****************************************************************************/
82 static bool bios_parser_construct(
83 	struct bios_parser *bp,
84 	struct bp_init_data *init,
85 	enum dce_version dce_version);
86 
87 static uint8_t bios_parser_get_connectors_number(
88 	struct dc_bios *dcb);
89 
90 static enum bp_result bios_parser_get_embedded_panel_info(
91 	struct dc_bios *dcb,
92 	struct embedded_panel_info *info);
93 
94 /*****************************************************************************/
95 
96 struct dc_bios *bios_parser_create(
97 	struct bp_init_data *init,
98 	enum dce_version dce_version)
99 {
100 	struct bios_parser *bp = NULL;
101 
102 	bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL);
103 	if (!bp)
104 		return NULL;
105 
106 	if (bios_parser_construct(bp, init, dce_version))
107 		return &bp->base;
108 
109 	kfree(bp);
110 	BREAK_TO_DEBUGGER();
111 	return NULL;
112 }
113 
114 static void bios_parser_destruct(struct bios_parser *bp)
115 {
116 	kfree(bp->base.bios_local_image);
117 	kfree(bp->base.integrated_info);
118 }
119 
120 static void bios_parser_destroy(struct dc_bios **dcb)
121 {
122 	struct bios_parser *bp = BP_FROM_DCB(*dcb);
123 
124 	if (!bp) {
125 		BREAK_TO_DEBUGGER();
126 		return;
127 	}
128 
129 	bios_parser_destruct(bp);
130 
131 	kfree(bp);
132 	*dcb = NULL;
133 }
134 
135 static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset)
136 {
137 	ATOM_OBJECT_TABLE *table;
138 
139 	uint32_t object_table_offset = bp->object_info_tbl_offset + offset;
140 
141 	table = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base,
142 				object_table_offset,
143 				struct_size(table, asObjects, 1)));
144 
145 	if (!table)
146 		return 0;
147 	else
148 		return table->ucNumberOfObjects;
149 }
150 
151 static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)
152 {
153 	struct bios_parser *bp = BP_FROM_DCB(dcb);
154 
155 	return get_number_of_objects(bp,
156 		le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset));
157 }
158 
159 static struct graphics_object_id bios_parser_get_connector_id(
160 	struct dc_bios *dcb,
161 	uint8_t i)
162 {
163 	struct bios_parser *bp = BP_FROM_DCB(dcb);
164 	struct graphics_object_id object_id = dal_graphics_object_id_init(
165 		0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
166 	uint16_t id;
167 
168 	uint32_t connector_table_offset = bp->object_info_tbl_offset
169 		+ le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
170 
171 	ATOM_OBJECT_TABLE *tbl = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base,
172 				connector_table_offset,
173 				struct_size(tbl, asObjects, 1)));
174 
175 	if (!tbl) {
176 		dm_error("Can't get connector table from atom bios.\n");
177 		return object_id;
178 	}
179 
180 	if (tbl->ucNumberOfObjects <= i) {
181 		dm_error("Can't find connector id %d in connector table of size %d.\n",
182 			 i, tbl->ucNumberOfObjects);
183 		return object_id;
184 	}
185 
186 	id = le16_to_cpu(tbl->asObjects[i].usObjectID);
187 	object_id = object_id_from_bios_object_id(id);
188 	return object_id;
189 }
190 
191 static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
192 	struct graphics_object_id object_id, uint32_t index,
193 	struct graphics_object_id *src_object_id)
194 {
195 	uint32_t number;
196 	uint16_t *id;
197 	ATOM_OBJECT *object;
198 	struct bios_parser *bp = BP_FROM_DCB(dcb);
199 
200 	if (!src_object_id)
201 		return BP_RESULT_BADINPUT;
202 
203 	object = get_bios_object(bp, object_id);
204 
205 	if (!object) {
206 		BREAK_TO_DEBUGGER(); /* Invalid object id */
207 		return BP_RESULT_BADINPUT;
208 	}
209 
210 	number = get_src_obj_list(bp, object, &id);
211 
212 	if (number <= index)
213 		return BP_RESULT_BADINPUT;
214 
215 	*src_object_id = object_id_from_bios_object_id(id[index]);
216 
217 	return BP_RESULT_OK;
218 }
219 
220 static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
221 	struct graphics_object_id id,
222 	struct graphics_object_i2c_info *info)
223 {
224 	uint32_t offset;
225 	ATOM_OBJECT *object;
226 	ATOM_COMMON_RECORD_HEADER *header;
227 	ATOM_I2C_RECORD *record;
228 	struct bios_parser *bp = BP_FROM_DCB(dcb);
229 
230 	if (!info)
231 		return BP_RESULT_BADINPUT;
232 
233 	object = get_bios_object(bp, id);
234 
235 	if (!object)
236 		return BP_RESULT_BADINPUT;
237 
238 	offset = le16_to_cpu(object->usRecordOffset)
239 			+ bp->object_info_tbl_offset;
240 
241 	for (;;) {
242 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
243 
244 		if (!header)
245 			return BP_RESULT_BADBIOSTABLE;
246 
247 		if (LAST_RECORD_TYPE == header->ucRecordType ||
248 			!header->ucRecordSize)
249 			break;
250 
251 		if (ATOM_I2C_RECORD_TYPE == header->ucRecordType
252 			&& sizeof(ATOM_I2C_RECORD) <= header->ucRecordSize) {
253 			/* get the I2C info */
254 			record = (ATOM_I2C_RECORD *) header;
255 
256 			if (get_gpio_i2c_info(bp, record, info) == BP_RESULT_OK)
257 				return BP_RESULT_OK;
258 		}
259 
260 		offset += header->ucRecordSize;
261 	}
262 
263 	return BP_RESULT_NORECORD;
264 }
265 
266 static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb,
267 	struct graphics_object_id id,
268 	struct graphics_object_hpd_info *info)
269 {
270 	struct bios_parser *bp = BP_FROM_DCB(dcb);
271 	ATOM_OBJECT *object;
272 	ATOM_HPD_INT_RECORD *record = NULL;
273 
274 	if (!info)
275 		return BP_RESULT_BADINPUT;
276 
277 	object = get_bios_object(bp, id);
278 
279 	if (!object)
280 		return BP_RESULT_BADINPUT;
281 
282 	record = get_hpd_record(bp, object);
283 
284 	if (record != NULL) {
285 		info->hpd_int_gpio_uid = record->ucHPDIntGPIOID;
286 		info->hpd_active = record->ucPlugged_PinState;
287 		return BP_RESULT_OK;
288 	}
289 
290 	return BP_RESULT_NORECORD;
291 }
292 
293 static enum bp_result bios_parser_get_device_tag_record(
294 	struct bios_parser *bp,
295 	ATOM_OBJECT *object,
296 	ATOM_CONNECTOR_DEVICE_TAG_RECORD **record)
297 {
298 	ATOM_COMMON_RECORD_HEADER *header;
299 	uint32_t offset;
300 
301 	offset = le16_to_cpu(object->usRecordOffset)
302 			+ bp->object_info_tbl_offset;
303 
304 	for (;;) {
305 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
306 
307 		if (!header)
308 			return BP_RESULT_BADBIOSTABLE;
309 
310 		offset += header->ucRecordSize;
311 
312 		if (LAST_RECORD_TYPE == header->ucRecordType ||
313 			!header->ucRecordSize)
314 			break;
315 
316 		if (ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE !=
317 			header->ucRecordType)
318 			continue;
319 
320 		if (sizeof(ATOM_CONNECTOR_DEVICE_TAG) > header->ucRecordSize)
321 			continue;
322 
323 		*record = (ATOM_CONNECTOR_DEVICE_TAG_RECORD *) header;
324 		return BP_RESULT_OK;
325 	}
326 
327 	return BP_RESULT_NORECORD;
328 }
329 
330 static enum bp_result bios_parser_get_device_tag(
331 	struct dc_bios *dcb,
332 	struct graphics_object_id connector_object_id,
333 	uint32_t device_tag_index,
334 	struct connector_device_tag_info *info)
335 {
336 	struct bios_parser *bp = BP_FROM_DCB(dcb);
337 	ATOM_OBJECT *object;
338 	ATOM_CONNECTOR_DEVICE_TAG_RECORD *record = NULL;
339 	ATOM_CONNECTOR_DEVICE_TAG *device_tag;
340 
341 	if (!info)
342 		return BP_RESULT_BADINPUT;
343 
344 	/* getBiosObject will return MXM object */
345 	object = get_bios_object(bp, connector_object_id);
346 
347 	if (!object) {
348 		BREAK_TO_DEBUGGER(); /* Invalid object id */
349 		return BP_RESULT_BADINPUT;
350 	}
351 
352 	if (bios_parser_get_device_tag_record(bp, object, &record)
353 		!= BP_RESULT_OK)
354 		return BP_RESULT_NORECORD;
355 
356 	if (device_tag_index >= record->ucNumberOfDevice)
357 		return BP_RESULT_NORECORD;
358 
359 	device_tag = &record->asDeviceTag[device_tag_index];
360 
361 	info->acpi_device = le32_to_cpu(device_tag->ulACPIDeviceEnum);
362 	info->dev_id =
363 		device_type_from_device_id(le16_to_cpu(device_tag->usDeviceID));
364 
365 	return BP_RESULT_OK;
366 }
367 
368 static enum bp_result get_firmware_info_v1_4(
369 	struct bios_parser *bp,
370 	struct dc_firmware_info *info);
371 static enum bp_result get_firmware_info_v2_1(
372 	struct bios_parser *bp,
373 	struct dc_firmware_info *info);
374 static enum bp_result get_firmware_info_v2_2(
375 	struct bios_parser *bp,
376 	struct dc_firmware_info *info);
377 
378 static enum bp_result bios_parser_get_firmware_info(
379 	struct dc_bios *dcb,
380 	struct dc_firmware_info *info)
381 {
382 	struct bios_parser *bp = BP_FROM_DCB(dcb);
383 	enum bp_result result = BP_RESULT_BADBIOSTABLE;
384 	ATOM_COMMON_TABLE_HEADER *header;
385 	struct atom_data_revision revision;
386 
387 	if (info && DATA_TABLES(FirmwareInfo)) {
388 		header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
389 			DATA_TABLES(FirmwareInfo));
390 		get_atom_data_table_revision(header, &revision);
391 		switch (revision.major) {
392 		case 1:
393 			switch (revision.minor) {
394 			case 4:
395 				result = get_firmware_info_v1_4(bp, info);
396 				break;
397 			default:
398 				break;
399 			}
400 			break;
401 
402 		case 2:
403 			switch (revision.minor) {
404 			case 1:
405 				result = get_firmware_info_v2_1(bp, info);
406 				break;
407 			case 2:
408 				result = get_firmware_info_v2_2(bp, info);
409 				break;
410 			default:
411 				break;
412 			}
413 			break;
414 		default:
415 			break;
416 		}
417 	}
418 
419 	return result;
420 }
421 
422 static enum bp_result get_firmware_info_v1_4(
423 	struct bios_parser *bp,
424 	struct dc_firmware_info *info)
425 {
426 	ATOM_FIRMWARE_INFO_V1_4 *firmware_info =
427 		GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4,
428 			DATA_TABLES(FirmwareInfo));
429 
430 	if (!info)
431 		return BP_RESULT_BADINPUT;
432 
433 	if (!firmware_info)
434 		return BP_RESULT_BADBIOSTABLE;
435 
436 	memset(info, 0, sizeof(*info));
437 
438 	/* Pixel clock pll information. We need to convert from 10KHz units into
439 	 * KHz units */
440 	info->pll_info.crystal_frequency =
441 		le16_to_cpu(firmware_info->usReferenceClock) * 10;
442 	info->pll_info.min_input_pxl_clk_pll_frequency =
443 		le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
444 	info->pll_info.max_input_pxl_clk_pll_frequency =
445 		le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
446 	info->pll_info.min_output_pxl_clk_pll_frequency =
447 		le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
448 	info->pll_info.max_output_pxl_clk_pll_frequency =
449 		le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
450 
451 	if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
452 		/* Since there is no information on the SS, report conservative
453 		 * value 3% for bandwidth calculation */
454 		/* unit of 0.01% */
455 		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
456 
457 	if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
458 		/* Since there is no information on the SS,report conservative
459 		 * value 3% for bandwidth calculation */
460 		/* unit of 0.01% */
461 		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
462 
463 	return BP_RESULT_OK;
464 }
465 
466 static enum bp_result get_ss_info_v3_1(
467 	struct bios_parser *bp,
468 	uint32_t id,
469 	uint32_t index,
470 	struct spread_spectrum_info *ss_info);
471 
472 static enum bp_result get_firmware_info_v2_1(
473 	struct bios_parser *bp,
474 	struct dc_firmware_info *info)
475 {
476 	ATOM_FIRMWARE_INFO_V2_1 *firmwareInfo =
477 		GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1, DATA_TABLES(FirmwareInfo));
478 	struct spread_spectrum_info internalSS;
479 	uint32_t index;
480 
481 	if (!info)
482 		return BP_RESULT_BADINPUT;
483 
484 	if (!firmwareInfo)
485 		return BP_RESULT_BADBIOSTABLE;
486 
487 	memset(info, 0, sizeof(*info));
488 
489 	/* Pixel clock pll information. We need to convert from 10KHz units into
490 	 * KHz units */
491 	info->pll_info.crystal_frequency =
492 		le16_to_cpu(firmwareInfo->usCoreReferenceClock) * 10;
493 	info->pll_info.min_input_pxl_clk_pll_frequency =
494 		le16_to_cpu(firmwareInfo->usMinPixelClockPLL_Input) * 10;
495 	info->pll_info.max_input_pxl_clk_pll_frequency =
496 		le16_to_cpu(firmwareInfo->usMaxPixelClockPLL_Input) * 10;
497 	info->pll_info.min_output_pxl_clk_pll_frequency =
498 		le32_to_cpu(firmwareInfo->ulMinPixelClockPLL_Output) * 10;
499 	info->pll_info.max_output_pxl_clk_pll_frequency =
500 		le32_to_cpu(firmwareInfo->ulMaxPixelClockPLL_Output) * 10;
501 	info->default_display_engine_pll_frequency =
502 		le32_to_cpu(firmwareInfo->ulDefaultDispEngineClkFreq) * 10;
503 	info->external_clock_source_frequency_for_dp =
504 		le16_to_cpu(firmwareInfo->usUniphyDPModeExtClkFreq) * 10;
505 	info->min_allowed_bl_level = firmwareInfo->ucMinAllowedBL_Level;
506 
507 	/* There should be only one entry in the SS info table for Memory Clock
508 	 */
509 	index = 0;
510 	if (firmwareInfo->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
511 		/* Since there is no information for external SS, report
512 		 *  conservative value 3% for bandwidth calculation */
513 		/* unit of 0.01% */
514 		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
515 	else if (get_ss_info_v3_1(bp,
516 		ASIC_INTERNAL_MEMORY_SS, index, &internalSS) == BP_RESULT_OK) {
517 		if (internalSS.spread_spectrum_percentage) {
518 			info->feature.memory_clk_ss_percentage =
519 				internalSS.spread_spectrum_percentage;
520 			if (internalSS.type.CENTER_MODE) {
521 				/* if it is centermode, the exact SS Percentage
522 				 * will be round up of half of the percentage
523 				 * reported in the SS table */
524 				++info->feature.memory_clk_ss_percentage;
525 				info->feature.memory_clk_ss_percentage /= 2;
526 			}
527 		}
528 	}
529 
530 	/* There should be only one entry in the SS info table for Engine Clock
531 	 */
532 	index = 1;
533 	if (firmwareInfo->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
534 		/* Since there is no information for external SS, report
535 		 * conservative value 3% for bandwidth calculation */
536 		/* unit of 0.01% */
537 		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
538 	else if (get_ss_info_v3_1(bp,
539 		ASIC_INTERNAL_ENGINE_SS, index, &internalSS) == BP_RESULT_OK) {
540 		if (internalSS.spread_spectrum_percentage) {
541 			info->feature.engine_clk_ss_percentage =
542 				internalSS.spread_spectrum_percentage;
543 			if (internalSS.type.CENTER_MODE) {
544 				/* if it is centermode, the exact SS Percentage
545 				 * will be round up of half of the percentage
546 				 * reported in the SS table */
547 				++info->feature.engine_clk_ss_percentage;
548 				info->feature.engine_clk_ss_percentage /= 2;
549 			}
550 		}
551 	}
552 
553 	return BP_RESULT_OK;
554 }
555 
556 static enum bp_result get_firmware_info_v2_2(
557 	struct bios_parser *bp,
558 	struct dc_firmware_info *info)
559 {
560 	ATOM_FIRMWARE_INFO_V2_2 *firmware_info;
561 	struct spread_spectrum_info internal_ss;
562 	uint32_t index;
563 
564 	if (!info)
565 		return BP_RESULT_BADINPUT;
566 
567 	firmware_info = GET_IMAGE(ATOM_FIRMWARE_INFO_V2_2,
568 		DATA_TABLES(FirmwareInfo));
569 
570 	if (!firmware_info)
571 		return BP_RESULT_BADBIOSTABLE;
572 
573 	memset(info, 0, sizeof(*info));
574 
575 	/* Pixel clock pll information. We need to convert from 10KHz units into
576 	 * KHz units */
577 	info->pll_info.crystal_frequency =
578 		le16_to_cpu(firmware_info->usCoreReferenceClock) * 10;
579 	info->pll_info.min_input_pxl_clk_pll_frequency =
580 		le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
581 	info->pll_info.max_input_pxl_clk_pll_frequency =
582 		le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
583 	info->pll_info.min_output_pxl_clk_pll_frequency =
584 		le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
585 	info->pll_info.max_output_pxl_clk_pll_frequency =
586 		le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
587 	info->default_display_engine_pll_frequency =
588 		le32_to_cpu(firmware_info->ulDefaultDispEngineClkFreq) * 10;
589 	info->external_clock_source_frequency_for_dp =
590 		le16_to_cpu(firmware_info->usUniphyDPModeExtClkFreq) * 10;
591 
592 	/* There should be only one entry in the SS info table for Memory Clock
593 	 */
594 	index = 0;
595 	if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
596 		/* Since there is no information for external SS, report
597 		 *  conservative value 3% for bandwidth calculation */
598 		/* unit of 0.01% */
599 		info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
600 	else if (get_ss_info_v3_1(bp,
601 			ASIC_INTERNAL_MEMORY_SS, index, &internal_ss) == BP_RESULT_OK) {
602 		if (internal_ss.spread_spectrum_percentage) {
603 			info->feature.memory_clk_ss_percentage =
604 					internal_ss.spread_spectrum_percentage;
605 			if (internal_ss.type.CENTER_MODE) {
606 				/* if it is centermode, the exact SS Percentage
607 				 * will be round up of half of the percentage
608 				 * reported in the SS table */
609 				++info->feature.memory_clk_ss_percentage;
610 				info->feature.memory_clk_ss_percentage /= 2;
611 			}
612 		}
613 	}
614 
615 	/* There should be only one entry in the SS info table for Engine Clock
616 	 */
617 	index = 1;
618 	if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
619 		/* Since there is no information for external SS, report
620 		 * conservative value 3% for bandwidth calculation */
621 		/* unit of 0.01% */
622 		info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
623 	else if (get_ss_info_v3_1(bp,
624 			ASIC_INTERNAL_ENGINE_SS, index, &internal_ss) == BP_RESULT_OK) {
625 		if (internal_ss.spread_spectrum_percentage) {
626 			info->feature.engine_clk_ss_percentage =
627 					internal_ss.spread_spectrum_percentage;
628 			if (internal_ss.type.CENTER_MODE) {
629 				/* if it is centermode, the exact SS Percentage
630 				 * will be round up of half of the percentage
631 				 * reported in the SS table */
632 				++info->feature.engine_clk_ss_percentage;
633 				info->feature.engine_clk_ss_percentage /= 2;
634 			}
635 		}
636 	}
637 
638 	/* Remote Display */
639 	info->remote_display_config = firmware_info->ucRemoteDisplayConfig;
640 
641 	/* Is allowed minimum BL level */
642 	info->min_allowed_bl_level = firmware_info->ucMinAllowedBL_Level;
643 	/* Used starting from CI */
644 	info->smu_gpu_pll_output_freq =
645 			(uint32_t) (le32_to_cpu(firmware_info->ulGPUPLL_OutputFreq) * 10);
646 
647 	return BP_RESULT_OK;
648 }
649 
650 static enum bp_result get_ss_info_v3_1(
651 	struct bios_parser *bp,
652 	uint32_t id,
653 	uint32_t index,
654 	struct spread_spectrum_info *ss_info)
655 {
656 	ATOM_ASIC_INTERNAL_SS_INFO_V3 *ss_table_header_include;
657 	ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
658 	uint32_t table_size;
659 	uint32_t i;
660 	uint32_t table_index = 0;
661 
662 	if (!ss_info)
663 		return BP_RESULT_BADINPUT;
664 
665 	if (!DATA_TABLES(ASIC_InternalSS_Info))
666 		return BP_RESULT_UNSUPPORTED;
667 
668 	ss_table_header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V3 *) bios_get_image(&bp->base,
669 				DATA_TABLES(ASIC_InternalSS_Info),
670 				struct_size(ss_table_header_include, asSpreadSpectrum, 1)));
671 	table_size =
672 		(le16_to_cpu(ss_table_header_include->sHeader.usStructureSize)
673 				- sizeof(ATOM_COMMON_TABLE_HEADER))
674 				/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
675 
676 	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
677 				&ss_table_header_include->asSpreadSpectrum[0];
678 
679 	memset(ss_info, 0, sizeof(struct spread_spectrum_info));
680 
681 	for (i = 0; i < table_size; i++) {
682 		if (tbl[i].ucClockIndication != (uint8_t) id)
683 			continue;
684 
685 		if (table_index != index) {
686 			table_index++;
687 			continue;
688 		}
689 		/* VBIOS introduced new defines for Version 3, same values as
690 		 *  before, so now use these new ones for Version 3.
691 		 * Shouldn't affect field VBIOS's V3 as define values are still
692 		 *  same.
693 		 * #define SS_MODE_V3_CENTRE_SPREAD_MASK                0x01
694 		 * #define SS_MODE_V3_EXTERNAL_SS_MASK                  0x02
695 
696 		 * Old VBIOS defines:
697 		 * #define ATOM_SS_CENTRE_SPREAD_MODE_MASK        0x00000001
698 		 * #define ATOM_EXTERNAL_SS_MASK                  0x00000002
699 		 */
700 
701 		if (SS_MODE_V3_EXTERNAL_SS_MASK & tbl[i].ucSpreadSpectrumMode)
702 			ss_info->type.EXTERNAL = true;
703 
704 		if (SS_MODE_V3_CENTRE_SPREAD_MASK & tbl[i].ucSpreadSpectrumMode)
705 			ss_info->type.CENTER_MODE = true;
706 
707 		/* Older VBIOS (in field) always provides SS percentage in 0.01%
708 		 * units set Divider to 100 */
709 		ss_info->spread_percentage_divider = 100;
710 
711 		/* #define SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 0x10 */
712 		if (SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK
713 				& tbl[i].ucSpreadSpectrumMode)
714 			ss_info->spread_percentage_divider = 1000;
715 
716 		ss_info->type.STEP_AND_DELAY_INFO = false;
717 		/* convert [10KHz] into [KHz] */
718 		ss_info->target_clock_range =
719 				le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
720 		ss_info->spread_spectrum_percentage =
721 				(uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
722 		ss_info->spread_spectrum_range =
723 				(uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
724 
725 		return BP_RESULT_OK;
726 	}
727 	return BP_RESULT_NORECORD;
728 }
729 
730 static enum bp_result bios_parser_transmitter_control(
731 	struct dc_bios *dcb,
732 	struct bp_transmitter_control *cntl)
733 {
734 	struct bios_parser *bp = BP_FROM_DCB(dcb);
735 
736 	if (!bp->cmd_tbl.transmitter_control)
737 		return BP_RESULT_FAILURE;
738 
739 	return bp->cmd_tbl.transmitter_control(bp, cntl);
740 }
741 
742 static enum bp_result bios_parser_encoder_control(
743 	struct dc_bios *dcb,
744 	struct bp_encoder_control *cntl)
745 {
746 	struct bios_parser *bp = BP_FROM_DCB(dcb);
747 
748 	if (!bp->cmd_tbl.dig_encoder_control)
749 		return BP_RESULT_FAILURE;
750 
751 	return bp->cmd_tbl.dig_encoder_control(bp, cntl);
752 }
753 
754 static enum bp_result bios_parser_adjust_pixel_clock(
755 	struct dc_bios *dcb,
756 	struct bp_adjust_pixel_clock_parameters *bp_params)
757 {
758 	struct bios_parser *bp = BP_FROM_DCB(dcb);
759 
760 	if (!bp->cmd_tbl.adjust_display_pll)
761 		return BP_RESULT_FAILURE;
762 
763 	return bp->cmd_tbl.adjust_display_pll(bp, bp_params);
764 }
765 
766 static enum bp_result bios_parser_set_pixel_clock(
767 	struct dc_bios *dcb,
768 	struct bp_pixel_clock_parameters *bp_params)
769 {
770 	struct bios_parser *bp = BP_FROM_DCB(dcb);
771 
772 	if (!bp->cmd_tbl.set_pixel_clock)
773 		return BP_RESULT_FAILURE;
774 
775 	return bp->cmd_tbl.set_pixel_clock(bp, bp_params);
776 }
777 
778 static enum bp_result bios_parser_set_dce_clock(
779 	struct dc_bios *dcb,
780 	struct bp_set_dce_clock_parameters *bp_params)
781 {
782 	struct bios_parser *bp = BP_FROM_DCB(dcb);
783 
784 	if (!bp->cmd_tbl.set_dce_clock)
785 		return BP_RESULT_FAILURE;
786 
787 	return bp->cmd_tbl.set_dce_clock(bp, bp_params);
788 }
789 
790 static enum bp_result bios_parser_enable_spread_spectrum_on_ppll(
791 	struct dc_bios *dcb,
792 	struct bp_spread_spectrum_parameters *bp_params,
793 	bool enable)
794 {
795 	struct bios_parser *bp = BP_FROM_DCB(dcb);
796 
797 	if (!bp->cmd_tbl.enable_spread_spectrum_on_ppll)
798 		return BP_RESULT_FAILURE;
799 
800 	return bp->cmd_tbl.enable_spread_spectrum_on_ppll(
801 			bp, bp_params, enable);
802 
803 }
804 
805 static enum bp_result bios_parser_program_crtc_timing(
806 	struct dc_bios *dcb,
807 	struct bp_hw_crtc_timing_parameters *bp_params)
808 {
809 	struct bios_parser *bp = BP_FROM_DCB(dcb);
810 
811 	if (!bp->cmd_tbl.set_crtc_timing)
812 		return BP_RESULT_FAILURE;
813 
814 	return bp->cmd_tbl.set_crtc_timing(bp, bp_params);
815 }
816 
817 static enum bp_result bios_parser_program_display_engine_pll(
818 	struct dc_bios *dcb,
819 	struct bp_pixel_clock_parameters *bp_params)
820 {
821 	struct bios_parser *bp = BP_FROM_DCB(dcb);
822 
823 	if (!bp->cmd_tbl.program_clock)
824 		return BP_RESULT_FAILURE;
825 
826 	return bp->cmd_tbl.program_clock(bp, bp_params);
827 
828 }
829 
830 
831 static enum bp_result bios_parser_enable_crtc(
832 	struct dc_bios *dcb,
833 	enum controller_id id,
834 	bool enable)
835 {
836 	struct bios_parser *bp = BP_FROM_DCB(dcb);
837 
838 	if (!bp->cmd_tbl.enable_crtc)
839 		return BP_RESULT_FAILURE;
840 
841 	return bp->cmd_tbl.enable_crtc(bp, id, enable);
842 }
843 
844 static enum bp_result bios_parser_enable_disp_power_gating(
845 	struct dc_bios *dcb,
846 	enum controller_id controller_id,
847 	enum bp_pipe_control_action action)
848 {
849 	struct bios_parser *bp = BP_FROM_DCB(dcb);
850 
851 	if (!bp->cmd_tbl.enable_disp_power_gating)
852 		return BP_RESULT_FAILURE;
853 
854 	return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id,
855 		action);
856 }
857 
858 static bool bios_parser_is_device_id_supported(
859 	struct dc_bios *dcb,
860 	struct device_id id)
861 {
862 	struct bios_parser *bp = BP_FROM_DCB(dcb);
863 
864 	uint32_t mask = get_support_mask_for_device_id(id);
865 
866 	return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0;
867 }
868 
869 static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
870 	ATOM_OBJECT *object)
871 {
872 	ATOM_COMMON_RECORD_HEADER *header;
873 	uint32_t offset;
874 
875 	if (!object) {
876 		BREAK_TO_DEBUGGER(); /* Invalid object */
877 		return NULL;
878 	}
879 
880 	offset = le16_to_cpu(object->usRecordOffset)
881 			+ bp->object_info_tbl_offset;
882 
883 	for (;;) {
884 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
885 
886 		if (!header)
887 			return NULL;
888 
889 		if (LAST_RECORD_TYPE == header->ucRecordType ||
890 			!header->ucRecordSize)
891 			break;
892 
893 		if (ATOM_HPD_INT_RECORD_TYPE == header->ucRecordType
894 			&& sizeof(ATOM_HPD_INT_RECORD) <= header->ucRecordSize)
895 			return (ATOM_HPD_INT_RECORD *) header;
896 
897 		offset += header->ucRecordSize;
898 	}
899 
900 	return NULL;
901 }
902 
903 static enum bp_result get_ss_info_from_ss_info_table(
904 	struct bios_parser *bp,
905 	uint32_t id,
906 	struct spread_spectrum_info *ss_info);
907 static enum bp_result get_ss_info_from_tbl(
908 	struct bios_parser *bp,
909 	uint32_t id,
910 	struct spread_spectrum_info *ss_info);
911 /**
912  * bios_parser_get_spread_spectrum_info
913  * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or
914  * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info
915  * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info ver 3.1,
916  * there is only one entry for each signal /ss id.  However, there is
917  * no planning of supporting multiple spread Sprectum entry for EverGreen
918  * @dcb:     pointer to the DC BIOS
919  * @signal:  ASSignalType to be converted to info index
920  * @index:   number of entries that match the converted info index
921  * @ss_info: sprectrum information structure,
922  * return:   Bios parser result code
923  */
924 static enum bp_result bios_parser_get_spread_spectrum_info(
925 	struct dc_bios *dcb,
926 	enum as_signal_type signal,
927 	uint32_t index,
928 	struct spread_spectrum_info *ss_info)
929 {
930 	struct bios_parser *bp = BP_FROM_DCB(dcb);
931 	enum bp_result result = BP_RESULT_UNSUPPORTED;
932 	uint32_t clk_id_ss = 0;
933 	ATOM_COMMON_TABLE_HEADER *header;
934 	struct atom_data_revision tbl_revision;
935 
936 	if (!ss_info) /* check for bad input */
937 		return BP_RESULT_BADINPUT;
938 	/* signal translation */
939 	clk_id_ss = signal_to_ss_id(signal);
940 
941 	if (!DATA_TABLES(ASIC_InternalSS_Info))
942 		if (!index)
943 			return get_ss_info_from_ss_info_table(bp, clk_id_ss,
944 				ss_info);
945 
946 	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
947 		DATA_TABLES(ASIC_InternalSS_Info));
948 	get_atom_data_table_revision(header, &tbl_revision);
949 
950 	switch (tbl_revision.major) {
951 	case 2:
952 		switch (tbl_revision.minor) {
953 		case 1:
954 			/* there can not be more then one entry for Internal
955 			 * SS Info table version 2.1 */
956 			if (!index)
957 				return get_ss_info_from_tbl(bp, clk_id_ss,
958 						ss_info);
959 			break;
960 		default:
961 			break;
962 		}
963 		break;
964 
965 	case 3:
966 		switch (tbl_revision.minor) {
967 		case 1:
968 			return get_ss_info_v3_1(bp, clk_id_ss, index, ss_info);
969 		default:
970 			break;
971 		}
972 		break;
973 	default:
974 		break;
975 	}
976 	/* there can not be more then one entry for SS Info table */
977 	return result;
978 }
979 
980 static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
981 	struct bios_parser *bp,
982 	uint32_t id,
983 	struct spread_spectrum_info *info);
984 
985 /**
986  * get_ss_info_from_tbl
987  * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
988  * SS_Info table from the VBIOS
989  * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or
990  * SS_Info.
991  *
992  * @bp:      pointer to the BIOS parser
993  * @id:      spread sprectrum info index
994  * @ss_info: sprectrum information structure,
995  * return:   BIOS parser result code
996  */
997 static enum bp_result get_ss_info_from_tbl(
998 	struct bios_parser *bp,
999 	uint32_t id,
1000 	struct spread_spectrum_info *ss_info)
1001 {
1002 	if (!ss_info) /* check for bad input, if ss_info is not NULL */
1003 		return BP_RESULT_BADINPUT;
1004 	/* for SS_Info table only support DP and LVDS */
1005 	if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
1006 		return get_ss_info_from_ss_info_table(bp, id, ss_info);
1007 	else
1008 		return get_ss_info_from_internal_ss_info_tbl_V2_1(bp, id,
1009 			ss_info);
1010 }
1011 
1012 /**
1013  * get_ss_info_from_internal_ss_info_tbl_V2_1
1014  * Get spread sprectrum information from the ASIC_InternalSS_Info table Ver 2.1
1015  * from the VBIOS
1016  * There will not be multiple entry for Ver 2.1
1017  *
1018  * @bp:    pointer to the Bios parser
1019  * @id:    spread sprectrum info index
1020  * @info:  sprectrum information structure,
1021  * return: Bios parser result code
1022  */
1023 static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
1024 	struct bios_parser *bp,
1025 	uint32_t id,
1026 	struct spread_spectrum_info *info)
1027 {
1028 	enum bp_result result = BP_RESULT_UNSUPPORTED;
1029 	ATOM_ASIC_INTERNAL_SS_INFO_V2 *header;
1030 	ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
1031 	uint32_t tbl_size, i;
1032 
1033 	if (!DATA_TABLES(ASIC_InternalSS_Info))
1034 		return result;
1035 
1036 	header = ((ATOM_ASIC_INTERNAL_SS_INFO_V2 *) bios_get_image(
1037 				&bp->base,
1038 				DATA_TABLES(ASIC_InternalSS_Info),
1039 				struct_size(header, asSpreadSpectrum, 1)));
1040 
1041 	memset(info, 0, sizeof(struct spread_spectrum_info));
1042 
1043 	tbl_size = (le16_to_cpu(header->sHeader.usStructureSize)
1044 			- sizeof(ATOM_COMMON_TABLE_HEADER))
1045 					/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
1046 
1047 	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
1048 					&(header->asSpreadSpectrum[0]);
1049 	for (i = 0; i < tbl_size; i++) {
1050 		result = BP_RESULT_NORECORD;
1051 
1052 		if (tbl[i].ucClockIndication != (uint8_t)id)
1053 			continue;
1054 
1055 		if (ATOM_EXTERNAL_SS_MASK
1056 			& tbl[i].ucSpreadSpectrumMode) {
1057 			info->type.EXTERNAL = true;
1058 		}
1059 		if (ATOM_SS_CENTRE_SPREAD_MODE_MASK
1060 			& tbl[i].ucSpreadSpectrumMode) {
1061 			info->type.CENTER_MODE = true;
1062 		}
1063 		info->type.STEP_AND_DELAY_INFO = false;
1064 		/* convert [10KHz] into [KHz] */
1065 		info->target_clock_range =
1066 			le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
1067 		info->spread_spectrum_percentage =
1068 			(uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
1069 		info->spread_spectrum_range =
1070 			(uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
1071 		result = BP_RESULT_OK;
1072 		break;
1073 	}
1074 
1075 	return result;
1076 
1077 }
1078 
1079 /**
1080  * get_ss_info_from_ss_info_table
1081  * Get spread sprectrum information from the SS_Info table from the VBIOS
1082  * if the pointer to info is NULL, indicate the caller what to know the number
1083  * of entries that matches the id
1084  * for, the SS_Info table, there should not be more than 1 entry match.
1085  *
1086  * @bp:      pointer to the Bios parser
1087  * @id:      spread sprectrum id
1088  * @ss_info: sprectrum information structure,
1089  * return:   Bios parser result code
1090  */
1091 static enum bp_result get_ss_info_from_ss_info_table(
1092 	struct bios_parser *bp,
1093 	uint32_t id,
1094 	struct spread_spectrum_info *ss_info)
1095 {
1096 	enum bp_result result = BP_RESULT_UNSUPPORTED;
1097 	ATOM_SPREAD_SPECTRUM_INFO *tbl;
1098 	ATOM_COMMON_TABLE_HEADER *header;
1099 	uint32_t table_size;
1100 	uint32_t i;
1101 	uint32_t id_local = SS_ID_UNKNOWN;
1102 	struct atom_data_revision revision;
1103 
1104 	/* exist of the SS_Info table */
1105 	/* check for bad input, pSSinfo can not be NULL */
1106 	if (!DATA_TABLES(SS_Info) || !ss_info)
1107 		return result;
1108 
1109 	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(SS_Info));
1110 	get_atom_data_table_revision(header, &revision);
1111 
1112 	tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, DATA_TABLES(SS_Info));
1113 
1114 	if (1 != revision.major || 2 > revision.minor)
1115 		return result;
1116 
1117 	/* have to convert from Internal_SS format to SS_Info format */
1118 	switch (id) {
1119 	case ASIC_INTERNAL_SS_ON_DP:
1120 		id_local = SS_ID_DP1;
1121 		break;
1122 	case ASIC_INTERNAL_SS_ON_LVDS:
1123 	{
1124 		struct embedded_panel_info panel_info;
1125 
1126 		if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
1127 				== BP_RESULT_OK)
1128 			id_local = panel_info.ss_id;
1129 		break;
1130 	}
1131 	default:
1132 		break;
1133 	}
1134 
1135 	if (id_local == SS_ID_UNKNOWN)
1136 		return result;
1137 
1138 	table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
1139 			sizeof(ATOM_COMMON_TABLE_HEADER)) /
1140 					sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
1141 
1142 	for (i = 0; i < table_size; i++) {
1143 		if (id_local != (uint32_t)tbl->asSS_Info[i].ucSS_Id)
1144 			continue;
1145 
1146 		memset(ss_info, 0, sizeof(struct spread_spectrum_info));
1147 
1148 		if (ATOM_EXTERNAL_SS_MASK &
1149 				tbl->asSS_Info[i].ucSpreadSpectrumType)
1150 			ss_info->type.EXTERNAL = true;
1151 
1152 		if (ATOM_SS_CENTRE_SPREAD_MODE_MASK &
1153 				tbl->asSS_Info[i].ucSpreadSpectrumType)
1154 			ss_info->type.CENTER_MODE = true;
1155 
1156 		ss_info->type.STEP_AND_DELAY_INFO = true;
1157 		ss_info->spread_spectrum_percentage =
1158 			(uint32_t)le16_to_cpu(tbl->asSS_Info[i].usSpreadSpectrumPercentage);
1159 		ss_info->step_and_delay_info.step = tbl->asSS_Info[i].ucSS_Step;
1160 		ss_info->step_and_delay_info.delay =
1161 			tbl->asSS_Info[i].ucSS_Delay;
1162 		ss_info->step_and_delay_info.recommended_ref_div =
1163 			tbl->asSS_Info[i].ucRecommendedRef_Div;
1164 		ss_info->spread_spectrum_range =
1165 			(uint32_t)tbl->asSS_Info[i].ucSS_Range * 10000;
1166 
1167 		/* there will be only one entry for each display type in SS_info
1168 		 * table */
1169 		result = BP_RESULT_OK;
1170 		break;
1171 	}
1172 
1173 	return result;
1174 }
1175 static enum bp_result get_embedded_panel_info_v1_2(
1176 	struct bios_parser *bp,
1177 	struct embedded_panel_info *info);
1178 static enum bp_result get_embedded_panel_info_v1_3(
1179 	struct bios_parser *bp,
1180 	struct embedded_panel_info *info);
1181 
1182 static enum bp_result bios_parser_get_embedded_panel_info(
1183 	struct dc_bios *dcb,
1184 	struct embedded_panel_info *info)
1185 {
1186 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1187 	ATOM_COMMON_TABLE_HEADER *hdr;
1188 
1189 	if (!DATA_TABLES(LCD_Info))
1190 		return BP_RESULT_FAILURE;
1191 
1192 	hdr = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(LCD_Info));
1193 
1194 	if (!hdr)
1195 		return BP_RESULT_BADBIOSTABLE;
1196 
1197 	switch (hdr->ucTableFormatRevision) {
1198 	case 1:
1199 		switch (hdr->ucTableContentRevision) {
1200 		case 0:
1201 		case 1:
1202 		case 2:
1203 			return get_embedded_panel_info_v1_2(bp, info);
1204 		case 3:
1205 			return get_embedded_panel_info_v1_3(bp, info);
1206 		default:
1207 			break;
1208 		}
1209 		break;
1210 	default:
1211 		break;
1212 	}
1213 
1214 	return BP_RESULT_FAILURE;
1215 }
1216 
1217 static enum bp_result get_embedded_panel_info_v1_2(
1218 	struct bios_parser *bp,
1219 	struct embedded_panel_info *info)
1220 {
1221 	ATOM_LVDS_INFO_V12 *lvds;
1222 
1223 	if (!info)
1224 		return BP_RESULT_BADINPUT;
1225 
1226 	if (!DATA_TABLES(LVDS_Info))
1227 		return BP_RESULT_UNSUPPORTED;
1228 
1229 	lvds =
1230 		GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info));
1231 
1232 	if (!lvds)
1233 		return BP_RESULT_BADBIOSTABLE;
1234 
1235 	if (1 != lvds->sHeader.ucTableFormatRevision
1236 		|| 2 > lvds->sHeader.ucTableContentRevision)
1237 		return BP_RESULT_UNSUPPORTED;
1238 
1239 	memset(info, 0, sizeof(struct embedded_panel_info));
1240 
1241 	/* We need to convert from 10KHz units into KHz units*/
1242 	info->lcd_timing.pixel_clk =
1243 		le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
1244 	/* usHActive does not include borders, according to VBIOS team*/
1245 	info->lcd_timing.horizontal_addressable =
1246 		le16_to_cpu(lvds->sLCDTiming.usHActive);
1247 	/* usHBlanking_Time includes borders, so we should really be subtracting
1248 	 * borders duing this translation, but LVDS generally*/
1249 	/* doesn't have borders, so we should be okay leaving this as is for
1250 	 * now.  May need to revisit if we ever have LVDS with borders*/
1251 	info->lcd_timing.horizontal_blanking_time =
1252 			le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
1253 	/* usVActive does not include borders, according to VBIOS team*/
1254 	info->lcd_timing.vertical_addressable =
1255 			le16_to_cpu(lvds->sLCDTiming.usVActive);
1256 	/* usVBlanking_Time includes borders, so we should really be subtracting
1257 	 * borders duing this translation, but LVDS generally*/
1258 	/* doesn't have borders, so we should be okay leaving this as is for
1259 	 * now. May need to revisit if we ever have LVDS with borders*/
1260 	info->lcd_timing.vertical_blanking_time =
1261 		le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
1262 	info->lcd_timing.horizontal_sync_offset =
1263 		le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
1264 	info->lcd_timing.horizontal_sync_width =
1265 		le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
1266 	info->lcd_timing.vertical_sync_offset =
1267 		le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
1268 	info->lcd_timing.vertical_sync_width =
1269 		le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
1270 	info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
1271 	info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
1272 	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
1273 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
1274 	info->lcd_timing.misc_info.H_SYNC_POLARITY =
1275 		~(uint32_t)
1276 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
1277 	info->lcd_timing.misc_info.V_SYNC_POLARITY =
1278 		~(uint32_t)
1279 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
1280 	info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
1281 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
1282 	info->lcd_timing.misc_info.H_REPLICATION_BY2 =
1283 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
1284 	info->lcd_timing.misc_info.V_REPLICATION_BY2 =
1285 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
1286 	info->lcd_timing.misc_info.COMPOSITE_SYNC =
1287 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
1288 	info->lcd_timing.misc_info.INTERLACE =
1289 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
1290 	info->lcd_timing.misc_info.DOUBLE_CLOCK =
1291 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
1292 	info->ss_id = lvds->ucSS_Id;
1293 
1294 	{
1295 		uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate);
1296 		/* Get minimum supported refresh rate*/
1297 		if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
1298 			info->supported_rr.REFRESH_RATE_30HZ = 1;
1299 		else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
1300 			info->supported_rr.REFRESH_RATE_40HZ = 1;
1301 		else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
1302 			info->supported_rr.REFRESH_RATE_48HZ = 1;
1303 		else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
1304 			info->supported_rr.REFRESH_RATE_50HZ = 1;
1305 		else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
1306 			info->supported_rr.REFRESH_RATE_60HZ = 1;
1307 	}
1308 
1309 	/*Drr panel support can be reported by VBIOS*/
1310 	if (LCDPANEL_CAP_DRR_SUPPORTED
1311 			& lvds->ucLCDPanel_SpecialHandlingCap)
1312 		info->drr_enabled = 1;
1313 
1314 	if (ATOM_PANEL_MISC_DUAL & lvds->ucLVDS_Misc)
1315 		info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
1316 
1317 	if (ATOM_PANEL_MISC_888RGB & lvds->ucLVDS_Misc)
1318 		info->lcd_timing.misc_info.RGB888 = true;
1319 
1320 	info->lcd_timing.misc_info.GREY_LEVEL =
1321 		(uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL &
1322 			lvds->ucLVDS_Misc) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT;
1323 
1324 	if (ATOM_PANEL_MISC_SPATIAL & lvds->ucLVDS_Misc)
1325 		info->lcd_timing.misc_info.SPATIAL = true;
1326 
1327 	if (ATOM_PANEL_MISC_TEMPORAL & lvds->ucLVDS_Misc)
1328 		info->lcd_timing.misc_info.TEMPORAL = true;
1329 
1330 	if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc)
1331 		info->lcd_timing.misc_info.API_ENABLED = true;
1332 
1333 	return BP_RESULT_OK;
1334 }
1335 
1336 static enum bp_result get_embedded_panel_info_v1_3(
1337 	struct bios_parser *bp,
1338 	struct embedded_panel_info *info)
1339 {
1340 	ATOM_LCD_INFO_V13 *lvds;
1341 
1342 	if (!info)
1343 		return BP_RESULT_BADINPUT;
1344 
1345 	if (!DATA_TABLES(LCD_Info))
1346 		return BP_RESULT_UNSUPPORTED;
1347 
1348 	lvds = GET_IMAGE(ATOM_LCD_INFO_V13, DATA_TABLES(LCD_Info));
1349 
1350 	if (!lvds)
1351 		return BP_RESULT_BADBIOSTABLE;
1352 
1353 	if (!((1 == lvds->sHeader.ucTableFormatRevision)
1354 			&& (3 <= lvds->sHeader.ucTableContentRevision)))
1355 		return BP_RESULT_UNSUPPORTED;
1356 
1357 	memset(info, 0, sizeof(struct embedded_panel_info));
1358 
1359 	/* We need to convert from 10KHz units into KHz units */
1360 	info->lcd_timing.pixel_clk =
1361 			le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
1362 	/* usHActive does not include borders, according to VBIOS team */
1363 	info->lcd_timing.horizontal_addressable =
1364 			le16_to_cpu(lvds->sLCDTiming.usHActive);
1365 	/* usHBlanking_Time includes borders, so we should really be subtracting
1366 	 * borders duing this translation, but LVDS generally*/
1367 	/* doesn't have borders, so we should be okay leaving this as is for
1368 	 * now.  May need to revisit if we ever have LVDS with borders*/
1369 	info->lcd_timing.horizontal_blanking_time =
1370 		le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
1371 	/* usVActive does not include borders, according to VBIOS team*/
1372 	info->lcd_timing.vertical_addressable =
1373 		le16_to_cpu(lvds->sLCDTiming.usVActive);
1374 	/* usVBlanking_Time includes borders, so we should really be subtracting
1375 	 * borders duing this translation, but LVDS generally*/
1376 	/* doesn't have borders, so we should be okay leaving this as is for
1377 	 * now. May need to revisit if we ever have LVDS with borders*/
1378 	info->lcd_timing.vertical_blanking_time =
1379 		le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
1380 	info->lcd_timing.horizontal_sync_offset =
1381 		le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
1382 	info->lcd_timing.horizontal_sync_width =
1383 		le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
1384 	info->lcd_timing.vertical_sync_offset =
1385 		le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
1386 	info->lcd_timing.vertical_sync_width =
1387 		le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
1388 	info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
1389 	info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
1390 	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
1391 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
1392 	info->lcd_timing.misc_info.H_SYNC_POLARITY =
1393 		~(uint32_t)
1394 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
1395 	info->lcd_timing.misc_info.V_SYNC_POLARITY =
1396 		~(uint32_t)
1397 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
1398 	info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
1399 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
1400 	info->lcd_timing.misc_info.H_REPLICATION_BY2 =
1401 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
1402 	info->lcd_timing.misc_info.V_REPLICATION_BY2 =
1403 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
1404 	info->lcd_timing.misc_info.COMPOSITE_SYNC =
1405 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
1406 	info->lcd_timing.misc_info.INTERLACE =
1407 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
1408 	info->lcd_timing.misc_info.DOUBLE_CLOCK =
1409 		lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
1410 	info->ss_id = lvds->ucSS_Id;
1411 
1412 	/* Drr panel support can be reported by VBIOS*/
1413 	if (LCDPANEL_CAP_V13_DRR_SUPPORTED
1414 			& lvds->ucLCDPanel_SpecialHandlingCap)
1415 		info->drr_enabled = 1;
1416 
1417 	/* Get supported refresh rate*/
1418 	if (info->drr_enabled == 1) {
1419 		uint8_t min_rr =
1420 				lvds->sRefreshRateSupport.ucMinRefreshRateForDRR;
1421 		uint8_t rr = lvds->sRefreshRateSupport.ucSupportedRefreshRate;
1422 
1423 		if (min_rr != 0) {
1424 			if (SUPPORTED_LCD_REFRESHRATE_30Hz & min_rr)
1425 				info->supported_rr.REFRESH_RATE_30HZ = 1;
1426 			else if (SUPPORTED_LCD_REFRESHRATE_40Hz & min_rr)
1427 				info->supported_rr.REFRESH_RATE_40HZ = 1;
1428 			else if (SUPPORTED_LCD_REFRESHRATE_48Hz & min_rr)
1429 				info->supported_rr.REFRESH_RATE_48HZ = 1;
1430 			else if (SUPPORTED_LCD_REFRESHRATE_50Hz & min_rr)
1431 				info->supported_rr.REFRESH_RATE_50HZ = 1;
1432 			else if (SUPPORTED_LCD_REFRESHRATE_60Hz & min_rr)
1433 				info->supported_rr.REFRESH_RATE_60HZ = 1;
1434 		} else {
1435 			if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
1436 				info->supported_rr.REFRESH_RATE_30HZ = 1;
1437 			else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
1438 				info->supported_rr.REFRESH_RATE_40HZ = 1;
1439 			else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
1440 				info->supported_rr.REFRESH_RATE_48HZ = 1;
1441 			else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
1442 				info->supported_rr.REFRESH_RATE_50HZ = 1;
1443 			else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
1444 				info->supported_rr.REFRESH_RATE_60HZ = 1;
1445 		}
1446 	}
1447 
1448 	if (ATOM_PANEL_MISC_V13_DUAL & lvds->ucLCD_Misc)
1449 		info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
1450 
1451 	if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR & lvds->ucLCD_Misc)
1452 		info->lcd_timing.misc_info.RGB888 = true;
1453 
1454 	info->lcd_timing.misc_info.GREY_LEVEL =
1455 			(uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL &
1456 				lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT;
1457 
1458 	return BP_RESULT_OK;
1459 }
1460 
1461 /**
1462  * bios_parser_get_encoder_cap_info - get encoder capability
1463  *                                    information of input object id
1464  *
1465  * @dcb:       pointer to the DC BIOS
1466  * @object_id: object id
1467  * @info:      encoder cap information structure
1468  *
1469  * return: Bios parser result code
1470  */
1471 static enum bp_result bios_parser_get_encoder_cap_info(
1472 	struct dc_bios *dcb,
1473 	struct graphics_object_id object_id,
1474 	struct bp_encoder_cap_info *info)
1475 {
1476 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1477 	ATOM_OBJECT *object;
1478 	ATOM_ENCODER_CAP_RECORD_V2 *record = NULL;
1479 
1480 	if (!info)
1481 		return BP_RESULT_BADINPUT;
1482 
1483 	object = get_bios_object(bp, object_id);
1484 
1485 	if (!object)
1486 		return BP_RESULT_BADINPUT;
1487 
1488 	record = get_encoder_cap_record(bp, object);
1489 	if (!record)
1490 		return BP_RESULT_NORECORD;
1491 
1492 	info->DP_HBR2_EN = record->usHBR2En;
1493 	info->DP_HBR3_EN = record->usHBR3En;
1494 	info->HDMI_6GB_EN = record->usHDMI6GEn;
1495 	return BP_RESULT_OK;
1496 }
1497 
1498 /**
1499  * get_encoder_cap_record - Get encoder cap record for the object
1500  *
1501  * @bp:      pointer to the BIOS parser
1502  * @object:  ATOM object
1503  * return:   atom encoder cap record
1504  * note:     search all records to find the ATOM_ENCODER_CAP_RECORD_V2 record
1505  */
1506 static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
1507 	struct bios_parser *bp,
1508 	ATOM_OBJECT *object)
1509 {
1510 	ATOM_COMMON_RECORD_HEADER *header;
1511 	uint32_t offset;
1512 
1513 	if (!object) {
1514 		BREAK_TO_DEBUGGER(); /* Invalid object */
1515 		return NULL;
1516 	}
1517 
1518 	offset = le16_to_cpu(object->usRecordOffset)
1519 					+ bp->object_info_tbl_offset;
1520 
1521 	for (;;) {
1522 		header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
1523 
1524 		if (!header)
1525 			return NULL;
1526 
1527 		offset += header->ucRecordSize;
1528 
1529 		if (LAST_RECORD_TYPE == header->ucRecordType ||
1530 				!header->ucRecordSize)
1531 			break;
1532 
1533 		if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType)
1534 			continue;
1535 
1536 		if (sizeof(ATOM_ENCODER_CAP_RECORD_V2) <= header->ucRecordSize)
1537 			return (ATOM_ENCODER_CAP_RECORD_V2 *)header;
1538 	}
1539 
1540 	return NULL;
1541 }
1542 
1543 static uint32_t get_ss_entry_number(
1544 	struct bios_parser *bp,
1545 	uint32_t id);
1546 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
1547 	struct bios_parser *bp,
1548 	uint32_t id);
1549 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1550 	struct bios_parser *bp,
1551 	uint32_t id);
1552 static uint32_t get_ss_entry_number_from_ss_info_tbl(
1553 	struct bios_parser *bp,
1554 	uint32_t id);
1555 
1556 /**
1557  * bios_parser_get_ss_entry_number
1558  * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from
1559  * the VBIOS that match the SSid (to be converted from signal)
1560  *
1561  * @dcb:    pointer to the DC BIOS
1562  * @signal: ASSignalType to be converted to SSid
1563  * return: number of SS Entry that match the signal
1564  */
1565 static uint32_t bios_parser_get_ss_entry_number(
1566 	struct dc_bios *dcb,
1567 	enum as_signal_type signal)
1568 {
1569 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1570 	uint32_t ss_id = 0;
1571 	ATOM_COMMON_TABLE_HEADER *header;
1572 	struct atom_data_revision revision;
1573 
1574 	ss_id = signal_to_ss_id(signal);
1575 
1576 	if (!DATA_TABLES(ASIC_InternalSS_Info))
1577 		return get_ss_entry_number_from_ss_info_tbl(bp, ss_id);
1578 
1579 	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
1580 			DATA_TABLES(ASIC_InternalSS_Info));
1581 	get_atom_data_table_revision(header, &revision);
1582 
1583 	switch (revision.major) {
1584 	case 2:
1585 		switch (revision.minor) {
1586 		case 1:
1587 			return get_ss_entry_number(bp, ss_id);
1588 		default:
1589 			break;
1590 		}
1591 		break;
1592 	case 3:
1593 		switch (revision.minor) {
1594 		case 1:
1595 			return
1596 				get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1597 						bp, ss_id);
1598 		default:
1599 			break;
1600 		}
1601 		break;
1602 	default:
1603 		break;
1604 	}
1605 
1606 	return 0;
1607 }
1608 
1609 /**
1610  * get_ss_entry_number_from_ss_info_tbl
1611  * Get Number of spread spectrum entry from the SS_Info table from the VBIOS.
1612  *
1613  * @bp:  pointer to the BIOS parser
1614  * @id:  spread spectrum id
1615  * return: number of SS Entry that match the id
1616  * note: There can only be one entry for each id for SS_Info Table
1617  */
1618 static uint32_t get_ss_entry_number_from_ss_info_tbl(
1619 	struct bios_parser *bp,
1620 	uint32_t id)
1621 {
1622 	ATOM_SPREAD_SPECTRUM_INFO *tbl;
1623 	ATOM_COMMON_TABLE_HEADER *header;
1624 	uint32_t table_size;
1625 	uint32_t i;
1626 	uint32_t number = 0;
1627 	uint32_t id_local = SS_ID_UNKNOWN;
1628 	struct atom_data_revision revision;
1629 
1630 	/* SS_Info table exist */
1631 	if (!DATA_TABLES(SS_Info))
1632 		return number;
1633 
1634 	header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
1635 			DATA_TABLES(SS_Info));
1636 	get_atom_data_table_revision(header, &revision);
1637 
1638 	tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO,
1639 			DATA_TABLES(SS_Info));
1640 
1641 	if (1 != revision.major || 2 > revision.minor)
1642 		return number;
1643 
1644 	/* have to convert from Internal_SS format to SS_Info format */
1645 	switch (id) {
1646 	case ASIC_INTERNAL_SS_ON_DP:
1647 		id_local = SS_ID_DP1;
1648 		break;
1649 	case ASIC_INTERNAL_SS_ON_LVDS: {
1650 		struct embedded_panel_info panel_info;
1651 
1652 		if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
1653 				== BP_RESULT_OK)
1654 			id_local = panel_info.ss_id;
1655 		break;
1656 	}
1657 	default:
1658 		break;
1659 	}
1660 
1661 	if (id_local == SS_ID_UNKNOWN)
1662 		return number;
1663 
1664 	table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
1665 			sizeof(ATOM_COMMON_TABLE_HEADER)) /
1666 					sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
1667 
1668 	for (i = 0; i < table_size; i++)
1669 		if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) {
1670 			number = 1;
1671 			break;
1672 		}
1673 
1674 	return number;
1675 }
1676 
1677 /**
1678  * get_ss_entry_number
1679  * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
1680  * SS_Info table from the VBIOS
1681  * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or
1682  * SS_Info.
1683  *
1684  * @bp:    pointer to the BIOS parser
1685  * @id:    spread sprectrum info index
1686  * return: Bios parser result code
1687  */
1688 static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id)
1689 {
1690 	if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
1691 		return get_ss_entry_number_from_ss_info_tbl(bp, id);
1692 
1693 	return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id);
1694 }
1695 
1696 /**
1697  * get_ss_entry_number_from_internal_ss_info_tbl_v2_1
1698  * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table
1699  * Ver 2.1 from the VBIOS
1700  * There will not be multiple entry for Ver 2.1
1701  *
1702  * @bp:    pointer to the BIOS parser
1703  * @id:    spread sprectrum info index
1704  * return: number of SS Entry that match the id
1705  */
1706 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
1707 	struct bios_parser *bp,
1708 	uint32_t id)
1709 {
1710 	ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include;
1711 	ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
1712 	uint32_t size;
1713 	uint32_t i;
1714 
1715 	if (!DATA_TABLES(ASIC_InternalSS_Info))
1716 		return 0;
1717 
1718 	header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V2 *) bios_get_image(
1719 				&bp->base,
1720 				DATA_TABLES(ASIC_InternalSS_Info),
1721 				struct_size(header_include, asSpreadSpectrum, 1)));
1722 
1723 	size = (le16_to_cpu(header_include->sHeader.usStructureSize)
1724 			- sizeof(ATOM_COMMON_TABLE_HEADER))
1725 						/ sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
1726 
1727 	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
1728 				&header_include->asSpreadSpectrum[0];
1729 	for (i = 0; i < size; i++)
1730 		if (tbl[i].ucClockIndication == (uint8_t)id)
1731 			return 1;
1732 
1733 	return 0;
1734 }
1735 /**
1736  * get_ss_entry_number_from_internal_ss_info_tbl_V3_1
1737  * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of
1738  * the VBIOS that matches id
1739  *
1740  * @bp:    pointer to the BIOS parser
1741  * @id:    spread sprectrum id
1742  * return: number of SS Entry that match the id
1743  */
1744 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1745 	struct bios_parser *bp,
1746 	uint32_t id)
1747 {
1748 	uint32_t number = 0;
1749 	ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include;
1750 	ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
1751 	uint32_t size;
1752 	uint32_t i;
1753 
1754 	if (!DATA_TABLES(ASIC_InternalSS_Info))
1755 		return number;
1756 
1757 	header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V3 *) bios_get_image(&bp->base,
1758 				DATA_TABLES(ASIC_InternalSS_Info),
1759 				struct_size(header_include, asSpreadSpectrum, 1)));
1760 	size = (le16_to_cpu(header_include->sHeader.usStructureSize) -
1761 			sizeof(ATOM_COMMON_TABLE_HEADER)) /
1762 					sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
1763 
1764 	tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
1765 				&header_include->asSpreadSpectrum[0];
1766 
1767 	for (i = 0; i < size; i++)
1768 		if (tbl[i].ucClockIndication == (uint8_t)id)
1769 			number++;
1770 
1771 	return number;
1772 }
1773 
1774 /**
1775  * bios_parser_get_gpio_pin_info
1776  * Get GpioPin information of input gpio id
1777  *
1778  * @dcb:     pointer to the DC BIOS
1779  * @gpio_id: GPIO ID
1780  * @info:    GpioPin information structure
1781  * return:   Bios parser result code
1782  * note:
1783  *  to get the GPIO PIN INFO, we need:
1784  *  1. get the GPIO_ID from other object table, see GetHPDInfo()
1785  *  2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA
1786  *  offset/mask
1787  */
1788 static enum bp_result bios_parser_get_gpio_pin_info(
1789 	struct dc_bios *dcb,
1790 	uint32_t gpio_id,
1791 	struct gpio_pin_info *info)
1792 {
1793 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1794 	ATOM_GPIO_PIN_LUT *header;
1795 	uint32_t count = 0;
1796 	uint32_t i = 0;
1797 
1798 	if (!DATA_TABLES(GPIO_Pin_LUT))
1799 		return BP_RESULT_BADBIOSTABLE;
1800 
1801 	header = ((ATOM_GPIO_PIN_LUT *) bios_get_image(&bp->base,
1802 				DATA_TABLES(GPIO_Pin_LUT),
1803 				struct_size(header, asGPIO_Pin, 1)));
1804 	if (!header)
1805 		return BP_RESULT_BADBIOSTABLE;
1806 
1807 	if (sizeof(ATOM_COMMON_TABLE_HEADER) + struct_size(header, asGPIO_Pin, 1)
1808 			> le16_to_cpu(header->sHeader.usStructureSize))
1809 		return BP_RESULT_BADBIOSTABLE;
1810 
1811 	if (1 != header->sHeader.ucTableContentRevision)
1812 		return BP_RESULT_UNSUPPORTED;
1813 
1814 	count = (le16_to_cpu(header->sHeader.usStructureSize)
1815 			- sizeof(ATOM_COMMON_TABLE_HEADER))
1816 				/ sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
1817 	for (i = 0; i < count; ++i) {
1818 		if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id)
1819 			continue;
1820 
1821 		info->offset =
1822 			(uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex);
1823 		info->offset_y = info->offset + 2;
1824 		info->offset_en = info->offset + 1;
1825 		info->offset_mask = info->offset - 1;
1826 
1827 		info->mask = (uint32_t) (1 <<
1828 			header->asGPIO_Pin[i].ucGpioPinBitShift);
1829 		info->mask_y = info->mask + 2;
1830 		info->mask_en = info->mask + 1;
1831 		info->mask_mask = info->mask - 1;
1832 
1833 		return BP_RESULT_OK;
1834 	}
1835 
1836 	return BP_RESULT_NORECORD;
1837 }
1838 
1839 static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
1840 	ATOM_I2C_RECORD *record,
1841 	struct graphics_object_i2c_info *info)
1842 {
1843 	ATOM_GPIO_I2C_INFO *header;
1844 	uint32_t count = 0;
1845 
1846 	if (!info)
1847 		return BP_RESULT_BADINPUT;
1848 
1849 	/* get the GPIO_I2C info */
1850 	if (!DATA_TABLES(GPIO_I2C_Info))
1851 		return BP_RESULT_BADBIOSTABLE;
1852 
1853 	header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info));
1854 	if (!header)
1855 		return BP_RESULT_BADBIOSTABLE;
1856 
1857 	if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT)
1858 			> le16_to_cpu(header->sHeader.usStructureSize))
1859 		return BP_RESULT_BADBIOSTABLE;
1860 
1861 	if (1 != header->sHeader.ucTableContentRevision)
1862 		return BP_RESULT_UNSUPPORTED;
1863 
1864 	/* get data count */
1865 	count = (le16_to_cpu(header->sHeader.usStructureSize)
1866 			- sizeof(ATOM_COMMON_TABLE_HEADER))
1867 				/ sizeof(ATOM_GPIO_I2C_ASSIGMENT);
1868 	if (count < record->sucI2cId.bfI2C_LineMux)
1869 		return BP_RESULT_BADBIOSTABLE;
1870 
1871 	/* get the GPIO_I2C_INFO */
1872 	info->i2c_hw_assist = record->sucI2cId.bfHW_Capable;
1873 	info->i2c_line = record->sucI2cId.bfI2C_LineMux;
1874 	info->i2c_engine_id = record->sucI2cId.bfHW_EngineID;
1875 	info->i2c_slave_address = record->ucI2CAddr;
1876 
1877 	info->gpio_info.clk_mask_register_index =
1878 			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex);
1879 	info->gpio_info.clk_en_register_index =
1880 			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex);
1881 	info->gpio_info.clk_y_register_index =
1882 			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex);
1883 	info->gpio_info.clk_a_register_index =
1884 			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex);
1885 	info->gpio_info.data_mask_register_index =
1886 			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex);
1887 	info->gpio_info.data_en_register_index =
1888 			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex);
1889 	info->gpio_info.data_y_register_index =
1890 			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex);
1891 	info->gpio_info.data_a_register_index =
1892 			le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex);
1893 
1894 	info->gpio_info.clk_mask_shift =
1895 			header->asGPIO_Info[info->i2c_line].ucClkMaskShift;
1896 	info->gpio_info.clk_en_shift =
1897 			header->asGPIO_Info[info->i2c_line].ucClkEnShift;
1898 	info->gpio_info.clk_y_shift =
1899 			header->asGPIO_Info[info->i2c_line].ucClkY_Shift;
1900 	info->gpio_info.clk_a_shift =
1901 			header->asGPIO_Info[info->i2c_line].ucClkA_Shift;
1902 	info->gpio_info.data_mask_shift =
1903 			header->asGPIO_Info[info->i2c_line].ucDataMaskShift;
1904 	info->gpio_info.data_en_shift =
1905 			header->asGPIO_Info[info->i2c_line].ucDataEnShift;
1906 	info->gpio_info.data_y_shift =
1907 			header->asGPIO_Info[info->i2c_line].ucDataY_Shift;
1908 	info->gpio_info.data_a_shift =
1909 			header->asGPIO_Info[info->i2c_line].ucDataA_Shift;
1910 
1911 	return BP_RESULT_OK;
1912 }
1913 
1914 static bool dal_graphics_object_id_is_valid(struct graphics_object_id id)
1915 {
1916 	bool rc = true;
1917 
1918 	switch (id.type) {
1919 	case OBJECT_TYPE_UNKNOWN:
1920 		rc = false;
1921 		break;
1922 	case OBJECT_TYPE_GPU:
1923 	case OBJECT_TYPE_ENGINE:
1924 		/* do NOT check for id.id == 0 */
1925 		if (id.enum_id == ENUM_ID_UNKNOWN)
1926 			rc = false;
1927 		break;
1928 	default:
1929 		if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN)
1930 			rc = false;
1931 		break;
1932 	}
1933 
1934 	return rc;
1935 }
1936 
1937 static bool dal_graphics_object_id_is_equal(
1938 	struct graphics_object_id id1,
1939 	struct graphics_object_id id2)
1940 {
1941 	if (false == dal_graphics_object_id_is_valid(id1)) {
1942 		dm_output_to_console(
1943 		"%s: Warning: comparing invalid object 'id1'!\n", __func__);
1944 		return false;
1945 	}
1946 
1947 	if (false == dal_graphics_object_id_is_valid(id2)) {
1948 		dm_output_to_console(
1949 		"%s: Warning: comparing invalid object 'id2'!\n", __func__);
1950 		return false;
1951 	}
1952 
1953 	if (id1.id == id2.id && id1.enum_id == id2.enum_id
1954 		&& id1.type == id2.type)
1955 		return true;
1956 
1957 	return false;
1958 }
1959 
1960 static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
1961 	struct graphics_object_id id)
1962 {
1963 	uint32_t offset;
1964 	ATOM_OBJECT_TABLE *tbl;
1965 	uint32_t i;
1966 
1967 	switch (id.type) {
1968 	case OBJECT_TYPE_ENCODER:
1969 		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
1970 		break;
1971 
1972 	case OBJECT_TYPE_CONNECTOR:
1973 		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
1974 		break;
1975 
1976 	case OBJECT_TYPE_ROUTER:
1977 		offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset);
1978 		break;
1979 
1980 	case OBJECT_TYPE_GENERIC:
1981 		if (bp->object_info_tbl.revision.minor < 3)
1982 			return NULL;
1983 		offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset);
1984 		break;
1985 
1986 	default:
1987 		return NULL;
1988 	}
1989 
1990 	offset += bp->object_info_tbl_offset;
1991 
1992 	tbl = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base, offset,
1993 				struct_size(tbl, asObjects, 1)));
1994 	if (!tbl)
1995 		return NULL;
1996 
1997 	for (i = 0; i < tbl->ucNumberOfObjects; i++)
1998 		if (dal_graphics_object_id_is_equal(id,
1999 				object_id_from_bios_object_id(
2000 						le16_to_cpu(tbl->asObjects[i].usObjectID))))
2001 			return &tbl->asObjects[i];
2002 
2003 	return NULL;
2004 }
2005 
2006 static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
2007 	uint16_t **id_list)
2008 {
2009 	uint32_t offset;
2010 	uint8_t *number;
2011 
2012 	if (!object) {
2013 		BREAK_TO_DEBUGGER(); /* Invalid object id */
2014 		return 0;
2015 	}
2016 
2017 	offset = le16_to_cpu(object->usSrcDstTableOffset)
2018 					+ bp->object_info_tbl_offset;
2019 
2020 	number = GET_IMAGE(uint8_t, offset);
2021 	if (!number)
2022 		return 0;
2023 
2024 	offset += sizeof(uint8_t);
2025 	*id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t));
2026 
2027 	if (!*id_list)
2028 		return 0;
2029 
2030 	return *number;
2031 }
2032 
2033 static struct device_id device_type_from_device_id(uint16_t device_id)
2034 {
2035 
2036 	struct device_id result_device_id = {0};
2037 
2038 	switch (device_id) {
2039 	case ATOM_DEVICE_LCD1_SUPPORT:
2040 		result_device_id.device_type = DEVICE_TYPE_LCD;
2041 		result_device_id.enum_id = 1;
2042 		break;
2043 
2044 	case ATOM_DEVICE_LCD2_SUPPORT:
2045 		result_device_id.device_type = DEVICE_TYPE_LCD;
2046 		result_device_id.enum_id = 2;
2047 		break;
2048 
2049 	case ATOM_DEVICE_CRT1_SUPPORT:
2050 		result_device_id.device_type = DEVICE_TYPE_CRT;
2051 		result_device_id.enum_id = 1;
2052 		break;
2053 
2054 	case ATOM_DEVICE_CRT2_SUPPORT:
2055 		result_device_id.device_type = DEVICE_TYPE_CRT;
2056 		result_device_id.enum_id = 2;
2057 		break;
2058 
2059 	case ATOM_DEVICE_DFP1_SUPPORT:
2060 		result_device_id.device_type = DEVICE_TYPE_DFP;
2061 		result_device_id.enum_id = 1;
2062 		break;
2063 
2064 	case ATOM_DEVICE_DFP2_SUPPORT:
2065 		result_device_id.device_type = DEVICE_TYPE_DFP;
2066 		result_device_id.enum_id = 2;
2067 		break;
2068 
2069 	case ATOM_DEVICE_DFP3_SUPPORT:
2070 		result_device_id.device_type = DEVICE_TYPE_DFP;
2071 		result_device_id.enum_id = 3;
2072 		break;
2073 
2074 	case ATOM_DEVICE_DFP4_SUPPORT:
2075 		result_device_id.device_type = DEVICE_TYPE_DFP;
2076 		result_device_id.enum_id = 4;
2077 		break;
2078 
2079 	case ATOM_DEVICE_DFP5_SUPPORT:
2080 		result_device_id.device_type = DEVICE_TYPE_DFP;
2081 		result_device_id.enum_id = 5;
2082 		break;
2083 
2084 	case ATOM_DEVICE_DFP6_SUPPORT:
2085 		result_device_id.device_type = DEVICE_TYPE_DFP;
2086 		result_device_id.enum_id = 6;
2087 		break;
2088 
2089 	default:
2090 		BREAK_TO_DEBUGGER(); /* Invalid device Id */
2091 		result_device_id.device_type = DEVICE_TYPE_UNKNOWN;
2092 		result_device_id.enum_id = 0;
2093 	}
2094 	return result_device_id;
2095 }
2096 
2097 static void get_atom_data_table_revision(
2098 	ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
2099 	struct atom_data_revision *tbl_revision)
2100 {
2101 	if (!tbl_revision)
2102 		return;
2103 
2104 	/* initialize the revision to 0 which is invalid revision */
2105 	tbl_revision->major = 0;
2106 	tbl_revision->minor = 0;
2107 
2108 	if (!atom_data_tbl)
2109 		return;
2110 
2111 	tbl_revision->major =
2112 			(uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl);
2113 	tbl_revision->minor =
2114 			(uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl);
2115 }
2116 
2117 static uint32_t signal_to_ss_id(enum as_signal_type signal)
2118 {
2119 	uint32_t clk_id_ss = 0;
2120 
2121 	switch (signal) {
2122 	case AS_SIGNAL_TYPE_DVI:
2123 		clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS;
2124 		break;
2125 	case AS_SIGNAL_TYPE_HDMI:
2126 		clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI;
2127 		break;
2128 	case AS_SIGNAL_TYPE_LVDS:
2129 		clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS;
2130 		break;
2131 	case AS_SIGNAL_TYPE_DISPLAY_PORT:
2132 		clk_id_ss = ASIC_INTERNAL_SS_ON_DP;
2133 		break;
2134 	case AS_SIGNAL_TYPE_GPU_PLL:
2135 		clk_id_ss = ASIC_INTERNAL_GPUPLL_SS;
2136 		break;
2137 	default:
2138 		break;
2139 	}
2140 	return clk_id_ss;
2141 }
2142 
2143 static uint32_t get_support_mask_for_device_id(struct device_id device_id)
2144 {
2145 	enum dal_device_type device_type = device_id.device_type;
2146 	uint32_t enum_id = device_id.enum_id;
2147 
2148 	switch (device_type) {
2149 	case DEVICE_TYPE_LCD:
2150 		switch (enum_id) {
2151 		case 1:
2152 			return ATOM_DEVICE_LCD1_SUPPORT;
2153 		case 2:
2154 			return ATOM_DEVICE_LCD2_SUPPORT;
2155 		default:
2156 			break;
2157 		}
2158 		break;
2159 	case DEVICE_TYPE_CRT:
2160 		switch (enum_id) {
2161 		case 1:
2162 			return ATOM_DEVICE_CRT1_SUPPORT;
2163 		case 2:
2164 			return ATOM_DEVICE_CRT2_SUPPORT;
2165 		default:
2166 			break;
2167 		}
2168 		break;
2169 	case DEVICE_TYPE_DFP:
2170 		switch (enum_id) {
2171 		case 1:
2172 			return ATOM_DEVICE_DFP1_SUPPORT;
2173 		case 2:
2174 			return ATOM_DEVICE_DFP2_SUPPORT;
2175 		case 3:
2176 			return ATOM_DEVICE_DFP3_SUPPORT;
2177 		case 4:
2178 			return ATOM_DEVICE_DFP4_SUPPORT;
2179 		case 5:
2180 			return ATOM_DEVICE_DFP5_SUPPORT;
2181 		case 6:
2182 			return ATOM_DEVICE_DFP6_SUPPORT;
2183 		default:
2184 			break;
2185 		}
2186 		break;
2187 	case DEVICE_TYPE_CV:
2188 		switch (enum_id) {
2189 		case 1:
2190 			return ATOM_DEVICE_CV_SUPPORT;
2191 		default:
2192 			break;
2193 		}
2194 		break;
2195 	case DEVICE_TYPE_TV:
2196 		switch (enum_id) {
2197 		case 1:
2198 			return ATOM_DEVICE_TV1_SUPPORT;
2199 		default:
2200 			break;
2201 		}
2202 		break;
2203 	default:
2204 		break;
2205 	}
2206 
2207 	/* Unidentified device ID, return empty support mask. */
2208 	return 0;
2209 }
2210 
2211 /**
2212  * bios_parser_set_scratch_critical_state - update critical state
2213  *                                          bit in VBIOS scratch register
2214  * @dcb:    pointer to the DC BIOS
2215  * @state:  set or reset state
2216  */
2217 static void bios_parser_set_scratch_critical_state(
2218 	struct dc_bios *dcb,
2219 	bool state)
2220 {
2221 	bios_set_scratch_critical_state(dcb, state);
2222 }
2223 
2224 /*
2225  * get_integrated_info_v8
2226  *
2227  * @brief
2228  * Get V8 integrated BIOS information
2229  *
2230  * @param
2231  * bios_parser *bp - [in]BIOS parser handler to get master data table
2232  * integrated_info *info - [out] store and output integrated info
2233  *
2234  * return:
2235  * enum bp_result - BP_RESULT_OK if information is available,
2236  *                  BP_RESULT_BADBIOSTABLE otherwise.
2237  */
2238 static enum bp_result get_integrated_info_v8(
2239 	struct bios_parser *bp,
2240 	struct integrated_info *info)
2241 {
2242 	ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8;
2243 	uint32_t i;
2244 
2245 	info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8,
2246 			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
2247 
2248 	if (info_v8 == NULL)
2249 		return BP_RESULT_BADBIOSTABLE;
2250 	info->boot_up_engine_clock = le32_to_cpu(info_v8->ulBootUpEngineClock) * 10;
2251 	info->dentist_vco_freq = le32_to_cpu(info_v8->ulDentistVCOFreq) * 10;
2252 	info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
2253 
2254 	for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2255 		/* Convert [10KHz] into [KHz] */
2256 		info->disp_clk_voltage[i].max_supported_clk =
2257 			le32_to_cpu(info_v8->sDISPCLK_Voltage[i].
2258 				    ulMaximumSupportedCLK) * 10;
2259 		info->disp_clk_voltage[i].voltage_index =
2260 			le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex);
2261 	}
2262 
2263 	info->boot_up_req_display_vector =
2264 		le32_to_cpu(info_v8->ulBootUpReqDisplayVector);
2265 	info->gpu_cap_info =
2266 		le32_to_cpu(info_v8->ulGPUCapInfo);
2267 
2268 	/*
2269 	 * system_config: Bit[0] = 0 : PCIE power gating disabled
2270 	 *                       = 1 : PCIE power gating enabled
2271 	 *                Bit[1] = 0 : DDR-PLL shut down disabled
2272 	 *                       = 1 : DDR-PLL shut down enabled
2273 	 *                Bit[2] = 0 : DDR-PLL power down disabled
2274 	 *                       = 1 : DDR-PLL power down enabled
2275 	 */
2276 	info->system_config = le32_to_cpu(info_v8->ulSystemConfig);
2277 	info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo);
2278 	info->boot_up_nb_voltage =
2279 		le16_to_cpu(info_v8->usBootUpNBVoltage);
2280 	info->ext_disp_conn_info_offset =
2281 		le16_to_cpu(info_v8->usExtDispConnInfoOffset);
2282 	info->memory_type = info_v8->ucMemoryType;
2283 	info->ma_channel_number = info_v8->ucUMAChannelNumber;
2284 	info->gmc_restore_reset_time =
2285 		le32_to_cpu(info_v8->ulGMCRestoreResetTime);
2286 
2287 	info->minimum_n_clk =
2288 		le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]);
2289 	for (i = 1; i < 4; ++i)
2290 		info->minimum_n_clk =
2291 			info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ?
2292 			info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]);
2293 
2294 	info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk);
2295 	info->ddr_dll_power_up_time =
2296 		le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime);
2297 	info->ddr_pll_power_up_time =
2298 		le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime);
2299 	info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType);
2300 	info->lvds_ss_percentage =
2301 		le16_to_cpu(info_v8->usLvdsSSPercentage);
2302 	info->lvds_sspread_rate_in_10hz =
2303 		le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz);
2304 	info->hdmi_ss_percentage =
2305 		le16_to_cpu(info_v8->usHDMISSPercentage);
2306 	info->hdmi_sspread_rate_in_10hz =
2307 		le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz);
2308 	info->dvi_ss_percentage =
2309 		le16_to_cpu(info_v8->usDVISSPercentage);
2310 	info->dvi_sspread_rate_in_10_hz =
2311 		le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz);
2312 
2313 	info->max_lvds_pclk_freq_in_single_link =
2314 		le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink);
2315 	info->lvds_misc = info_v8->ucLvdsMisc;
2316 	info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
2317 		info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
2318 	info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
2319 		info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
2320 	info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
2321 		info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
2322 	info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
2323 		info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
2324 	info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
2325 		info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
2326 	info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
2327 		info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
2328 	info->lvds_off_to_on_delay_in_4ms =
2329 		info_v8->ucLVDSOffToOnDelay_in4Ms;
2330 	info->lvds_bit_depth_control_val =
2331 		le32_to_cpu(info_v8->ulLCDBitDepthControlVal);
2332 
2333 	for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
2334 		/* Convert [10KHz] into [KHz] */
2335 		info->avail_s_clk[i].supported_s_clk =
2336 			le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10;
2337 		info->avail_s_clk[i].voltage_index =
2338 			le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex);
2339 		info->avail_s_clk[i].voltage_id =
2340 			le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID);
2341 	}
2342 
2343 	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2344 		info->ext_disp_conn_info.gu_id[i] =
2345 			info_v8->sExtDispConnInfo.ucGuid[i];
2346 	}
2347 
2348 	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2349 		info->ext_disp_conn_info.path[i].device_connector_id =
2350 			object_id_from_bios_object_id(
2351 				le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector));
2352 
2353 		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2354 			object_id_from_bios_object_id(
2355 				le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
2356 
2357 		info->ext_disp_conn_info.path[i].device_tag =
2358 			le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag);
2359 		info->ext_disp_conn_info.path[i].device_acpi_enum =
2360 			le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
2361 		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2362 			info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
2363 		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2364 			info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
2365 		info->ext_disp_conn_info.path[i].channel_mapping.raw =
2366 			info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping;
2367 	}
2368 	info->ext_disp_conn_info.checksum =
2369 		info_v8->sExtDispConnInfo.ucChecksum;
2370 
2371 	return BP_RESULT_OK;
2372 }
2373 
2374 /*
2375  * get_integrated_info_v8
2376  *
2377  * @brief
2378  * Get V8 integrated BIOS information
2379  *
2380  * @param
2381  * bios_parser *bp - [in]BIOS parser handler to get master data table
2382  * integrated_info *info - [out] store and output integrated info
2383  *
2384  * return:
2385  * enum bp_result - BP_RESULT_OK if information is available,
2386  *                  BP_RESULT_BADBIOSTABLE otherwise.
2387  */
2388 static enum bp_result get_integrated_info_v9(
2389 	struct bios_parser *bp,
2390 	struct integrated_info *info)
2391 {
2392 	ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9;
2393 	uint32_t i;
2394 
2395 	info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9,
2396 			bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
2397 
2398 	if (!info_v9)
2399 		return BP_RESULT_BADBIOSTABLE;
2400 
2401 	info->boot_up_engine_clock = le32_to_cpu(info_v9->ulBootUpEngineClock) * 10;
2402 	info->dentist_vco_freq = le32_to_cpu(info_v9->ulDentistVCOFreq) * 10;
2403 	info->boot_up_uma_clock = le32_to_cpu(info_v9->ulBootUpUMAClock) * 10;
2404 
2405 	for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2406 		/* Convert [10KHz] into [KHz] */
2407 		info->disp_clk_voltage[i].max_supported_clk =
2408 			le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10;
2409 		info->disp_clk_voltage[i].voltage_index =
2410 			le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex);
2411 	}
2412 
2413 	info->boot_up_req_display_vector =
2414 		le32_to_cpu(info_v9->ulBootUpReqDisplayVector);
2415 	info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo);
2416 
2417 	/*
2418 	 * system_config: Bit[0] = 0 : PCIE power gating disabled
2419 	 *                       = 1 : PCIE power gating enabled
2420 	 *                Bit[1] = 0 : DDR-PLL shut down disabled
2421 	 *                       = 1 : DDR-PLL shut down enabled
2422 	 *                Bit[2] = 0 : DDR-PLL power down disabled
2423 	 *                       = 1 : DDR-PLL power down enabled
2424 	 */
2425 	info->system_config = le32_to_cpu(info_v9->ulSystemConfig);
2426 	info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo);
2427 	info->boot_up_nb_voltage = le16_to_cpu(info_v9->usBootUpNBVoltage);
2428 	info->ext_disp_conn_info_offset = le16_to_cpu(info_v9->usExtDispConnInfoOffset);
2429 	info->memory_type = info_v9->ucMemoryType;
2430 	info->ma_channel_number = info_v9->ucUMAChannelNumber;
2431 	info->gmc_restore_reset_time = le32_to_cpu(info_v9->ulGMCRestoreResetTime);
2432 
2433 	info->minimum_n_clk = le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]);
2434 	for (i = 1; i < 4; ++i)
2435 		info->minimum_n_clk =
2436 			info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ?
2437 			info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]);
2438 
2439 	info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk);
2440 	info->ddr_dll_power_up_time = le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime);
2441 	info->ddr_pll_power_up_time = le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime);
2442 	info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType);
2443 	info->lvds_ss_percentage = le16_to_cpu(info_v9->usLvdsSSPercentage);
2444 	info->lvds_sspread_rate_in_10hz = le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz);
2445 	info->hdmi_ss_percentage = le16_to_cpu(info_v9->usHDMISSPercentage);
2446 	info->hdmi_sspread_rate_in_10hz = le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz);
2447 	info->dvi_ss_percentage = le16_to_cpu(info_v9->usDVISSPercentage);
2448 	info->dvi_sspread_rate_in_10_hz = le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz);
2449 
2450 	info->max_lvds_pclk_freq_in_single_link =
2451 		le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink);
2452 	info->lvds_misc = info_v9->ucLvdsMisc;
2453 	info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
2454 		info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
2455 	info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
2456 		info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
2457 	info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
2458 		info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
2459 	info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
2460 		info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
2461 	info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
2462 		info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
2463 	info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
2464 		info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
2465 	info->lvds_off_to_on_delay_in_4ms =
2466 		info_v9->ucLVDSOffToOnDelay_in4Ms;
2467 	info->lvds_bit_depth_control_val =
2468 		le32_to_cpu(info_v9->ulLCDBitDepthControlVal);
2469 
2470 	for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
2471 		/* Convert [10KHz] into [KHz] */
2472 		info->avail_s_clk[i].supported_s_clk =
2473 			le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10;
2474 		info->avail_s_clk[i].voltage_index =
2475 			le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex);
2476 		info->avail_s_clk[i].voltage_id =
2477 			le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID);
2478 	}
2479 
2480 	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2481 		info->ext_disp_conn_info.gu_id[i] =
2482 			info_v9->sExtDispConnInfo.ucGuid[i];
2483 	}
2484 
2485 	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2486 		info->ext_disp_conn_info.path[i].device_connector_id =
2487 			object_id_from_bios_object_id(
2488 				le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector));
2489 
2490 		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2491 			object_id_from_bios_object_id(
2492 				le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
2493 
2494 		info->ext_disp_conn_info.path[i].device_tag =
2495 			le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag);
2496 		info->ext_disp_conn_info.path[i].device_acpi_enum =
2497 			le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
2498 		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2499 			info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
2500 		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2501 			info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
2502 		info->ext_disp_conn_info.path[i].channel_mapping.raw =
2503 			info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping;
2504 	}
2505 	info->ext_disp_conn_info.checksum =
2506 		info_v9->sExtDispConnInfo.ucChecksum;
2507 
2508 	return BP_RESULT_OK;
2509 }
2510 
2511 /*
2512  * construct_integrated_info
2513  *
2514  * @brief
2515  * Get integrated BIOS information based on table revision
2516  *
2517  * @param
2518  * bios_parser *bp - [in]BIOS parser handler to get master data table
2519  * integrated_info *info - [out] store and output integrated info
2520  *
2521  * return:
2522  * enum bp_result - BP_RESULT_OK if information is available,
2523  *                  BP_RESULT_BADBIOSTABLE otherwise.
2524  */
2525 static enum bp_result construct_integrated_info(
2526 	struct bios_parser *bp,
2527 	struct integrated_info *info)
2528 {
2529 	enum bp_result result = BP_RESULT_BADBIOSTABLE;
2530 
2531 	ATOM_COMMON_TABLE_HEADER *header;
2532 	struct atom_data_revision revision;
2533 
2534 	if (bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) {
2535 		header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
2536 				bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
2537 
2538 		get_atom_data_table_revision(header, &revision);
2539 
2540 		/* Don't need to check major revision as they are all 1 */
2541 		switch (revision.minor) {
2542 		case 8:
2543 			result = get_integrated_info_v8(bp, info);
2544 			break;
2545 		case 9:
2546 			result = get_integrated_info_v9(bp, info);
2547 			break;
2548 		default:
2549 			return result;
2550 
2551 		}
2552 	}
2553 
2554 	/* Sort voltage table from low to high*/
2555 	if (result == BP_RESULT_OK) {
2556 		uint32_t i;
2557 		uint32_t j;
2558 
2559 		for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2560 			for (j = i; j > 0; --j) {
2561 				if (
2562 						info->disp_clk_voltage[j].max_supported_clk <
2563 						info->disp_clk_voltage[j-1].max_supported_clk) {
2564 					/* swap j and j - 1*/
2565 					swap(info->disp_clk_voltage[j - 1],
2566 					     info->disp_clk_voltage[j]);
2567 				}
2568 			}
2569 		}
2570 
2571 	}
2572 
2573 	return result;
2574 }
2575 
2576 static struct integrated_info *bios_parser_create_integrated_info(
2577 	struct dc_bios *dcb)
2578 {
2579 	struct bios_parser *bp = BP_FROM_DCB(dcb);
2580 	struct integrated_info *info = NULL;
2581 
2582 	info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL);
2583 
2584 	if (info == NULL) {
2585 		ASSERT_CRITICAL(0);
2586 		return NULL;
2587 	}
2588 
2589 	if (construct_integrated_info(bp, info) == BP_RESULT_OK)
2590 		return info;
2591 
2592 	kfree(info);
2593 
2594 	return NULL;
2595 }
2596 
2597 static enum bp_result update_slot_layout_info(
2598 	struct dc_bios *dcb,
2599 	unsigned int i,
2600 	struct slot_layout_info *slot_layout_info,
2601 	unsigned int record_offset)
2602 {
2603 	unsigned int j;
2604 	struct bios_parser *bp;
2605 	ATOM_BRACKET_LAYOUT_RECORD *record;
2606 	ATOM_COMMON_RECORD_HEADER *record_header;
2607 	enum bp_result result = BP_RESULT_NORECORD;
2608 
2609 	bp = BP_FROM_DCB(dcb);
2610 	record = NULL;
2611 	record_header = NULL;
2612 
2613 	for (;;) {
2614 
2615 		record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);
2616 		if (record_header == NULL) {
2617 			result = BP_RESULT_BADBIOSTABLE;
2618 			break;
2619 		}
2620 
2621 		/* the end of the list */
2622 		if (record_header->ucRecordType == 0xff ||
2623 			record_header->ucRecordSize == 0)	{
2624 			break;
2625 		}
2626 
2627 		if (record_header->ucRecordType ==
2628 			ATOM_BRACKET_LAYOUT_RECORD_TYPE &&
2629 			struct_size(record, asConnInfo, 1)
2630 			<= record_header->ucRecordSize) {
2631 			record = (ATOM_BRACKET_LAYOUT_RECORD *)
2632 				(record_header);
2633 			result = BP_RESULT_OK;
2634 			break;
2635 		}
2636 
2637 		record_offset += record_header->ucRecordSize;
2638 	}
2639 
2640 	/* return if the record not found */
2641 	if (result != BP_RESULT_OK)
2642 		return result;
2643 
2644 	/* get slot sizes */
2645 	slot_layout_info->length = record->ucLength;
2646 	slot_layout_info->width = record->ucWidth;
2647 
2648 	/* get info for each connector in the slot */
2649 	slot_layout_info->num_of_connectors = record->ucConnNum;
2650 	for (j = 0; j < slot_layout_info->num_of_connectors; ++j) {
2651 		slot_layout_info->connectors[j].connector_type =
2652 			(enum connector_layout_type)
2653 			(record->asConnInfo[j].ucConnectorType);
2654 		switch (record->asConnInfo[j].ucConnectorType) {
2655 		case CONNECTOR_TYPE_DVI_D:
2656 			slot_layout_info->connectors[j].connector_type =
2657 				CONNECTOR_LAYOUT_TYPE_DVI_D;
2658 			slot_layout_info->connectors[j].length =
2659 				CONNECTOR_SIZE_DVI;
2660 			break;
2661 
2662 		case CONNECTOR_TYPE_HDMI:
2663 			slot_layout_info->connectors[j].connector_type =
2664 				CONNECTOR_LAYOUT_TYPE_HDMI;
2665 			slot_layout_info->connectors[j].length =
2666 				CONNECTOR_SIZE_HDMI;
2667 			break;
2668 
2669 		case CONNECTOR_TYPE_DISPLAY_PORT:
2670 			slot_layout_info->connectors[j].connector_type =
2671 				CONNECTOR_LAYOUT_TYPE_DP;
2672 			slot_layout_info->connectors[j].length =
2673 				CONNECTOR_SIZE_DP;
2674 			break;
2675 
2676 		case CONNECTOR_TYPE_MINI_DISPLAY_PORT:
2677 			slot_layout_info->connectors[j].connector_type =
2678 				CONNECTOR_LAYOUT_TYPE_MINI_DP;
2679 			slot_layout_info->connectors[j].length =
2680 				CONNECTOR_SIZE_MINI_DP;
2681 			break;
2682 
2683 		default:
2684 			slot_layout_info->connectors[j].connector_type =
2685 				CONNECTOR_LAYOUT_TYPE_UNKNOWN;
2686 			slot_layout_info->connectors[j].length =
2687 				CONNECTOR_SIZE_UNKNOWN;
2688 		}
2689 
2690 		slot_layout_info->connectors[j].position =
2691 			record->asConnInfo[j].ucPosition;
2692 		slot_layout_info->connectors[j].connector_id =
2693 			object_id_from_bios_object_id(
2694 				record->asConnInfo[j].usConnectorObjectId);
2695 	}
2696 	return result;
2697 }
2698 
2699 
2700 static enum bp_result get_bracket_layout_record(
2701 	struct dc_bios *dcb,
2702 	unsigned int bracket_layout_id,
2703 	struct slot_layout_info *slot_layout_info)
2704 {
2705 	unsigned int i;
2706 	unsigned int record_offset;
2707 	struct bios_parser *bp;
2708 	enum bp_result result;
2709 	ATOM_OBJECT *object;
2710 	ATOM_OBJECT_TABLE *object_table;
2711 	unsigned int genericTableOffset;
2712 
2713 	bp = BP_FROM_DCB(dcb);
2714 	object = NULL;
2715 	if (slot_layout_info == NULL) {
2716 		DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");
2717 		return BP_RESULT_BADINPUT;
2718 	}
2719 
2720 
2721 	genericTableOffset = bp->object_info_tbl_offset +
2722 		bp->object_info_tbl.v1_3->usMiscObjectTableOffset;
2723 	object_table = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base,
2724 				genericTableOffset,
2725 				struct_size(object_table, asObjects, 1)));
2726 	if (!object_table)
2727 		return BP_RESULT_FAILURE;
2728 
2729 	result = BP_RESULT_NORECORD;
2730 	for (i = 0; i < object_table->ucNumberOfObjects; ++i) {
2731 
2732 		if (bracket_layout_id ==
2733 			object_table->asObjects[i].usObjectID) {
2734 
2735 			object = &object_table->asObjects[i];
2736 			record_offset = object->usRecordOffset +
2737 				bp->object_info_tbl_offset;
2738 
2739 			result = update_slot_layout_info(dcb, i,
2740 				slot_layout_info, record_offset);
2741 			break;
2742 		}
2743 	}
2744 	return result;
2745 }
2746 
2747 static enum bp_result bios_get_board_layout_info(
2748 	struct dc_bios *dcb,
2749 	struct board_layout_info *board_layout_info)
2750 {
2751 	unsigned int i;
2752 	enum bp_result record_result;
2753 
2754 	const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {
2755 		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1,
2756 		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2,
2757 		0, 0
2758 	};
2759 
2760 	if (board_layout_info == NULL) {
2761 		DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");
2762 		return BP_RESULT_BADINPUT;
2763 	}
2764 
2765 	board_layout_info->num_of_slots = 0;
2766 
2767 	for (i = 0; i < MAX_BOARD_SLOTS; ++i) {
2768 		record_result = get_bracket_layout_record(dcb,
2769 			slot_index_to_vbios_id[i],
2770 			&board_layout_info->slots[i]);
2771 
2772 		if (record_result == BP_RESULT_NORECORD && i > 0)
2773 			break; /* no more slots present in bios */
2774 		else if (record_result != BP_RESULT_OK)
2775 			return record_result;  /* fail */
2776 
2777 		++board_layout_info->num_of_slots;
2778 	}
2779 
2780 	/* all data is valid */
2781 	board_layout_info->is_number_of_slots_valid = 1;
2782 	board_layout_info->is_slots_size_valid = 1;
2783 	board_layout_info->is_connector_offsets_valid = 1;
2784 	board_layout_info->is_connector_lengths_valid = 1;
2785 
2786 	return BP_RESULT_OK;
2787 }
2788 
2789 /******************************************************************************/
2790 
2791 static const struct dc_vbios_funcs vbios_funcs = {
2792 	.get_connectors_number = bios_parser_get_connectors_number,
2793 
2794 	.get_connector_id = bios_parser_get_connector_id,
2795 
2796 	.get_src_obj = bios_parser_get_src_obj,
2797 
2798 	.get_i2c_info = bios_parser_get_i2c_info,
2799 
2800 	.get_hpd_info = bios_parser_get_hpd_info,
2801 
2802 	.get_device_tag = bios_parser_get_device_tag,
2803 
2804 	.get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
2805 
2806 	.get_ss_entry_number = bios_parser_get_ss_entry_number,
2807 
2808 	.get_embedded_panel_info = bios_parser_get_embedded_panel_info,
2809 
2810 	.get_gpio_pin_info = bios_parser_get_gpio_pin_info,
2811 
2812 	.get_encoder_cap_info = bios_parser_get_encoder_cap_info,
2813 
2814 	/* bios scratch register communication */
2815 	.is_accelerated_mode = bios_is_accelerated_mode,
2816 
2817 	.set_scratch_critical_state = bios_parser_set_scratch_critical_state,
2818 
2819 	.is_device_id_supported = bios_parser_is_device_id_supported,
2820 
2821 	/* COMMANDS */
2822 	.encoder_control = bios_parser_encoder_control,
2823 
2824 	.transmitter_control = bios_parser_transmitter_control,
2825 
2826 	.enable_crtc = bios_parser_enable_crtc,
2827 
2828 	.adjust_pixel_clock = bios_parser_adjust_pixel_clock,
2829 
2830 	.set_pixel_clock = bios_parser_set_pixel_clock,
2831 
2832 	.set_dce_clock = bios_parser_set_dce_clock,
2833 
2834 	.enable_spread_spectrum_on_ppll = bios_parser_enable_spread_spectrum_on_ppll,
2835 
2836 	.program_crtc_timing = bios_parser_program_crtc_timing, /* still use.  should probably retire and program directly */
2837 
2838 	.program_display_engine_pll = bios_parser_program_display_engine_pll,
2839 
2840 	.enable_disp_power_gating = bios_parser_enable_disp_power_gating,
2841 
2842 	/* SW init and patch */
2843 
2844 	.bios_parser_destroy = bios_parser_destroy,
2845 
2846 	.get_board_layout_info = bios_get_board_layout_info,
2847 
2848 	.get_atom_dc_golden_table = NULL
2849 };
2850 
2851 static bool bios_parser_construct(
2852 	struct bios_parser *bp,
2853 	struct bp_init_data *init,
2854 	enum dce_version dce_version)
2855 {
2856 	uint16_t *rom_header_offset = NULL;
2857 	ATOM_ROM_HEADER *rom_header = NULL;
2858 	ATOM_OBJECT_HEADER *object_info_tbl;
2859 	struct atom_data_revision tbl_rev = {0};
2860 
2861 	if (!init)
2862 		return false;
2863 
2864 	if (!init->bios)
2865 		return false;
2866 
2867 	bp->base.funcs = &vbios_funcs;
2868 	bp->base.bios = init->bios;
2869 	bp->base.bios_size = bp->base.bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT;
2870 
2871 	bp->base.ctx = init->ctx;
2872 	bp->base.bios_local_image = NULL;
2873 
2874 	rom_header_offset =
2875 	GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER);
2876 
2877 	if (!rom_header_offset)
2878 		return false;
2879 
2880 	rom_header = GET_IMAGE(ATOM_ROM_HEADER, *rom_header_offset);
2881 
2882 	if (!rom_header)
2883 		return false;
2884 
2885 	get_atom_data_table_revision(&rom_header->sHeader, &tbl_rev);
2886 	if (tbl_rev.major >= 2 && tbl_rev.minor >= 2)
2887 		return false;
2888 
2889 	bp->master_data_tbl =
2890 	GET_IMAGE(ATOM_MASTER_DATA_TABLE,
2891 		rom_header->usMasterDataTableOffset);
2892 
2893 	if (!bp->master_data_tbl)
2894 		return false;
2895 
2896 	bp->object_info_tbl_offset = DATA_TABLES(Object_Header);
2897 
2898 	if (!bp->object_info_tbl_offset)
2899 		return false;
2900 
2901 	object_info_tbl =
2902 	GET_IMAGE(ATOM_OBJECT_HEADER, bp->object_info_tbl_offset);
2903 
2904 	if (!object_info_tbl)
2905 		return false;
2906 
2907 	get_atom_data_table_revision(&object_info_tbl->sHeader,
2908 		&bp->object_info_tbl.revision);
2909 
2910 	if (bp->object_info_tbl.revision.major == 1
2911 		&& bp->object_info_tbl.revision.minor >= 3) {
2912 		ATOM_OBJECT_HEADER_V3 *tbl_v3;
2913 
2914 		tbl_v3 = GET_IMAGE(ATOM_OBJECT_HEADER_V3,
2915 			bp->object_info_tbl_offset);
2916 		if (!tbl_v3)
2917 			return false;
2918 
2919 		bp->object_info_tbl.v1_3 = tbl_v3;
2920 	} else if (bp->object_info_tbl.revision.major == 1
2921 		&& bp->object_info_tbl.revision.minor >= 1)
2922 		bp->object_info_tbl.v1_1 = object_info_tbl;
2923 	else
2924 		return false;
2925 
2926 	dal_bios_parser_init_cmd_tbl(bp);
2927 	dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version);
2928 
2929 	bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);
2930 	bp->base.fw_info_valid = bios_parser_get_firmware_info(&bp->base, &bp->base.fw_info) == BP_RESULT_OK;
2931 
2932 	return true;
2933 }
2934 
2935 /******************************************************************************/
2936