xref: /openbsd-src/sys/dev/pci/drm/amd/display/dc/bios/bios_parser2.c (revision 777bfb8a6e3527904a896b86f659da0272a97f72)
1fb4d8502Sjsg /*
2fb4d8502Sjsg  * Copyright 2012-15 Advanced Micro Devices, Inc.
3fb4d8502Sjsg  *
4fb4d8502Sjsg  * Permission is hereby granted, free of charge, to any person obtaining a
5fb4d8502Sjsg  * copy of this software and associated documentation files (the "Software"),
6fb4d8502Sjsg  * to deal in the Software without restriction, including without limitation
7fb4d8502Sjsg  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8fb4d8502Sjsg  * and/or sell copies of the Software, and to permit persons to whom the
9fb4d8502Sjsg  * Software is furnished to do so, subject to the following conditions:
10fb4d8502Sjsg  *
11fb4d8502Sjsg  * The above copyright notice and this permission notice shall be included in
12fb4d8502Sjsg  * all copies or substantial portions of the Software.
13fb4d8502Sjsg  *
14fb4d8502Sjsg  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15fb4d8502Sjsg  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16fb4d8502Sjsg  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17fb4d8502Sjsg  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18fb4d8502Sjsg  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19fb4d8502Sjsg  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20fb4d8502Sjsg  * OTHER DEALINGS IN THE SOFTWARE.
21fb4d8502Sjsg  *
22fb4d8502Sjsg  * Authors: AMD
23fb4d8502Sjsg  *
24fb4d8502Sjsg  */
25fb4d8502Sjsg 
26fb4d8502Sjsg #include "dm_services.h"
271bb76ff1Sjsg #include "core_types.h"
28fb4d8502Sjsg 
29fb4d8502Sjsg #include "ObjectID.h"
30fb4d8502Sjsg #include "atomfirmware.h"
31fb4d8502Sjsg 
32fb4d8502Sjsg #include "dc_bios_types.h"
33fb4d8502Sjsg #include "include/grph_object_ctrl_defs.h"
34fb4d8502Sjsg #include "include/bios_parser_interface.h"
35fb4d8502Sjsg #include "include/logger_interface.h"
36fb4d8502Sjsg 
37fb4d8502Sjsg #include "command_table2.h"
38fb4d8502Sjsg 
39fb4d8502Sjsg #include "bios_parser_helper.h"
40fb4d8502Sjsg #include "command_table_helper2.h"
41fb4d8502Sjsg #include "bios_parser2.h"
42fb4d8502Sjsg #include "bios_parser_types_internal2.h"
43fb4d8502Sjsg #include "bios_parser_interface.h"
44fb4d8502Sjsg 
45fb4d8502Sjsg #include "bios_parser_common.h"
46fb4d8502Sjsg 
47fb4d8502Sjsg #define DC_LOGGER \
48fb4d8502Sjsg 	bp->base.ctx->logger
49fb4d8502Sjsg 
50fb4d8502Sjsg #define LAST_RECORD_TYPE 0xff
51fb4d8502Sjsg #define SMU9_SYSPLL0_ID  0
52fb4d8502Sjsg 
53fb4d8502Sjsg static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
54fb4d8502Sjsg 	struct atom_i2c_record *record,
55fb4d8502Sjsg 	struct graphics_object_i2c_info *info);
56fb4d8502Sjsg 
57fb4d8502Sjsg static enum bp_result bios_parser_get_firmware_info(
58fb4d8502Sjsg 	struct dc_bios *dcb,
59fb4d8502Sjsg 	struct dc_firmware_info *info);
60fb4d8502Sjsg 
61fb4d8502Sjsg static enum bp_result bios_parser_get_encoder_cap_info(
62fb4d8502Sjsg 	struct dc_bios *dcb,
63fb4d8502Sjsg 	struct graphics_object_id object_id,
64fb4d8502Sjsg 	struct bp_encoder_cap_info *info);
65fb4d8502Sjsg 
66fb4d8502Sjsg static enum bp_result get_firmware_info_v3_1(
67fb4d8502Sjsg 	struct bios_parser *bp,
68fb4d8502Sjsg 	struct dc_firmware_info *info);
69fb4d8502Sjsg 
70fb4d8502Sjsg static enum bp_result get_firmware_info_v3_2(
71fb4d8502Sjsg 	struct bios_parser *bp,
72fb4d8502Sjsg 	struct dc_firmware_info *info);
73fb4d8502Sjsg 
741bb76ff1Sjsg static enum bp_result get_firmware_info_v3_4(
751bb76ff1Sjsg 	struct bios_parser *bp,
761bb76ff1Sjsg 	struct dc_firmware_info *info);
771bb76ff1Sjsg 
78fb4d8502Sjsg static struct atom_hpd_int_record *get_hpd_record(struct bios_parser *bp,
79fb4d8502Sjsg 		struct atom_display_object_path_v2 *object);
80fb4d8502Sjsg 
81fb4d8502Sjsg static struct atom_encoder_caps_record *get_encoder_cap_record(
82fb4d8502Sjsg 	struct bios_parser *bp,
83fb4d8502Sjsg 	struct atom_display_object_path_v2 *object);
84fb4d8502Sjsg 
85fb4d8502Sjsg #define BIOS_IMAGE_SIZE_OFFSET 2
86fb4d8502Sjsg #define BIOS_IMAGE_SIZE_UNIT 512
87fb4d8502Sjsg 
88fb4d8502Sjsg #define DATA_TABLES(table) (bp->master_data_tbl->listOfdatatables.table)
89fb4d8502Sjsg 
90c349dbc7Sjsg static void bios_parser2_destruct(struct bios_parser *bp)
91fb4d8502Sjsg {
92fb4d8502Sjsg 	kfree(bp->base.bios_local_image);
93fb4d8502Sjsg 	kfree(bp->base.integrated_info);
94fb4d8502Sjsg }
95fb4d8502Sjsg 
96fb4d8502Sjsg static void firmware_parser_destroy(struct dc_bios **dcb)
97fb4d8502Sjsg {
98fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(*dcb);
99fb4d8502Sjsg 
100fb4d8502Sjsg 	if (!bp) {
101fb4d8502Sjsg 		BREAK_TO_DEBUGGER();
102fb4d8502Sjsg 		return;
103fb4d8502Sjsg 	}
104fb4d8502Sjsg 
105c349dbc7Sjsg 	bios_parser2_destruct(bp);
106fb4d8502Sjsg 
107fb4d8502Sjsg 	kfree(bp);
108fb4d8502Sjsg 	*dcb = NULL;
109fb4d8502Sjsg }
110fb4d8502Sjsg 
111fb4d8502Sjsg static void get_atom_data_table_revision(
112fb4d8502Sjsg 	struct atom_common_table_header *atom_data_tbl,
113fb4d8502Sjsg 	struct atom_data_revision *tbl_revision)
114fb4d8502Sjsg {
115fb4d8502Sjsg 	if (!tbl_revision)
116fb4d8502Sjsg 		return;
117fb4d8502Sjsg 
118fb4d8502Sjsg 	/* initialize the revision to 0 which is invalid revision */
119fb4d8502Sjsg 	tbl_revision->major = 0;
120fb4d8502Sjsg 	tbl_revision->minor = 0;
121fb4d8502Sjsg 
122fb4d8502Sjsg 	if (!atom_data_tbl)
123fb4d8502Sjsg 		return;
124fb4d8502Sjsg 
125fb4d8502Sjsg 	tbl_revision->major =
126fb4d8502Sjsg 			(uint32_t) atom_data_tbl->format_revision & 0x3f;
127fb4d8502Sjsg 	tbl_revision->minor =
128fb4d8502Sjsg 			(uint32_t) atom_data_tbl->content_revision & 0x3f;
129fb4d8502Sjsg }
130fb4d8502Sjsg 
131fb4d8502Sjsg /* BIOS oject table displaypath is per connector.
132fb4d8502Sjsg  * There is extra path not for connector. BIOS fill its encoderid as 0
133fb4d8502Sjsg  */
134fb4d8502Sjsg static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)
135fb4d8502Sjsg {
136fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
137fb4d8502Sjsg 	unsigned int count = 0;
138fb4d8502Sjsg 	unsigned int i;
139fb4d8502Sjsg 
1401bb76ff1Sjsg 	switch (bp->object_info_tbl.revision.minor) {
1411bb76ff1Sjsg 	default:
1421bb76ff1Sjsg 	case 4:
1431bb76ff1Sjsg 		for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++)
144fb4d8502Sjsg 			if (bp->object_info_tbl.v1_4->display_path[i].encoderobjid != 0)
145fb4d8502Sjsg 				count++;
1461bb76ff1Sjsg 
1471bb76ff1Sjsg 		break;
1481bb76ff1Sjsg 
1491bb76ff1Sjsg 	case 5:
1501bb76ff1Sjsg 		for (i = 0; i < bp->object_info_tbl.v1_5->number_of_path; i++)
1511bb76ff1Sjsg 			if (bp->object_info_tbl.v1_5->display_path[i].encoderobjid != 0)
1521bb76ff1Sjsg 				count++;
1531bb76ff1Sjsg 
1541bb76ff1Sjsg 		break;
155fb4d8502Sjsg 	}
156fb4d8502Sjsg 	return count;
157fb4d8502Sjsg }
158fb4d8502Sjsg 
159fb4d8502Sjsg static struct graphics_object_id bios_parser_get_connector_id(
160fb4d8502Sjsg 	struct dc_bios *dcb,
161fb4d8502Sjsg 	uint8_t i)
162fb4d8502Sjsg {
163fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
164fb4d8502Sjsg 	struct graphics_object_id object_id = dal_graphics_object_id_init(
165fb4d8502Sjsg 		0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
166fb4d8502Sjsg 	struct object_info_table *tbl = &bp->object_info_tbl;
167fb4d8502Sjsg 	struct display_object_info_table_v1_4 *v1_4 = tbl->v1_4;
168fb4d8502Sjsg 
1691bb76ff1Sjsg 	struct display_object_info_table_v1_5 *v1_5 = tbl->v1_5;
1701bb76ff1Sjsg 
1711bb76ff1Sjsg 	switch (bp->object_info_tbl.revision.minor) {
1721bb76ff1Sjsg 	default:
1731bb76ff1Sjsg 	case 4:
174fb4d8502Sjsg 		if (v1_4->number_of_path > i) {
175fb4d8502Sjsg 			/* If display_objid is generic object id,  the encoderObj
176fb4d8502Sjsg 			 * /extencoderobjId should be 0
177fb4d8502Sjsg 			 */
178fb4d8502Sjsg 			if (v1_4->display_path[i].encoderobjid != 0 &&
179fb4d8502Sjsg 			    v1_4->display_path[i].display_objid != 0)
180fb4d8502Sjsg 				object_id = object_id_from_bios_object_id(
181fb4d8502Sjsg 					v1_4->display_path[i].display_objid);
182fb4d8502Sjsg 		}
1831bb76ff1Sjsg 		break;
184fb4d8502Sjsg 
1851bb76ff1Sjsg 	case 5:
1861bb76ff1Sjsg 		if (v1_5->number_of_path > i) {
1871bb76ff1Sjsg 			/* If display_objid is generic object id,  the encoderObjId
1881bb76ff1Sjsg 		 * should be 0
1891bb76ff1Sjsg 		 */
1901bb76ff1Sjsg 			if (v1_5->display_path[i].encoderobjid != 0 &&
1911bb76ff1Sjsg 			    v1_5->display_path[i].display_objid != 0)
1921bb76ff1Sjsg 				object_id = object_id_from_bios_object_id(
1931bb76ff1Sjsg 					v1_5->display_path[i].display_objid);
1941bb76ff1Sjsg 		}
1951bb76ff1Sjsg 		break;
1961bb76ff1Sjsg 	}
197fb4d8502Sjsg 	return object_id;
198fb4d8502Sjsg }
199fb4d8502Sjsg 
200fb4d8502Sjsg static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
201fb4d8502Sjsg 	struct graphics_object_id object_id, uint32_t index,
202fb4d8502Sjsg 	struct graphics_object_id *src_object_id)
203fb4d8502Sjsg {
204fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
205fb4d8502Sjsg 	unsigned int i;
206fb4d8502Sjsg 	enum bp_result bp_result = BP_RESULT_BADINPUT;
207fb4d8502Sjsg 	struct graphics_object_id obj_id = { 0 };
208fb4d8502Sjsg 	struct object_info_table *tbl = &bp->object_info_tbl;
209fb4d8502Sjsg 
210fb4d8502Sjsg 	if (!src_object_id)
211fb4d8502Sjsg 		return bp_result;
212fb4d8502Sjsg 
213fb4d8502Sjsg 	switch (object_id.type) {
214fb4d8502Sjsg 	/* Encoder's Source is GPU.  BIOS does not provide GPU, since all
215fb4d8502Sjsg 	 * displaypaths point to same GPU (0x1100).  Hardcode GPU object type
216fb4d8502Sjsg 	 */
217fb4d8502Sjsg 	case OBJECT_TYPE_ENCODER:
218fb4d8502Sjsg 		/* TODO: since num of src must be less than 2.
219fb4d8502Sjsg 		 * If found in for loop, should break.
220fb4d8502Sjsg 		 * DAL2 implementation may be changed too
221fb4d8502Sjsg 		 */
2221bb76ff1Sjsg 		switch (bp->object_info_tbl.revision.minor) {
2231bb76ff1Sjsg 		default:
2241bb76ff1Sjsg 		case 4:
225fb4d8502Sjsg 			for (i = 0; i < tbl->v1_4->number_of_path; i++) {
226fb4d8502Sjsg 				obj_id = object_id_from_bios_object_id(
227fb4d8502Sjsg 					tbl->v1_4->display_path[i].encoderobjid);
228fb4d8502Sjsg 				if (object_id.type == obj_id.type &&
229fb4d8502Sjsg 				    object_id.id == obj_id.id &&
2301bb76ff1Sjsg 				    object_id.enum_id == obj_id.enum_id) {
231fb4d8502Sjsg 					*src_object_id =
2321bb76ff1Sjsg 						object_id_from_bios_object_id(
2331bb76ff1Sjsg 							0x1100);
234fb4d8502Sjsg 					/* break; */
235fb4d8502Sjsg 				}
236fb4d8502Sjsg 			}
237fb4d8502Sjsg 			bp_result = BP_RESULT_OK;
238fb4d8502Sjsg 			break;
2391bb76ff1Sjsg 
2401bb76ff1Sjsg 		case 5:
2411bb76ff1Sjsg 			for (i = 0; i < tbl->v1_5->number_of_path; i++) {
2421bb76ff1Sjsg 				obj_id = object_id_from_bios_object_id(
2431bb76ff1Sjsg 					tbl->v1_5->display_path[i].encoderobjid);
2441bb76ff1Sjsg 				if (object_id.type == obj_id.type &&
2451bb76ff1Sjsg 				    object_id.id == obj_id.id &&
2461bb76ff1Sjsg 				    object_id.enum_id == obj_id.enum_id) {
2471bb76ff1Sjsg 					*src_object_id =
2481bb76ff1Sjsg 						object_id_from_bios_object_id(
2491bb76ff1Sjsg 							0x1100);
2501bb76ff1Sjsg 					/* break; */
2511bb76ff1Sjsg 				}
2521bb76ff1Sjsg 			}
2531bb76ff1Sjsg 			bp_result = BP_RESULT_OK;
2541bb76ff1Sjsg 			break;
2551bb76ff1Sjsg 		}
2561bb76ff1Sjsg 		break;
257fb4d8502Sjsg 	case OBJECT_TYPE_CONNECTOR:
2581bb76ff1Sjsg 		switch (bp->object_info_tbl.revision.minor) {
2591bb76ff1Sjsg 		default:
2601bb76ff1Sjsg 		case 4:
261fb4d8502Sjsg 			for (i = 0; i < tbl->v1_4->number_of_path; i++) {
262fb4d8502Sjsg 				obj_id = object_id_from_bios_object_id(
2631bb76ff1Sjsg 					tbl->v1_4->display_path[i]
2641bb76ff1Sjsg 						.display_objid);
265fb4d8502Sjsg 
266fb4d8502Sjsg 				if (object_id.type == obj_id.type &&
267fb4d8502Sjsg 				    object_id.id == obj_id.id &&
268fb4d8502Sjsg 				    object_id.enum_id == obj_id.enum_id) {
269fb4d8502Sjsg 					*src_object_id =
270fb4d8502Sjsg 						object_id_from_bios_object_id(
2711bb76ff1Sjsg 							tbl->v1_4
2721bb76ff1Sjsg 								->display_path[i]
2731bb76ff1Sjsg 								.encoderobjid);
274fb4d8502Sjsg 					/* break; */
275fb4d8502Sjsg 				}
276fb4d8502Sjsg 			}
277fb4d8502Sjsg 			bp_result = BP_RESULT_OK;
278fb4d8502Sjsg 			break;
2791bb76ff1Sjsg 		}
2801bb76ff1Sjsg 		bp_result = BP_RESULT_OK;
2811bb76ff1Sjsg 		break;
2821bb76ff1Sjsg 		case 5:
2831bb76ff1Sjsg 			for (i = 0; i < tbl->v1_5->number_of_path; i++) {
2841bb76ff1Sjsg 				obj_id = object_id_from_bios_object_id(
2851bb76ff1Sjsg 								       tbl->v1_5->display_path[i].display_objid);
2861bb76ff1Sjsg 
2871bb76ff1Sjsg 				if (object_id.type == obj_id.type &&
2881bb76ff1Sjsg 				    object_id.id == obj_id.id &&
2891bb76ff1Sjsg 				    object_id.enum_id == obj_id.enum_id) {
2901bb76ff1Sjsg 					*src_object_id = object_id_from_bios_object_id(
2911bb76ff1Sjsg 										       tbl->v1_5->display_path[i].encoderobjid);
2921bb76ff1Sjsg 					/* break; */
2931bb76ff1Sjsg 				}
2941bb76ff1Sjsg 			}
2951bb76ff1Sjsg 		bp_result = BP_RESULT_OK;
2961bb76ff1Sjsg 		break;
2971bb76ff1Sjsg 
298fb4d8502Sjsg 	default:
2991bb76ff1Sjsg 		bp_result = BP_RESULT_OK;
300fb4d8502Sjsg 		break;
301fb4d8502Sjsg 	}
302fb4d8502Sjsg 
303fb4d8502Sjsg 	return bp_result;
304fb4d8502Sjsg }
305fb4d8502Sjsg 
306fb4d8502Sjsg /* from graphics_object_id, find display path which includes the object_id */
307fb4d8502Sjsg static struct atom_display_object_path_v2 *get_bios_object(
308fb4d8502Sjsg 		struct bios_parser *bp,
309fb4d8502Sjsg 		struct graphics_object_id id)
310fb4d8502Sjsg {
311fb4d8502Sjsg 	unsigned int i;
312fb4d8502Sjsg 	struct graphics_object_id obj_id = {0};
313fb4d8502Sjsg 
314fb4d8502Sjsg 	switch (id.type) {
315fb4d8502Sjsg 	case OBJECT_TYPE_ENCODER:
316fb4d8502Sjsg 		for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) {
317fb4d8502Sjsg 			obj_id = object_id_from_bios_object_id(
318fb4d8502Sjsg 					bp->object_info_tbl.v1_4->display_path[i].encoderobjid);
319c349dbc7Sjsg 			if (id.type == obj_id.type && id.id == obj_id.id
320c349dbc7Sjsg 					&& id.enum_id == obj_id.enum_id)
321c349dbc7Sjsg 				return &bp->object_info_tbl.v1_4->display_path[i];
322fb4d8502Sjsg 		}
323c349dbc7Sjsg 		fallthrough;
324fb4d8502Sjsg 	case OBJECT_TYPE_CONNECTOR:
325fb4d8502Sjsg 	case OBJECT_TYPE_GENERIC:
326fb4d8502Sjsg 		/* Both Generic and Connector Object ID
327fb4d8502Sjsg 		 * will be stored on display_objid
328fb4d8502Sjsg 		 */
329fb4d8502Sjsg 		for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) {
330fb4d8502Sjsg 			obj_id = object_id_from_bios_object_id(
331c349dbc7Sjsg 					bp->object_info_tbl.v1_4->display_path[i].display_objid);
332c349dbc7Sjsg 			if (id.type == obj_id.type && id.id == obj_id.id
333c349dbc7Sjsg 					&& id.enum_id == obj_id.enum_id)
334c349dbc7Sjsg 				return &bp->object_info_tbl.v1_4->display_path[i];
335fb4d8502Sjsg 		}
336c349dbc7Sjsg 		fallthrough;
337fb4d8502Sjsg 	default:
338fb4d8502Sjsg 		return NULL;
339fb4d8502Sjsg 	}
340fb4d8502Sjsg }
341fb4d8502Sjsg 
3421bb76ff1Sjsg /* from graphics_object_id, find display path which includes the object_id */
343f005ef32Sjsg static struct atom_display_object_path_v3 *get_bios_object_from_path_v3(struct bios_parser *bp,
3441bb76ff1Sjsg 									struct graphics_object_id id)
3451bb76ff1Sjsg {
3461bb76ff1Sjsg 	unsigned int i;
3471bb76ff1Sjsg 	struct graphics_object_id obj_id = {0};
3481bb76ff1Sjsg 
3491bb76ff1Sjsg 	switch (id.type) {
3501bb76ff1Sjsg 	case OBJECT_TYPE_ENCODER:
3511bb76ff1Sjsg 		for (i = 0; i < bp->object_info_tbl.v1_5->number_of_path; i++) {
3521bb76ff1Sjsg 			obj_id = object_id_from_bios_object_id(
3531bb76ff1Sjsg 					bp->object_info_tbl.v1_5->display_path[i].encoderobjid);
3541bb76ff1Sjsg 			if (id.type == obj_id.type && id.id == obj_id.id
3551bb76ff1Sjsg 					&& id.enum_id == obj_id.enum_id)
3561bb76ff1Sjsg 				return &bp->object_info_tbl.v1_5->display_path[i];
3571bb76ff1Sjsg 		}
3581bb76ff1Sjsg         break;
3591bb76ff1Sjsg 
3601bb76ff1Sjsg 	case OBJECT_TYPE_CONNECTOR:
3611bb76ff1Sjsg 	case OBJECT_TYPE_GENERIC:
3621bb76ff1Sjsg 		/* Both Generic and Connector Object ID
3631bb76ff1Sjsg 		 * will be stored on display_objid
3641bb76ff1Sjsg 		 */
3651bb76ff1Sjsg 		for (i = 0; i < bp->object_info_tbl.v1_5->number_of_path; i++) {
3661bb76ff1Sjsg 			obj_id = object_id_from_bios_object_id(
3671bb76ff1Sjsg 					bp->object_info_tbl.v1_5->display_path[i].display_objid);
3681bb76ff1Sjsg 			if (id.type == obj_id.type && id.id == obj_id.id
3691bb76ff1Sjsg 					&& id.enum_id == obj_id.enum_id)
3701bb76ff1Sjsg 				return &bp->object_info_tbl.v1_5->display_path[i];
3711bb76ff1Sjsg 		}
3721bb76ff1Sjsg         break;
3731bb76ff1Sjsg 
3741bb76ff1Sjsg 	default:
3751bb76ff1Sjsg 		return NULL;
3761bb76ff1Sjsg 	}
3771bb76ff1Sjsg 
3781bb76ff1Sjsg 	return NULL;
3791bb76ff1Sjsg }
3801bb76ff1Sjsg 
381fb4d8502Sjsg static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
382fb4d8502Sjsg 	struct graphics_object_id id,
383fb4d8502Sjsg 	struct graphics_object_i2c_info *info)
384fb4d8502Sjsg {
385fb4d8502Sjsg 	uint32_t offset;
386fb4d8502Sjsg 	struct atom_display_object_path_v2 *object;
3871bb76ff1Sjsg 
3881bb76ff1Sjsg 	struct atom_display_object_path_v3 *object_path_v3;
3891bb76ff1Sjsg 
390fb4d8502Sjsg 	struct atom_common_record_header *header;
391fb4d8502Sjsg 	struct atom_i2c_record *record;
392c349dbc7Sjsg 	struct atom_i2c_record dummy_record = {0};
393fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
394fb4d8502Sjsg 
395fb4d8502Sjsg 	if (!info)
396fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
397fb4d8502Sjsg 
398c349dbc7Sjsg 	if (id.type == OBJECT_TYPE_GENERIC) {
399c349dbc7Sjsg 		dummy_record.i2c_id = id.id;
400c349dbc7Sjsg 
401c349dbc7Sjsg 		if (get_gpio_i2c_info(bp, &dummy_record, info) == BP_RESULT_OK)
402c349dbc7Sjsg 			return BP_RESULT_OK;
403c349dbc7Sjsg 		else
404c349dbc7Sjsg 			return BP_RESULT_NORECORD;
405c349dbc7Sjsg 	}
406c349dbc7Sjsg 
4071bb76ff1Sjsg 	switch (bp->object_info_tbl.revision.minor) {
4081bb76ff1Sjsg 	    case 4:
4091bb76ff1Sjsg 	    default:
410fb4d8502Sjsg 	        object = get_bios_object(bp, id);
411fb4d8502Sjsg 
412fb4d8502Sjsg 	        if (!object)
413fb4d8502Sjsg 				return BP_RESULT_BADINPUT;
414fb4d8502Sjsg 
415fb4d8502Sjsg 	        offset = object->disp_recordoffset + bp->object_info_tbl_offset;
4161bb76ff1Sjsg 	        break;
4171bb76ff1Sjsg 	    case 5:
4181bb76ff1Sjsg 		object_path_v3 = get_bios_object_from_path_v3(bp, id);
4191bb76ff1Sjsg 
4201bb76ff1Sjsg 		if (!object_path_v3)
4211bb76ff1Sjsg 			return BP_RESULT_BADINPUT;
4221bb76ff1Sjsg 
4231bb76ff1Sjsg 		offset = object_path_v3->disp_recordoffset + bp->object_info_tbl_offset;
4241bb76ff1Sjsg 		break;
4251bb76ff1Sjsg 	}
426fb4d8502Sjsg 
427fb4d8502Sjsg 	for (;;) {
428fb4d8502Sjsg 		header = GET_IMAGE(struct atom_common_record_header, offset);
429fb4d8502Sjsg 
430fb4d8502Sjsg 		if (!header)
431fb4d8502Sjsg 			return BP_RESULT_BADBIOSTABLE;
432fb4d8502Sjsg 
433fb4d8502Sjsg 		if (header->record_type == LAST_RECORD_TYPE ||
434fb4d8502Sjsg 			!header->record_size)
435fb4d8502Sjsg 			break;
436fb4d8502Sjsg 
437fb4d8502Sjsg 		if (header->record_type == ATOM_I2C_RECORD_TYPE
438fb4d8502Sjsg 			&& sizeof(struct atom_i2c_record) <=
439fb4d8502Sjsg 							header->record_size) {
440fb4d8502Sjsg 			/* get the I2C info */
441fb4d8502Sjsg 			record = (struct atom_i2c_record *) header;
442fb4d8502Sjsg 
443fb4d8502Sjsg 			if (get_gpio_i2c_info(bp, record, info) ==
444fb4d8502Sjsg 								BP_RESULT_OK)
445fb4d8502Sjsg 				return BP_RESULT_OK;
446fb4d8502Sjsg 		}
447fb4d8502Sjsg 
448fb4d8502Sjsg 		offset += header->record_size;
449fb4d8502Sjsg 	}
450fb4d8502Sjsg 
451fb4d8502Sjsg 	return BP_RESULT_NORECORD;
452fb4d8502Sjsg }
453fb4d8502Sjsg 
454fb4d8502Sjsg static enum bp_result get_gpio_i2c_info(
455fb4d8502Sjsg 	struct bios_parser *bp,
456fb4d8502Sjsg 	struct atom_i2c_record *record,
457fb4d8502Sjsg 	struct graphics_object_i2c_info *info)
458fb4d8502Sjsg {
459fb4d8502Sjsg 	struct atom_gpio_pin_lut_v2_1 *header;
460fb4d8502Sjsg 	uint32_t count = 0;
461fb4d8502Sjsg 	unsigned int table_index = 0;
462c349dbc7Sjsg 	bool find_valid = false;
4631bb76ff1Sjsg 	struct atom_gpio_pin_assignment *pin;
464fb4d8502Sjsg 
465fb4d8502Sjsg 	if (!info)
466fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
467fb4d8502Sjsg 
468fb4d8502Sjsg 	/* get the GPIO_I2C info */
469fb4d8502Sjsg 	if (!DATA_TABLES(gpio_pin_lut))
470fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
471fb4d8502Sjsg 
472fb4d8502Sjsg 	header = GET_IMAGE(struct atom_gpio_pin_lut_v2_1,
473fb4d8502Sjsg 					DATA_TABLES(gpio_pin_lut));
474fb4d8502Sjsg 	if (!header)
475fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
476fb4d8502Sjsg 
477fb4d8502Sjsg 	if (sizeof(struct atom_common_table_header) +
478fb4d8502Sjsg 			sizeof(struct atom_gpio_pin_assignment)	>
479fb4d8502Sjsg 			le16_to_cpu(header->table_header.structuresize))
480fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
481fb4d8502Sjsg 
482fb4d8502Sjsg 	/* TODO: is version change? */
483fb4d8502Sjsg 	if (header->table_header.content_revision != 1)
484fb4d8502Sjsg 		return BP_RESULT_UNSUPPORTED;
485fb4d8502Sjsg 
486fb4d8502Sjsg 	/* get data count */
487fb4d8502Sjsg 	count = (le16_to_cpu(header->table_header.structuresize)
488fb4d8502Sjsg 			- sizeof(struct atom_common_table_header))
489fb4d8502Sjsg 				/ sizeof(struct atom_gpio_pin_assignment);
490fb4d8502Sjsg 
4911bb76ff1Sjsg 	pin = (struct atom_gpio_pin_assignment *) header->gpio_pin;
4921bb76ff1Sjsg 
493fb4d8502Sjsg 	for (table_index = 0; table_index < count; table_index++) {
4941bb76ff1Sjsg 		if (((record->i2c_id & I2C_HW_CAP) 				== (pin->gpio_id & I2C_HW_CAP)) &&
4951bb76ff1Sjsg 		    ((record->i2c_id & I2C_HW_ENGINE_ID_MASK)	== (pin->gpio_id & I2C_HW_ENGINE_ID_MASK)) &&
4961bb76ff1Sjsg 		    ((record->i2c_id & I2C_HW_LANE_MUX) 		== (pin->gpio_id & I2C_HW_LANE_MUX))) {
497fb4d8502Sjsg 			/* still valid */
498fb4d8502Sjsg 			find_valid = true;
499fb4d8502Sjsg 			break;
500fb4d8502Sjsg 		}
5011bb76ff1Sjsg 		pin = (struct atom_gpio_pin_assignment *)((uint8_t *)pin + sizeof(struct atom_gpio_pin_assignment));
502fb4d8502Sjsg 	}
503c349dbc7Sjsg 
504fb4d8502Sjsg 	/* If we don't find the entry that we are looking for then
505fb4d8502Sjsg 	 *  we will return BP_Result_BadBiosTable.
506fb4d8502Sjsg 	 */
507fb4d8502Sjsg 	if (find_valid == false)
508fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
509fb4d8502Sjsg 
510fb4d8502Sjsg 	/* get the GPIO_I2C_INFO */
511fb4d8502Sjsg 	info->i2c_hw_assist = (record->i2c_id & I2C_HW_CAP) ? true : false;
512fb4d8502Sjsg 	info->i2c_line = record->i2c_id & I2C_HW_LANE_MUX;
513fb4d8502Sjsg 	info->i2c_engine_id = (record->i2c_id & I2C_HW_ENGINE_ID_MASK) >> 4;
514fb4d8502Sjsg 	info->i2c_slave_address = record->i2c_slave_addr;
515fb4d8502Sjsg 
516fb4d8502Sjsg 	/* TODO: check how to get register offset for en, Y, etc. */
517ab6bc2c8Sjsg 	info->gpio_info.clk_a_register_index = le16_to_cpu(pin->data_a_reg_index);
518ab6bc2c8Sjsg 	info->gpio_info.clk_a_shift = pin->gpio_bitshift;
519fb4d8502Sjsg 
520fb4d8502Sjsg 	return BP_RESULT_OK;
521fb4d8502Sjsg }
522fb4d8502Sjsg 
523f005ef32Sjsg static struct atom_hpd_int_record *get_hpd_record_for_path_v3(struct bios_parser *bp,
5241bb76ff1Sjsg 							      struct atom_display_object_path_v3 *object)
5251bb76ff1Sjsg {
5261bb76ff1Sjsg 	struct atom_common_record_header *header;
5271bb76ff1Sjsg 	uint32_t offset;
5281bb76ff1Sjsg 
5291bb76ff1Sjsg 	if (!object) {
5301bb76ff1Sjsg 		BREAK_TO_DEBUGGER(); /* Invalid object */
5311bb76ff1Sjsg 		return NULL;
5321bb76ff1Sjsg 	}
5331bb76ff1Sjsg 
5341bb76ff1Sjsg 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
5351bb76ff1Sjsg 
5361bb76ff1Sjsg 	for (;;) {
5371bb76ff1Sjsg 		header = GET_IMAGE(struct atom_common_record_header, offset);
5381bb76ff1Sjsg 
5391bb76ff1Sjsg 		if (!header)
5401bb76ff1Sjsg 			return NULL;
5411bb76ff1Sjsg 
5421bb76ff1Sjsg 		if (header->record_type == ATOM_RECORD_END_TYPE ||
5431bb76ff1Sjsg 			!header->record_size)
5441bb76ff1Sjsg 			break;
5451bb76ff1Sjsg 
5461bb76ff1Sjsg 		if (header->record_type == ATOM_HPD_INT_RECORD_TYPE
5471bb76ff1Sjsg 			&& sizeof(struct atom_hpd_int_record) <=
5481bb76ff1Sjsg 							header->record_size)
5491bb76ff1Sjsg 			return (struct atom_hpd_int_record *) header;
5501bb76ff1Sjsg 
5511bb76ff1Sjsg 		offset += header->record_size;
5521bb76ff1Sjsg 	}
5531bb76ff1Sjsg 
5541bb76ff1Sjsg 	return NULL;
5551bb76ff1Sjsg }
5561bb76ff1Sjsg 
557fb4d8502Sjsg static enum bp_result bios_parser_get_hpd_info(
558fb4d8502Sjsg 	struct dc_bios *dcb,
559fb4d8502Sjsg 	struct graphics_object_id id,
560fb4d8502Sjsg 	struct graphics_object_hpd_info *info)
561fb4d8502Sjsg {
562fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
563fb4d8502Sjsg 	struct atom_display_object_path_v2 *object;
5641bb76ff1Sjsg 	struct atom_display_object_path_v3 *object_path_v3;
565fb4d8502Sjsg 	struct atom_hpd_int_record *record = NULL;
566fb4d8502Sjsg 
567fb4d8502Sjsg 	if (!info)
568fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
569fb4d8502Sjsg 
5701bb76ff1Sjsg 	switch (bp->object_info_tbl.revision.minor) {
5711bb76ff1Sjsg 	    case 4:
5721bb76ff1Sjsg 	    default:
573fb4d8502Sjsg 	        object = get_bios_object(bp, id);
574fb4d8502Sjsg 
575fb4d8502Sjsg 		if (!object)
576fb4d8502Sjsg 			return BP_RESULT_BADINPUT;
577fb4d8502Sjsg 
578fb4d8502Sjsg 	        record = get_hpd_record(bp, object);
579fb4d8502Sjsg 
5801bb76ff1Sjsg 	        break;
5811bb76ff1Sjsg 	    case 5:
5821bb76ff1Sjsg 		object_path_v3 = get_bios_object_from_path_v3(bp, id);
5831bb76ff1Sjsg 
5841bb76ff1Sjsg 		if (!object_path_v3)
5851bb76ff1Sjsg 			return BP_RESULT_BADINPUT;
5861bb76ff1Sjsg 
5871bb76ff1Sjsg 		record = get_hpd_record_for_path_v3(bp, object_path_v3);
5881bb76ff1Sjsg 		break;
5891bb76ff1Sjsg 	}
5901bb76ff1Sjsg 
591fb4d8502Sjsg 	if (record != NULL) {
592fb4d8502Sjsg 		info->hpd_int_gpio_uid = record->pin_id;
593fb4d8502Sjsg 		info->hpd_active = record->plugin_pin_state;
594fb4d8502Sjsg 		return BP_RESULT_OK;
595fb4d8502Sjsg 	}
596fb4d8502Sjsg 
597fb4d8502Sjsg 	return BP_RESULT_NORECORD;
598fb4d8502Sjsg }
599fb4d8502Sjsg 
600fb4d8502Sjsg static struct atom_hpd_int_record *get_hpd_record(
601fb4d8502Sjsg 	struct bios_parser *bp,
602fb4d8502Sjsg 	struct atom_display_object_path_v2 *object)
603fb4d8502Sjsg {
604fb4d8502Sjsg 	struct atom_common_record_header *header;
605fb4d8502Sjsg 	uint32_t offset;
606fb4d8502Sjsg 
607fb4d8502Sjsg 	if (!object) {
608fb4d8502Sjsg 		BREAK_TO_DEBUGGER(); /* Invalid object */
609fb4d8502Sjsg 		return NULL;
610fb4d8502Sjsg 	}
611fb4d8502Sjsg 
612fb4d8502Sjsg 	offset = le16_to_cpu(object->disp_recordoffset)
613fb4d8502Sjsg 			+ bp->object_info_tbl_offset;
614fb4d8502Sjsg 
615fb4d8502Sjsg 	for (;;) {
616fb4d8502Sjsg 		header = GET_IMAGE(struct atom_common_record_header, offset);
617fb4d8502Sjsg 
618fb4d8502Sjsg 		if (!header)
619fb4d8502Sjsg 			return NULL;
620fb4d8502Sjsg 
621fb4d8502Sjsg 		if (header->record_type == LAST_RECORD_TYPE ||
622fb4d8502Sjsg 			!header->record_size)
623fb4d8502Sjsg 			break;
624fb4d8502Sjsg 
625fb4d8502Sjsg 		if (header->record_type == ATOM_HPD_INT_RECORD_TYPE
626fb4d8502Sjsg 			&& sizeof(struct atom_hpd_int_record) <=
627fb4d8502Sjsg 							header->record_size)
628fb4d8502Sjsg 			return (struct atom_hpd_int_record *) header;
629fb4d8502Sjsg 
630fb4d8502Sjsg 		offset += header->record_size;
631fb4d8502Sjsg 	}
632fb4d8502Sjsg 
633fb4d8502Sjsg 	return NULL;
634fb4d8502Sjsg }
635fb4d8502Sjsg 
636fb4d8502Sjsg /**
637fb4d8502Sjsg  * bios_parser_get_gpio_pin_info
638fb4d8502Sjsg  * Get GpioPin information of input gpio id
639fb4d8502Sjsg  *
6405ca02815Sjsg  * @dcb:     pointer to the DC BIOS
6415ca02815Sjsg  * @gpio_id: GPIO ID
6425ca02815Sjsg  * @info:    GpioPin information structure
6435ca02815Sjsg  * return: Bios parser result code
6445ca02815Sjsg  * note:
645fb4d8502Sjsg  *  to get the GPIO PIN INFO, we need:
646fb4d8502Sjsg  *  1. get the GPIO_ID from other object table, see GetHPDInfo()
647fb4d8502Sjsg  *  2. in DATA_TABLE.GPIO_Pin_LUT, search all records,
648fb4d8502Sjsg  *	to get the registerA  offset/mask
649fb4d8502Sjsg  */
650fb4d8502Sjsg static enum bp_result bios_parser_get_gpio_pin_info(
651fb4d8502Sjsg 	struct dc_bios *dcb,
652fb4d8502Sjsg 	uint32_t gpio_id,
653fb4d8502Sjsg 	struct gpio_pin_info *info)
654fb4d8502Sjsg {
655fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
656fb4d8502Sjsg 	struct atom_gpio_pin_lut_v2_1 *header;
657fb4d8502Sjsg 	uint32_t count = 0;
658fb4d8502Sjsg 	uint32_t i = 0;
659fb4d8502Sjsg 
660fb4d8502Sjsg 	if (!DATA_TABLES(gpio_pin_lut))
661fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
662fb4d8502Sjsg 
663fb4d8502Sjsg 	header = GET_IMAGE(struct atom_gpio_pin_lut_v2_1,
664fb4d8502Sjsg 						DATA_TABLES(gpio_pin_lut));
665fb4d8502Sjsg 	if (!header)
666fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
667fb4d8502Sjsg 
668fb4d8502Sjsg 	if (sizeof(struct atom_common_table_header) +
669fb4d8502Sjsg 			sizeof(struct atom_gpio_pin_assignment)
670fb4d8502Sjsg 			> le16_to_cpu(header->table_header.structuresize))
671fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
672fb4d8502Sjsg 
673fb4d8502Sjsg 	if (header->table_header.content_revision != 1)
674fb4d8502Sjsg 		return BP_RESULT_UNSUPPORTED;
675fb4d8502Sjsg 
676fb4d8502Sjsg 	/* Temporary hard code gpio pin info */
677fb4d8502Sjsg 	count = (le16_to_cpu(header->table_header.structuresize)
678fb4d8502Sjsg 			- sizeof(struct atom_common_table_header))
679fb4d8502Sjsg 				/ sizeof(struct atom_gpio_pin_assignment);
680fb4d8502Sjsg 	for (i = 0; i < count; ++i) {
681fb4d8502Sjsg 		if (header->gpio_pin[i].gpio_id != gpio_id)
682fb4d8502Sjsg 			continue;
683fb4d8502Sjsg 
684fb4d8502Sjsg 		info->offset =
685fb4d8502Sjsg 			(uint32_t) le16_to_cpu(
686fb4d8502Sjsg 					header->gpio_pin[i].data_a_reg_index);
687fb4d8502Sjsg 		info->offset_y = info->offset + 2;
688fb4d8502Sjsg 		info->offset_en = info->offset + 1;
689fb4d8502Sjsg 		info->offset_mask = info->offset - 1;
690fb4d8502Sjsg 
691fb4d8502Sjsg 		info->mask = (uint32_t) (1 <<
692fb4d8502Sjsg 			header->gpio_pin[i].gpio_bitshift);
693fb4d8502Sjsg 		info->mask_y = info->mask + 2;
694fb4d8502Sjsg 		info->mask_en = info->mask + 1;
695fb4d8502Sjsg 		info->mask_mask = info->mask - 1;
696fb4d8502Sjsg 
697fb4d8502Sjsg 		return BP_RESULT_OK;
698fb4d8502Sjsg 	}
699fb4d8502Sjsg 
700fb4d8502Sjsg 	return BP_RESULT_NORECORD;
701fb4d8502Sjsg }
702fb4d8502Sjsg 
703fb4d8502Sjsg static struct device_id device_type_from_device_id(uint16_t device_id)
704fb4d8502Sjsg {
705fb4d8502Sjsg 
706fb4d8502Sjsg 	struct device_id result_device_id;
707fb4d8502Sjsg 
708fb4d8502Sjsg 	result_device_id.raw_device_tag = device_id;
709fb4d8502Sjsg 
710fb4d8502Sjsg 	switch (device_id) {
711fb4d8502Sjsg 	case ATOM_DISPLAY_LCD1_SUPPORT:
712fb4d8502Sjsg 		result_device_id.device_type = DEVICE_TYPE_LCD;
713fb4d8502Sjsg 		result_device_id.enum_id = 1;
714fb4d8502Sjsg 		break;
715fb4d8502Sjsg 
7165ca02815Sjsg 	case ATOM_DISPLAY_LCD2_SUPPORT:
7175ca02815Sjsg 		result_device_id.device_type = DEVICE_TYPE_LCD;
7185ca02815Sjsg 		result_device_id.enum_id = 2;
7195ca02815Sjsg 		break;
7205ca02815Sjsg 
721fb4d8502Sjsg 	case ATOM_DISPLAY_DFP1_SUPPORT:
722fb4d8502Sjsg 		result_device_id.device_type = DEVICE_TYPE_DFP;
723fb4d8502Sjsg 		result_device_id.enum_id = 1;
724fb4d8502Sjsg 		break;
725fb4d8502Sjsg 
726fb4d8502Sjsg 	case ATOM_DISPLAY_DFP2_SUPPORT:
727fb4d8502Sjsg 		result_device_id.device_type = DEVICE_TYPE_DFP;
728fb4d8502Sjsg 		result_device_id.enum_id = 2;
729fb4d8502Sjsg 		break;
730fb4d8502Sjsg 
731fb4d8502Sjsg 	case ATOM_DISPLAY_DFP3_SUPPORT:
732fb4d8502Sjsg 		result_device_id.device_type = DEVICE_TYPE_DFP;
733fb4d8502Sjsg 		result_device_id.enum_id = 3;
734fb4d8502Sjsg 		break;
735fb4d8502Sjsg 
736fb4d8502Sjsg 	case ATOM_DISPLAY_DFP4_SUPPORT:
737fb4d8502Sjsg 		result_device_id.device_type = DEVICE_TYPE_DFP;
738fb4d8502Sjsg 		result_device_id.enum_id = 4;
739fb4d8502Sjsg 		break;
740fb4d8502Sjsg 
741fb4d8502Sjsg 	case ATOM_DISPLAY_DFP5_SUPPORT:
742fb4d8502Sjsg 		result_device_id.device_type = DEVICE_TYPE_DFP;
743fb4d8502Sjsg 		result_device_id.enum_id = 5;
744fb4d8502Sjsg 		break;
745fb4d8502Sjsg 
746fb4d8502Sjsg 	case ATOM_DISPLAY_DFP6_SUPPORT:
747fb4d8502Sjsg 		result_device_id.device_type = DEVICE_TYPE_DFP;
748fb4d8502Sjsg 		result_device_id.enum_id = 6;
749fb4d8502Sjsg 		break;
750fb4d8502Sjsg 
751fb4d8502Sjsg 	default:
752fb4d8502Sjsg 		BREAK_TO_DEBUGGER(); /* Invalid device Id */
753fb4d8502Sjsg 		result_device_id.device_type = DEVICE_TYPE_UNKNOWN;
754fb4d8502Sjsg 		result_device_id.enum_id = 0;
755fb4d8502Sjsg 	}
756fb4d8502Sjsg 	return result_device_id;
757fb4d8502Sjsg }
758fb4d8502Sjsg 
759fb4d8502Sjsg static enum bp_result bios_parser_get_device_tag(
760fb4d8502Sjsg 	struct dc_bios *dcb,
761fb4d8502Sjsg 	struct graphics_object_id connector_object_id,
762fb4d8502Sjsg 	uint32_t device_tag_index,
763fb4d8502Sjsg 	struct connector_device_tag_info *info)
764fb4d8502Sjsg {
765fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
766fb4d8502Sjsg 	struct atom_display_object_path_v2 *object;
767fb4d8502Sjsg 
7681bb76ff1Sjsg 	struct atom_display_object_path_v3 *object_path_v3;
7691bb76ff1Sjsg 
7701bb76ff1Sjsg 
771fb4d8502Sjsg 	if (!info)
772fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
773fb4d8502Sjsg 
7741bb76ff1Sjsg 	switch (bp->object_info_tbl.revision.minor) {
7751bb76ff1Sjsg 	case 4:
7761bb76ff1Sjsg 	default:
777fb4d8502Sjsg 	        /* getBiosObject will return MXM object */
778fb4d8502Sjsg 		object = get_bios_object(bp, connector_object_id);
779fb4d8502Sjsg 
780fb4d8502Sjsg 		if (!object) {
781fb4d8502Sjsg 			BREAK_TO_DEBUGGER(); /* Invalid object id */
782fb4d8502Sjsg 			return BP_RESULT_BADINPUT;
783fb4d8502Sjsg 		}
784fb4d8502Sjsg 
785fb4d8502Sjsg 		info->acpi_device = 0; /* BIOS no longer provides this */
786fb4d8502Sjsg 		info->dev_id = device_type_from_device_id(object->device_tag);
7871bb76ff1Sjsg 		break;
7881bb76ff1Sjsg 	case 5:
7891bb76ff1Sjsg 		object_path_v3 = get_bios_object_from_path_v3(bp, connector_object_id);
7901bb76ff1Sjsg 
7911bb76ff1Sjsg 		if (!object_path_v3) {
7921bb76ff1Sjsg 			BREAK_TO_DEBUGGER(); /* Invalid object id */
7931bb76ff1Sjsg 			return BP_RESULT_BADINPUT;
7941bb76ff1Sjsg 		}
7951bb76ff1Sjsg 		info->acpi_device = 0; /* BIOS no longer provides this */
7961bb76ff1Sjsg 		info->dev_id = device_type_from_device_id(object_path_v3->device_tag);
7971bb76ff1Sjsg 		break;
7981bb76ff1Sjsg 	}
799fb4d8502Sjsg 
800fb4d8502Sjsg 	return BP_RESULT_OK;
801fb4d8502Sjsg }
802fb4d8502Sjsg 
803fb4d8502Sjsg static enum bp_result get_ss_info_v4_1(
804fb4d8502Sjsg 	struct bios_parser *bp,
805fb4d8502Sjsg 	uint32_t id,
806fb4d8502Sjsg 	uint32_t index,
807fb4d8502Sjsg 	struct spread_spectrum_info *ss_info)
808fb4d8502Sjsg {
809fb4d8502Sjsg 	enum bp_result result = BP_RESULT_OK;
810fb4d8502Sjsg 	struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL;
811c349dbc7Sjsg 	struct atom_smu_info_v3_3 *smu_info = NULL;
812fb4d8502Sjsg 
813fb4d8502Sjsg 	if (!ss_info)
814fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
815fb4d8502Sjsg 
816fb4d8502Sjsg 	if (!DATA_TABLES(dce_info))
817fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
818fb4d8502Sjsg 
819fb4d8502Sjsg 	disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_1,
820fb4d8502Sjsg 							DATA_TABLES(dce_info));
821fb4d8502Sjsg 	if (!disp_cntl_tbl)
822fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
823fb4d8502Sjsg 
824c349dbc7Sjsg 
825fb4d8502Sjsg 	ss_info->type.STEP_AND_DELAY_INFO = false;
826fb4d8502Sjsg 	ss_info->spread_percentage_divider = 1000;
827fb4d8502Sjsg 	/* BIOS no longer uses target clock.  Always enable for now */
828fb4d8502Sjsg 	ss_info->target_clock_range = 0xffffffff;
829fb4d8502Sjsg 
830fb4d8502Sjsg 	switch (id) {
831fb4d8502Sjsg 	case AS_SIGNAL_TYPE_DVI:
832fb4d8502Sjsg 		ss_info->spread_spectrum_percentage =
833fb4d8502Sjsg 				disp_cntl_tbl->dvi_ss_percentage;
834fb4d8502Sjsg 		ss_info->spread_spectrum_range =
835fb4d8502Sjsg 				disp_cntl_tbl->dvi_ss_rate_10hz * 10;
836fb4d8502Sjsg 		if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
837fb4d8502Sjsg 			ss_info->type.CENTER_MODE = true;
8381bb76ff1Sjsg 
8391bb76ff1Sjsg 		DC_LOG_BIOS("AS_SIGNAL_TYPE_DVI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
840fb4d8502Sjsg 		break;
841fb4d8502Sjsg 	case AS_SIGNAL_TYPE_HDMI:
842fb4d8502Sjsg 		ss_info->spread_spectrum_percentage =
843fb4d8502Sjsg 				disp_cntl_tbl->hdmi_ss_percentage;
844fb4d8502Sjsg 		ss_info->spread_spectrum_range =
845fb4d8502Sjsg 				disp_cntl_tbl->hdmi_ss_rate_10hz * 10;
846fb4d8502Sjsg 		if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
847fb4d8502Sjsg 			ss_info->type.CENTER_MODE = true;
8481bb76ff1Sjsg 
8491bb76ff1Sjsg 		DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
850fb4d8502Sjsg 		break;
851fb4d8502Sjsg 	/* TODO LVDS not support anymore? */
852fb4d8502Sjsg 	case AS_SIGNAL_TYPE_DISPLAY_PORT:
853fb4d8502Sjsg 		ss_info->spread_spectrum_percentage =
854fb4d8502Sjsg 				disp_cntl_tbl->dp_ss_percentage;
855fb4d8502Sjsg 		ss_info->spread_spectrum_range =
856fb4d8502Sjsg 				disp_cntl_tbl->dp_ss_rate_10hz * 10;
857fb4d8502Sjsg 		if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
858fb4d8502Sjsg 			ss_info->type.CENTER_MODE = true;
8591bb76ff1Sjsg 
8601bb76ff1Sjsg 		DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
861fb4d8502Sjsg 		break;
862fb4d8502Sjsg 	case AS_SIGNAL_TYPE_GPU_PLL:
863fb4d8502Sjsg 		/* atom_firmware: DAL only get data from dce_info table.
864fb4d8502Sjsg 		 * if data within smu_info is needed for DAL, VBIOS should
865fb4d8502Sjsg 		 * copy it into dce_info
866fb4d8502Sjsg 		 */
867fb4d8502Sjsg 		result = BP_RESULT_UNSUPPORTED;
868fb4d8502Sjsg 		break;
869c349dbc7Sjsg 	case AS_SIGNAL_TYPE_XGMI:
870c349dbc7Sjsg 		smu_info =  GET_IMAGE(struct atom_smu_info_v3_3,
871c349dbc7Sjsg 				      DATA_TABLES(smu_info));
872c349dbc7Sjsg 		if (!smu_info)
873c349dbc7Sjsg 			return BP_RESULT_BADBIOSTABLE;
8741bb76ff1Sjsg 		DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info->gpuclk_ss_percentage);
875c349dbc7Sjsg 		ss_info->spread_spectrum_percentage =
876c349dbc7Sjsg 				smu_info->waflclk_ss_percentage;
877c349dbc7Sjsg 		ss_info->spread_spectrum_range =
878c349dbc7Sjsg 				smu_info->gpuclk_ss_rate_10hz * 10;
879c349dbc7Sjsg 		if (smu_info->waflclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
880c349dbc7Sjsg 			ss_info->type.CENTER_MODE = true;
8811bb76ff1Sjsg 
8821bb76ff1Sjsg 		DC_LOG_BIOS("AS_SIGNAL_TYPE_XGMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
883c349dbc7Sjsg 		break;
884fb4d8502Sjsg 	default:
885fb4d8502Sjsg 		result = BP_RESULT_UNSUPPORTED;
886fb4d8502Sjsg 	}
887fb4d8502Sjsg 
888fb4d8502Sjsg 	return result;
889fb4d8502Sjsg }
890fb4d8502Sjsg 
891fb4d8502Sjsg static enum bp_result get_ss_info_v4_2(
892fb4d8502Sjsg 	struct bios_parser *bp,
893fb4d8502Sjsg 	uint32_t id,
894fb4d8502Sjsg 	uint32_t index,
895fb4d8502Sjsg 	struct spread_spectrum_info *ss_info)
896fb4d8502Sjsg {
897fb4d8502Sjsg 	enum bp_result result = BP_RESULT_OK;
898fb4d8502Sjsg 	struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL;
899fb4d8502Sjsg 	struct atom_smu_info_v3_1 *smu_info = NULL;
900fb4d8502Sjsg 
901fb4d8502Sjsg 	if (!ss_info)
902fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
903fb4d8502Sjsg 
904fb4d8502Sjsg 	if (!DATA_TABLES(dce_info))
905fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
906fb4d8502Sjsg 
907fb4d8502Sjsg 	if (!DATA_TABLES(smu_info))
908fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
909fb4d8502Sjsg 
910fb4d8502Sjsg 	disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_2,
911fb4d8502Sjsg 							DATA_TABLES(dce_info));
912fb4d8502Sjsg 	if (!disp_cntl_tbl)
913fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
914fb4d8502Sjsg 
915fb4d8502Sjsg 	smu_info =  GET_IMAGE(struct atom_smu_info_v3_1, DATA_TABLES(smu_info));
916fb4d8502Sjsg 	if (!smu_info)
917fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
918fb4d8502Sjsg 
9191bb76ff1Sjsg 	DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info->gpuclk_ss_percentage);
920fb4d8502Sjsg 	ss_info->type.STEP_AND_DELAY_INFO = false;
921fb4d8502Sjsg 	ss_info->spread_percentage_divider = 1000;
922fb4d8502Sjsg 	/* BIOS no longer uses target clock.  Always enable for now */
923fb4d8502Sjsg 	ss_info->target_clock_range = 0xffffffff;
924fb4d8502Sjsg 
925fb4d8502Sjsg 	switch (id) {
926fb4d8502Sjsg 	case AS_SIGNAL_TYPE_DVI:
927fb4d8502Sjsg 		ss_info->spread_spectrum_percentage =
928fb4d8502Sjsg 				disp_cntl_tbl->dvi_ss_percentage;
929fb4d8502Sjsg 		ss_info->spread_spectrum_range =
930fb4d8502Sjsg 				disp_cntl_tbl->dvi_ss_rate_10hz * 10;
931fb4d8502Sjsg 		if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
932fb4d8502Sjsg 			ss_info->type.CENTER_MODE = true;
9331bb76ff1Sjsg 
9341bb76ff1Sjsg 		DC_LOG_BIOS("AS_SIGNAL_TYPE_DVI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
935fb4d8502Sjsg 		break;
936fb4d8502Sjsg 	case AS_SIGNAL_TYPE_HDMI:
937fb4d8502Sjsg 		ss_info->spread_spectrum_percentage =
938fb4d8502Sjsg 				disp_cntl_tbl->hdmi_ss_percentage;
939fb4d8502Sjsg 		ss_info->spread_spectrum_range =
940fb4d8502Sjsg 				disp_cntl_tbl->hdmi_ss_rate_10hz * 10;
941fb4d8502Sjsg 		if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
942fb4d8502Sjsg 			ss_info->type.CENTER_MODE = true;
9431bb76ff1Sjsg 
9441bb76ff1Sjsg 		DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
945fb4d8502Sjsg 		break;
946fb4d8502Sjsg 	/* TODO LVDS not support anymore? */
947fb4d8502Sjsg 	case AS_SIGNAL_TYPE_DISPLAY_PORT:
948fb4d8502Sjsg 		ss_info->spread_spectrum_percentage =
949fb4d8502Sjsg 				smu_info->gpuclk_ss_percentage;
950fb4d8502Sjsg 		ss_info->spread_spectrum_range =
951fb4d8502Sjsg 				smu_info->gpuclk_ss_rate_10hz * 10;
952fb4d8502Sjsg 		if (smu_info->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
953fb4d8502Sjsg 			ss_info->type.CENTER_MODE = true;
9541bb76ff1Sjsg 
9551bb76ff1Sjsg 		DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
956fb4d8502Sjsg 		break;
957fb4d8502Sjsg 	case AS_SIGNAL_TYPE_GPU_PLL:
958fb4d8502Sjsg 		/* atom_firmware: DAL only get data from dce_info table.
959fb4d8502Sjsg 		 * if data within smu_info is needed for DAL, VBIOS should
960fb4d8502Sjsg 		 * copy it into dce_info
961fb4d8502Sjsg 		 */
962fb4d8502Sjsg 		result = BP_RESULT_UNSUPPORTED;
963fb4d8502Sjsg 		break;
964fb4d8502Sjsg 	default:
965fb4d8502Sjsg 		result = BP_RESULT_UNSUPPORTED;
966fb4d8502Sjsg 	}
967fb4d8502Sjsg 
968fb4d8502Sjsg 	return result;
969fb4d8502Sjsg }
970fb4d8502Sjsg 
9711bb76ff1Sjsg static enum bp_result get_ss_info_v4_5(
9721bb76ff1Sjsg 	struct bios_parser *bp,
9731bb76ff1Sjsg 	uint32_t id,
9741bb76ff1Sjsg 	uint32_t index,
9751bb76ff1Sjsg 	struct spread_spectrum_info *ss_info)
9761bb76ff1Sjsg {
9771bb76ff1Sjsg 	enum bp_result result = BP_RESULT_OK;
9781bb76ff1Sjsg 	struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
9791bb76ff1Sjsg 
9801bb76ff1Sjsg 	if (!ss_info)
9811bb76ff1Sjsg 		return BP_RESULT_BADINPUT;
9821bb76ff1Sjsg 
9831bb76ff1Sjsg 	if (!DATA_TABLES(dce_info))
9841bb76ff1Sjsg 		return BP_RESULT_BADBIOSTABLE;
9851bb76ff1Sjsg 
9861bb76ff1Sjsg 	disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_5,
9871bb76ff1Sjsg 							DATA_TABLES(dce_info));
9881bb76ff1Sjsg 	if (!disp_cntl_tbl)
9891bb76ff1Sjsg 		return BP_RESULT_BADBIOSTABLE;
9901bb76ff1Sjsg 
9911bb76ff1Sjsg 	ss_info->type.STEP_AND_DELAY_INFO = false;
9921bb76ff1Sjsg 	ss_info->spread_percentage_divider = 1000;
9931bb76ff1Sjsg 	/* BIOS no longer uses target clock.  Always enable for now */
9941bb76ff1Sjsg 	ss_info->target_clock_range = 0xffffffff;
9951bb76ff1Sjsg 
9961bb76ff1Sjsg 	switch (id) {
9971bb76ff1Sjsg 	case AS_SIGNAL_TYPE_DVI:
9981bb76ff1Sjsg 		ss_info->spread_spectrum_percentage =
9991bb76ff1Sjsg 				disp_cntl_tbl->dvi_ss_percentage;
10001bb76ff1Sjsg 		ss_info->spread_spectrum_range =
10011bb76ff1Sjsg 				disp_cntl_tbl->dvi_ss_rate_10hz * 10;
10021bb76ff1Sjsg 		if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
10031bb76ff1Sjsg 			ss_info->type.CENTER_MODE = true;
10041bb76ff1Sjsg 
10051bb76ff1Sjsg 		DC_LOG_BIOS("AS_SIGNAL_TYPE_DVI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
10061bb76ff1Sjsg 		break;
10071bb76ff1Sjsg 	case AS_SIGNAL_TYPE_HDMI:
10081bb76ff1Sjsg 		ss_info->spread_spectrum_percentage =
10091bb76ff1Sjsg 				disp_cntl_tbl->hdmi_ss_percentage;
10101bb76ff1Sjsg 		ss_info->spread_spectrum_range =
10111bb76ff1Sjsg 				disp_cntl_tbl->hdmi_ss_rate_10hz * 10;
10121bb76ff1Sjsg 		if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
10131bb76ff1Sjsg 			ss_info->type.CENTER_MODE = true;
10141bb76ff1Sjsg 
10151bb76ff1Sjsg 		DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
10161bb76ff1Sjsg 		break;
10171bb76ff1Sjsg 	case AS_SIGNAL_TYPE_DISPLAY_PORT:
10182d4ce006Sjsg 		if (bp->base.integrated_info) {
10192d4ce006Sjsg 			DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", bp->base.integrated_info->gpuclk_ss_percentage);
10202d4ce006Sjsg 			ss_info->spread_spectrum_percentage =
10212d4ce006Sjsg 					bp->base.integrated_info->gpuclk_ss_percentage;
10222d4ce006Sjsg 			ss_info->type.CENTER_MODE =
10232d4ce006Sjsg 					bp->base.integrated_info->gpuclk_ss_type;
10242d4ce006Sjsg 		} else {
10251bb76ff1Sjsg 			ss_info->spread_spectrum_percentage =
10261bb76ff1Sjsg 				disp_cntl_tbl->dp_ss_percentage;
10271bb76ff1Sjsg 			ss_info->spread_spectrum_range =
10281bb76ff1Sjsg 				disp_cntl_tbl->dp_ss_rate_10hz * 10;
10291bb76ff1Sjsg 			if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
10301bb76ff1Sjsg 				ss_info->type.CENTER_MODE = true;
10312d4ce006Sjsg 		}
10321bb76ff1Sjsg 		DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage);
10331bb76ff1Sjsg 		break;
10341bb76ff1Sjsg 	case AS_SIGNAL_TYPE_GPU_PLL:
10351bb76ff1Sjsg 		/* atom_smu_info_v4_0 does not have fields for SS for SMU Display PLL anymore.
10361bb76ff1Sjsg 		 * SMU Display PLL supposed to be without spread.
10371bb76ff1Sjsg 		 * Better place for it would be in atom_display_controller_info_v4_5 table.
10381bb76ff1Sjsg 		 */
10391bb76ff1Sjsg 		result = BP_RESULT_UNSUPPORTED;
10401bb76ff1Sjsg 		break;
10411bb76ff1Sjsg 	default:
10421bb76ff1Sjsg 		result = BP_RESULT_UNSUPPORTED;
10431bb76ff1Sjsg 		break;
10441bb76ff1Sjsg 	}
10451bb76ff1Sjsg 
10461bb76ff1Sjsg 	return result;
10471bb76ff1Sjsg }
10481bb76ff1Sjsg 
1049fb4d8502Sjsg /**
1050fb4d8502Sjsg  * bios_parser_get_spread_spectrum_info
1051fb4d8502Sjsg  * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or
1052fb4d8502Sjsg  * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info
1053fb4d8502Sjsg  * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info
1054fb4d8502Sjsg  * ver 3.1,
1055fb4d8502Sjsg  * there is only one entry for each signal /ss id.  However, there is
1056fb4d8502Sjsg  * no planning of supporting multiple spread Sprectum entry for EverGreen
10575ca02815Sjsg  * @dcb:     pointer to the DC BIOS
10585ca02815Sjsg  * @signal:  ASSignalType to be converted to info index
10595ca02815Sjsg  * @index:   number of entries that match the converted info index
10605ca02815Sjsg  * @ss_info: sprectrum information structure,
10615ca02815Sjsg  * return: Bios parser result code
1062fb4d8502Sjsg  */
1063fb4d8502Sjsg static enum bp_result bios_parser_get_spread_spectrum_info(
1064fb4d8502Sjsg 	struct dc_bios *dcb,
1065fb4d8502Sjsg 	enum as_signal_type signal,
1066fb4d8502Sjsg 	uint32_t index,
1067fb4d8502Sjsg 	struct spread_spectrum_info *ss_info)
1068fb4d8502Sjsg {
1069fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1070fb4d8502Sjsg 	enum bp_result result = BP_RESULT_UNSUPPORTED;
1071fb4d8502Sjsg 	struct atom_common_table_header *header;
1072fb4d8502Sjsg 	struct atom_data_revision tbl_revision;
1073fb4d8502Sjsg 
1074fb4d8502Sjsg 	if (!ss_info) /* check for bad input */
1075fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
1076fb4d8502Sjsg 
1077fb4d8502Sjsg 	if (!DATA_TABLES(dce_info))
1078fb4d8502Sjsg 		return BP_RESULT_UNSUPPORTED;
1079fb4d8502Sjsg 
1080fb4d8502Sjsg 	header = GET_IMAGE(struct atom_common_table_header,
1081fb4d8502Sjsg 						DATA_TABLES(dce_info));
1082fb4d8502Sjsg 	get_atom_data_table_revision(header, &tbl_revision);
1083fb4d8502Sjsg 
1084fb4d8502Sjsg 	switch (tbl_revision.major) {
1085fb4d8502Sjsg 	case 4:
1086fb4d8502Sjsg 		switch (tbl_revision.minor) {
1087fb4d8502Sjsg 		case 1:
1088fb4d8502Sjsg 			return get_ss_info_v4_1(bp, signal, index, ss_info);
1089fb4d8502Sjsg 		case 2:
1090c349dbc7Sjsg 		case 3:
10915ca02815Sjsg 		case 4:
1092fb4d8502Sjsg 			return get_ss_info_v4_2(bp, signal, index, ss_info);
10931bb76ff1Sjsg 		case 5:
10941bb76ff1Sjsg 			return get_ss_info_v4_5(bp, signal, index, ss_info);
10951bb76ff1Sjsg 
1096fb4d8502Sjsg 		default:
10975ca02815Sjsg 			ASSERT(0);
1098fb4d8502Sjsg 			break;
1099fb4d8502Sjsg 		}
1100fb4d8502Sjsg 		break;
1101fb4d8502Sjsg 	default:
1102fb4d8502Sjsg 		break;
1103fb4d8502Sjsg 	}
1104fb4d8502Sjsg 	/* there can not be more then one entry for SS Info table */
1105fb4d8502Sjsg 	return result;
1106fb4d8502Sjsg }
1107fb4d8502Sjsg 
1108ad8b1aafSjsg static enum bp_result get_soc_bb_info_v4_4(
1109ad8b1aafSjsg 	struct bios_parser *bp,
1110ad8b1aafSjsg 	struct bp_soc_bb_info *soc_bb_info)
1111ad8b1aafSjsg {
1112ad8b1aafSjsg 	enum bp_result result = BP_RESULT_OK;
1113ad8b1aafSjsg 	struct atom_display_controller_info_v4_4 *disp_cntl_tbl = NULL;
1114ad8b1aafSjsg 
1115ad8b1aafSjsg 	if (!soc_bb_info)
1116ad8b1aafSjsg 		return BP_RESULT_BADINPUT;
1117ad8b1aafSjsg 
1118ad8b1aafSjsg 	if (!DATA_TABLES(dce_info))
1119ad8b1aafSjsg 		return BP_RESULT_BADBIOSTABLE;
1120ad8b1aafSjsg 
1121ad8b1aafSjsg 	if (!DATA_TABLES(smu_info))
1122ad8b1aafSjsg 		return BP_RESULT_BADBIOSTABLE;
1123ad8b1aafSjsg 
1124ad8b1aafSjsg 	disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_4,
1125ad8b1aafSjsg 							DATA_TABLES(dce_info));
1126ad8b1aafSjsg 	if (!disp_cntl_tbl)
1127ad8b1aafSjsg 		return BP_RESULT_BADBIOSTABLE;
1128ad8b1aafSjsg 
1129ad8b1aafSjsg 	soc_bb_info->dram_clock_change_latency_100ns = disp_cntl_tbl->max_mclk_chg_lat;
1130ad8b1aafSjsg 	soc_bb_info->dram_sr_enter_exit_latency_100ns = disp_cntl_tbl->max_sr_enter_exit_lat;
1131ad8b1aafSjsg 	soc_bb_info->dram_sr_exit_latency_100ns = disp_cntl_tbl->max_sr_exit_lat;
1132ad8b1aafSjsg 
1133ad8b1aafSjsg 	return result;
1134ad8b1aafSjsg }
1135ad8b1aafSjsg 
11361bb76ff1Sjsg static enum bp_result get_soc_bb_info_v4_5(
11371bb76ff1Sjsg 	struct bios_parser *bp,
11381bb76ff1Sjsg 	struct bp_soc_bb_info *soc_bb_info)
11391bb76ff1Sjsg {
11401bb76ff1Sjsg 	enum bp_result result = BP_RESULT_OK;
11411bb76ff1Sjsg 	struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
11421bb76ff1Sjsg 
11431bb76ff1Sjsg 	if (!soc_bb_info)
11441bb76ff1Sjsg 		return BP_RESULT_BADINPUT;
11451bb76ff1Sjsg 
11461bb76ff1Sjsg 	if (!DATA_TABLES(dce_info))
11471bb76ff1Sjsg 		return BP_RESULT_BADBIOSTABLE;
11481bb76ff1Sjsg 
11491bb76ff1Sjsg 	disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_5,
11501bb76ff1Sjsg 							DATA_TABLES(dce_info));
11511bb76ff1Sjsg 	if (!disp_cntl_tbl)
11521bb76ff1Sjsg 		return BP_RESULT_BADBIOSTABLE;
11531bb76ff1Sjsg 
11541bb76ff1Sjsg 	soc_bb_info->dram_clock_change_latency_100ns = disp_cntl_tbl->max_mclk_chg_lat;
11551bb76ff1Sjsg 	soc_bb_info->dram_sr_enter_exit_latency_100ns = disp_cntl_tbl->max_sr_enter_exit_lat;
11561bb76ff1Sjsg 	soc_bb_info->dram_sr_exit_latency_100ns = disp_cntl_tbl->max_sr_exit_lat;
11571bb76ff1Sjsg 
11581bb76ff1Sjsg 	return result;
11591bb76ff1Sjsg }
11601bb76ff1Sjsg 
1161ad8b1aafSjsg static enum bp_result bios_parser_get_soc_bb_info(
1162ad8b1aafSjsg 	struct dc_bios *dcb,
1163ad8b1aafSjsg 	struct bp_soc_bb_info *soc_bb_info)
1164ad8b1aafSjsg {
1165ad8b1aafSjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1166ad8b1aafSjsg 	enum bp_result result = BP_RESULT_UNSUPPORTED;
1167ad8b1aafSjsg 	struct atom_common_table_header *header;
1168ad8b1aafSjsg 	struct atom_data_revision tbl_revision;
1169ad8b1aafSjsg 
1170ad8b1aafSjsg 	if (!soc_bb_info) /* check for bad input */
1171ad8b1aafSjsg 		return BP_RESULT_BADINPUT;
1172ad8b1aafSjsg 
1173ad8b1aafSjsg 	if (!DATA_TABLES(dce_info))
1174ad8b1aafSjsg 		return BP_RESULT_UNSUPPORTED;
1175ad8b1aafSjsg 
1176ad8b1aafSjsg 	header = GET_IMAGE(struct atom_common_table_header,
1177ad8b1aafSjsg 						DATA_TABLES(dce_info));
1178ad8b1aafSjsg 	get_atom_data_table_revision(header, &tbl_revision);
1179ad8b1aafSjsg 
1180ad8b1aafSjsg 	switch (tbl_revision.major) {
1181ad8b1aafSjsg 	case 4:
1182ad8b1aafSjsg 		switch (tbl_revision.minor) {
1183ad8b1aafSjsg 		case 1:
1184ad8b1aafSjsg 		case 2:
1185ad8b1aafSjsg 		case 3:
1186ad8b1aafSjsg 			break;
1187ad8b1aafSjsg 		case 4:
1188ad8b1aafSjsg 			result = get_soc_bb_info_v4_4(bp, soc_bb_info);
11895ca02815Sjsg 			break;
11901bb76ff1Sjsg 		case 5:
11911bb76ff1Sjsg 			result = get_soc_bb_info_v4_5(bp, soc_bb_info);
11921bb76ff1Sjsg 			break;
11935ca02815Sjsg 		default:
11945ca02815Sjsg 			break;
11955ca02815Sjsg 		}
11965ca02815Sjsg 		break;
11975ca02815Sjsg 	default:
11985ca02815Sjsg 		break;
11995ca02815Sjsg 	}
12005ca02815Sjsg 
12015ca02815Sjsg 	return result;
12025ca02815Sjsg }
12035ca02815Sjsg 
12045ca02815Sjsg static enum bp_result get_disp_caps_v4_1(
12055ca02815Sjsg 	struct bios_parser *bp,
12065ca02815Sjsg 	uint8_t *dce_caps)
12075ca02815Sjsg {
12085ca02815Sjsg 	enum bp_result result = BP_RESULT_OK;
12095ca02815Sjsg 	struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL;
12105ca02815Sjsg 
12115ca02815Sjsg 	if (!dce_caps)
12125ca02815Sjsg 		return BP_RESULT_BADINPUT;
12135ca02815Sjsg 
12145ca02815Sjsg 	if (!DATA_TABLES(dce_info))
12155ca02815Sjsg 		return BP_RESULT_BADBIOSTABLE;
12165ca02815Sjsg 
12175ca02815Sjsg 	disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_1,
12185ca02815Sjsg 							DATA_TABLES(dce_info));
12195ca02815Sjsg 
12205ca02815Sjsg 	if (!disp_cntl_tbl)
12215ca02815Sjsg 		return BP_RESULT_BADBIOSTABLE;
12225ca02815Sjsg 
12235ca02815Sjsg 	*dce_caps = disp_cntl_tbl->display_caps;
12245ca02815Sjsg 
12255ca02815Sjsg 	return result;
12265ca02815Sjsg }
12275ca02815Sjsg 
12285ca02815Sjsg static enum bp_result get_disp_caps_v4_2(
12295ca02815Sjsg 	struct bios_parser *bp,
12305ca02815Sjsg 	uint8_t *dce_caps)
12315ca02815Sjsg {
12325ca02815Sjsg 	enum bp_result result = BP_RESULT_OK;
12335ca02815Sjsg 	struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL;
12345ca02815Sjsg 
12355ca02815Sjsg 	if (!dce_caps)
12365ca02815Sjsg 		return BP_RESULT_BADINPUT;
12375ca02815Sjsg 
12385ca02815Sjsg 	if (!DATA_TABLES(dce_info))
12395ca02815Sjsg 		return BP_RESULT_BADBIOSTABLE;
12405ca02815Sjsg 
12415ca02815Sjsg 	disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_2,
12425ca02815Sjsg 							DATA_TABLES(dce_info));
12435ca02815Sjsg 
12445ca02815Sjsg 	if (!disp_cntl_tbl)
12455ca02815Sjsg 		return BP_RESULT_BADBIOSTABLE;
12465ca02815Sjsg 
12475ca02815Sjsg 	*dce_caps = disp_cntl_tbl->display_caps;
12485ca02815Sjsg 
12495ca02815Sjsg 	return result;
12505ca02815Sjsg }
12515ca02815Sjsg 
12525ca02815Sjsg static enum bp_result get_disp_caps_v4_3(
12535ca02815Sjsg 	struct bios_parser *bp,
12545ca02815Sjsg 	uint8_t *dce_caps)
12555ca02815Sjsg {
12565ca02815Sjsg 	enum bp_result result = BP_RESULT_OK;
12575ca02815Sjsg 	struct atom_display_controller_info_v4_3 *disp_cntl_tbl = NULL;
12585ca02815Sjsg 
12595ca02815Sjsg 	if (!dce_caps)
12605ca02815Sjsg 		return BP_RESULT_BADINPUT;
12615ca02815Sjsg 
12625ca02815Sjsg 	if (!DATA_TABLES(dce_info))
12635ca02815Sjsg 		return BP_RESULT_BADBIOSTABLE;
12645ca02815Sjsg 
12655ca02815Sjsg 	disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_3,
12665ca02815Sjsg 							DATA_TABLES(dce_info));
12675ca02815Sjsg 
12685ca02815Sjsg 	if (!disp_cntl_tbl)
12695ca02815Sjsg 		return BP_RESULT_BADBIOSTABLE;
12705ca02815Sjsg 
12715ca02815Sjsg 	*dce_caps = disp_cntl_tbl->display_caps;
12725ca02815Sjsg 
12735ca02815Sjsg 	return result;
12745ca02815Sjsg }
12755ca02815Sjsg 
12765ca02815Sjsg static enum bp_result get_disp_caps_v4_4(
12775ca02815Sjsg 	struct bios_parser *bp,
12785ca02815Sjsg 	uint8_t *dce_caps)
12795ca02815Sjsg {
12805ca02815Sjsg 	enum bp_result result = BP_RESULT_OK;
12815ca02815Sjsg 	struct atom_display_controller_info_v4_4 *disp_cntl_tbl = NULL;
12825ca02815Sjsg 
12835ca02815Sjsg 	if (!dce_caps)
12845ca02815Sjsg 		return BP_RESULT_BADINPUT;
12855ca02815Sjsg 
12865ca02815Sjsg 	if (!DATA_TABLES(dce_info))
12875ca02815Sjsg 		return BP_RESULT_BADBIOSTABLE;
12885ca02815Sjsg 
12895ca02815Sjsg 	disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_4,
12905ca02815Sjsg 							DATA_TABLES(dce_info));
12915ca02815Sjsg 
12925ca02815Sjsg 	if (!disp_cntl_tbl)
12935ca02815Sjsg 		return BP_RESULT_BADBIOSTABLE;
12945ca02815Sjsg 
12955ca02815Sjsg 	*dce_caps = disp_cntl_tbl->display_caps;
12965ca02815Sjsg 
12975ca02815Sjsg 	return result;
12985ca02815Sjsg }
12995ca02815Sjsg 
13001bb76ff1Sjsg static enum bp_result get_disp_caps_v4_5(
13011bb76ff1Sjsg 	struct bios_parser *bp,
13021bb76ff1Sjsg 	uint8_t *dce_caps)
13031bb76ff1Sjsg {
13041bb76ff1Sjsg 	enum bp_result result = BP_RESULT_OK;
13051bb76ff1Sjsg 	struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
13061bb76ff1Sjsg 
13071bb76ff1Sjsg 	if (!dce_caps)
13081bb76ff1Sjsg 		return BP_RESULT_BADINPUT;
13091bb76ff1Sjsg 
13101bb76ff1Sjsg 	if (!DATA_TABLES(dce_info))
13111bb76ff1Sjsg 		return BP_RESULT_BADBIOSTABLE;
13121bb76ff1Sjsg 
13131bb76ff1Sjsg 	disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_5,
13141bb76ff1Sjsg 							DATA_TABLES(dce_info));
13151bb76ff1Sjsg 
13161bb76ff1Sjsg 	if (!disp_cntl_tbl)
13171bb76ff1Sjsg 		return BP_RESULT_BADBIOSTABLE;
13181bb76ff1Sjsg 
13191bb76ff1Sjsg 	*dce_caps = disp_cntl_tbl->display_caps;
13201bb76ff1Sjsg 
13211bb76ff1Sjsg 	return result;
13221bb76ff1Sjsg }
13231bb76ff1Sjsg 
13245ca02815Sjsg static enum bp_result bios_parser_get_lttpr_interop(
13255ca02815Sjsg 	struct dc_bios *dcb,
13265ca02815Sjsg 	uint8_t *dce_caps)
13275ca02815Sjsg {
13285ca02815Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
13295ca02815Sjsg 	enum bp_result result = BP_RESULT_UNSUPPORTED;
13305ca02815Sjsg 	struct atom_common_table_header *header;
13315ca02815Sjsg 	struct atom_data_revision tbl_revision;
13325ca02815Sjsg 
13335ca02815Sjsg 	if (!DATA_TABLES(dce_info))
13345ca02815Sjsg 		return BP_RESULT_UNSUPPORTED;
13355ca02815Sjsg 
13365ca02815Sjsg 	header = GET_IMAGE(struct atom_common_table_header,
13375ca02815Sjsg 						DATA_TABLES(dce_info));
13385ca02815Sjsg 	get_atom_data_table_revision(header, &tbl_revision);
13395ca02815Sjsg 	switch (tbl_revision.major) {
13405ca02815Sjsg 	case 4:
13415ca02815Sjsg 		switch (tbl_revision.minor) {
13425ca02815Sjsg 		case 1:
13435ca02815Sjsg 			result = get_disp_caps_v4_1(bp, dce_caps);
13445ca02815Sjsg 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
13455ca02815Sjsg 			break;
13465ca02815Sjsg 		case 2:
13475ca02815Sjsg 			result = get_disp_caps_v4_2(bp, dce_caps);
13485ca02815Sjsg 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
13495ca02815Sjsg 			break;
13505ca02815Sjsg 		case 3:
13515ca02815Sjsg 			result = get_disp_caps_v4_3(bp, dce_caps);
13525ca02815Sjsg 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
13535ca02815Sjsg 			break;
13545ca02815Sjsg 		case 4:
13555ca02815Sjsg 			result = get_disp_caps_v4_4(bp, dce_caps);
13565ca02815Sjsg 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
13575ca02815Sjsg 			break;
13581bb76ff1Sjsg 		case 5:
13591bb76ff1Sjsg 			result = get_disp_caps_v4_5(bp, dce_caps);
13601bb76ff1Sjsg 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);
13615ca02815Sjsg 			break;
13625ca02815Sjsg 
13631bb76ff1Sjsg 		default:
13641bb76ff1Sjsg 			break;
13651bb76ff1Sjsg 		}
13661bb76ff1Sjsg 		break;
13671bb76ff1Sjsg 	default:
13681bb76ff1Sjsg 		break;
13691bb76ff1Sjsg 	}
13701bb76ff1Sjsg 	DC_LOG_BIOS("DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE: %d tbl_revision.major = %d tbl_revision.minor = %d\n", *dce_caps, tbl_revision.major, tbl_revision.minor);
13715ca02815Sjsg 	return result;
13725ca02815Sjsg }
13735ca02815Sjsg 
13745ca02815Sjsg static enum bp_result bios_parser_get_lttpr_caps(
13755ca02815Sjsg 	struct dc_bios *dcb,
13765ca02815Sjsg 	uint8_t *dce_caps)
13775ca02815Sjsg {
13785ca02815Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
13795ca02815Sjsg 	enum bp_result result = BP_RESULT_UNSUPPORTED;
13805ca02815Sjsg 	struct atom_common_table_header *header;
13815ca02815Sjsg 	struct atom_data_revision tbl_revision;
13825ca02815Sjsg 
13835ca02815Sjsg 	if (!DATA_TABLES(dce_info))
13845ca02815Sjsg 		return BP_RESULT_UNSUPPORTED;
13855ca02815Sjsg 
13861bb76ff1Sjsg 	*dce_caps  = 0;
13875ca02815Sjsg 	header = GET_IMAGE(struct atom_common_table_header,
13885ca02815Sjsg 						DATA_TABLES(dce_info));
13895ca02815Sjsg 	get_atom_data_table_revision(header, &tbl_revision);
13905ca02815Sjsg 	switch (tbl_revision.major) {
13915ca02815Sjsg 	case 4:
13925ca02815Sjsg 		switch (tbl_revision.minor) {
13935ca02815Sjsg 		case 1:
13945ca02815Sjsg 			result = get_disp_caps_v4_1(bp, dce_caps);
13955ca02815Sjsg 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
13965ca02815Sjsg 			break;
13975ca02815Sjsg 		case 2:
13985ca02815Sjsg 			result = get_disp_caps_v4_2(bp, dce_caps);
13995ca02815Sjsg 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
14005ca02815Sjsg 			break;
14015ca02815Sjsg 		case 3:
14025ca02815Sjsg 			result = get_disp_caps_v4_3(bp, dce_caps);
14035ca02815Sjsg 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
14045ca02815Sjsg 			break;
14055ca02815Sjsg 		case 4:
14065ca02815Sjsg 			result = get_disp_caps_v4_4(bp, dce_caps);
14075ca02815Sjsg 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
14085ca02815Sjsg 			break;
14091bb76ff1Sjsg 		case 5:
14101bb76ff1Sjsg 			result = get_disp_caps_v4_5(bp, dce_caps);
14111bb76ff1Sjsg 			*dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);
14121bb76ff1Sjsg 			break;
1413ad8b1aafSjsg 		default:
1414ad8b1aafSjsg 			break;
1415ad8b1aafSjsg 		}
1416ad8b1aafSjsg 		break;
1417ad8b1aafSjsg 	default:
1418ad8b1aafSjsg 		break;
1419ad8b1aafSjsg 	}
14201bb76ff1Sjsg 	DC_LOG_BIOS("DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE: %d tbl_revision.major = %d tbl_revision.minor = %d\n", *dce_caps, tbl_revision.major, tbl_revision.minor);
14211bb76ff1Sjsg 	if (dcb->ctx->dc->config.force_bios_enable_lttpr && *dce_caps == 0) {
14221bb76ff1Sjsg 		*dce_caps = 1;
14231bb76ff1Sjsg 		DC_LOG_BIOS("DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE: forced enabled");
14241bb76ff1Sjsg 	}
1425ad8b1aafSjsg 	return result;
1426ad8b1aafSjsg }
1427ad8b1aafSjsg 
1428fb4d8502Sjsg static enum bp_result get_embedded_panel_info_v2_1(
1429fb4d8502Sjsg 		struct bios_parser *bp,
1430fb4d8502Sjsg 		struct embedded_panel_info *info)
1431fb4d8502Sjsg {
1432fb4d8502Sjsg 	struct lcd_info_v2_1 *lvds;
1433fb4d8502Sjsg 
1434fb4d8502Sjsg 	if (!info)
1435fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
1436fb4d8502Sjsg 
1437fb4d8502Sjsg 	if (!DATA_TABLES(lcd_info))
1438fb4d8502Sjsg 		return BP_RESULT_UNSUPPORTED;
1439fb4d8502Sjsg 
1440fb4d8502Sjsg 	lvds = GET_IMAGE(struct lcd_info_v2_1, DATA_TABLES(lcd_info));
1441fb4d8502Sjsg 
1442fb4d8502Sjsg 	if (!lvds)
1443fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
1444fb4d8502Sjsg 
1445fb4d8502Sjsg 	/* TODO: previous vv1_3, should v2_1 */
1446fb4d8502Sjsg 	if (!((lvds->table_header.format_revision == 2)
1447fb4d8502Sjsg 			&& (lvds->table_header.content_revision >= 1)))
1448fb4d8502Sjsg 		return BP_RESULT_UNSUPPORTED;
1449fb4d8502Sjsg 
1450fb4d8502Sjsg 	memset(info, 0, sizeof(struct embedded_panel_info));
1451fb4d8502Sjsg 
1452fb4d8502Sjsg 	/* We need to convert from 10KHz units into KHz units */
1453c349dbc7Sjsg 	info->lcd_timing.pixel_clk = le16_to_cpu(lvds->lcd_timing.pixclk) * 10;
1454fb4d8502Sjsg 	/* usHActive does not include borders, according to VBIOS team */
1455c349dbc7Sjsg 	info->lcd_timing.horizontal_addressable = le16_to_cpu(lvds->lcd_timing.h_active);
1456fb4d8502Sjsg 	/* usHBlanking_Time includes borders, so we should really be
1457fb4d8502Sjsg 	 * subtractingborders duing this translation, but LVDS generally
1458fb4d8502Sjsg 	 * doesn't have borders, so we should be okay leaving this as is for
1459fb4d8502Sjsg 	 * now.  May need to revisit if we ever have LVDS with borders
1460fb4d8502Sjsg 	 */
1461c349dbc7Sjsg 	info->lcd_timing.horizontal_blanking_time = le16_to_cpu(lvds->lcd_timing.h_blanking_time);
1462fb4d8502Sjsg 	/* usVActive does not include borders, according to VBIOS team*/
1463c349dbc7Sjsg 	info->lcd_timing.vertical_addressable = le16_to_cpu(lvds->lcd_timing.v_active);
1464fb4d8502Sjsg 	/* usVBlanking_Time includes borders, so we should really be
1465fb4d8502Sjsg 	 * subtracting borders duing this translation, but LVDS generally
1466fb4d8502Sjsg 	 * doesn't have borders, so we should be okay leaving this as is for
1467fb4d8502Sjsg 	 * now. May need to revisit if we ever have LVDS with borders
1468fb4d8502Sjsg 	 */
1469c349dbc7Sjsg 	info->lcd_timing.vertical_blanking_time = le16_to_cpu(lvds->lcd_timing.v_blanking_time);
1470c349dbc7Sjsg 	info->lcd_timing.horizontal_sync_offset = le16_to_cpu(lvds->lcd_timing.h_sync_offset);
1471c349dbc7Sjsg 	info->lcd_timing.horizontal_sync_width = le16_to_cpu(lvds->lcd_timing.h_sync_width);
1472c349dbc7Sjsg 	info->lcd_timing.vertical_sync_offset = le16_to_cpu(lvds->lcd_timing.v_sync_offset);
1473c349dbc7Sjsg 	info->lcd_timing.vertical_sync_width = le16_to_cpu(lvds->lcd_timing.v_syncwidth);
1474fb4d8502Sjsg 	info->lcd_timing.horizontal_border = lvds->lcd_timing.h_border;
1475fb4d8502Sjsg 	info->lcd_timing.vertical_border = lvds->lcd_timing.v_border;
1476fb4d8502Sjsg 
1477fb4d8502Sjsg 	/* not provided by VBIOS */
1478fb4d8502Sjsg 	info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 0;
1479fb4d8502Sjsg 
1480c349dbc7Sjsg 	info->lcd_timing.misc_info.H_SYNC_POLARITY = ~(uint32_t) (lvds->lcd_timing.miscinfo
1481c349dbc7Sjsg 			& ATOM_HSYNC_POLARITY);
1482c349dbc7Sjsg 	info->lcd_timing.misc_info.V_SYNC_POLARITY = ~(uint32_t) (lvds->lcd_timing.miscinfo
1483c349dbc7Sjsg 			& ATOM_VSYNC_POLARITY);
1484fb4d8502Sjsg 
1485fb4d8502Sjsg 	/* not provided by VBIOS */
1486fb4d8502Sjsg 	info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0;
1487fb4d8502Sjsg 
1488c349dbc7Sjsg 	info->lcd_timing.misc_info.H_REPLICATION_BY2 = !!(lvds->lcd_timing.miscinfo
1489c349dbc7Sjsg 			& ATOM_H_REPLICATIONBY2);
1490c349dbc7Sjsg 	info->lcd_timing.misc_info.V_REPLICATION_BY2 = !!(lvds->lcd_timing.miscinfo
1491c349dbc7Sjsg 			& ATOM_V_REPLICATIONBY2);
1492c349dbc7Sjsg 	info->lcd_timing.misc_info.COMPOSITE_SYNC = !!(lvds->lcd_timing.miscinfo
1493c349dbc7Sjsg 			& ATOM_COMPOSITESYNC);
1494c349dbc7Sjsg 	info->lcd_timing.misc_info.INTERLACE = !!(lvds->lcd_timing.miscinfo & ATOM_INTERLACE);
1495fb4d8502Sjsg 
1496fb4d8502Sjsg 	/* not provided by VBIOS*/
1497fb4d8502Sjsg 	info->lcd_timing.misc_info.DOUBLE_CLOCK = 0;
1498fb4d8502Sjsg 	/* not provided by VBIOS*/
1499fb4d8502Sjsg 	info->ss_id = 0;
1500fb4d8502Sjsg 
1501c349dbc7Sjsg 	info->realtek_eDPToLVDS = !!(lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID);
1502fb4d8502Sjsg 
1503fb4d8502Sjsg 	return BP_RESULT_OK;
1504fb4d8502Sjsg }
1505fb4d8502Sjsg 
1506fb4d8502Sjsg static enum bp_result bios_parser_get_embedded_panel_info(
1507fb4d8502Sjsg 		struct dc_bios *dcb,
1508fb4d8502Sjsg 		struct embedded_panel_info *info)
1509fb4d8502Sjsg {
1510c349dbc7Sjsg 	struct bios_parser
1511c349dbc7Sjsg 	*bp = BP_FROM_DCB(dcb);
1512fb4d8502Sjsg 	struct atom_common_table_header *header;
1513fb4d8502Sjsg 	struct atom_data_revision tbl_revision;
1514fb4d8502Sjsg 
1515fb4d8502Sjsg 	if (!DATA_TABLES(lcd_info))
1516fb4d8502Sjsg 		return BP_RESULT_FAILURE;
1517fb4d8502Sjsg 
1518c349dbc7Sjsg 	header = GET_IMAGE(struct atom_common_table_header, DATA_TABLES(lcd_info));
1519fb4d8502Sjsg 
1520fb4d8502Sjsg 	if (!header)
1521fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
1522fb4d8502Sjsg 
1523fb4d8502Sjsg 	get_atom_data_table_revision(header, &tbl_revision);
1524fb4d8502Sjsg 
1525fb4d8502Sjsg 	switch (tbl_revision.major) {
1526fb4d8502Sjsg 	case 2:
1527fb4d8502Sjsg 		switch (tbl_revision.minor) {
1528fb4d8502Sjsg 		case 1:
1529fb4d8502Sjsg 			return get_embedded_panel_info_v2_1(bp, info);
1530fb4d8502Sjsg 		default:
1531fb4d8502Sjsg 			break;
1532fb4d8502Sjsg 		}
15335ca02815Sjsg 		break;
1534fb4d8502Sjsg 	default:
1535fb4d8502Sjsg 		break;
1536fb4d8502Sjsg 	}
1537fb4d8502Sjsg 
1538fb4d8502Sjsg 	return BP_RESULT_FAILURE;
1539fb4d8502Sjsg }
1540fb4d8502Sjsg 
1541fb4d8502Sjsg static uint32_t get_support_mask_for_device_id(struct device_id device_id)
1542fb4d8502Sjsg {
1543fb4d8502Sjsg 	enum dal_device_type device_type = device_id.device_type;
1544fb4d8502Sjsg 	uint32_t enum_id = device_id.enum_id;
1545fb4d8502Sjsg 
1546fb4d8502Sjsg 	switch (device_type) {
1547fb4d8502Sjsg 	case DEVICE_TYPE_LCD:
1548fb4d8502Sjsg 		switch (enum_id) {
1549fb4d8502Sjsg 		case 1:
1550fb4d8502Sjsg 			return ATOM_DISPLAY_LCD1_SUPPORT;
1551fb4d8502Sjsg 		default:
1552fb4d8502Sjsg 			break;
1553fb4d8502Sjsg 		}
1554fb4d8502Sjsg 		break;
1555fb4d8502Sjsg 	case DEVICE_TYPE_DFP:
1556fb4d8502Sjsg 		switch (enum_id) {
1557fb4d8502Sjsg 		case 1:
1558fb4d8502Sjsg 			return ATOM_DISPLAY_DFP1_SUPPORT;
1559fb4d8502Sjsg 		case 2:
1560fb4d8502Sjsg 			return ATOM_DISPLAY_DFP2_SUPPORT;
1561fb4d8502Sjsg 		case 3:
1562fb4d8502Sjsg 			return ATOM_DISPLAY_DFP3_SUPPORT;
1563fb4d8502Sjsg 		case 4:
1564fb4d8502Sjsg 			return ATOM_DISPLAY_DFP4_SUPPORT;
1565fb4d8502Sjsg 		case 5:
1566fb4d8502Sjsg 			return ATOM_DISPLAY_DFP5_SUPPORT;
1567fb4d8502Sjsg 		case 6:
1568fb4d8502Sjsg 			return ATOM_DISPLAY_DFP6_SUPPORT;
1569fb4d8502Sjsg 		default:
1570fb4d8502Sjsg 			break;
1571fb4d8502Sjsg 		}
1572fb4d8502Sjsg 		break;
1573fb4d8502Sjsg 	default:
1574fb4d8502Sjsg 		break;
1575c349dbc7Sjsg 	}
1576fb4d8502Sjsg 
1577fb4d8502Sjsg 	/* Unidentified device ID, return empty support mask. */
1578fb4d8502Sjsg 	return 0;
1579fb4d8502Sjsg }
1580fb4d8502Sjsg 
1581fb4d8502Sjsg static bool bios_parser_is_device_id_supported(
1582fb4d8502Sjsg 	struct dc_bios *dcb,
1583fb4d8502Sjsg 	struct device_id id)
1584fb4d8502Sjsg {
1585fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1586fb4d8502Sjsg 
1587fb4d8502Sjsg 	uint32_t mask = get_support_mask_for_device_id(id);
1588fb4d8502Sjsg 
15891bb76ff1Sjsg 	switch (bp->object_info_tbl.revision.minor) {
15901bb76ff1Sjsg 	case 4:
15911bb76ff1Sjsg 	default:
15921bb76ff1Sjsg 		return (le16_to_cpu(bp->object_info_tbl.v1_4->supporteddevices) & mask) != 0;
15931bb76ff1Sjsg 		break;
15941bb76ff1Sjsg 	case 5:
15951bb76ff1Sjsg 		return (le16_to_cpu(bp->object_info_tbl.v1_5->supporteddevices) & mask) != 0;
15961bb76ff1Sjsg 		break;
15971bb76ff1Sjsg 	}
15981bb76ff1Sjsg 
15991bb76ff1Sjsg 	return false;
1600fb4d8502Sjsg }
1601fb4d8502Sjsg 
1602fb4d8502Sjsg static uint32_t bios_parser_get_ss_entry_number(
1603fb4d8502Sjsg 	struct dc_bios *dcb,
1604fb4d8502Sjsg 	enum as_signal_type signal)
1605fb4d8502Sjsg {
1606fb4d8502Sjsg 	/* TODO: DAL2 atomfirmware implementation does not need this.
1607fb4d8502Sjsg 	 * why DAL3 need this?
1608fb4d8502Sjsg 	 */
1609fb4d8502Sjsg 	return 1;
1610fb4d8502Sjsg }
1611fb4d8502Sjsg 
1612fb4d8502Sjsg static enum bp_result bios_parser_transmitter_control(
1613fb4d8502Sjsg 	struct dc_bios *dcb,
1614fb4d8502Sjsg 	struct bp_transmitter_control *cntl)
1615fb4d8502Sjsg {
1616fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1617fb4d8502Sjsg 
1618fb4d8502Sjsg 	if (!bp->cmd_tbl.transmitter_control)
1619fb4d8502Sjsg 		return BP_RESULT_FAILURE;
1620fb4d8502Sjsg 
1621fb4d8502Sjsg 	return bp->cmd_tbl.transmitter_control(bp, cntl);
1622fb4d8502Sjsg }
1623fb4d8502Sjsg 
1624fb4d8502Sjsg static enum bp_result bios_parser_encoder_control(
1625fb4d8502Sjsg 	struct dc_bios *dcb,
1626fb4d8502Sjsg 	struct bp_encoder_control *cntl)
1627fb4d8502Sjsg {
1628fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1629fb4d8502Sjsg 
1630fb4d8502Sjsg 	if (!bp->cmd_tbl.dig_encoder_control)
1631fb4d8502Sjsg 		return BP_RESULT_FAILURE;
1632fb4d8502Sjsg 
1633fb4d8502Sjsg 	return bp->cmd_tbl.dig_encoder_control(bp, cntl);
1634fb4d8502Sjsg }
1635fb4d8502Sjsg 
1636fb4d8502Sjsg static enum bp_result bios_parser_set_pixel_clock(
1637fb4d8502Sjsg 	struct dc_bios *dcb,
1638fb4d8502Sjsg 	struct bp_pixel_clock_parameters *bp_params)
1639fb4d8502Sjsg {
1640fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1641fb4d8502Sjsg 
1642fb4d8502Sjsg 	if (!bp->cmd_tbl.set_pixel_clock)
1643fb4d8502Sjsg 		return BP_RESULT_FAILURE;
1644fb4d8502Sjsg 
1645fb4d8502Sjsg 	return bp->cmd_tbl.set_pixel_clock(bp, bp_params);
1646fb4d8502Sjsg }
1647fb4d8502Sjsg 
1648fb4d8502Sjsg static enum bp_result bios_parser_set_dce_clock(
1649fb4d8502Sjsg 	struct dc_bios *dcb,
1650fb4d8502Sjsg 	struct bp_set_dce_clock_parameters *bp_params)
1651fb4d8502Sjsg {
1652fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1653fb4d8502Sjsg 
1654fb4d8502Sjsg 	if (!bp->cmd_tbl.set_dce_clock)
1655fb4d8502Sjsg 		return BP_RESULT_FAILURE;
1656fb4d8502Sjsg 
1657fb4d8502Sjsg 	return bp->cmd_tbl.set_dce_clock(bp, bp_params);
1658fb4d8502Sjsg }
1659fb4d8502Sjsg 
1660fb4d8502Sjsg static enum bp_result bios_parser_program_crtc_timing(
1661fb4d8502Sjsg 	struct dc_bios *dcb,
1662fb4d8502Sjsg 	struct bp_hw_crtc_timing_parameters *bp_params)
1663fb4d8502Sjsg {
1664fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1665fb4d8502Sjsg 
1666fb4d8502Sjsg 	if (!bp->cmd_tbl.set_crtc_timing)
1667fb4d8502Sjsg 		return BP_RESULT_FAILURE;
1668fb4d8502Sjsg 
1669fb4d8502Sjsg 	return bp->cmd_tbl.set_crtc_timing(bp, bp_params);
1670fb4d8502Sjsg }
1671fb4d8502Sjsg 
1672fb4d8502Sjsg static enum bp_result bios_parser_enable_crtc(
1673fb4d8502Sjsg 	struct dc_bios *dcb,
1674fb4d8502Sjsg 	enum controller_id id,
1675fb4d8502Sjsg 	bool enable)
1676fb4d8502Sjsg {
1677fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1678fb4d8502Sjsg 
1679fb4d8502Sjsg 	if (!bp->cmd_tbl.enable_crtc)
1680fb4d8502Sjsg 		return BP_RESULT_FAILURE;
1681fb4d8502Sjsg 
1682fb4d8502Sjsg 	return bp->cmd_tbl.enable_crtc(bp, id, enable);
1683fb4d8502Sjsg }
1684fb4d8502Sjsg 
1685fb4d8502Sjsg static enum bp_result bios_parser_enable_disp_power_gating(
1686fb4d8502Sjsg 	struct dc_bios *dcb,
1687fb4d8502Sjsg 	enum controller_id controller_id,
1688fb4d8502Sjsg 	enum bp_pipe_control_action action)
1689fb4d8502Sjsg {
1690fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1691fb4d8502Sjsg 
1692fb4d8502Sjsg 	if (!bp->cmd_tbl.enable_disp_power_gating)
1693fb4d8502Sjsg 		return BP_RESULT_FAILURE;
1694fb4d8502Sjsg 
1695fb4d8502Sjsg 	return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id,
1696fb4d8502Sjsg 		action);
1697fb4d8502Sjsg }
1698fb4d8502Sjsg 
1699ad8b1aafSjsg static enum bp_result bios_parser_enable_lvtma_control(
1700ad8b1aafSjsg 	struct dc_bios *dcb,
17015ca02815Sjsg 	uint8_t uc_pwr_on,
1702c1e59e83Sjsg 	uint8_t pwrseq_instance,
1703f005ef32Sjsg 	uint8_t bypass_panel_control_wait)
1704ad8b1aafSjsg {
1705ad8b1aafSjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
1706ad8b1aafSjsg 
1707ad8b1aafSjsg 	if (!bp->cmd_tbl.enable_lvtma_control)
1708ad8b1aafSjsg 		return BP_RESULT_FAILURE;
1709ad8b1aafSjsg 
1710c1e59e83Sjsg 	return bp->cmd_tbl.enable_lvtma_control(bp, uc_pwr_on, pwrseq_instance, bypass_panel_control_wait);
1711ad8b1aafSjsg }
1712ad8b1aafSjsg 
1713fb4d8502Sjsg static bool bios_parser_is_accelerated_mode(
1714fb4d8502Sjsg 	struct dc_bios *dcb)
1715fb4d8502Sjsg {
1716fb4d8502Sjsg 	return bios_is_accelerated_mode(dcb);
1717fb4d8502Sjsg }
1718fb4d8502Sjsg 
1719fb4d8502Sjsg /**
17205ca02815Sjsg  * bios_parser_set_scratch_critical_state - update critical state bit
17215ca02815Sjsg  *                                          in VBIOS scratch register
1722fb4d8502Sjsg  *
17235ca02815Sjsg  * @dcb:   pointer to the DC BIO
17245ca02815Sjsg  * @state: set or reset state
1725fb4d8502Sjsg  */
1726fb4d8502Sjsg static void bios_parser_set_scratch_critical_state(
1727fb4d8502Sjsg 	struct dc_bios *dcb,
1728fb4d8502Sjsg 	bool state)
1729fb4d8502Sjsg {
1730fb4d8502Sjsg 	bios_set_scratch_critical_state(dcb, state);
1731fb4d8502Sjsg }
1732fb4d8502Sjsg 
17331bb76ff1Sjsg struct atom_dig_transmitter_info_header_v5_3 {
17341bb76ff1Sjsg     struct atom_common_table_header table_header;
17351bb76ff1Sjsg     uint16_t dpphy_hdmi_settings_offset;
17361bb76ff1Sjsg     uint16_t dpphy_dvi_settings_offset;
17371bb76ff1Sjsg     uint16_t dpphy_dp_setting_table_offset;
17381bb76ff1Sjsg     uint16_t uniphy_xbar_settings_v2_table_offset;
17391bb76ff1Sjsg     uint16_t dpphy_internal_reg_overide_offset;
17401bb76ff1Sjsg };
17411bb76ff1Sjsg 
1742fb4d8502Sjsg static enum bp_result bios_parser_get_firmware_info(
1743fb4d8502Sjsg 	struct dc_bios *dcb,
1744fb4d8502Sjsg 	struct dc_firmware_info *info)
1745fb4d8502Sjsg {
1746fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
17471bb76ff1Sjsg 	static enum bp_result result = BP_RESULT_BADBIOSTABLE;
1748fb4d8502Sjsg 	struct atom_common_table_header *header;
1749fb4d8502Sjsg 
1750fb4d8502Sjsg 	struct atom_data_revision revision;
1751fb4d8502Sjsg 
1752fb4d8502Sjsg 	if (info && DATA_TABLES(firmwareinfo)) {
1753fb4d8502Sjsg 		header = GET_IMAGE(struct atom_common_table_header,
1754fb4d8502Sjsg 				DATA_TABLES(firmwareinfo));
1755fb4d8502Sjsg 		get_atom_data_table_revision(header, &revision);
1756fb4d8502Sjsg 		switch (revision.major) {
1757fb4d8502Sjsg 		case 3:
1758fb4d8502Sjsg 			switch (revision.minor) {
1759fb4d8502Sjsg 			case 1:
1760fb4d8502Sjsg 				result = get_firmware_info_v3_1(bp, info);
1761fb4d8502Sjsg 				break;
1762fb4d8502Sjsg 			case 2:
1763fb4d8502Sjsg 			case 3:
1764fb4d8502Sjsg 				result = get_firmware_info_v3_2(bp, info);
1765fb4d8502Sjsg 			break;
17661bb76ff1Sjsg 			case 4:
17671bb76ff1Sjsg 				result = get_firmware_info_v3_4(bp, info);
17681bb76ff1Sjsg 				break;
1769fb4d8502Sjsg 			default:
1770fb4d8502Sjsg 				break;
1771fb4d8502Sjsg 			}
1772fb4d8502Sjsg 			break;
1773fb4d8502Sjsg 		default:
1774fb4d8502Sjsg 			break;
1775fb4d8502Sjsg 		}
1776fb4d8502Sjsg 	}
1777fb4d8502Sjsg 
1778fb4d8502Sjsg 	return result;
1779fb4d8502Sjsg }
1780fb4d8502Sjsg 
1781fb4d8502Sjsg static enum bp_result get_firmware_info_v3_1(
1782fb4d8502Sjsg 	struct bios_parser *bp,
1783fb4d8502Sjsg 	struct dc_firmware_info *info)
1784fb4d8502Sjsg {
1785fb4d8502Sjsg 	struct atom_firmware_info_v3_1 *firmware_info;
1786fb4d8502Sjsg 	struct atom_display_controller_info_v4_1 *dce_info = NULL;
1787fb4d8502Sjsg 
1788fb4d8502Sjsg 	if (!info)
1789fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
1790fb4d8502Sjsg 
1791fb4d8502Sjsg 	firmware_info = GET_IMAGE(struct atom_firmware_info_v3_1,
1792fb4d8502Sjsg 			DATA_TABLES(firmwareinfo));
1793fb4d8502Sjsg 
1794fb4d8502Sjsg 	dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1,
1795fb4d8502Sjsg 			DATA_TABLES(dce_info));
1796fb4d8502Sjsg 
1797fb4d8502Sjsg 	if (!firmware_info || !dce_info)
1798fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
1799fb4d8502Sjsg 
1800fb4d8502Sjsg 	memset(info, 0, sizeof(*info));
1801fb4d8502Sjsg 
1802fb4d8502Sjsg 	/* Pixel clock pll information. */
1803fb4d8502Sjsg 	 /* We need to convert from 10KHz units into KHz units */
1804fb4d8502Sjsg 	info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
1805fb4d8502Sjsg 	info->default_engine_clk = firmware_info->bootup_sclk_in10khz * 10;
1806fb4d8502Sjsg 
1807fb4d8502Sjsg 	 /* 27MHz for Vega10: */
1808fb4d8502Sjsg 	info->pll_info.crystal_frequency = dce_info->dce_refclk_10khz * 10;
1809fb4d8502Sjsg 
1810fb4d8502Sjsg 	/* Hardcode frequency if BIOS gives no DCE Ref Clk */
1811fb4d8502Sjsg 	if (info->pll_info.crystal_frequency == 0)
1812fb4d8502Sjsg 		info->pll_info.crystal_frequency = 27000;
1813fb4d8502Sjsg 	/*dp_phy_ref_clk is not correct for atom_display_controller_info_v4_2, but we don't use it*/
1814fb4d8502Sjsg 	info->dp_phy_ref_clk     = dce_info->dpphy_refclk_10khz * 10;
1815fb4d8502Sjsg 	info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10;
1816fb4d8502Sjsg 
1817fb4d8502Sjsg 	/* Get GPU PLL VCO Clock */
1818fb4d8502Sjsg 
1819fb4d8502Sjsg 	if (bp->cmd_tbl.get_smu_clock_info != NULL) {
1820fb4d8502Sjsg 		/* VBIOS gives in 10KHz */
1821fb4d8502Sjsg 		info->smu_gpu_pll_output_freq =
1822fb4d8502Sjsg 				bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;
1823fb4d8502Sjsg 	}
1824fb4d8502Sjsg 
1825c349dbc7Sjsg 	info->oem_i2c_present = false;
1826c349dbc7Sjsg 
1827fb4d8502Sjsg 	return BP_RESULT_OK;
1828fb4d8502Sjsg }
1829fb4d8502Sjsg 
1830fb4d8502Sjsg static enum bp_result get_firmware_info_v3_2(
1831fb4d8502Sjsg 	struct bios_parser *bp,
1832fb4d8502Sjsg 	struct dc_firmware_info *info)
1833fb4d8502Sjsg {
1834fb4d8502Sjsg 	struct atom_firmware_info_v3_2 *firmware_info;
1835fb4d8502Sjsg 	struct atom_display_controller_info_v4_1 *dce_info = NULL;
1836fb4d8502Sjsg 	struct atom_common_table_header *header;
1837fb4d8502Sjsg 	struct atom_data_revision revision;
1838fb4d8502Sjsg 	struct atom_smu_info_v3_2 *smu_info_v3_2 = NULL;
1839fb4d8502Sjsg 	struct atom_smu_info_v3_3 *smu_info_v3_3 = NULL;
1840fb4d8502Sjsg 
1841fb4d8502Sjsg 	if (!info)
1842fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
1843fb4d8502Sjsg 
1844fb4d8502Sjsg 	firmware_info = GET_IMAGE(struct atom_firmware_info_v3_2,
1845fb4d8502Sjsg 			DATA_TABLES(firmwareinfo));
1846fb4d8502Sjsg 
1847fb4d8502Sjsg 	dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1,
1848fb4d8502Sjsg 			DATA_TABLES(dce_info));
1849fb4d8502Sjsg 
1850fb4d8502Sjsg 	if (!firmware_info || !dce_info)
1851fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
1852fb4d8502Sjsg 
1853fb4d8502Sjsg 	memset(info, 0, sizeof(*info));
1854fb4d8502Sjsg 
1855fb4d8502Sjsg 	header = GET_IMAGE(struct atom_common_table_header,
1856fb4d8502Sjsg 					DATA_TABLES(smu_info));
1857fb4d8502Sjsg 	get_atom_data_table_revision(header, &revision);
1858fb4d8502Sjsg 
1859fb4d8502Sjsg 	if (revision.minor == 2) {
1860fb4d8502Sjsg 		/* Vega12 */
1861fb4d8502Sjsg 		smu_info_v3_2 = GET_IMAGE(struct atom_smu_info_v3_2,
1862fb4d8502Sjsg 							DATA_TABLES(smu_info));
1863fb4d8502Sjsg 		if (!smu_info_v3_2)
1864fb4d8502Sjsg 			return BP_RESULT_BADBIOSTABLE;
1865fb4d8502Sjsg 
1866a8749599Sjsg 		DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_2->gpuclk_ss_percentage);
1867a8749599Sjsg 
1868fb4d8502Sjsg 		info->default_engine_clk = smu_info_v3_2->bootup_dcefclk_10khz * 10;
1869fb4d8502Sjsg 	} else if (revision.minor == 3) {
1870fb4d8502Sjsg 		/* Vega20 */
1871fb4d8502Sjsg 		smu_info_v3_3 = GET_IMAGE(struct atom_smu_info_v3_3,
1872fb4d8502Sjsg 							DATA_TABLES(smu_info));
1873fb4d8502Sjsg 		if (!smu_info_v3_3)
1874fb4d8502Sjsg 			return BP_RESULT_BADBIOSTABLE;
1875fb4d8502Sjsg 
1876a8749599Sjsg 		DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_3->gpuclk_ss_percentage);
1877a8749599Sjsg 
1878fb4d8502Sjsg 		info->default_engine_clk = smu_info_v3_3->bootup_dcefclk_10khz * 10;
1879fb4d8502Sjsg 	}
1880fb4d8502Sjsg 
1881fb4d8502Sjsg 	 // We need to convert from 10KHz units into KHz units.
1882fb4d8502Sjsg 	info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
1883fb4d8502Sjsg 
1884fb4d8502Sjsg 	 /* 27MHz for Vega10 & Vega12; 100MHz for Vega20 */
1885fb4d8502Sjsg 	info->pll_info.crystal_frequency = dce_info->dce_refclk_10khz * 10;
1886fb4d8502Sjsg 	/* Hardcode frequency if BIOS gives no DCE Ref Clk */
1887fb4d8502Sjsg 	if (info->pll_info.crystal_frequency == 0) {
1888fb4d8502Sjsg 		if (revision.minor == 2)
1889fb4d8502Sjsg 			info->pll_info.crystal_frequency = 27000;
1890fb4d8502Sjsg 		else if (revision.minor == 3)
1891fb4d8502Sjsg 			info->pll_info.crystal_frequency = 100000;
1892fb4d8502Sjsg 	}
1893fb4d8502Sjsg 	/*dp_phy_ref_clk is not correct for atom_display_controller_info_v4_2, but we don't use it*/
1894fb4d8502Sjsg 	info->dp_phy_ref_clk     = dce_info->dpphy_refclk_10khz * 10;
1895fb4d8502Sjsg 	info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10;
1896fb4d8502Sjsg 
1897fb4d8502Sjsg 	/* Get GPU PLL VCO Clock */
1898fb4d8502Sjsg 	if (bp->cmd_tbl.get_smu_clock_info != NULL) {
1899fb4d8502Sjsg 		if (revision.minor == 2)
1900fb4d8502Sjsg 			info->smu_gpu_pll_output_freq =
1901fb4d8502Sjsg 					bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;
1902fb4d8502Sjsg 		else if (revision.minor == 3)
1903fb4d8502Sjsg 			info->smu_gpu_pll_output_freq =
1904fb4d8502Sjsg 					bp->cmd_tbl.get_smu_clock_info(bp, SMU11_SYSPLL3_0_ID) * 10;
1905fb4d8502Sjsg 	}
1906fb4d8502Sjsg 
1907c349dbc7Sjsg 	if (firmware_info->board_i2c_feature_id == 0x2) {
1908c349dbc7Sjsg 		info->oem_i2c_present = true;
1909c349dbc7Sjsg 		info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;
1910c349dbc7Sjsg 	} else {
1911c349dbc7Sjsg 		info->oem_i2c_present = false;
1912c349dbc7Sjsg 	}
1913c349dbc7Sjsg 
1914fb4d8502Sjsg 	return BP_RESULT_OK;
1915fb4d8502Sjsg }
1916fb4d8502Sjsg 
19171bb76ff1Sjsg static enum bp_result get_firmware_info_v3_4(
19181bb76ff1Sjsg 	struct bios_parser *bp,
19191bb76ff1Sjsg 	struct dc_firmware_info *info)
19201bb76ff1Sjsg {
19211bb76ff1Sjsg 	struct atom_firmware_info_v3_4 *firmware_info;
19221bb76ff1Sjsg 	struct atom_common_table_header *header;
19231bb76ff1Sjsg 	struct atom_data_revision revision;
19241bb76ff1Sjsg 	struct atom_display_controller_info_v4_1 *dce_info_v4_1 = NULL;
19251bb76ff1Sjsg 	struct atom_display_controller_info_v4_4 *dce_info_v4_4 = NULL;
19261bb76ff1Sjsg 
19271bb76ff1Sjsg 	struct atom_smu_info_v3_5 *smu_info_v3_5 = NULL;
19281bb76ff1Sjsg 	struct atom_display_controller_info_v4_5 *dce_info_v4_5 = NULL;
19291bb76ff1Sjsg 	struct atom_smu_info_v4_0 *smu_info_v4_0 = NULL;
19301bb76ff1Sjsg 
19311bb76ff1Sjsg 	if (!info)
19321bb76ff1Sjsg 		return BP_RESULT_BADINPUT;
19331bb76ff1Sjsg 
19341bb76ff1Sjsg 	firmware_info = GET_IMAGE(struct atom_firmware_info_v3_4,
19351bb76ff1Sjsg 			DATA_TABLES(firmwareinfo));
19361bb76ff1Sjsg 
19371bb76ff1Sjsg 	if (!firmware_info)
19381bb76ff1Sjsg 		return BP_RESULT_BADBIOSTABLE;
19391bb76ff1Sjsg 
19401bb76ff1Sjsg 	memset(info, 0, sizeof(*info));
19411bb76ff1Sjsg 
19421bb76ff1Sjsg 	header = GET_IMAGE(struct atom_common_table_header,
19431bb76ff1Sjsg 					DATA_TABLES(dce_info));
19441bb76ff1Sjsg 
19451bb76ff1Sjsg 	get_atom_data_table_revision(header, &revision);
19461bb76ff1Sjsg 
19471bb76ff1Sjsg 	switch (revision.major) {
19481bb76ff1Sjsg 	case 4:
19491bb76ff1Sjsg 		switch (revision.minor) {
19501bb76ff1Sjsg 		case 5:
19511bb76ff1Sjsg 			dce_info_v4_5 = GET_IMAGE(struct atom_display_controller_info_v4_5,
19521bb76ff1Sjsg 							DATA_TABLES(dce_info));
19531bb76ff1Sjsg 
19541bb76ff1Sjsg 			if (!dce_info_v4_5)
19551bb76ff1Sjsg 				return BP_RESULT_BADBIOSTABLE;
19561bb76ff1Sjsg 
19571bb76ff1Sjsg 			 /* 100MHz expected */
19581bb76ff1Sjsg 			info->pll_info.crystal_frequency = dce_info_v4_5->dce_refclk_10khz * 10;
19591bb76ff1Sjsg 			info->dp_phy_ref_clk             = dce_info_v4_5->dpphy_refclk_10khz * 10;
19601bb76ff1Sjsg 			 /* 50MHz expected */
19611bb76ff1Sjsg 			info->i2c_engine_ref_clk         = dce_info_v4_5->i2c_engine_refclk_10khz * 10;
19621bb76ff1Sjsg 
19631bb76ff1Sjsg 			/* For DCN32/321 Display PLL VCO Frequency from dce_info_v4_5 may not be reliable */
19641bb76ff1Sjsg 			break;
19651bb76ff1Sjsg 
19661bb76ff1Sjsg 		case 4:
19671bb76ff1Sjsg 			dce_info_v4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,
19681bb76ff1Sjsg 							DATA_TABLES(dce_info));
19691bb76ff1Sjsg 
19701bb76ff1Sjsg 			if (!dce_info_v4_4)
19711bb76ff1Sjsg 				return BP_RESULT_BADBIOSTABLE;
19721bb76ff1Sjsg 
19731bb76ff1Sjsg 			/* 100MHz expected */
19741bb76ff1Sjsg 			info->pll_info.crystal_frequency = dce_info_v4_4->dce_refclk_10khz * 10;
19751bb76ff1Sjsg 			info->dp_phy_ref_clk             = dce_info_v4_4->dpphy_refclk_10khz * 10;
19761bb76ff1Sjsg 			/* 50MHz expected */
19771bb76ff1Sjsg 			info->i2c_engine_ref_clk         = dce_info_v4_4->i2c_engine_refclk_10khz * 10;
19781bb76ff1Sjsg 
19791bb76ff1Sjsg 			/* Get SMU Display PLL VCO Frequency in KHz*/
19801bb76ff1Sjsg 			info->smu_gpu_pll_output_freq =	dce_info_v4_4->dispclk_pll_vco_freq * 10;
19811bb76ff1Sjsg 			break;
19821bb76ff1Sjsg 
19831bb76ff1Sjsg 		default:
19841bb76ff1Sjsg 			/* should not come here, keep as backup, as was before */
19851bb76ff1Sjsg 			dce_info_v4_1 = GET_IMAGE(struct atom_display_controller_info_v4_1,
19861bb76ff1Sjsg 							DATA_TABLES(dce_info));
19871bb76ff1Sjsg 
19881bb76ff1Sjsg 			if (!dce_info_v4_1)
19891bb76ff1Sjsg 				return BP_RESULT_BADBIOSTABLE;
19901bb76ff1Sjsg 
19911bb76ff1Sjsg 			info->pll_info.crystal_frequency = dce_info_v4_1->dce_refclk_10khz * 10;
19921bb76ff1Sjsg 			info->dp_phy_ref_clk             = dce_info_v4_1->dpphy_refclk_10khz * 10;
19931bb76ff1Sjsg 			info->i2c_engine_ref_clk         = dce_info_v4_1->i2c_engine_refclk_10khz * 10;
19941bb76ff1Sjsg 			break;
19951bb76ff1Sjsg 		}
19961bb76ff1Sjsg 		break;
19971bb76ff1Sjsg 
19981bb76ff1Sjsg 	default:
19991bb76ff1Sjsg 		ASSERT(0);
20001bb76ff1Sjsg 		break;
20011bb76ff1Sjsg 	}
20021bb76ff1Sjsg 
20031bb76ff1Sjsg 	header = GET_IMAGE(struct atom_common_table_header,
20041bb76ff1Sjsg 					DATA_TABLES(smu_info));
20051bb76ff1Sjsg 	get_atom_data_table_revision(header, &revision);
20061bb76ff1Sjsg 
20071bb76ff1Sjsg 	switch (revision.major) {
20081bb76ff1Sjsg 	case 3:
20091bb76ff1Sjsg 		switch (revision.minor) {
20101bb76ff1Sjsg 		case 5:
20111bb76ff1Sjsg 			smu_info_v3_5 = GET_IMAGE(struct atom_smu_info_v3_5,
20121bb76ff1Sjsg 							DATA_TABLES(smu_info));
20131bb76ff1Sjsg 
20141bb76ff1Sjsg 			if (!smu_info_v3_5)
20151bb76ff1Sjsg 				return BP_RESULT_BADBIOSTABLE;
20161bb76ff1Sjsg 			DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_5->gpuclk_ss_percentage);
20171bb76ff1Sjsg 			info->default_engine_clk = smu_info_v3_5->bootup_dcefclk_10khz * 10;
20181bb76ff1Sjsg 			break;
20191bb76ff1Sjsg 
20201bb76ff1Sjsg 		default:
20211bb76ff1Sjsg 			break;
20221bb76ff1Sjsg 		}
20231bb76ff1Sjsg 		break;
20241bb76ff1Sjsg 
20251bb76ff1Sjsg 	case 4:
20261bb76ff1Sjsg 		switch (revision.minor) {
20271bb76ff1Sjsg 		case 0:
20281bb76ff1Sjsg 			smu_info_v4_0 = GET_IMAGE(struct atom_smu_info_v4_0,
20291bb76ff1Sjsg 							DATA_TABLES(smu_info));
20301bb76ff1Sjsg 
20311bb76ff1Sjsg 			if (!smu_info_v4_0)
20321bb76ff1Sjsg 				return BP_RESULT_BADBIOSTABLE;
20331bb76ff1Sjsg 
20341bb76ff1Sjsg 			/* For DCN32/321 bootup DCFCLK from smu_info_v4_0 may not be reliable */
20351bb76ff1Sjsg 			break;
20361bb76ff1Sjsg 
20371bb76ff1Sjsg 		default:
20381bb76ff1Sjsg 			break;
20391bb76ff1Sjsg 		}
20401bb76ff1Sjsg 		break;
20411bb76ff1Sjsg 
20421bb76ff1Sjsg 	default:
20431bb76ff1Sjsg 		break;
20441bb76ff1Sjsg 	}
20451bb76ff1Sjsg 
20461bb76ff1Sjsg 	 // We need to convert from 10KHz units into KHz units.
20471bb76ff1Sjsg 	info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
20481bb76ff1Sjsg 
20491bb76ff1Sjsg 	if (firmware_info->board_i2c_feature_id == 0x2) {
20501bb76ff1Sjsg 		info->oem_i2c_present = true;
20511bb76ff1Sjsg 		info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;
20521bb76ff1Sjsg 	} else {
20531bb76ff1Sjsg 		info->oem_i2c_present = false;
20541bb76ff1Sjsg 	}
20551bb76ff1Sjsg 
20561bb76ff1Sjsg 	return BP_RESULT_OK;
20571bb76ff1Sjsg }
20581bb76ff1Sjsg 
2059fb4d8502Sjsg static enum bp_result bios_parser_get_encoder_cap_info(
2060fb4d8502Sjsg 	struct dc_bios *dcb,
2061fb4d8502Sjsg 	struct graphics_object_id object_id,
2062fb4d8502Sjsg 	struct bp_encoder_cap_info *info)
2063fb4d8502Sjsg {
2064fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
2065fb4d8502Sjsg 	struct atom_display_object_path_v2 *object;
2066fb4d8502Sjsg 	struct atom_encoder_caps_record *record = NULL;
2067fb4d8502Sjsg 
2068fb4d8502Sjsg 	if (!info)
2069fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
2070fb4d8502Sjsg 
2071f005ef32Sjsg #if defined(CONFIG_DRM_AMD_DC_FP)
20721bb76ff1Sjsg 	/* encoder cap record not available in v1_5 */
20731bb76ff1Sjsg 	if (bp->object_info_tbl.revision.minor == 5)
20741bb76ff1Sjsg 		return BP_RESULT_NORECORD;
20751bb76ff1Sjsg #endif
20761bb76ff1Sjsg 
2077fb4d8502Sjsg 	object = get_bios_object(bp, object_id);
2078fb4d8502Sjsg 
2079fb4d8502Sjsg 	if (!object)
2080fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
2081fb4d8502Sjsg 
2082fb4d8502Sjsg 	record = get_encoder_cap_record(bp, object);
2083fb4d8502Sjsg 	if (!record)
2084fb4d8502Sjsg 		return BP_RESULT_NORECORD;
20851bb76ff1Sjsg 	DC_LOG_BIOS("record->encodercaps 0x%x for object_id 0x%x", record->encodercaps, object_id.id);
2086fb4d8502Sjsg 
2087fb4d8502Sjsg 	info->DP_HBR2_CAP = (record->encodercaps &
2088fb4d8502Sjsg 			ATOM_ENCODER_CAP_RECORD_HBR2) ? 1 : 0;
2089fb4d8502Sjsg 	info->DP_HBR2_EN = (record->encodercaps &
2090fb4d8502Sjsg 			ATOM_ENCODER_CAP_RECORD_HBR2_EN) ? 1 : 0;
2091fb4d8502Sjsg 	info->DP_HBR3_EN = (record->encodercaps &
2092fb4d8502Sjsg 			ATOM_ENCODER_CAP_RECORD_HBR3_EN) ? 1 : 0;
2093fb4d8502Sjsg 	info->HDMI_6GB_EN = (record->encodercaps &
2094fb4d8502Sjsg 			ATOM_ENCODER_CAP_RECORD_HDMI6Gbps_EN) ? 1 : 0;
20951bb76ff1Sjsg 	info->IS_DP2_CAPABLE = (record->encodercaps &
20961bb76ff1Sjsg 			ATOM_ENCODER_CAP_RECORD_DP2) ? 1 : 0;
20971bb76ff1Sjsg 	info->DP_UHBR10_EN = (record->encodercaps &
20981bb76ff1Sjsg 			ATOM_ENCODER_CAP_RECORD_UHBR10_EN) ? 1 : 0;
20991bb76ff1Sjsg 	info->DP_UHBR13_5_EN = (record->encodercaps &
21001bb76ff1Sjsg 			ATOM_ENCODER_CAP_RECORD_UHBR13_5_EN) ? 1 : 0;
21011bb76ff1Sjsg 	info->DP_UHBR20_EN = (record->encodercaps &
21021bb76ff1Sjsg 			ATOM_ENCODER_CAP_RECORD_UHBR20_EN) ? 1 : 0;
2103c349dbc7Sjsg 	info->DP_IS_USB_C = (record->encodercaps &
2104c349dbc7Sjsg 			ATOM_ENCODER_CAP_RECORD_USB_C_TYPE) ? 1 : 0;
21051bb76ff1Sjsg 	DC_LOG_BIOS("\t info->DP_IS_USB_C %d", info->DP_IS_USB_C);
2106fb4d8502Sjsg 
2107fb4d8502Sjsg 	return BP_RESULT_OK;
2108fb4d8502Sjsg }
2109fb4d8502Sjsg 
2110fb4d8502Sjsg 
2111fb4d8502Sjsg static struct atom_encoder_caps_record *get_encoder_cap_record(
2112fb4d8502Sjsg 	struct bios_parser *bp,
2113fb4d8502Sjsg 	struct atom_display_object_path_v2 *object)
2114fb4d8502Sjsg {
2115fb4d8502Sjsg 	struct atom_common_record_header *header;
2116fb4d8502Sjsg 	uint32_t offset;
2117fb4d8502Sjsg 
2118fb4d8502Sjsg 	if (!object) {
2119fb4d8502Sjsg 		BREAK_TO_DEBUGGER(); /* Invalid object */
2120fb4d8502Sjsg 		return NULL;
2121fb4d8502Sjsg 	}
2122fb4d8502Sjsg 
2123fb4d8502Sjsg 	offset = object->encoder_recordoffset + bp->object_info_tbl_offset;
2124fb4d8502Sjsg 
2125fb4d8502Sjsg 	for (;;) {
2126fb4d8502Sjsg 		header = GET_IMAGE(struct atom_common_record_header, offset);
2127fb4d8502Sjsg 
2128fb4d8502Sjsg 		if (!header)
2129fb4d8502Sjsg 			return NULL;
2130fb4d8502Sjsg 
2131fb4d8502Sjsg 		offset += header->record_size;
2132fb4d8502Sjsg 
2133fb4d8502Sjsg 		if (header->record_type == LAST_RECORD_TYPE ||
2134fb4d8502Sjsg 				!header->record_size)
2135fb4d8502Sjsg 			break;
2136fb4d8502Sjsg 
2137fb4d8502Sjsg 		if (header->record_type != ATOM_ENCODER_CAP_RECORD_TYPE)
2138fb4d8502Sjsg 			continue;
2139fb4d8502Sjsg 
2140fb4d8502Sjsg 		if (sizeof(struct atom_encoder_caps_record) <=
2141fb4d8502Sjsg 							header->record_size)
2142fb4d8502Sjsg 			return (struct atom_encoder_caps_record *)header;
2143fb4d8502Sjsg 	}
2144fb4d8502Sjsg 
2145fb4d8502Sjsg 	return NULL;
2146fb4d8502Sjsg }
2147fb4d8502Sjsg 
21485ca02815Sjsg static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(
21495ca02815Sjsg 	struct bios_parser *bp,
21505ca02815Sjsg 	struct atom_display_object_path_v2 *object)
21515ca02815Sjsg {
21525ca02815Sjsg 	struct atom_common_record_header *header;
21535ca02815Sjsg 	uint32_t offset;
21545ca02815Sjsg 
21555ca02815Sjsg 	if (!object) {
21565ca02815Sjsg 		BREAK_TO_DEBUGGER(); /* Invalid object */
21575ca02815Sjsg 		return NULL;
21585ca02815Sjsg 	}
21595ca02815Sjsg 
21605ca02815Sjsg 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
21615ca02815Sjsg 
21625ca02815Sjsg 	for (;;) {
21635ca02815Sjsg 		header = GET_IMAGE(struct atom_common_record_header, offset);
21645ca02815Sjsg 
21655ca02815Sjsg 		if (!header)
21665ca02815Sjsg 			return NULL;
21675ca02815Sjsg 
21685ca02815Sjsg 		offset += header->record_size;
21695ca02815Sjsg 
21705ca02815Sjsg 		if (header->record_type == LAST_RECORD_TYPE ||
21715ca02815Sjsg 				!header->record_size)
21725ca02815Sjsg 			break;
21735ca02815Sjsg 
21745ca02815Sjsg 		if (header->record_type != ATOM_DISP_CONNECTOR_CAPS_RECORD_TYPE)
21755ca02815Sjsg 			continue;
21765ca02815Sjsg 
21775ca02815Sjsg 		if (sizeof(struct atom_disp_connector_caps_record) <=
21785ca02815Sjsg 							header->record_size)
21795ca02815Sjsg 			return (struct atom_disp_connector_caps_record *)header;
21805ca02815Sjsg 	}
21815ca02815Sjsg 
21825ca02815Sjsg 	return NULL;
21835ca02815Sjsg }
21845ca02815Sjsg 
2185f005ef32Sjsg static struct atom_connector_caps_record *get_connector_caps_record(struct bios_parser *bp,
21861bb76ff1Sjsg 								    struct atom_display_object_path_v3 *object)
21871bb76ff1Sjsg {
21881bb76ff1Sjsg 	struct atom_common_record_header *header;
21891bb76ff1Sjsg 	uint32_t offset;
21901bb76ff1Sjsg 
21911bb76ff1Sjsg 	if (!object) {
21921bb76ff1Sjsg 		BREAK_TO_DEBUGGER(); /* Invalid object */
21931bb76ff1Sjsg 		return NULL;
21941bb76ff1Sjsg 	}
21951bb76ff1Sjsg 
21961bb76ff1Sjsg 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
21971bb76ff1Sjsg 
21981bb76ff1Sjsg 	for (;;) {
21991bb76ff1Sjsg 		header = GET_IMAGE(struct atom_common_record_header, offset);
22001bb76ff1Sjsg 
22011bb76ff1Sjsg 		if (!header)
22021bb76ff1Sjsg 			return NULL;
22031bb76ff1Sjsg 
22041bb76ff1Sjsg 		offset += header->record_size;
22051bb76ff1Sjsg 
22061bb76ff1Sjsg 		if (header->record_type == ATOM_RECORD_END_TYPE ||
22071bb76ff1Sjsg 				!header->record_size)
22081bb76ff1Sjsg 			break;
22091bb76ff1Sjsg 
22101bb76ff1Sjsg 		if (header->record_type != ATOM_CONNECTOR_CAP_RECORD_TYPE)
22111bb76ff1Sjsg 			continue;
22121bb76ff1Sjsg 
22131bb76ff1Sjsg 		if (sizeof(struct atom_connector_caps_record) <= header->record_size)
22141bb76ff1Sjsg 			return (struct atom_connector_caps_record *)header;
22151bb76ff1Sjsg 	}
22161bb76ff1Sjsg 
22171bb76ff1Sjsg 	return NULL;
22181bb76ff1Sjsg }
22191bb76ff1Sjsg 
22205ca02815Sjsg static enum bp_result bios_parser_get_disp_connector_caps_info(
22215ca02815Sjsg 	struct dc_bios *dcb,
22225ca02815Sjsg 	struct graphics_object_id object_id,
22235ca02815Sjsg 	struct bp_disp_connector_caps_info *info)
22245ca02815Sjsg {
22255ca02815Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
22265ca02815Sjsg 	struct atom_display_object_path_v2 *object;
22271bb76ff1Sjsg 
22281bb76ff1Sjsg 	struct atom_display_object_path_v3 *object_path_v3;
22291bb76ff1Sjsg 	struct atom_connector_caps_record *record_path_v3;
22301bb76ff1Sjsg 
22315ca02815Sjsg 	struct atom_disp_connector_caps_record *record = NULL;
22325ca02815Sjsg 
22335ca02815Sjsg 	if (!info)
22345ca02815Sjsg 		return BP_RESULT_BADINPUT;
22355ca02815Sjsg 
22361bb76ff1Sjsg 	switch (bp->object_info_tbl.revision.minor) {
22371bb76ff1Sjsg 	case 4:
22381bb76ff1Sjsg 	    default:
22395ca02815Sjsg 		    object = get_bios_object(bp, object_id);
22405ca02815Sjsg 
22415ca02815Sjsg 		    if (!object)
22425ca02815Sjsg 			    return BP_RESULT_BADINPUT;
22435ca02815Sjsg 
22445ca02815Sjsg 		    record = get_disp_connector_caps_record(bp, object);
22455ca02815Sjsg 		    if (!record)
22465ca02815Sjsg 			    return BP_RESULT_NORECORD;
22475ca02815Sjsg 
22481bb76ff1Sjsg 		    info->INTERNAL_DISPLAY =
22491bb76ff1Sjsg 			    (record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY) ? 1 : 0;
22501bb76ff1Sjsg 		    info->INTERNAL_DISPLAY_BL =
22511bb76ff1Sjsg 			    (record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL) ? 1 : 0;
22521bb76ff1Sjsg 		    break;
22531bb76ff1Sjsg 	    case 5:
22541bb76ff1Sjsg 		object_path_v3 = get_bios_object_from_path_v3(bp, object_id);
22555ca02815Sjsg 
22561bb76ff1Sjsg 		if (!object_path_v3)
22571bb76ff1Sjsg 			return BP_RESULT_BADINPUT;
22581bb76ff1Sjsg 
22591bb76ff1Sjsg 		record_path_v3 = get_connector_caps_record(bp, object_path_v3);
22601bb76ff1Sjsg 		if (!record_path_v3)
22611bb76ff1Sjsg 			return BP_RESULT_NORECORD;
22621bb76ff1Sjsg 
22631bb76ff1Sjsg 		info->INTERNAL_DISPLAY = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY)
22641bb76ff1Sjsg 									? 1 : 0;
22651bb76ff1Sjsg 		info->INTERNAL_DISPLAY_BL = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL)
22661bb76ff1Sjsg 										? 1 : 0;
22671bb76ff1Sjsg 		break;
22681bb76ff1Sjsg 	}
22691bb76ff1Sjsg 
22701bb76ff1Sjsg 	return BP_RESULT_OK;
22711bb76ff1Sjsg }
22721bb76ff1Sjsg 
2273f005ef32Sjsg static struct atom_connector_speed_record *get_connector_speed_cap_record(struct bios_parser *bp,
22741bb76ff1Sjsg 									  struct atom_display_object_path_v3 *object)
22751bb76ff1Sjsg {
22761bb76ff1Sjsg 	struct atom_common_record_header *header;
22771bb76ff1Sjsg 	uint32_t offset;
22781bb76ff1Sjsg 
22791bb76ff1Sjsg 	if (!object) {
22801bb76ff1Sjsg 		BREAK_TO_DEBUGGER(); /* Invalid object */
22811bb76ff1Sjsg 		return NULL;
22821bb76ff1Sjsg 	}
22831bb76ff1Sjsg 
22841bb76ff1Sjsg 	offset = object->disp_recordoffset + bp->object_info_tbl_offset;
22851bb76ff1Sjsg 
22861bb76ff1Sjsg 	for (;;) {
22871bb76ff1Sjsg 		header = GET_IMAGE(struct atom_common_record_header, offset);
22881bb76ff1Sjsg 
22891bb76ff1Sjsg 		if (!header)
22901bb76ff1Sjsg 			return NULL;
22911bb76ff1Sjsg 
22921bb76ff1Sjsg 		offset += header->record_size;
22931bb76ff1Sjsg 
22941bb76ff1Sjsg 		if (header->record_type == ATOM_RECORD_END_TYPE ||
22951bb76ff1Sjsg 				!header->record_size)
22961bb76ff1Sjsg 			break;
22971bb76ff1Sjsg 
22981bb76ff1Sjsg 		if (header->record_type != ATOM_CONNECTOR_SPEED_UPTO)
22991bb76ff1Sjsg 			continue;
23001bb76ff1Sjsg 
23011bb76ff1Sjsg 		if (sizeof(struct atom_connector_speed_record) <= header->record_size)
23021bb76ff1Sjsg 			return (struct atom_connector_speed_record *)header;
23031bb76ff1Sjsg 	}
23041bb76ff1Sjsg 
23051bb76ff1Sjsg 	return NULL;
23061bb76ff1Sjsg }
23071bb76ff1Sjsg 
23081bb76ff1Sjsg static enum bp_result bios_parser_get_connector_speed_cap_info(
23091bb76ff1Sjsg 	struct dc_bios *dcb,
23101bb76ff1Sjsg 	struct graphics_object_id object_id,
23111bb76ff1Sjsg 	struct bp_connector_speed_cap_info *info)
23121bb76ff1Sjsg {
23131bb76ff1Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
23141bb76ff1Sjsg 	struct atom_display_object_path_v3 *object_path_v3;
23151bb76ff1Sjsg 	//struct atom_connector_speed_record *record = NULL;
23161bb76ff1Sjsg 	struct atom_connector_speed_record *record;
23171bb76ff1Sjsg 
23181bb76ff1Sjsg 	if (!info)
23191bb76ff1Sjsg 		return BP_RESULT_BADINPUT;
23201bb76ff1Sjsg 
23211bb76ff1Sjsg 	object_path_v3 = get_bios_object_from_path_v3(bp, object_id);
23221bb76ff1Sjsg 
23231bb76ff1Sjsg 	if (!object_path_v3)
23241bb76ff1Sjsg 		return BP_RESULT_BADINPUT;
23251bb76ff1Sjsg 
23261bb76ff1Sjsg 	record = get_connector_speed_cap_record(bp, object_path_v3);
23271bb76ff1Sjsg 	if (!record)
23281bb76ff1Sjsg 		return BP_RESULT_NORECORD;
23291bb76ff1Sjsg 
23301bb76ff1Sjsg 	info->DP_HBR2_EN = (record->connector_max_speed >= 5400) ? 1 : 0;
23311bb76ff1Sjsg 	info->DP_HBR3_EN = (record->connector_max_speed >= 8100) ? 1 : 0;
23321bb76ff1Sjsg 	info->HDMI_6GB_EN = (record->connector_max_speed >= 5940) ? 1 : 0;
23331bb76ff1Sjsg 	info->DP_UHBR10_EN = (record->connector_max_speed >= 10000) ? 1 : 0;
23341bb76ff1Sjsg 	info->DP_UHBR13_5_EN = (record->connector_max_speed >= 13500) ? 1 : 0;
23351bb76ff1Sjsg 	info->DP_UHBR20_EN = (record->connector_max_speed >= 20000) ? 1 : 0;
23365ca02815Sjsg 	return BP_RESULT_OK;
23375ca02815Sjsg }
23385ca02815Sjsg 
2339ad8b1aafSjsg static enum bp_result get_vram_info_v23(
2340ad8b1aafSjsg 	struct bios_parser *bp,
2341ad8b1aafSjsg 	struct dc_vram_info *info)
2342ad8b1aafSjsg {
2343ad8b1aafSjsg 	struct atom_vram_info_header_v2_3 *info_v23;
23441bb76ff1Sjsg 	static enum bp_result result = BP_RESULT_OK;
2345ad8b1aafSjsg 
2346ad8b1aafSjsg 	info_v23 = GET_IMAGE(struct atom_vram_info_header_v2_3,
2347ad8b1aafSjsg 						DATA_TABLES(vram_info));
2348ad8b1aafSjsg 
2349ad8b1aafSjsg 	if (info_v23 == NULL)
2350ad8b1aafSjsg 		return BP_RESULT_BADBIOSTABLE;
2351ad8b1aafSjsg 
2352ad8b1aafSjsg 	info->num_chans = info_v23->vram_module[0].channel_num;
2353ad8b1aafSjsg 	info->dram_channel_width_bytes = (1 << info_v23->vram_module[0].channel_width) / 8;
2354ad8b1aafSjsg 
2355ad8b1aafSjsg 	return result;
2356ad8b1aafSjsg }
2357ad8b1aafSjsg 
2358ad8b1aafSjsg static enum bp_result get_vram_info_v24(
2359ad8b1aafSjsg 	struct bios_parser *bp,
2360ad8b1aafSjsg 	struct dc_vram_info *info)
2361ad8b1aafSjsg {
2362ad8b1aafSjsg 	struct atom_vram_info_header_v2_4 *info_v24;
23631bb76ff1Sjsg 	static enum bp_result result = BP_RESULT_OK;
2364ad8b1aafSjsg 
2365ad8b1aafSjsg 	info_v24 = GET_IMAGE(struct atom_vram_info_header_v2_4,
2366ad8b1aafSjsg 						DATA_TABLES(vram_info));
2367ad8b1aafSjsg 
2368ad8b1aafSjsg 	if (info_v24 == NULL)
2369ad8b1aafSjsg 		return BP_RESULT_BADBIOSTABLE;
2370ad8b1aafSjsg 
2371ad8b1aafSjsg 	info->num_chans = info_v24->vram_module[0].channel_num;
2372ad8b1aafSjsg 	info->dram_channel_width_bytes = (1 << info_v24->vram_module[0].channel_width) / 8;
2373ad8b1aafSjsg 
2374ad8b1aafSjsg 	return result;
2375ad8b1aafSjsg }
2376ad8b1aafSjsg 
2377ad8b1aafSjsg static enum bp_result get_vram_info_v25(
2378ad8b1aafSjsg 	struct bios_parser *bp,
2379ad8b1aafSjsg 	struct dc_vram_info *info)
2380ad8b1aafSjsg {
2381ad8b1aafSjsg 	struct atom_vram_info_header_v2_5 *info_v25;
23821bb76ff1Sjsg 	static enum bp_result result = BP_RESULT_OK;
2383ad8b1aafSjsg 
2384ad8b1aafSjsg 	info_v25 = GET_IMAGE(struct atom_vram_info_header_v2_5,
2385ad8b1aafSjsg 						DATA_TABLES(vram_info));
2386ad8b1aafSjsg 
2387ad8b1aafSjsg 	if (info_v25 == NULL)
2388ad8b1aafSjsg 		return BP_RESULT_BADBIOSTABLE;
2389ad8b1aafSjsg 
2390ad8b1aafSjsg 	info->num_chans = info_v25->vram_module[0].channel_num;
2391ad8b1aafSjsg 	info->dram_channel_width_bytes = (1 << info_v25->vram_module[0].channel_width) / 8;
2392ad8b1aafSjsg 
2393ad8b1aafSjsg 	return result;
2394ad8b1aafSjsg }
2395ad8b1aafSjsg 
23961bb76ff1Sjsg static enum bp_result get_vram_info_v30(
23971bb76ff1Sjsg 	struct bios_parser *bp,
23981bb76ff1Sjsg 	struct dc_vram_info *info)
23991bb76ff1Sjsg {
24001bb76ff1Sjsg 	struct atom_vram_info_header_v3_0 *info_v30;
24011bb76ff1Sjsg 	enum bp_result result = BP_RESULT_OK;
24021bb76ff1Sjsg 
24031bb76ff1Sjsg 	info_v30 = GET_IMAGE(struct atom_vram_info_header_v3_0,
24041bb76ff1Sjsg 						DATA_TABLES(vram_info));
24051bb76ff1Sjsg 
24061bb76ff1Sjsg 	if (info_v30 == NULL)
24071bb76ff1Sjsg 		return BP_RESULT_BADBIOSTABLE;
24081bb76ff1Sjsg 
24091bb76ff1Sjsg 	info->num_chans = info_v30->channel_num;
24101bb76ff1Sjsg 	info->dram_channel_width_bytes = (1 << info_v30->channel_width) / 8;
24111bb76ff1Sjsg 
24121bb76ff1Sjsg 	return result;
24131bb76ff1Sjsg }
24141bb76ff1Sjsg 
24151bb76ff1Sjsg 
2416fb4d8502Sjsg /*
2417fb4d8502Sjsg  * get_integrated_info_v11
2418fb4d8502Sjsg  *
2419fb4d8502Sjsg  * @brief
2420fb4d8502Sjsg  * Get V8 integrated BIOS information
2421fb4d8502Sjsg  *
2422fb4d8502Sjsg  * @param
2423fb4d8502Sjsg  * bios_parser *bp - [in]BIOS parser handler to get master data table
2424fb4d8502Sjsg  * integrated_info *info - [out] store and output integrated info
2425fb4d8502Sjsg  *
2426fb4d8502Sjsg  * @return
24271bb76ff1Sjsg  * static enum bp_result - BP_RESULT_OK if information is available,
2428fb4d8502Sjsg  *                  BP_RESULT_BADBIOSTABLE otherwise.
2429fb4d8502Sjsg  */
2430fb4d8502Sjsg static enum bp_result get_integrated_info_v11(
2431fb4d8502Sjsg 	struct bios_parser *bp,
2432fb4d8502Sjsg 	struct integrated_info *info)
2433fb4d8502Sjsg {
2434fb4d8502Sjsg 	struct atom_integrated_system_info_v1_11 *info_v11;
2435fb4d8502Sjsg 	uint32_t i;
2436fb4d8502Sjsg 
2437fb4d8502Sjsg 	info_v11 = GET_IMAGE(struct atom_integrated_system_info_v1_11,
2438fb4d8502Sjsg 					DATA_TABLES(integratedsysteminfo));
2439fb4d8502Sjsg 
2440fb4d8502Sjsg 	if (info_v11 == NULL)
2441fb4d8502Sjsg 		return BP_RESULT_BADBIOSTABLE;
2442fb4d8502Sjsg 
2443a8749599Sjsg 	DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v11->gpuclk_ss_percentage);
2444a8749599Sjsg 
2445fb4d8502Sjsg 	info->gpu_cap_info =
2446fb4d8502Sjsg 	le32_to_cpu(info_v11->gpucapinfo);
2447fb4d8502Sjsg 	/*
2448fb4d8502Sjsg 	* system_config: Bit[0] = 0 : PCIE power gating disabled
2449fb4d8502Sjsg 	*                       = 1 : PCIE power gating enabled
2450fb4d8502Sjsg 	*                Bit[1] = 0 : DDR-PLL shut down disabled
2451fb4d8502Sjsg 	*                       = 1 : DDR-PLL shut down enabled
2452fb4d8502Sjsg 	*                Bit[2] = 0 : DDR-PLL power down disabled
2453fb4d8502Sjsg 	*                       = 1 : DDR-PLL power down enabled
2454fb4d8502Sjsg 	*/
2455fb4d8502Sjsg 	info->system_config = le32_to_cpu(info_v11->system_config);
2456fb4d8502Sjsg 	info->cpu_cap_info = le32_to_cpu(info_v11->cpucapinfo);
2457fb4d8502Sjsg 	info->memory_type = info_v11->memorytype;
2458fb4d8502Sjsg 	info->ma_channel_number = info_v11->umachannelnumber;
2459fb4d8502Sjsg 	info->lvds_ss_percentage =
2460fb4d8502Sjsg 	le16_to_cpu(info_v11->lvds_ss_percentage);
2461c349dbc7Sjsg 	info->dp_ss_control =
2462c349dbc7Sjsg 	le16_to_cpu(info_v11->reserved1);
2463fb4d8502Sjsg 	info->lvds_sspread_rate_in_10hz =
2464fb4d8502Sjsg 	le16_to_cpu(info_v11->lvds_ss_rate_10hz);
2465fb4d8502Sjsg 	info->hdmi_ss_percentage =
2466fb4d8502Sjsg 	le16_to_cpu(info_v11->hdmi_ss_percentage);
2467fb4d8502Sjsg 	info->hdmi_sspread_rate_in_10hz =
2468fb4d8502Sjsg 	le16_to_cpu(info_v11->hdmi_ss_rate_10hz);
2469fb4d8502Sjsg 	info->dvi_ss_percentage =
2470fb4d8502Sjsg 	le16_to_cpu(info_v11->dvi_ss_percentage);
2471fb4d8502Sjsg 	info->dvi_sspread_rate_in_10_hz =
2472fb4d8502Sjsg 	le16_to_cpu(info_v11->dvi_ss_rate_10hz);
2473fb4d8502Sjsg 	info->lvds_misc = info_v11->lvds_misc;
2474fb4d8502Sjsg 	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2475fb4d8502Sjsg 		info->ext_disp_conn_info.gu_id[i] =
2476fb4d8502Sjsg 				info_v11->extdispconninfo.guid[i];
2477fb4d8502Sjsg 	}
2478fb4d8502Sjsg 
2479fb4d8502Sjsg 	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2480fb4d8502Sjsg 		info->ext_disp_conn_info.path[i].device_connector_id =
2481fb4d8502Sjsg 		object_id_from_bios_object_id(
2482fb4d8502Sjsg 		le16_to_cpu(info_v11->extdispconninfo.path[i].connectorobjid));
2483fb4d8502Sjsg 
2484fb4d8502Sjsg 		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2485fb4d8502Sjsg 		object_id_from_bios_object_id(
2486fb4d8502Sjsg 			le16_to_cpu(
2487fb4d8502Sjsg 			info_v11->extdispconninfo.path[i].ext_encoder_objid));
2488fb4d8502Sjsg 
2489fb4d8502Sjsg 		info->ext_disp_conn_info.path[i].device_tag =
2490fb4d8502Sjsg 			le16_to_cpu(
2491fb4d8502Sjsg 				info_v11->extdispconninfo.path[i].device_tag);
2492fb4d8502Sjsg 		info->ext_disp_conn_info.path[i].device_acpi_enum =
2493fb4d8502Sjsg 		le16_to_cpu(
2494fb4d8502Sjsg 			info_v11->extdispconninfo.path[i].device_acpi_enum);
2495fb4d8502Sjsg 		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2496fb4d8502Sjsg 			info_v11->extdispconninfo.path[i].auxddclut_index;
2497fb4d8502Sjsg 		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2498fb4d8502Sjsg 			info_v11->extdispconninfo.path[i].hpdlut_index;
2499fb4d8502Sjsg 		info->ext_disp_conn_info.path[i].channel_mapping.raw =
2500fb4d8502Sjsg 			info_v11->extdispconninfo.path[i].channelmapping;
2501fb4d8502Sjsg 		info->ext_disp_conn_info.path[i].caps =
2502fb4d8502Sjsg 				le16_to_cpu(info_v11->extdispconninfo.path[i].caps);
2503fb4d8502Sjsg 	}
2504fb4d8502Sjsg 	info->ext_disp_conn_info.checksum =
2505fb4d8502Sjsg 	info_v11->extdispconninfo.checksum;
2506fb4d8502Sjsg 
2507fb4d8502Sjsg 	info->dp0_ext_hdmi_slv_addr = info_v11->dp0_retimer_set.HdmiSlvAddr;
2508fb4d8502Sjsg 	info->dp0_ext_hdmi_reg_num = info_v11->dp0_retimer_set.HdmiRegNum;
2509fb4d8502Sjsg 	for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
2510fb4d8502Sjsg 		info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
2511fb4d8502Sjsg 				info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2512fb4d8502Sjsg 		info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
2513fb4d8502Sjsg 				info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2514fb4d8502Sjsg 	}
2515fb4d8502Sjsg 	info->dp0_ext_hdmi_6g_reg_num = info_v11->dp0_retimer_set.Hdmi6GRegNum;
2516fb4d8502Sjsg 	for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
2517fb4d8502Sjsg 		info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2518fb4d8502Sjsg 				info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2519fb4d8502Sjsg 		info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2520fb4d8502Sjsg 				info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2521fb4d8502Sjsg 	}
2522fb4d8502Sjsg 
2523fb4d8502Sjsg 	info->dp1_ext_hdmi_slv_addr = info_v11->dp1_retimer_set.HdmiSlvAddr;
2524fb4d8502Sjsg 	info->dp1_ext_hdmi_reg_num = info_v11->dp1_retimer_set.HdmiRegNum;
2525fb4d8502Sjsg 	for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
2526fb4d8502Sjsg 		info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
2527fb4d8502Sjsg 				info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2528fb4d8502Sjsg 		info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
2529fb4d8502Sjsg 				info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2530fb4d8502Sjsg 	}
2531fb4d8502Sjsg 	info->dp1_ext_hdmi_6g_reg_num = info_v11->dp1_retimer_set.Hdmi6GRegNum;
2532fb4d8502Sjsg 	for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
2533fb4d8502Sjsg 		info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2534fb4d8502Sjsg 				info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2535fb4d8502Sjsg 		info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2536fb4d8502Sjsg 				info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2537fb4d8502Sjsg 	}
2538fb4d8502Sjsg 
2539fb4d8502Sjsg 	info->dp2_ext_hdmi_slv_addr = info_v11->dp2_retimer_set.HdmiSlvAddr;
2540fb4d8502Sjsg 	info->dp2_ext_hdmi_reg_num = info_v11->dp2_retimer_set.HdmiRegNum;
2541fb4d8502Sjsg 	for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
2542fb4d8502Sjsg 		info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
2543fb4d8502Sjsg 				info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2544fb4d8502Sjsg 		info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
2545fb4d8502Sjsg 				info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2546fb4d8502Sjsg 	}
2547fb4d8502Sjsg 	info->dp2_ext_hdmi_6g_reg_num = info_v11->dp2_retimer_set.Hdmi6GRegNum;
2548fb4d8502Sjsg 	for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
2549fb4d8502Sjsg 		info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2550fb4d8502Sjsg 				info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2551fb4d8502Sjsg 		info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2552fb4d8502Sjsg 				info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2553fb4d8502Sjsg 	}
2554fb4d8502Sjsg 
2555fb4d8502Sjsg 	info->dp3_ext_hdmi_slv_addr = info_v11->dp3_retimer_set.HdmiSlvAddr;
2556fb4d8502Sjsg 	info->dp3_ext_hdmi_reg_num = info_v11->dp3_retimer_set.HdmiRegNum;
2557fb4d8502Sjsg 	for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
2558fb4d8502Sjsg 		info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
2559fb4d8502Sjsg 				info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
2560fb4d8502Sjsg 		info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
2561fb4d8502Sjsg 				info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
2562fb4d8502Sjsg 	}
2563fb4d8502Sjsg 	info->dp3_ext_hdmi_6g_reg_num = info_v11->dp3_retimer_set.Hdmi6GRegNum;
2564fb4d8502Sjsg 	for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
2565fb4d8502Sjsg 		info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
2566fb4d8502Sjsg 				info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
2567fb4d8502Sjsg 		info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
2568fb4d8502Sjsg 				info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
2569fb4d8502Sjsg 	}
2570fb4d8502Sjsg 
2571fb4d8502Sjsg 
2572fb4d8502Sjsg 	/** TODO - review **/
2573fb4d8502Sjsg 	#if 0
2574fb4d8502Sjsg 	info->boot_up_engine_clock = le32_to_cpu(info_v11->ulBootUpEngineClock)
2575fb4d8502Sjsg 									* 10;
2576fb4d8502Sjsg 	info->dentist_vco_freq = le32_to_cpu(info_v11->ulDentistVCOFreq) * 10;
2577fb4d8502Sjsg 	info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
2578fb4d8502Sjsg 
2579fb4d8502Sjsg 	for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2580fb4d8502Sjsg 		/* Convert [10KHz] into [KHz] */
2581fb4d8502Sjsg 		info->disp_clk_voltage[i].max_supported_clk =
2582fb4d8502Sjsg 		le32_to_cpu(info_v11->sDISPCLK_Voltage[i].
2583fb4d8502Sjsg 			ulMaximumSupportedCLK) * 10;
2584fb4d8502Sjsg 		info->disp_clk_voltage[i].voltage_index =
2585fb4d8502Sjsg 		le32_to_cpu(info_v11->sDISPCLK_Voltage[i].ulVoltageIndex);
2586fb4d8502Sjsg 	}
2587fb4d8502Sjsg 
2588fb4d8502Sjsg 	info->boot_up_req_display_vector =
2589fb4d8502Sjsg 			le32_to_cpu(info_v11->ulBootUpReqDisplayVector);
2590fb4d8502Sjsg 	info->boot_up_nb_voltage =
2591fb4d8502Sjsg 			le16_to_cpu(info_v11->usBootUpNBVoltage);
2592fb4d8502Sjsg 	info->ext_disp_conn_info_offset =
2593fb4d8502Sjsg 			le16_to_cpu(info_v11->usExtDispConnInfoOffset);
2594fb4d8502Sjsg 	info->gmc_restore_reset_time =
2595fb4d8502Sjsg 			le32_to_cpu(info_v11->ulGMCRestoreResetTime);
2596fb4d8502Sjsg 	info->minimum_n_clk =
2597fb4d8502Sjsg 			le32_to_cpu(info_v11->ulNbpStateNClkFreq[0]);
2598fb4d8502Sjsg 	for (i = 1; i < 4; ++i)
2599fb4d8502Sjsg 		info->minimum_n_clk =
2600fb4d8502Sjsg 				info->minimum_n_clk <
2601fb4d8502Sjsg 				le32_to_cpu(info_v11->ulNbpStateNClkFreq[i]) ?
2602fb4d8502Sjsg 				info->minimum_n_clk : le32_to_cpu(
2603fb4d8502Sjsg 					info_v11->ulNbpStateNClkFreq[i]);
2604fb4d8502Sjsg 
2605fb4d8502Sjsg 	info->idle_n_clk = le32_to_cpu(info_v11->ulIdleNClk);
2606fb4d8502Sjsg 	info->ddr_dll_power_up_time =
2607fb4d8502Sjsg 	    le32_to_cpu(info_v11->ulDDR_DLL_PowerUpTime);
2608fb4d8502Sjsg 	info->ddr_pll_power_up_time =
2609fb4d8502Sjsg 		le32_to_cpu(info_v11->ulDDR_PLL_PowerUpTime);
2610fb4d8502Sjsg 	info->pcie_clk_ss_type = le16_to_cpu(info_v11->usPCIEClkSSType);
2611fb4d8502Sjsg 	info->max_lvds_pclk_freq_in_single_link =
2612fb4d8502Sjsg 		le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink);
2613fb4d8502Sjsg 	info->max_lvds_pclk_freq_in_single_link =
2614fb4d8502Sjsg 		le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink);
2615fb4d8502Sjsg 	info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
2616fb4d8502Sjsg 		info_v11->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
2617fb4d8502Sjsg 	info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
2618fb4d8502Sjsg 		info_v11->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
2619fb4d8502Sjsg 	info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
2620fb4d8502Sjsg 		info_v11->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
2621fb4d8502Sjsg 	info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
2622fb4d8502Sjsg 		info_v11->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
2623fb4d8502Sjsg 	info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
2624fb4d8502Sjsg 		info_v11->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
2625fb4d8502Sjsg 	info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
2626fb4d8502Sjsg 		info_v11->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
2627fb4d8502Sjsg 	info->lvds_off_to_on_delay_in_4ms =
2628fb4d8502Sjsg 		info_v11->ucLVDSOffToOnDelay_in4Ms;
2629fb4d8502Sjsg 	info->lvds_bit_depth_control_val =
2630fb4d8502Sjsg 		le32_to_cpu(info_v11->ulLCDBitDepthControlVal);
2631fb4d8502Sjsg 
2632fb4d8502Sjsg 	for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
2633fb4d8502Sjsg 		/* Convert [10KHz] into [KHz] */
2634fb4d8502Sjsg 		info->avail_s_clk[i].supported_s_clk =
2635fb4d8502Sjsg 			le32_to_cpu(info_v11->sAvail_SCLK[i].ulSupportedSCLK)
2636fb4d8502Sjsg 									* 10;
2637fb4d8502Sjsg 		info->avail_s_clk[i].voltage_index =
2638fb4d8502Sjsg 			le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageIndex);
2639fb4d8502Sjsg 		info->avail_s_clk[i].voltage_id =
2640fb4d8502Sjsg 			le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageID);
2641fb4d8502Sjsg 	}
2642fb4d8502Sjsg 	#endif /* TODO*/
2643fb4d8502Sjsg 
2644fb4d8502Sjsg 	return BP_RESULT_OK;
2645fb4d8502Sjsg }
2646fb4d8502Sjsg 
26475ca02815Sjsg static enum bp_result get_integrated_info_v2_1(
26485ca02815Sjsg 	struct bios_parser *bp,
26495ca02815Sjsg 	struct integrated_info *info)
26505ca02815Sjsg {
26515ca02815Sjsg 	struct atom_integrated_system_info_v2_1 *info_v2_1;
26525ca02815Sjsg 	uint32_t i;
26535ca02815Sjsg 
26545ca02815Sjsg 	info_v2_1 = GET_IMAGE(struct atom_integrated_system_info_v2_1,
26555ca02815Sjsg 					DATA_TABLES(integratedsysteminfo));
26565ca02815Sjsg 
26575ca02815Sjsg 	if (info_v2_1 == NULL)
26585ca02815Sjsg 		return BP_RESULT_BADBIOSTABLE;
26595ca02815Sjsg 
2660a8749599Sjsg 	DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_1->gpuclk_ss_percentage);
2661a8749599Sjsg 
26625ca02815Sjsg 	info->gpu_cap_info =
26635ca02815Sjsg 	le32_to_cpu(info_v2_1->gpucapinfo);
26645ca02815Sjsg 	/*
26655ca02815Sjsg 	* system_config: Bit[0] = 0 : PCIE power gating disabled
26665ca02815Sjsg 	*                       = 1 : PCIE power gating enabled
26675ca02815Sjsg 	*                Bit[1] = 0 : DDR-PLL shut down disabled
26685ca02815Sjsg 	*                       = 1 : DDR-PLL shut down enabled
26695ca02815Sjsg 	*                Bit[2] = 0 : DDR-PLL power down disabled
26705ca02815Sjsg 	*                       = 1 : DDR-PLL power down enabled
26715ca02815Sjsg 	*/
26725ca02815Sjsg 	info->system_config = le32_to_cpu(info_v2_1->system_config);
26735ca02815Sjsg 	info->cpu_cap_info = le32_to_cpu(info_v2_1->cpucapinfo);
26745ca02815Sjsg 	info->memory_type = info_v2_1->memorytype;
26755ca02815Sjsg 	info->ma_channel_number = info_v2_1->umachannelnumber;
26765ca02815Sjsg 	info->dp_ss_control =
26775ca02815Sjsg 		le16_to_cpu(info_v2_1->reserved1);
26785ca02815Sjsg 
26795ca02815Sjsg 	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
26805ca02815Sjsg 		info->ext_disp_conn_info.gu_id[i] =
26815ca02815Sjsg 				info_v2_1->extdispconninfo.guid[i];
26825ca02815Sjsg 	}
26835ca02815Sjsg 
26845ca02815Sjsg 	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
26855ca02815Sjsg 		info->ext_disp_conn_info.path[i].device_connector_id =
26865ca02815Sjsg 		object_id_from_bios_object_id(
26875ca02815Sjsg 		le16_to_cpu(info_v2_1->extdispconninfo.path[i].connectorobjid));
26885ca02815Sjsg 
26895ca02815Sjsg 		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
26905ca02815Sjsg 		object_id_from_bios_object_id(
26915ca02815Sjsg 			le16_to_cpu(
26925ca02815Sjsg 			info_v2_1->extdispconninfo.path[i].ext_encoder_objid));
26935ca02815Sjsg 
26945ca02815Sjsg 		info->ext_disp_conn_info.path[i].device_tag =
26955ca02815Sjsg 			le16_to_cpu(
26965ca02815Sjsg 				info_v2_1->extdispconninfo.path[i].device_tag);
26975ca02815Sjsg 		info->ext_disp_conn_info.path[i].device_acpi_enum =
26985ca02815Sjsg 		le16_to_cpu(
26995ca02815Sjsg 			info_v2_1->extdispconninfo.path[i].device_acpi_enum);
27005ca02815Sjsg 		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
27015ca02815Sjsg 			info_v2_1->extdispconninfo.path[i].auxddclut_index;
27025ca02815Sjsg 		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
27035ca02815Sjsg 			info_v2_1->extdispconninfo.path[i].hpdlut_index;
27045ca02815Sjsg 		info->ext_disp_conn_info.path[i].channel_mapping.raw =
27055ca02815Sjsg 			info_v2_1->extdispconninfo.path[i].channelmapping;
27065ca02815Sjsg 		info->ext_disp_conn_info.path[i].caps =
27075ca02815Sjsg 				le16_to_cpu(info_v2_1->extdispconninfo.path[i].caps);
27085ca02815Sjsg 	}
27095ca02815Sjsg 
27105ca02815Sjsg 	info->ext_disp_conn_info.checksum =
27115ca02815Sjsg 		info_v2_1->extdispconninfo.checksum;
27125ca02815Sjsg 	info->dp0_ext_hdmi_slv_addr = info_v2_1->dp0_retimer_set.HdmiSlvAddr;
27135ca02815Sjsg 	info->dp0_ext_hdmi_reg_num = info_v2_1->dp0_retimer_set.HdmiRegNum;
27145ca02815Sjsg 	for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {
27155ca02815Sjsg 		info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =
27165ca02815Sjsg 				info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
27175ca02815Sjsg 		info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =
27185ca02815Sjsg 				info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
27195ca02815Sjsg 	}
27205ca02815Sjsg 	info->dp0_ext_hdmi_6g_reg_num = info_v2_1->dp0_retimer_set.Hdmi6GRegNum;
27215ca02815Sjsg 	for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {
27225ca02815Sjsg 		info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
27235ca02815Sjsg 				info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
27245ca02815Sjsg 		info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
27255ca02815Sjsg 				info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
27265ca02815Sjsg 	}
27275ca02815Sjsg 	info->dp1_ext_hdmi_slv_addr = info_v2_1->dp1_retimer_set.HdmiSlvAddr;
27285ca02815Sjsg 	info->dp1_ext_hdmi_reg_num = info_v2_1->dp1_retimer_set.HdmiRegNum;
27295ca02815Sjsg 	for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {
27305ca02815Sjsg 		info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =
27315ca02815Sjsg 				info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
27325ca02815Sjsg 		info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =
27335ca02815Sjsg 				info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
27345ca02815Sjsg 	}
27355ca02815Sjsg 	info->dp1_ext_hdmi_6g_reg_num = info_v2_1->dp1_retimer_set.Hdmi6GRegNum;
27365ca02815Sjsg 	for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {
27375ca02815Sjsg 		info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
27385ca02815Sjsg 				info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
27395ca02815Sjsg 		info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
27405ca02815Sjsg 				info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
27415ca02815Sjsg 	}
27425ca02815Sjsg 	info->dp2_ext_hdmi_slv_addr = info_v2_1->dp2_retimer_set.HdmiSlvAddr;
27435ca02815Sjsg 	info->dp2_ext_hdmi_reg_num = info_v2_1->dp2_retimer_set.HdmiRegNum;
27445ca02815Sjsg 	for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {
27455ca02815Sjsg 		info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =
27465ca02815Sjsg 				info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
27475ca02815Sjsg 		info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =
27485ca02815Sjsg 				info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
27495ca02815Sjsg 	}
27505ca02815Sjsg 	info->dp2_ext_hdmi_6g_reg_num = info_v2_1->dp2_retimer_set.Hdmi6GRegNum;
27515ca02815Sjsg 	for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {
27525ca02815Sjsg 		info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
27535ca02815Sjsg 				info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
27545ca02815Sjsg 		info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
27555ca02815Sjsg 				info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
27565ca02815Sjsg 	}
27575ca02815Sjsg 	info->dp3_ext_hdmi_slv_addr = info_v2_1->dp3_retimer_set.HdmiSlvAddr;
27585ca02815Sjsg 	info->dp3_ext_hdmi_reg_num = info_v2_1->dp3_retimer_set.HdmiRegNum;
27595ca02815Sjsg 	for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {
27605ca02815Sjsg 		info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =
27615ca02815Sjsg 				info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;
27625ca02815Sjsg 		info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =
27635ca02815Sjsg 				info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;
27645ca02815Sjsg 	}
27655ca02815Sjsg 	info->dp3_ext_hdmi_6g_reg_num = info_v2_1->dp3_retimer_set.Hdmi6GRegNum;
27665ca02815Sjsg 	for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {
27675ca02815Sjsg 		info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =
27685ca02815Sjsg 				info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;
27695ca02815Sjsg 		info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val =
27705ca02815Sjsg 				info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;
27715ca02815Sjsg 	}
27725ca02815Sjsg 
27735ca02815Sjsg 	info->edp1_info.edp_backlight_pwm_hz =
27745ca02815Sjsg 	le16_to_cpu(info_v2_1->edp1_info.edp_backlight_pwm_hz);
27755ca02815Sjsg 	info->edp1_info.edp_ss_percentage =
27765ca02815Sjsg 	le16_to_cpu(info_v2_1->edp1_info.edp_ss_percentage);
27775ca02815Sjsg 	info->edp1_info.edp_ss_rate_10hz =
27785ca02815Sjsg 	le16_to_cpu(info_v2_1->edp1_info.edp_ss_rate_10hz);
27795ca02815Sjsg 	info->edp1_info.edp_pwr_on_off_delay =
27805ca02815Sjsg 		info_v2_1->edp1_info.edp_pwr_on_off_delay;
27815ca02815Sjsg 	info->edp1_info.edp_pwr_on_vary_bl_to_blon =
27825ca02815Sjsg 		info_v2_1->edp1_info.edp_pwr_on_vary_bl_to_blon;
27835ca02815Sjsg 	info->edp1_info.edp_pwr_down_bloff_to_vary_bloff =
27845ca02815Sjsg 		info_v2_1->edp1_info.edp_pwr_down_bloff_to_vary_bloff;
27855ca02815Sjsg 	info->edp1_info.edp_panel_bpc =
27865ca02815Sjsg 		info_v2_1->edp1_info.edp_panel_bpc;
27875ca02815Sjsg 	info->edp1_info.edp_bootup_bl_level = info_v2_1->edp1_info.edp_bootup_bl_level;
27885ca02815Sjsg 
27895ca02815Sjsg 	info->edp2_info.edp_backlight_pwm_hz =
27905ca02815Sjsg 	le16_to_cpu(info_v2_1->edp2_info.edp_backlight_pwm_hz);
27915ca02815Sjsg 	info->edp2_info.edp_ss_percentage =
27925ca02815Sjsg 	le16_to_cpu(info_v2_1->edp2_info.edp_ss_percentage);
27935ca02815Sjsg 	info->edp2_info.edp_ss_rate_10hz =
27945ca02815Sjsg 	le16_to_cpu(info_v2_1->edp2_info.edp_ss_rate_10hz);
27955ca02815Sjsg 	info->edp2_info.edp_pwr_on_off_delay =
27965ca02815Sjsg 		info_v2_1->edp2_info.edp_pwr_on_off_delay;
27975ca02815Sjsg 	info->edp2_info.edp_pwr_on_vary_bl_to_blon =
27985ca02815Sjsg 		info_v2_1->edp2_info.edp_pwr_on_vary_bl_to_blon;
27995ca02815Sjsg 	info->edp2_info.edp_pwr_down_bloff_to_vary_bloff =
28005ca02815Sjsg 		info_v2_1->edp2_info.edp_pwr_down_bloff_to_vary_bloff;
28015ca02815Sjsg 	info->edp2_info.edp_panel_bpc =
28025ca02815Sjsg 		info_v2_1->edp2_info.edp_panel_bpc;
28035ca02815Sjsg 	info->edp2_info.edp_bootup_bl_level =
28045ca02815Sjsg 		info_v2_1->edp2_info.edp_bootup_bl_level;
28055ca02815Sjsg 
28065ca02815Sjsg 	return BP_RESULT_OK;
28075ca02815Sjsg }
28085ca02815Sjsg 
28095ca02815Sjsg static enum bp_result get_integrated_info_v2_2(
28105ca02815Sjsg 	struct bios_parser *bp,
28115ca02815Sjsg 	struct integrated_info *info)
28125ca02815Sjsg {
28135ca02815Sjsg 	struct atom_integrated_system_info_v2_2 *info_v2_2;
28145ca02815Sjsg 	uint32_t i;
28155ca02815Sjsg 
28165ca02815Sjsg 	info_v2_2 = GET_IMAGE(struct atom_integrated_system_info_v2_2,
28175ca02815Sjsg 					DATA_TABLES(integratedsysteminfo));
28185ca02815Sjsg 
28195ca02815Sjsg 	if (info_v2_2 == NULL)
28205ca02815Sjsg 		return BP_RESULT_BADBIOSTABLE;
28215ca02815Sjsg 
2822a8749599Sjsg 	DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_2->gpuclk_ss_percentage);
2823a8749599Sjsg 
28245ca02815Sjsg 	info->gpu_cap_info =
28255ca02815Sjsg 	le32_to_cpu(info_v2_2->gpucapinfo);
28265ca02815Sjsg 	/*
28275ca02815Sjsg 	* system_config: Bit[0] = 0 : PCIE power gating disabled
28285ca02815Sjsg 	*                       = 1 : PCIE power gating enabled
28295ca02815Sjsg 	*                Bit[1] = 0 : DDR-PLL shut down disabled
28305ca02815Sjsg 	*                       = 1 : DDR-PLL shut down enabled
28315ca02815Sjsg 	*                Bit[2] = 0 : DDR-PLL power down disabled
28325ca02815Sjsg 	*                       = 1 : DDR-PLL power down enabled
28335ca02815Sjsg 	*/
28345ca02815Sjsg 	info->system_config = le32_to_cpu(info_v2_2->system_config);
28355ca02815Sjsg 	info->cpu_cap_info = le32_to_cpu(info_v2_2->cpucapinfo);
28365ca02815Sjsg 	info->memory_type = info_v2_2->memorytype;
28375ca02815Sjsg 	info->ma_channel_number = info_v2_2->umachannelnumber;
28385ca02815Sjsg 	info->dp_ss_control =
28395ca02815Sjsg 		le16_to_cpu(info_v2_2->reserved1);
28402d4ce006Sjsg 	info->gpuclk_ss_percentage = info_v2_2->gpuclk_ss_percentage;
28412d4ce006Sjsg 	info->gpuclk_ss_type = info_v2_2->gpuclk_ss_type;
28425ca02815Sjsg 
28435ca02815Sjsg 	for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
28445ca02815Sjsg 		info->ext_disp_conn_info.gu_id[i] =
28455ca02815Sjsg 				info_v2_2->extdispconninfo.guid[i];
28465ca02815Sjsg 	}
28475ca02815Sjsg 
28485ca02815Sjsg 	for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
28495ca02815Sjsg 		info->ext_disp_conn_info.path[i].device_connector_id =
28505ca02815Sjsg 		object_id_from_bios_object_id(
28515ca02815Sjsg 		le16_to_cpu(info_v2_2->extdispconninfo.path[i].connectorobjid));
28525ca02815Sjsg 
28535ca02815Sjsg 		info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
28545ca02815Sjsg 		object_id_from_bios_object_id(
28555ca02815Sjsg 			le16_to_cpu(
28565ca02815Sjsg 			info_v2_2->extdispconninfo.path[i].ext_encoder_objid));
28575ca02815Sjsg 
28585ca02815Sjsg 		info->ext_disp_conn_info.path[i].device_tag =
28595ca02815Sjsg 			le16_to_cpu(
28605ca02815Sjsg 				info_v2_2->extdispconninfo.path[i].device_tag);
28615ca02815Sjsg 		info->ext_disp_conn_info.path[i].device_acpi_enum =
28625ca02815Sjsg 		le16_to_cpu(
28635ca02815Sjsg 			info_v2_2->extdispconninfo.path[i].device_acpi_enum);
28645ca02815Sjsg 		info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
28655ca02815Sjsg 			info_v2_2->extdispconninfo.path[i].auxddclut_index;
28665ca02815Sjsg 		info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
28675ca02815Sjsg 			info_v2_2->extdispconninfo.path[i].hpdlut_index;
28685ca02815Sjsg 		info->ext_disp_conn_info.path[i].channel_mapping.raw =
28695ca02815Sjsg 			info_v2_2->extdispconninfo.path[i].channelmapping;
28705ca02815Sjsg 		info->ext_disp_conn_info.path[i].caps =
28715ca02815Sjsg 				le16_to_cpu(info_v2_2->extdispconninfo.path[i].caps);
28725ca02815Sjsg 	}
28735ca02815Sjsg 
28745ca02815Sjsg 	info->ext_disp_conn_info.checksum =
28755ca02815Sjsg 		info_v2_2->extdispconninfo.checksum;
28761bb76ff1Sjsg 	info->ext_disp_conn_info.fixdpvoltageswing =
28771bb76ff1Sjsg 		info_v2_2->extdispconninfo.fixdpvoltageswing;
28785ca02815Sjsg 
28795ca02815Sjsg 	info->edp1_info.edp_backlight_pwm_hz =
28805ca02815Sjsg 	le16_to_cpu(info_v2_2->edp1_info.edp_backlight_pwm_hz);
28815ca02815Sjsg 	info->edp1_info.edp_ss_percentage =
28825ca02815Sjsg 	le16_to_cpu(info_v2_2->edp1_info.edp_ss_percentage);
28835ca02815Sjsg 	info->edp1_info.edp_ss_rate_10hz =
28845ca02815Sjsg 	le16_to_cpu(info_v2_2->edp1_info.edp_ss_rate_10hz);
28855ca02815Sjsg 	info->edp1_info.edp_pwr_on_off_delay =
28865ca02815Sjsg 		info_v2_2->edp1_info.edp_pwr_on_off_delay;
28875ca02815Sjsg 	info->edp1_info.edp_pwr_on_vary_bl_to_blon =
28885ca02815Sjsg 		info_v2_2->edp1_info.edp_pwr_on_vary_bl_to_blon;
28895ca02815Sjsg 	info->edp1_info.edp_pwr_down_bloff_to_vary_bloff =
28905ca02815Sjsg 		info_v2_2->edp1_info.edp_pwr_down_bloff_to_vary_bloff;
28915ca02815Sjsg 	info->edp1_info.edp_panel_bpc =
28925ca02815Sjsg 		info_v2_2->edp1_info.edp_panel_bpc;
28935ca02815Sjsg 	info->edp1_info.edp_bootup_bl_level =
28945ca02815Sjsg 
28955ca02815Sjsg 	info->edp2_info.edp_backlight_pwm_hz =
28965ca02815Sjsg 	le16_to_cpu(info_v2_2->edp2_info.edp_backlight_pwm_hz);
28975ca02815Sjsg 	info->edp2_info.edp_ss_percentage =
28985ca02815Sjsg 	le16_to_cpu(info_v2_2->edp2_info.edp_ss_percentage);
28995ca02815Sjsg 	info->edp2_info.edp_ss_rate_10hz =
29005ca02815Sjsg 	le16_to_cpu(info_v2_2->edp2_info.edp_ss_rate_10hz);
29015ca02815Sjsg 	info->edp2_info.edp_pwr_on_off_delay =
29025ca02815Sjsg 		info_v2_2->edp2_info.edp_pwr_on_off_delay;
29035ca02815Sjsg 	info->edp2_info.edp_pwr_on_vary_bl_to_blon =
29045ca02815Sjsg 		info_v2_2->edp2_info.edp_pwr_on_vary_bl_to_blon;
29055ca02815Sjsg 	info->edp2_info.edp_pwr_down_bloff_to_vary_bloff =
29065ca02815Sjsg 		info_v2_2->edp2_info.edp_pwr_down_bloff_to_vary_bloff;
29075ca02815Sjsg 	info->edp2_info.edp_panel_bpc =
29085ca02815Sjsg 		info_v2_2->edp2_info.edp_panel_bpc;
29095ca02815Sjsg 	info->edp2_info.edp_bootup_bl_level =
29105ca02815Sjsg 		info_v2_2->edp2_info.edp_bootup_bl_level;
29115ca02815Sjsg 
29125ca02815Sjsg 	return BP_RESULT_OK;
29135ca02815Sjsg }
2914fb4d8502Sjsg 
2915fb4d8502Sjsg /*
2916fb4d8502Sjsg  * construct_integrated_info
2917fb4d8502Sjsg  *
2918fb4d8502Sjsg  * @brief
2919fb4d8502Sjsg  * Get integrated BIOS information based on table revision
2920fb4d8502Sjsg  *
2921fb4d8502Sjsg  * @param
2922fb4d8502Sjsg  * bios_parser *bp - [in]BIOS parser handler to get master data table
2923fb4d8502Sjsg  * integrated_info *info - [out] store and output integrated info
2924fb4d8502Sjsg  *
2925fb4d8502Sjsg  * @return
29261bb76ff1Sjsg  * static enum bp_result - BP_RESULT_OK if information is available,
2927fb4d8502Sjsg  *                  BP_RESULT_BADBIOSTABLE otherwise.
2928fb4d8502Sjsg  */
2929fb4d8502Sjsg static enum bp_result construct_integrated_info(
2930fb4d8502Sjsg 	struct bios_parser *bp,
2931fb4d8502Sjsg 	struct integrated_info *info)
2932fb4d8502Sjsg {
29331bb76ff1Sjsg 	static enum bp_result result = BP_RESULT_BADBIOSTABLE;
2934fb4d8502Sjsg 
2935fb4d8502Sjsg 	struct atom_common_table_header *header;
2936fb4d8502Sjsg 	struct atom_data_revision revision;
29371bb76ff1Sjsg 
2938*777bfb8aSjsg 	int32_t i;
2939*777bfb8aSjsg 	int32_t j;
2940*777bfb8aSjsg 
2941*777bfb8aSjsg 	if (!info)
2942*777bfb8aSjsg 		return result;
2943fb4d8502Sjsg 
2944fb4d8502Sjsg 	if (info && DATA_TABLES(integratedsysteminfo)) {
2945fb4d8502Sjsg 		header = GET_IMAGE(struct atom_common_table_header,
2946fb4d8502Sjsg 					DATA_TABLES(integratedsysteminfo));
2947fb4d8502Sjsg 
2948fb4d8502Sjsg 		get_atom_data_table_revision(header, &revision);
2949fb4d8502Sjsg 
29505ca02815Sjsg 		switch (revision.major) {
29515ca02815Sjsg 		case 1:
2952fb4d8502Sjsg 			switch (revision.minor) {
2953fb4d8502Sjsg 			case 11:
2954c349dbc7Sjsg 			case 12:
2955fb4d8502Sjsg 				result = get_integrated_info_v11(bp, info);
2956fb4d8502Sjsg 				break;
2957fb4d8502Sjsg 			default:
2958fb4d8502Sjsg 				return result;
2959fb4d8502Sjsg 			}
29605ca02815Sjsg 			break;
29615ca02815Sjsg 		case 2:
29625ca02815Sjsg 			switch (revision.minor) {
29635ca02815Sjsg 			case 1:
29645ca02815Sjsg 				result = get_integrated_info_v2_1(bp, info);
29655ca02815Sjsg 				break;
29665ca02815Sjsg 			case 2:
296727d456ebSjsg 			case 3:
29685ca02815Sjsg 				result = get_integrated_info_v2_2(bp, info);
29695ca02815Sjsg 				break;
29705ca02815Sjsg 			default:
29715ca02815Sjsg 				return result;
29725ca02815Sjsg 			}
29735ca02815Sjsg 			break;
29745ca02815Sjsg 		default:
29755ca02815Sjsg 			return result;
29765ca02815Sjsg 		}
29771bb76ff1Sjsg 		if (result == BP_RESULT_OK) {
29781bb76ff1Sjsg 
29791bb76ff1Sjsg 			DC_LOG_BIOS("edp1:\n"
29801bb76ff1Sjsg 						"\tedp_pwr_on_off_delay = %d\n"
29811bb76ff1Sjsg 						"\tedp_pwr_on_vary_bl_to_blon = %d\n"
29821bb76ff1Sjsg 						"\tedp_pwr_down_bloff_to_vary_bloff = %d\n"
29831bb76ff1Sjsg 						"\tedp_bootup_bl_level = %d\n",
29841bb76ff1Sjsg 						info->edp1_info.edp_pwr_on_off_delay,
29851bb76ff1Sjsg 						info->edp1_info.edp_pwr_on_vary_bl_to_blon,
29861bb76ff1Sjsg 						info->edp1_info.edp_pwr_down_bloff_to_vary_bloff,
29871bb76ff1Sjsg 						info->edp1_info.edp_bootup_bl_level);
29881bb76ff1Sjsg 			DC_LOG_BIOS("edp2:\n"
29891bb76ff1Sjsg 						"\tedp_pwr_on_off_delayv = %d\n"
29901bb76ff1Sjsg 						"\tedp_pwr_on_vary_bl_to_blon = %d\n"
29911bb76ff1Sjsg 						"\tedp_pwr_down_bloff_to_vary_bloff = %d\n"
29921bb76ff1Sjsg 						"\tedp_bootup_bl_level = %d\n",
29931bb76ff1Sjsg 						info->edp2_info.edp_pwr_on_off_delay,
29941bb76ff1Sjsg 						info->edp2_info.edp_pwr_on_vary_bl_to_blon,
29951bb76ff1Sjsg 						info->edp2_info.edp_pwr_down_bloff_to_vary_bloff,
29961bb76ff1Sjsg 						info->edp2_info.edp_bootup_bl_level);
29971bb76ff1Sjsg 		}
2998fb4d8502Sjsg 	}
2999fb4d8502Sjsg 
3000fb4d8502Sjsg 	if (result != BP_RESULT_OK)
3001fb4d8502Sjsg 		return result;
30021bb76ff1Sjsg 	else {
30031bb76ff1Sjsg 		// Log each external path
30041bb76ff1Sjsg 		for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {
30051bb76ff1Sjsg 			if (info->ext_disp_conn_info.path[i].device_tag != 0)
30061bb76ff1Sjsg 				DC_LOG_BIOS("integrated_info:For EXTERNAL DISPLAY PATH %d --------------\n"
30071bb76ff1Sjsg 						"DEVICE_TAG: 0x%x\n"
30081bb76ff1Sjsg 						"DEVICE_ACPI_ENUM: 0x%x\n"
30091bb76ff1Sjsg 						"DEVICE_CONNECTOR_ID: 0x%x\n"
30101bb76ff1Sjsg 						"EXT_AUX_DDC_LUT_INDEX: %d\n"
30111bb76ff1Sjsg 						"EXT_HPD_PIN_LUT_INDEX: %d\n"
30121bb76ff1Sjsg 						"EXT_ENCODER_OBJ_ID: 0x%x\n"
30131bb76ff1Sjsg 						"Encoder CAPS: 0x%x\n",
30141bb76ff1Sjsg 						i,
30151bb76ff1Sjsg 						info->ext_disp_conn_info.path[i].device_tag,
30161bb76ff1Sjsg 						info->ext_disp_conn_info.path[i].device_acpi_enum,
30171bb76ff1Sjsg 						info->ext_disp_conn_info.path[i].device_connector_id.id,
30181bb76ff1Sjsg 						info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index,
30191bb76ff1Sjsg 						info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index,
30201bb76ff1Sjsg 						info->ext_disp_conn_info.path[i].ext_encoder_obj_id.id,
30211bb76ff1Sjsg 						info->ext_disp_conn_info.path[i].caps
30221bb76ff1Sjsg 						);
30231bb76ff1Sjsg 			if (info->ext_disp_conn_info.path[i].caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN)
30241bb76ff1Sjsg 				DC_LOG_BIOS("BIOS EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);
30251bb76ff1Sjsg 			else if (bp->base.ctx->dc->config.force_bios_fixed_vs) {
30261bb76ff1Sjsg 				info->ext_disp_conn_info.path[i].caps |= EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN;
30271bb76ff1Sjsg 				DC_LOG_BIOS("driver forced EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);
30281bb76ff1Sjsg 			}
30291bb76ff1Sjsg 		}
30301bb76ff1Sjsg 		// Log the Checksum and Voltage Swing
30311bb76ff1Sjsg 		DC_LOG_BIOS("Integrated info table CHECKSUM: %d\n"
30321bb76ff1Sjsg 					"Integrated info table FIX_DP_VOLTAGE_SWING: %d\n",
30331bb76ff1Sjsg 					info->ext_disp_conn_info.checksum,
30341bb76ff1Sjsg 					info->ext_disp_conn_info.fixdpvoltageswing);
30351bb76ff1Sjsg 		if (bp->base.ctx->dc->config.force_bios_fixed_vs && info->ext_disp_conn_info.fixdpvoltageswing == 0) {
30361bb76ff1Sjsg 			info->ext_disp_conn_info.fixdpvoltageswing = bp->base.ctx->dc->config.force_bios_fixed_vs & 0xF;
30371bb76ff1Sjsg 			DC_LOG_BIOS("driver forced fixdpvoltageswing = %d\n", info->ext_disp_conn_info.fixdpvoltageswing);
30381bb76ff1Sjsg 		}
30391bb76ff1Sjsg 	}
3040fb4d8502Sjsg 	/* Sort voltage table from low to high*/
3041fb4d8502Sjsg 	for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
3042fb4d8502Sjsg 		for (j = i; j > 0; --j) {
3043fb4d8502Sjsg 			if (info->disp_clk_voltage[j].max_supported_clk <
3044f005ef32Sjsg 			    info->disp_clk_voltage[j-1].max_supported_clk)
3045f005ef32Sjsg 				swap(info->disp_clk_voltage[j-1], info->disp_clk_voltage[j]);
3046fb4d8502Sjsg 		}
3047fb4d8502Sjsg 	}
3048fb4d8502Sjsg 
3049fb4d8502Sjsg 	return result;
3050fb4d8502Sjsg }
3051fb4d8502Sjsg 
3052ad8b1aafSjsg static enum bp_result bios_parser_get_vram_info(
3053ad8b1aafSjsg 		struct dc_bios *dcb,
3054ad8b1aafSjsg 		struct dc_vram_info *info)
3055ad8b1aafSjsg {
3056ad8b1aafSjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
30571bb76ff1Sjsg 	static enum bp_result result = BP_RESULT_BADBIOSTABLE;
3058ad8b1aafSjsg 	struct atom_common_table_header *header;
3059ad8b1aafSjsg 	struct atom_data_revision revision;
3060ad8b1aafSjsg 
3061ad8b1aafSjsg 	if (info && DATA_TABLES(vram_info)) {
3062ad8b1aafSjsg 		header = GET_IMAGE(struct atom_common_table_header,
3063ad8b1aafSjsg 					DATA_TABLES(vram_info));
3064ad8b1aafSjsg 
3065ad8b1aafSjsg 		get_atom_data_table_revision(header, &revision);
3066ad8b1aafSjsg 
3067ad8b1aafSjsg 		switch (revision.major) {
3068ad8b1aafSjsg 		case 2:
3069ad8b1aafSjsg 			switch (revision.minor) {
3070ad8b1aafSjsg 			case 3:
3071ad8b1aafSjsg 				result = get_vram_info_v23(bp, info);
3072ad8b1aafSjsg 				break;
3073ad8b1aafSjsg 			case 4:
3074ad8b1aafSjsg 				result = get_vram_info_v24(bp, info);
3075ad8b1aafSjsg 				break;
3076ad8b1aafSjsg 			case 5:
3077ad8b1aafSjsg 				result = get_vram_info_v25(bp, info);
3078ad8b1aafSjsg 				break;
3079ad8b1aafSjsg 			default:
3080ad8b1aafSjsg 				break;
3081ad8b1aafSjsg 			}
3082ad8b1aafSjsg 			break;
3083ad8b1aafSjsg 
30841bb76ff1Sjsg 		case 3:
30851bb76ff1Sjsg 			switch (revision.minor) {
30861bb76ff1Sjsg 			case 0:
30871bb76ff1Sjsg 				result = get_vram_info_v30(bp, info);
30881bb76ff1Sjsg 				break;
30891bb76ff1Sjsg 			default:
30901bb76ff1Sjsg 				break;
30911bb76ff1Sjsg 			}
30921bb76ff1Sjsg 			break;
30931bb76ff1Sjsg 
3094ad8b1aafSjsg 		default:
3095ad8b1aafSjsg 			return result;
3096ad8b1aafSjsg 		}
3097ad8b1aafSjsg 
3098ad8b1aafSjsg 	}
3099ad8b1aafSjsg 	return result;
3100ad8b1aafSjsg }
3101ad8b1aafSjsg 
3102fb4d8502Sjsg static struct integrated_info *bios_parser_create_integrated_info(
3103fb4d8502Sjsg 	struct dc_bios *dcb)
3104fb4d8502Sjsg {
3105fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
3106f005ef32Sjsg 	struct integrated_info *info;
3107fb4d8502Sjsg 
3108fb4d8502Sjsg 	info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL);
3109fb4d8502Sjsg 
3110fb4d8502Sjsg 	if (info == NULL) {
3111fb4d8502Sjsg 		ASSERT_CRITICAL(0);
3112fb4d8502Sjsg 		return NULL;
3113fb4d8502Sjsg 	}
3114fb4d8502Sjsg 
3115fb4d8502Sjsg 	if (construct_integrated_info(bp, info) == BP_RESULT_OK)
3116fb4d8502Sjsg 		return info;
3117fb4d8502Sjsg 
3118fb4d8502Sjsg 	kfree(info);
3119fb4d8502Sjsg 
3120fb4d8502Sjsg 	return NULL;
3121fb4d8502Sjsg }
3122fb4d8502Sjsg 
3123fb4d8502Sjsg static enum bp_result update_slot_layout_info(
3124fb4d8502Sjsg 	struct dc_bios *dcb,
3125fb4d8502Sjsg 	unsigned int i,
3126fb4d8502Sjsg 	struct slot_layout_info *slot_layout_info)
3127fb4d8502Sjsg {
3128fb4d8502Sjsg 	unsigned int record_offset;
3129fb4d8502Sjsg 	unsigned int j;
3130fb4d8502Sjsg 	struct atom_display_object_path_v2 *object;
3131fb4d8502Sjsg 	struct atom_bracket_layout_record *record;
3132fb4d8502Sjsg 	struct atom_common_record_header *record_header;
31331bb76ff1Sjsg 	static enum bp_result result;
3134fb4d8502Sjsg 	struct bios_parser *bp;
3135fb4d8502Sjsg 	struct object_info_table *tbl;
3136fb4d8502Sjsg 	struct display_object_info_table_v1_4 *v1_4;
3137fb4d8502Sjsg 
3138fb4d8502Sjsg 	record = NULL;
3139fb4d8502Sjsg 	record_header = NULL;
3140fb4d8502Sjsg 	result = BP_RESULT_NORECORD;
3141fb4d8502Sjsg 
3142fb4d8502Sjsg 	bp = BP_FROM_DCB(dcb);
3143fb4d8502Sjsg 	tbl = &bp->object_info_tbl;
3144fb4d8502Sjsg 	v1_4 = tbl->v1_4;
3145fb4d8502Sjsg 
3146fb4d8502Sjsg 	object = &v1_4->display_path[i];
3147fb4d8502Sjsg 	record_offset = (unsigned int)
3148fb4d8502Sjsg 		(object->disp_recordoffset) +
3149fb4d8502Sjsg 		(unsigned int)(bp->object_info_tbl_offset);
3150fb4d8502Sjsg 
3151fb4d8502Sjsg 	for (;;) {
3152fb4d8502Sjsg 
3153fb4d8502Sjsg 		record_header = (struct atom_common_record_header *)
3154fb4d8502Sjsg 			GET_IMAGE(struct atom_common_record_header,
3155fb4d8502Sjsg 			record_offset);
3156fb4d8502Sjsg 		if (record_header == NULL) {
3157fb4d8502Sjsg 			result = BP_RESULT_BADBIOSTABLE;
3158fb4d8502Sjsg 			break;
3159fb4d8502Sjsg 		}
3160fb4d8502Sjsg 
3161fb4d8502Sjsg 		/* the end of the list */
3162fb4d8502Sjsg 		if (record_header->record_type == 0xff ||
3163fb4d8502Sjsg 			record_header->record_size == 0)	{
3164fb4d8502Sjsg 			break;
3165fb4d8502Sjsg 		}
3166fb4d8502Sjsg 
3167fb4d8502Sjsg 		if (record_header->record_type ==
3168fb4d8502Sjsg 			ATOM_BRACKET_LAYOUT_RECORD_TYPE &&
3169fb4d8502Sjsg 			sizeof(struct atom_bracket_layout_record)
3170fb4d8502Sjsg 			<= record_header->record_size) {
3171fb4d8502Sjsg 			record = (struct atom_bracket_layout_record *)
3172fb4d8502Sjsg 				(record_header);
3173fb4d8502Sjsg 			result = BP_RESULT_OK;
3174fb4d8502Sjsg 			break;
3175fb4d8502Sjsg 		}
3176fb4d8502Sjsg 
3177fb4d8502Sjsg 		record_offset += record_header->record_size;
3178fb4d8502Sjsg 	}
3179fb4d8502Sjsg 
3180fb4d8502Sjsg 	/* return if the record not found */
3181fb4d8502Sjsg 	if (result != BP_RESULT_OK)
3182fb4d8502Sjsg 		return result;
3183fb4d8502Sjsg 
3184fb4d8502Sjsg 	/* get slot sizes */
3185fb4d8502Sjsg 	slot_layout_info->length = record->bracketlen;
3186fb4d8502Sjsg 	slot_layout_info->width = record->bracketwidth;
3187fb4d8502Sjsg 
3188fb4d8502Sjsg 	/* get info for each connector in the slot */
3189fb4d8502Sjsg 	slot_layout_info->num_of_connectors = record->conn_num;
3190fb4d8502Sjsg 	for (j = 0; j < slot_layout_info->num_of_connectors; ++j) {
3191fb4d8502Sjsg 		slot_layout_info->connectors[j].connector_type =
3192fb4d8502Sjsg 			(enum connector_layout_type)
3193fb4d8502Sjsg 			(record->conn_info[j].connector_type);
3194fb4d8502Sjsg 		switch (record->conn_info[j].connector_type) {
3195fb4d8502Sjsg 		case CONNECTOR_TYPE_DVI_D:
3196fb4d8502Sjsg 			slot_layout_info->connectors[j].connector_type =
3197fb4d8502Sjsg 				CONNECTOR_LAYOUT_TYPE_DVI_D;
3198fb4d8502Sjsg 			slot_layout_info->connectors[j].length =
3199fb4d8502Sjsg 				CONNECTOR_SIZE_DVI;
3200fb4d8502Sjsg 			break;
3201fb4d8502Sjsg 
3202fb4d8502Sjsg 		case CONNECTOR_TYPE_HDMI:
3203fb4d8502Sjsg 			slot_layout_info->connectors[j].connector_type =
3204fb4d8502Sjsg 				CONNECTOR_LAYOUT_TYPE_HDMI;
3205fb4d8502Sjsg 			slot_layout_info->connectors[j].length =
3206fb4d8502Sjsg 				CONNECTOR_SIZE_HDMI;
3207fb4d8502Sjsg 			break;
3208fb4d8502Sjsg 
3209fb4d8502Sjsg 		case CONNECTOR_TYPE_DISPLAY_PORT:
3210fb4d8502Sjsg 			slot_layout_info->connectors[j].connector_type =
3211fb4d8502Sjsg 				CONNECTOR_LAYOUT_TYPE_DP;
3212fb4d8502Sjsg 			slot_layout_info->connectors[j].length =
3213fb4d8502Sjsg 				CONNECTOR_SIZE_DP;
3214fb4d8502Sjsg 			break;
3215fb4d8502Sjsg 
3216fb4d8502Sjsg 		case CONNECTOR_TYPE_MINI_DISPLAY_PORT:
3217fb4d8502Sjsg 			slot_layout_info->connectors[j].connector_type =
3218fb4d8502Sjsg 				CONNECTOR_LAYOUT_TYPE_MINI_DP;
3219fb4d8502Sjsg 			slot_layout_info->connectors[j].length =
3220fb4d8502Sjsg 				CONNECTOR_SIZE_MINI_DP;
3221fb4d8502Sjsg 			break;
3222fb4d8502Sjsg 
3223fb4d8502Sjsg 		default:
3224fb4d8502Sjsg 			slot_layout_info->connectors[j].connector_type =
3225fb4d8502Sjsg 				CONNECTOR_LAYOUT_TYPE_UNKNOWN;
3226fb4d8502Sjsg 			slot_layout_info->connectors[j].length =
3227fb4d8502Sjsg 				CONNECTOR_SIZE_UNKNOWN;
3228fb4d8502Sjsg 		}
3229fb4d8502Sjsg 
3230fb4d8502Sjsg 		slot_layout_info->connectors[j].position =
3231fb4d8502Sjsg 			record->conn_info[j].position;
3232fb4d8502Sjsg 		slot_layout_info->connectors[j].connector_id =
3233fb4d8502Sjsg 			object_id_from_bios_object_id(
3234fb4d8502Sjsg 				record->conn_info[j].connectorobjid);
3235fb4d8502Sjsg 	}
3236fb4d8502Sjsg 	return result;
3237fb4d8502Sjsg }
3238fb4d8502Sjsg 
32391bb76ff1Sjsg static enum bp_result update_slot_layout_info_v2(
32401bb76ff1Sjsg 	struct dc_bios *dcb,
32411bb76ff1Sjsg 	unsigned int i,
32421bb76ff1Sjsg 	struct slot_layout_info *slot_layout_info)
32431bb76ff1Sjsg {
32441bb76ff1Sjsg 	unsigned int record_offset;
32451bb76ff1Sjsg 	struct atom_display_object_path_v3 *object;
32461bb76ff1Sjsg 	struct atom_bracket_layout_record_v2 *record;
32471bb76ff1Sjsg 	struct atom_common_record_header *record_header;
32481bb76ff1Sjsg 	static enum bp_result result;
32491bb76ff1Sjsg 	struct bios_parser *bp;
32501bb76ff1Sjsg 	struct object_info_table *tbl;
32511bb76ff1Sjsg 	struct display_object_info_table_v1_5 *v1_5;
32521bb76ff1Sjsg 	struct graphics_object_id connector_id;
32531bb76ff1Sjsg 
32541bb76ff1Sjsg 	record = NULL;
32551bb76ff1Sjsg 	record_header = NULL;
32561bb76ff1Sjsg 	result = BP_RESULT_NORECORD;
32571bb76ff1Sjsg 
32581bb76ff1Sjsg 	bp = BP_FROM_DCB(dcb);
32591bb76ff1Sjsg 	tbl = &bp->object_info_tbl;
32601bb76ff1Sjsg 	v1_5 = tbl->v1_5;
32611bb76ff1Sjsg 
32621bb76ff1Sjsg 	object = &v1_5->display_path[i];
32631bb76ff1Sjsg 	record_offset = (unsigned int)
32641bb76ff1Sjsg 		(object->disp_recordoffset) +
32651bb76ff1Sjsg 		(unsigned int)(bp->object_info_tbl_offset);
32661bb76ff1Sjsg 
32671bb76ff1Sjsg 	for (;;) {
32681bb76ff1Sjsg 
32691bb76ff1Sjsg 		record_header = (struct atom_common_record_header *)
32701bb76ff1Sjsg 			GET_IMAGE(struct atom_common_record_header,
32711bb76ff1Sjsg 			record_offset);
32721bb76ff1Sjsg 		if (record_header == NULL) {
32731bb76ff1Sjsg 			result = BP_RESULT_BADBIOSTABLE;
32741bb76ff1Sjsg 			break;
32751bb76ff1Sjsg 		}
32761bb76ff1Sjsg 
32771bb76ff1Sjsg 		/* the end of the list */
32781bb76ff1Sjsg 		if (record_header->record_type == ATOM_RECORD_END_TYPE ||
32791bb76ff1Sjsg 			record_header->record_size == 0)	{
32801bb76ff1Sjsg 			break;
32811bb76ff1Sjsg 		}
32821bb76ff1Sjsg 
32831bb76ff1Sjsg 		if (record_header->record_type ==
32841bb76ff1Sjsg 			ATOM_BRACKET_LAYOUT_V2_RECORD_TYPE &&
32851bb76ff1Sjsg 			sizeof(struct atom_bracket_layout_record_v2)
32861bb76ff1Sjsg 			<= record_header->record_size) {
32871bb76ff1Sjsg 			record = (struct atom_bracket_layout_record_v2 *)
32881bb76ff1Sjsg 				(record_header);
32891bb76ff1Sjsg 			result = BP_RESULT_OK;
32901bb76ff1Sjsg 			break;
32911bb76ff1Sjsg 		}
32921bb76ff1Sjsg 
32931bb76ff1Sjsg 		record_offset += record_header->record_size;
32941bb76ff1Sjsg 	}
32951bb76ff1Sjsg 
32961bb76ff1Sjsg 	/* return if the record not found */
32971bb76ff1Sjsg 	if (result != BP_RESULT_OK)
32981bb76ff1Sjsg 		return result;
32991bb76ff1Sjsg 
33001bb76ff1Sjsg 	/* get slot sizes */
33011bb76ff1Sjsg 	connector_id = object_id_from_bios_object_id(object->display_objid);
33021bb76ff1Sjsg 
33031bb76ff1Sjsg 	slot_layout_info->length = record->bracketlen;
33041bb76ff1Sjsg 	slot_layout_info->width = record->bracketwidth;
33051bb76ff1Sjsg 	slot_layout_info->num_of_connectors = v1_5->number_of_path;
33061bb76ff1Sjsg 	slot_layout_info->connectors[i].position = record->conn_num;
33071bb76ff1Sjsg 	slot_layout_info->connectors[i].connector_id = connector_id;
33081bb76ff1Sjsg 
33091bb76ff1Sjsg 	switch (connector_id.id) {
33101bb76ff1Sjsg 	case CONNECTOR_ID_SINGLE_LINK_DVID:
33111bb76ff1Sjsg 	case CONNECTOR_ID_DUAL_LINK_DVID:
33121bb76ff1Sjsg 		slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_DVI_D;
33131bb76ff1Sjsg 		slot_layout_info->connectors[i].length = CONNECTOR_SIZE_DVI;
33141bb76ff1Sjsg 		break;
33151bb76ff1Sjsg 
33161bb76ff1Sjsg 	case CONNECTOR_ID_HDMI_TYPE_A:
33171bb76ff1Sjsg 		slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_HDMI;
33181bb76ff1Sjsg 		slot_layout_info->connectors[i].length = CONNECTOR_SIZE_HDMI;
33191bb76ff1Sjsg 		break;
33201bb76ff1Sjsg 
33211bb76ff1Sjsg 	case CONNECTOR_ID_DISPLAY_PORT:
33221bb76ff1Sjsg 	case CONNECTOR_ID_USBC:
33231bb76ff1Sjsg 		if (record->mini_type == MINI_TYPE_NORMAL) {
33241bb76ff1Sjsg 			slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_DP;
33251bb76ff1Sjsg 			slot_layout_info->connectors[i].length = CONNECTOR_SIZE_DP;
33261bb76ff1Sjsg 		} else {
33271bb76ff1Sjsg 			slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_MINI_DP;
33281bb76ff1Sjsg 			slot_layout_info->connectors[i].length = CONNECTOR_SIZE_MINI_DP;
33291bb76ff1Sjsg 		}
33301bb76ff1Sjsg 		break;
33311bb76ff1Sjsg 
33321bb76ff1Sjsg 	default:
33331bb76ff1Sjsg 		slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_UNKNOWN;
33341bb76ff1Sjsg 		slot_layout_info->connectors[i].length = CONNECTOR_SIZE_UNKNOWN;
33351bb76ff1Sjsg 	}
33361bb76ff1Sjsg 	return result;
33371bb76ff1Sjsg }
3338fb4d8502Sjsg 
3339fb4d8502Sjsg static enum bp_result get_bracket_layout_record(
3340fb4d8502Sjsg 	struct dc_bios *dcb,
3341fb4d8502Sjsg 	unsigned int bracket_layout_id,
3342fb4d8502Sjsg 	struct slot_layout_info *slot_layout_info)
3343fb4d8502Sjsg {
3344fb4d8502Sjsg 	unsigned int i;
3345fb4d8502Sjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
33461bb76ff1Sjsg 	static enum bp_result result;
3347fb4d8502Sjsg 	struct object_info_table *tbl;
3348fb4d8502Sjsg 	struct display_object_info_table_v1_4 *v1_4;
33491bb76ff1Sjsg 	struct display_object_info_table_v1_5 *v1_5;
3350fb4d8502Sjsg 
3351fb4d8502Sjsg 	if (slot_layout_info == NULL) {
3352fb4d8502Sjsg 		DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");
3353fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
3354fb4d8502Sjsg 	}
3355fb4d8502Sjsg 	tbl = &bp->object_info_tbl;
3356fb4d8502Sjsg 	v1_4 = tbl->v1_4;
33571bb76ff1Sjsg 	v1_5 = tbl->v1_5;
3358fb4d8502Sjsg 
3359fb4d8502Sjsg 	result = BP_RESULT_NORECORD;
33601bb76ff1Sjsg 	switch (bp->object_info_tbl.revision.minor) {
33611bb76ff1Sjsg 		case 4:
33621bb76ff1Sjsg 		default:
3363fb4d8502Sjsg 			for (i = 0; i < v1_4->number_of_path; ++i)	{
3364fb4d8502Sjsg 				if (bracket_layout_id ==
3365fb4d8502Sjsg 					v1_4->display_path[i].display_objid) {
33661bb76ff1Sjsg 					result = update_slot_layout_info(dcb, i, slot_layout_info);
3367fb4d8502Sjsg 					break;
3368fb4d8502Sjsg 				}
3369fb4d8502Sjsg 			}
33701bb76ff1Sjsg 		    break;
33711bb76ff1Sjsg 		case 5:
33721bb76ff1Sjsg 			for (i = 0; i < v1_5->number_of_path; ++i)
33731bb76ff1Sjsg 				result = update_slot_layout_info_v2(dcb, i, slot_layout_info);
33741bb76ff1Sjsg 			break;
33751bb76ff1Sjsg 	}
3376fb4d8502Sjsg 	return result;
3377fb4d8502Sjsg }
3378fb4d8502Sjsg 
3379fb4d8502Sjsg static enum bp_result bios_get_board_layout_info(
3380fb4d8502Sjsg 	struct dc_bios *dcb,
3381fb4d8502Sjsg 	struct board_layout_info *board_layout_info)
3382fb4d8502Sjsg {
3383fb4d8502Sjsg 	unsigned int i;
33841bb76ff1Sjsg 
33851bb76ff1Sjsg 	struct bios_parser *bp;
33861bb76ff1Sjsg 
33871bb76ff1Sjsg 	static enum bp_result record_result;
33881bb76ff1Sjsg 	unsigned int max_slots;
3389fb4d8502Sjsg 
3390fb4d8502Sjsg 	const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {
3391fb4d8502Sjsg 		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1,
3392fb4d8502Sjsg 		GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2,
3393fb4d8502Sjsg 		0, 0
3394fb4d8502Sjsg 	};
3395fb4d8502Sjsg 
33961bb76ff1Sjsg 
33971bb76ff1Sjsg 	bp = BP_FROM_DCB(dcb);
33981bb76ff1Sjsg 
3399fb4d8502Sjsg 	if (board_layout_info == NULL) {
3400fb4d8502Sjsg 		DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");
3401fb4d8502Sjsg 		return BP_RESULT_BADINPUT;
3402fb4d8502Sjsg 	}
3403fb4d8502Sjsg 
3404fb4d8502Sjsg 	board_layout_info->num_of_slots = 0;
34051bb76ff1Sjsg 	max_slots = MAX_BOARD_SLOTS;
3406fb4d8502Sjsg 
34071bb76ff1Sjsg 	// Assume single slot on v1_5
34081bb76ff1Sjsg 	if (bp->object_info_tbl.revision.minor == 5) {
34091bb76ff1Sjsg 		max_slots = 1;
34101bb76ff1Sjsg 	}
34111bb76ff1Sjsg 
34121bb76ff1Sjsg 	for (i = 0; i < max_slots; ++i) {
3413fb4d8502Sjsg 		record_result = get_bracket_layout_record(dcb,
3414fb4d8502Sjsg 			slot_index_to_vbios_id[i],
3415fb4d8502Sjsg 			&board_layout_info->slots[i]);
3416fb4d8502Sjsg 
3417fb4d8502Sjsg 		if (record_result == BP_RESULT_NORECORD && i > 0)
3418fb4d8502Sjsg 			break; /* no more slots present in bios */
3419fb4d8502Sjsg 		else if (record_result != BP_RESULT_OK)
3420fb4d8502Sjsg 			return record_result;  /* fail */
3421fb4d8502Sjsg 
3422fb4d8502Sjsg 		++board_layout_info->num_of_slots;
3423fb4d8502Sjsg 	}
3424fb4d8502Sjsg 
3425fb4d8502Sjsg 	/* all data is valid */
3426fb4d8502Sjsg 	board_layout_info->is_number_of_slots_valid = 1;
3427fb4d8502Sjsg 	board_layout_info->is_slots_size_valid = 1;
3428fb4d8502Sjsg 	board_layout_info->is_connector_offsets_valid = 1;
3429fb4d8502Sjsg 	board_layout_info->is_connector_lengths_valid = 1;
3430fb4d8502Sjsg 
3431fb4d8502Sjsg 	return BP_RESULT_OK;
3432fb4d8502Sjsg }
3433fb4d8502Sjsg 
3434ad8b1aafSjsg 
3435ad8b1aafSjsg static uint16_t bios_parser_pack_data_tables(
3436ad8b1aafSjsg 	struct dc_bios *dcb,
3437ad8b1aafSjsg 	void *dst)
3438ad8b1aafSjsg {
3439ad8b1aafSjsg 	// TODO: There is data bytes alignment issue, disable it for now.
3440ad8b1aafSjsg 	return 0;
3441ad8b1aafSjsg }
3442ad8b1aafSjsg 
3443ad8b1aafSjsg static struct atom_dc_golden_table_v1 *bios_get_golden_table(
3444ad8b1aafSjsg 		struct bios_parser *bp,
3445ad8b1aafSjsg 		uint32_t rev_major,
3446ad8b1aafSjsg 		uint32_t rev_minor,
3447ad8b1aafSjsg 		uint16_t *dc_golden_table_ver)
3448ad8b1aafSjsg {
3449ad8b1aafSjsg 	struct atom_display_controller_info_v4_4 *disp_cntl_tbl_4_4 = NULL;
3450ad8b1aafSjsg 	uint32_t dc_golden_offset = 0;
3451ad8b1aafSjsg 	*dc_golden_table_ver = 0;
3452ad8b1aafSjsg 
3453ad8b1aafSjsg 	if (!DATA_TABLES(dce_info))
3454ad8b1aafSjsg 		return NULL;
3455ad8b1aafSjsg 
3456ad8b1aafSjsg 	/* ver.4.4 or higher */
3457ad8b1aafSjsg 	switch (rev_major) {
3458ad8b1aafSjsg 	case 4:
3459ad8b1aafSjsg 		switch (rev_minor) {
3460ad8b1aafSjsg 		case 4:
3461ad8b1aafSjsg 			disp_cntl_tbl_4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,
3462ad8b1aafSjsg 									DATA_TABLES(dce_info));
3463ad8b1aafSjsg 			if (!disp_cntl_tbl_4_4)
3464ad8b1aafSjsg 				return NULL;
3465ad8b1aafSjsg 			dc_golden_offset = DATA_TABLES(dce_info) + disp_cntl_tbl_4_4->dc_golden_table_offset;
3466ad8b1aafSjsg 			*dc_golden_table_ver = disp_cntl_tbl_4_4->dc_golden_table_ver;
3467ad8b1aafSjsg 			break;
34681bb76ff1Sjsg 		case 5:
34691bb76ff1Sjsg 		default:
34701bb76ff1Sjsg 			/* For atom_display_controller_info_v4_5 there is no need to get golden table from
34711bb76ff1Sjsg 			 * dc_golden_table_offset as all these fields previously in golden table used for AUX
34721bb76ff1Sjsg 			 * pre-charge settings are now available directly in atom_display_controller_info_v4_5.
34731bb76ff1Sjsg 			 */
34741bb76ff1Sjsg 			break;
3475ad8b1aafSjsg 		}
3476ad8b1aafSjsg 		break;
3477ad8b1aafSjsg 	}
3478ad8b1aafSjsg 
3479ad8b1aafSjsg 	if (!dc_golden_offset)
3480ad8b1aafSjsg 		return NULL;
3481ad8b1aafSjsg 
3482ad8b1aafSjsg 	if (*dc_golden_table_ver != 1)
3483ad8b1aafSjsg 		return NULL;
3484ad8b1aafSjsg 
3485ad8b1aafSjsg 	return GET_IMAGE(struct atom_dc_golden_table_v1,
3486ad8b1aafSjsg 			dc_golden_offset);
3487ad8b1aafSjsg }
3488ad8b1aafSjsg 
3489ad8b1aafSjsg static enum bp_result bios_get_atom_dc_golden_table(
3490ad8b1aafSjsg 	struct dc_bios *dcb)
3491ad8b1aafSjsg {
3492ad8b1aafSjsg 	struct bios_parser *bp = BP_FROM_DCB(dcb);
3493ad8b1aafSjsg 	enum bp_result result = BP_RESULT_OK;
3494ad8b1aafSjsg 	struct atom_dc_golden_table_v1 *atom_dc_golden_table = NULL;
3495ad8b1aafSjsg 	struct atom_common_table_header *header;
3496ad8b1aafSjsg 	struct atom_data_revision tbl_revision;
3497ad8b1aafSjsg 	uint16_t dc_golden_table_ver = 0;
3498ad8b1aafSjsg 
3499ad8b1aafSjsg 	header = GET_IMAGE(struct atom_common_table_header,
3500ad8b1aafSjsg 							DATA_TABLES(dce_info));
3501ad8b1aafSjsg 	if (!header)
3502ad8b1aafSjsg 		return BP_RESULT_UNSUPPORTED;
3503ad8b1aafSjsg 
3504ad8b1aafSjsg 	get_atom_data_table_revision(header, &tbl_revision);
3505ad8b1aafSjsg 
3506ad8b1aafSjsg 	atom_dc_golden_table = bios_get_golden_table(bp,
3507ad8b1aafSjsg 			tbl_revision.major,
3508ad8b1aafSjsg 			tbl_revision.minor,
3509ad8b1aafSjsg 			&dc_golden_table_ver);
3510ad8b1aafSjsg 
3511ad8b1aafSjsg 	if (!atom_dc_golden_table)
3512ad8b1aafSjsg 		return BP_RESULT_UNSUPPORTED;
3513ad8b1aafSjsg 
3514ad8b1aafSjsg 	dcb->golden_table.dc_golden_table_ver = dc_golden_table_ver;
3515ad8b1aafSjsg 	dcb->golden_table.aux_dphy_rx_control0_val = atom_dc_golden_table->aux_dphy_rx_control0_val;
3516ad8b1aafSjsg 	dcb->golden_table.aux_dphy_rx_control1_val = atom_dc_golden_table->aux_dphy_rx_control1_val;
3517ad8b1aafSjsg 	dcb->golden_table.aux_dphy_tx_control_val = atom_dc_golden_table->aux_dphy_tx_control_val;
3518ad8b1aafSjsg 	dcb->golden_table.dc_gpio_aux_ctrl_0_val = atom_dc_golden_table->dc_gpio_aux_ctrl_0_val;
3519ad8b1aafSjsg 	dcb->golden_table.dc_gpio_aux_ctrl_1_val = atom_dc_golden_table->dc_gpio_aux_ctrl_1_val;
3520ad8b1aafSjsg 	dcb->golden_table.dc_gpio_aux_ctrl_2_val = atom_dc_golden_table->dc_gpio_aux_ctrl_2_val;
3521ad8b1aafSjsg 	dcb->golden_table.dc_gpio_aux_ctrl_3_val = atom_dc_golden_table->dc_gpio_aux_ctrl_3_val;
3522ad8b1aafSjsg 	dcb->golden_table.dc_gpio_aux_ctrl_4_val = atom_dc_golden_table->dc_gpio_aux_ctrl_4_val;
3523ad8b1aafSjsg 	dcb->golden_table.dc_gpio_aux_ctrl_5_val = atom_dc_golden_table->dc_gpio_aux_ctrl_5_val;
3524ad8b1aafSjsg 
3525ad8b1aafSjsg 	return result;
3526ad8b1aafSjsg }
3527ad8b1aafSjsg 
3528ad8b1aafSjsg 
3529fb4d8502Sjsg static const struct dc_vbios_funcs vbios_funcs = {
3530fb4d8502Sjsg 	.get_connectors_number = bios_parser_get_connectors_number,
3531fb4d8502Sjsg 
3532fb4d8502Sjsg 	.get_connector_id = bios_parser_get_connector_id,
3533fb4d8502Sjsg 
3534fb4d8502Sjsg 	.get_src_obj = bios_parser_get_src_obj,
3535fb4d8502Sjsg 
3536fb4d8502Sjsg 	.get_i2c_info = bios_parser_get_i2c_info,
3537fb4d8502Sjsg 
3538fb4d8502Sjsg 	.get_hpd_info = bios_parser_get_hpd_info,
3539fb4d8502Sjsg 
3540fb4d8502Sjsg 	.get_device_tag = bios_parser_get_device_tag,
3541fb4d8502Sjsg 
3542fb4d8502Sjsg 	.get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
3543fb4d8502Sjsg 
3544fb4d8502Sjsg 	.get_ss_entry_number = bios_parser_get_ss_entry_number,
3545fb4d8502Sjsg 
3546fb4d8502Sjsg 	.get_embedded_panel_info = bios_parser_get_embedded_panel_info,
3547fb4d8502Sjsg 
3548fb4d8502Sjsg 	.get_gpio_pin_info = bios_parser_get_gpio_pin_info,
3549fb4d8502Sjsg 
3550fb4d8502Sjsg 	.get_encoder_cap_info = bios_parser_get_encoder_cap_info,
3551fb4d8502Sjsg 
3552fb4d8502Sjsg 	.is_device_id_supported = bios_parser_is_device_id_supported,
3553fb4d8502Sjsg 
3554fb4d8502Sjsg 	.is_accelerated_mode = bios_parser_is_accelerated_mode,
3555fb4d8502Sjsg 
3556fb4d8502Sjsg 	.set_scratch_critical_state = bios_parser_set_scratch_critical_state,
3557fb4d8502Sjsg 
3558fb4d8502Sjsg 
3559fb4d8502Sjsg /*	 COMMANDS */
3560fb4d8502Sjsg 	.encoder_control = bios_parser_encoder_control,
3561fb4d8502Sjsg 
3562fb4d8502Sjsg 	.transmitter_control = bios_parser_transmitter_control,
3563fb4d8502Sjsg 
3564fb4d8502Sjsg 	.enable_crtc = bios_parser_enable_crtc,
3565fb4d8502Sjsg 
3566fb4d8502Sjsg 	.set_pixel_clock = bios_parser_set_pixel_clock,
3567fb4d8502Sjsg 
3568fb4d8502Sjsg 	.set_dce_clock = bios_parser_set_dce_clock,
3569fb4d8502Sjsg 
3570fb4d8502Sjsg 	.program_crtc_timing = bios_parser_program_crtc_timing,
3571fb4d8502Sjsg 
3572fb4d8502Sjsg 	.enable_disp_power_gating = bios_parser_enable_disp_power_gating,
3573fb4d8502Sjsg 
3574fb4d8502Sjsg 	.bios_parser_destroy = firmware_parser_destroy,
3575fb4d8502Sjsg 
3576fb4d8502Sjsg 	.get_board_layout_info = bios_get_board_layout_info,
35771bb76ff1Sjsg 	/* TODO: use this fn in hw init?*/
3578ad8b1aafSjsg 	.pack_data_tables = bios_parser_pack_data_tables,
3579ad8b1aafSjsg 
3580ad8b1aafSjsg 	.get_atom_dc_golden_table = bios_get_atom_dc_golden_table,
3581ad8b1aafSjsg 
3582ad8b1aafSjsg 	.enable_lvtma_control = bios_parser_enable_lvtma_control,
3583ad8b1aafSjsg 
3584ad8b1aafSjsg 	.get_soc_bb_info = bios_parser_get_soc_bb_info,
35855ca02815Sjsg 
35865ca02815Sjsg 	.get_disp_connector_caps_info = bios_parser_get_disp_connector_caps_info,
35875ca02815Sjsg 
35885ca02815Sjsg 	.get_lttpr_caps = bios_parser_get_lttpr_caps,
35895ca02815Sjsg 
35905ca02815Sjsg 	.get_lttpr_interop = bios_parser_get_lttpr_interop,
35911bb76ff1Sjsg 
35921bb76ff1Sjsg 	.get_connector_speed_cap_info = bios_parser_get_connector_speed_cap_info,
3593fb4d8502Sjsg };
3594fb4d8502Sjsg 
3595c349dbc7Sjsg static bool bios_parser2_construct(
3596fb4d8502Sjsg 	struct bios_parser *bp,
3597fb4d8502Sjsg 	struct bp_init_data *init,
3598fb4d8502Sjsg 	enum dce_version dce_version)
3599fb4d8502Sjsg {
3600fb4d8502Sjsg 	uint16_t *rom_header_offset = NULL;
3601fb4d8502Sjsg 	struct atom_rom_header_v2_2 *rom_header = NULL;
3602fb4d8502Sjsg 	struct display_object_info_table_v1_4 *object_info_tbl;
3603fb4d8502Sjsg 	struct atom_data_revision tbl_rev = {0};
3604fb4d8502Sjsg 
3605fb4d8502Sjsg 	if (!init)
3606fb4d8502Sjsg 		return false;
3607fb4d8502Sjsg 
3608fb4d8502Sjsg 	if (!init->bios)
3609fb4d8502Sjsg 		return false;
3610fb4d8502Sjsg 
3611fb4d8502Sjsg 	bp->base.funcs = &vbios_funcs;
3612fb4d8502Sjsg 	bp->base.bios = init->bios;
3613fb4d8502Sjsg 	bp->base.bios_size = bp->base.bios[OFFSET_TO_ATOM_ROM_IMAGE_SIZE] * BIOS_IMAGE_SIZE_UNIT;
3614fb4d8502Sjsg 
3615fb4d8502Sjsg 	bp->base.ctx = init->ctx;
3616fb4d8502Sjsg 
3617fb4d8502Sjsg 	bp->base.bios_local_image = NULL;
3618fb4d8502Sjsg 
3619fb4d8502Sjsg 	rom_header_offset =
3620fb4d8502Sjsg 			GET_IMAGE(uint16_t, OFFSET_TO_ATOM_ROM_HEADER_POINTER);
3621fb4d8502Sjsg 
3622fb4d8502Sjsg 	if (!rom_header_offset)
3623fb4d8502Sjsg 		return false;
3624fb4d8502Sjsg 
3625fb4d8502Sjsg 	rom_header = GET_IMAGE(struct atom_rom_header_v2_2, *rom_header_offset);
3626fb4d8502Sjsg 
3627fb4d8502Sjsg 	if (!rom_header)
3628fb4d8502Sjsg 		return false;
3629fb4d8502Sjsg 
3630fb4d8502Sjsg 	get_atom_data_table_revision(&rom_header->table_header, &tbl_rev);
3631fb4d8502Sjsg 	if (!(tbl_rev.major >= 2 && tbl_rev.minor >= 2))
3632fb4d8502Sjsg 		return false;
3633fb4d8502Sjsg 
3634fb4d8502Sjsg 	bp->master_data_tbl =
3635fb4d8502Sjsg 		GET_IMAGE(struct atom_master_data_table_v2_1,
3636fb4d8502Sjsg 				rom_header->masterdatatable_offset);
3637fb4d8502Sjsg 
3638fb4d8502Sjsg 	if (!bp->master_data_tbl)
3639fb4d8502Sjsg 		return false;
3640fb4d8502Sjsg 
3641fb4d8502Sjsg 	bp->object_info_tbl_offset = DATA_TABLES(displayobjectinfo);
3642fb4d8502Sjsg 
3643fb4d8502Sjsg 	if (!bp->object_info_tbl_offset)
3644fb4d8502Sjsg 		return false;
3645fb4d8502Sjsg 
3646fb4d8502Sjsg 	object_info_tbl =
3647fb4d8502Sjsg 			GET_IMAGE(struct display_object_info_table_v1_4,
3648fb4d8502Sjsg 						bp->object_info_tbl_offset);
3649fb4d8502Sjsg 
3650fb4d8502Sjsg 	if (!object_info_tbl)
3651fb4d8502Sjsg 		return false;
3652fb4d8502Sjsg 
3653fb4d8502Sjsg 	get_atom_data_table_revision(&object_info_tbl->table_header,
3654fb4d8502Sjsg 		&bp->object_info_tbl.revision);
3655fb4d8502Sjsg 
3656fb4d8502Sjsg 	if (bp->object_info_tbl.revision.major == 1
36571bb76ff1Sjsg 		&& bp->object_info_tbl.revision.minor == 4) {
3658fb4d8502Sjsg 		struct display_object_info_table_v1_4 *tbl_v1_4;
3659fb4d8502Sjsg 
3660fb4d8502Sjsg 		tbl_v1_4 = GET_IMAGE(struct display_object_info_table_v1_4,
3661fb4d8502Sjsg 			bp->object_info_tbl_offset);
3662fb4d8502Sjsg 		if (!tbl_v1_4)
3663fb4d8502Sjsg 			return false;
3664fb4d8502Sjsg 
3665fb4d8502Sjsg 		bp->object_info_tbl.v1_4 = tbl_v1_4;
36661bb76ff1Sjsg 	} else if (bp->object_info_tbl.revision.major == 1
36671bb76ff1Sjsg 		&& bp->object_info_tbl.revision.minor == 5) {
36681bb76ff1Sjsg 		struct display_object_info_table_v1_5 *tbl_v1_5;
36691bb76ff1Sjsg 
36701bb76ff1Sjsg 		tbl_v1_5 = GET_IMAGE(struct display_object_info_table_v1_5,
36711bb76ff1Sjsg 			bp->object_info_tbl_offset);
36721bb76ff1Sjsg 		if (!tbl_v1_5)
3673fb4d8502Sjsg 			return false;
3674fb4d8502Sjsg 
36751bb76ff1Sjsg 		bp->object_info_tbl.v1_5 = tbl_v1_5;
36761bb76ff1Sjsg 	} else {
36771bb76ff1Sjsg 		ASSERT(0);
36781bb76ff1Sjsg 		return false;
36791bb76ff1Sjsg 	}
36801bb76ff1Sjsg 
3681fb4d8502Sjsg 	dal_firmware_parser_init_cmd_tbl(bp);
3682fb4d8502Sjsg 	dal_bios_parser_init_cmd_tbl_helper2(&bp->cmd_helper, dce_version);
3683fb4d8502Sjsg 
3684fb4d8502Sjsg 	bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);
3685c349dbc7Sjsg 	bp->base.fw_info_valid = bios_parser_get_firmware_info(&bp->base, &bp->base.fw_info) == BP_RESULT_OK;
3686ad8b1aafSjsg 	bios_parser_get_vram_info(&bp->base, &bp->base.vram_info);
3687fb4d8502Sjsg 
3688fb4d8502Sjsg 	return true;
3689fb4d8502Sjsg }
3690fb4d8502Sjsg 
3691fb4d8502Sjsg struct dc_bios *firmware_parser_create(
3692fb4d8502Sjsg 	struct bp_init_data *init,
3693fb4d8502Sjsg 	enum dce_version dce_version)
3694fb4d8502Sjsg {
3695f005ef32Sjsg 	struct bios_parser *bp;
3696fb4d8502Sjsg 
3697fb4d8502Sjsg 	bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL);
3698fb4d8502Sjsg 	if (!bp)
3699fb4d8502Sjsg 		return NULL;
3700fb4d8502Sjsg 
3701c349dbc7Sjsg 	if (bios_parser2_construct(bp, init, dce_version))
3702fb4d8502Sjsg 		return &bp->base;
3703fb4d8502Sjsg 
3704fb4d8502Sjsg 	kfree(bp);
3705fb4d8502Sjsg 	return NULL;
3706fb4d8502Sjsg }
3707fb4d8502Sjsg 
3708fb4d8502Sjsg 
3709