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