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