]> Git Repo - linux.git/blob - drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
Merge tag 'drm-misc-fixes-2021-01-08' of git://anongit.freedesktop.org/drm/drm-misc...
[linux.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 bios_parser_destruct(struct bios_parser *bp)
115 {
116         kfree(bp->base.bios_local_image);
117         kfree(bp->base.integrated_info);
118 }
119
120 static void bios_parser_destroy(struct dc_bios **dcb)
121 {
122         struct bios_parser *bp = BP_FROM_DCB(*dcb);
123
124         if (!bp) {
125                 BREAK_TO_DEBUGGER();
126                 return;
127         }
128
129         bios_parser_destruct(bp);
130
131         kfree(bp);
132         *dcb = NULL;
133 }
134
135 static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset)
136 {
137         ATOM_OBJECT_TABLE *table;
138
139         uint32_t object_table_offset = bp->object_info_tbl_offset + offset;
140
141         table = 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                 break;
1202         default:
1203                 break;
1204         }
1205
1206         return BP_RESULT_FAILURE;
1207 }
1208
1209 static enum bp_result get_embedded_panel_info_v1_2(
1210         struct bios_parser *bp,
1211         struct embedded_panel_info *info)
1212 {
1213         ATOM_LVDS_INFO_V12 *lvds;
1214
1215         if (!info)
1216                 return BP_RESULT_BADINPUT;
1217
1218         if (!DATA_TABLES(LVDS_Info))
1219                 return BP_RESULT_UNSUPPORTED;
1220
1221         lvds =
1222                 GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info));
1223
1224         if (!lvds)
1225                 return BP_RESULT_BADBIOSTABLE;
1226
1227         if (1 != lvds->sHeader.ucTableFormatRevision
1228                 || 2 > lvds->sHeader.ucTableContentRevision)
1229                 return BP_RESULT_UNSUPPORTED;
1230
1231         memset(info, 0, sizeof(struct embedded_panel_info));
1232
1233         /* We need to convert from 10KHz units into KHz units*/
1234         info->lcd_timing.pixel_clk =
1235                 le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
1236         /* usHActive does not include borders, according to VBIOS team*/
1237         info->lcd_timing.horizontal_addressable =
1238                 le16_to_cpu(lvds->sLCDTiming.usHActive);
1239         /* usHBlanking_Time includes borders, so we should really be subtracting
1240          * borders duing this translation, but LVDS generally*/
1241         /* doesn't have borders, so we should be okay leaving this as is for
1242          * now.  May need to revisit if we ever have LVDS with borders*/
1243         info->lcd_timing.horizontal_blanking_time =
1244                         le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
1245         /* usVActive does not include borders, according to VBIOS team*/
1246         info->lcd_timing.vertical_addressable =
1247                         le16_to_cpu(lvds->sLCDTiming.usVActive);
1248         /* usVBlanking_Time includes borders, so we should really be subtracting
1249          * borders duing this translation, but LVDS generally*/
1250         /* doesn't have borders, so we should be okay leaving this as is for
1251          * now. May need to revisit if we ever have LVDS with borders*/
1252         info->lcd_timing.vertical_blanking_time =
1253                 le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
1254         info->lcd_timing.horizontal_sync_offset =
1255                 le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
1256         info->lcd_timing.horizontal_sync_width =
1257                 le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
1258         info->lcd_timing.vertical_sync_offset =
1259                 le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
1260         info->lcd_timing.vertical_sync_width =
1261                 le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
1262         info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
1263         info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
1264         info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
1265                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
1266         info->lcd_timing.misc_info.H_SYNC_POLARITY =
1267                 ~(uint32_t)
1268                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
1269         info->lcd_timing.misc_info.V_SYNC_POLARITY =
1270                 ~(uint32_t)
1271                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
1272         info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
1273                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
1274         info->lcd_timing.misc_info.H_REPLICATION_BY2 =
1275                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
1276         info->lcd_timing.misc_info.V_REPLICATION_BY2 =
1277                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
1278         info->lcd_timing.misc_info.COMPOSITE_SYNC =
1279                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
1280         info->lcd_timing.misc_info.INTERLACE =
1281                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
1282         info->lcd_timing.misc_info.DOUBLE_CLOCK =
1283                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
1284         info->ss_id = lvds->ucSS_Id;
1285
1286         {
1287                 uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate);
1288                 /* Get minimum supported refresh rate*/
1289                 if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
1290                         info->supported_rr.REFRESH_RATE_30HZ = 1;
1291                 else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
1292                         info->supported_rr.REFRESH_RATE_40HZ = 1;
1293                 else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
1294                         info->supported_rr.REFRESH_RATE_48HZ = 1;
1295                 else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
1296                         info->supported_rr.REFRESH_RATE_50HZ = 1;
1297                 else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
1298                         info->supported_rr.REFRESH_RATE_60HZ = 1;
1299         }
1300
1301         /*Drr panel support can be reported by VBIOS*/
1302         if (LCDPANEL_CAP_DRR_SUPPORTED
1303                         & lvds->ucLCDPanel_SpecialHandlingCap)
1304                 info->drr_enabled = 1;
1305
1306         if (ATOM_PANEL_MISC_DUAL & lvds->ucLVDS_Misc)
1307                 info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
1308
1309         if (ATOM_PANEL_MISC_888RGB & lvds->ucLVDS_Misc)
1310                 info->lcd_timing.misc_info.RGB888 = true;
1311
1312         info->lcd_timing.misc_info.GREY_LEVEL =
1313                 (uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL &
1314                         lvds->ucLVDS_Misc) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT;
1315
1316         if (ATOM_PANEL_MISC_SPATIAL & lvds->ucLVDS_Misc)
1317                 info->lcd_timing.misc_info.SPATIAL = true;
1318
1319         if (ATOM_PANEL_MISC_TEMPORAL & lvds->ucLVDS_Misc)
1320                 info->lcd_timing.misc_info.TEMPORAL = true;
1321
1322         if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc)
1323                 info->lcd_timing.misc_info.API_ENABLED = true;
1324
1325         return BP_RESULT_OK;
1326 }
1327
1328 static enum bp_result get_embedded_panel_info_v1_3(
1329         struct bios_parser *bp,
1330         struct embedded_panel_info *info)
1331 {
1332         ATOM_LCD_INFO_V13 *lvds;
1333
1334         if (!info)
1335                 return BP_RESULT_BADINPUT;
1336
1337         if (!DATA_TABLES(LCD_Info))
1338                 return BP_RESULT_UNSUPPORTED;
1339
1340         lvds = GET_IMAGE(ATOM_LCD_INFO_V13, DATA_TABLES(LCD_Info));
1341
1342         if (!lvds)
1343                 return BP_RESULT_BADBIOSTABLE;
1344
1345         if (!((1 == lvds->sHeader.ucTableFormatRevision)
1346                         && (3 <= lvds->sHeader.ucTableContentRevision)))
1347                 return BP_RESULT_UNSUPPORTED;
1348
1349         memset(info, 0, sizeof(struct embedded_panel_info));
1350
1351         /* We need to convert from 10KHz units into KHz units */
1352         info->lcd_timing.pixel_clk =
1353                         le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
1354         /* usHActive does not include borders, according to VBIOS team */
1355         info->lcd_timing.horizontal_addressable =
1356                         le16_to_cpu(lvds->sLCDTiming.usHActive);
1357         /* usHBlanking_Time includes borders, so we should really be subtracting
1358          * borders duing this translation, but LVDS generally*/
1359         /* doesn't have borders, so we should be okay leaving this as is for
1360          * now.  May need to revisit if we ever have LVDS with borders*/
1361         info->lcd_timing.horizontal_blanking_time =
1362                 le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
1363         /* usVActive does not include borders, according to VBIOS team*/
1364         info->lcd_timing.vertical_addressable =
1365                 le16_to_cpu(lvds->sLCDTiming.usVActive);
1366         /* usVBlanking_Time includes borders, so we should really be subtracting
1367          * borders duing this translation, but LVDS generally*/
1368         /* doesn't have borders, so we should be okay leaving this as is for
1369          * now. May need to revisit if we ever have LVDS with borders*/
1370         info->lcd_timing.vertical_blanking_time =
1371                 le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
1372         info->lcd_timing.horizontal_sync_offset =
1373                 le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
1374         info->lcd_timing.horizontal_sync_width =
1375                 le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
1376         info->lcd_timing.vertical_sync_offset =
1377                 le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
1378         info->lcd_timing.vertical_sync_width =
1379                 le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
1380         info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
1381         info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
1382         info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
1383                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
1384         info->lcd_timing.misc_info.H_SYNC_POLARITY =
1385                 ~(uint32_t)
1386                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
1387         info->lcd_timing.misc_info.V_SYNC_POLARITY =
1388                 ~(uint32_t)
1389                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
1390         info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
1391                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
1392         info->lcd_timing.misc_info.H_REPLICATION_BY2 =
1393                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
1394         info->lcd_timing.misc_info.V_REPLICATION_BY2 =
1395                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
1396         info->lcd_timing.misc_info.COMPOSITE_SYNC =
1397                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
1398         info->lcd_timing.misc_info.INTERLACE =
1399                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
1400         info->lcd_timing.misc_info.DOUBLE_CLOCK =
1401                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
1402         info->ss_id = lvds->ucSS_Id;
1403
1404         /* Drr panel support can be reported by VBIOS*/
1405         if (LCDPANEL_CAP_V13_DRR_SUPPORTED
1406                         & lvds->ucLCDPanel_SpecialHandlingCap)
1407                 info->drr_enabled = 1;
1408
1409         /* Get supported refresh rate*/
1410         if (info->drr_enabled == 1) {
1411                 uint8_t min_rr =
1412                                 lvds->sRefreshRateSupport.ucMinRefreshRateForDRR;
1413                 uint8_t rr = lvds->sRefreshRateSupport.ucSupportedRefreshRate;
1414
1415                 if (min_rr != 0) {
1416                         if (SUPPORTED_LCD_REFRESHRATE_30Hz & min_rr)
1417                                 info->supported_rr.REFRESH_RATE_30HZ = 1;
1418                         else if (SUPPORTED_LCD_REFRESHRATE_40Hz & min_rr)
1419                                 info->supported_rr.REFRESH_RATE_40HZ = 1;
1420                         else if (SUPPORTED_LCD_REFRESHRATE_48Hz & min_rr)
1421                                 info->supported_rr.REFRESH_RATE_48HZ = 1;
1422                         else if (SUPPORTED_LCD_REFRESHRATE_50Hz & min_rr)
1423                                 info->supported_rr.REFRESH_RATE_50HZ = 1;
1424                         else if (SUPPORTED_LCD_REFRESHRATE_60Hz & min_rr)
1425                                 info->supported_rr.REFRESH_RATE_60HZ = 1;
1426                 } else {
1427                         if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
1428                                 info->supported_rr.REFRESH_RATE_30HZ = 1;
1429                         else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
1430                                 info->supported_rr.REFRESH_RATE_40HZ = 1;
1431                         else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
1432                                 info->supported_rr.REFRESH_RATE_48HZ = 1;
1433                         else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
1434                                 info->supported_rr.REFRESH_RATE_50HZ = 1;
1435                         else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
1436                                 info->supported_rr.REFRESH_RATE_60HZ = 1;
1437                 }
1438         }
1439
1440         if (ATOM_PANEL_MISC_V13_DUAL & lvds->ucLCD_Misc)
1441                 info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
1442
1443         if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR & lvds->ucLCD_Misc)
1444                 info->lcd_timing.misc_info.RGB888 = true;
1445
1446         info->lcd_timing.misc_info.GREY_LEVEL =
1447                         (uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL &
1448                                 lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT;
1449
1450         return BP_RESULT_OK;
1451 }
1452
1453 /**
1454  * bios_parser_get_encoder_cap_info
1455  *
1456  * @brief
1457  *  Get encoder capability information of input object id
1458  *
1459  * @param object_id, Object id
1460  * @param object_id, encoder cap information structure
1461  *
1462  * @return Bios parser result code
1463  *
1464  */
1465 static enum bp_result bios_parser_get_encoder_cap_info(
1466         struct dc_bios *dcb,
1467         struct graphics_object_id object_id,
1468         struct bp_encoder_cap_info *info)
1469 {
1470         struct bios_parser *bp = BP_FROM_DCB(dcb);
1471         ATOM_OBJECT *object;
1472         ATOM_ENCODER_CAP_RECORD_V2 *record = NULL;
1473
1474         if (!info)
1475                 return BP_RESULT_BADINPUT;
1476
1477         object = get_bios_object(bp, object_id);
1478
1479         if (!object)
1480                 return BP_RESULT_BADINPUT;
1481
1482         record = get_encoder_cap_record(bp, object);
1483         if (!record)
1484                 return BP_RESULT_NORECORD;
1485
1486         info->DP_HBR2_EN = record->usHBR2En;
1487         info->DP_HBR3_EN = record->usHBR3En;
1488         info->HDMI_6GB_EN = record->usHDMI6GEn;
1489         return BP_RESULT_OK;
1490 }
1491
1492 /**
1493  * get_encoder_cap_record
1494  *
1495  * @brief
1496  *  Get encoder cap record for the object
1497  *
1498  * @param object, ATOM object
1499  *
1500  * @return atom encoder cap record
1501  *
1502  * @note
1503  *  search all records to find the ATOM_ENCODER_CAP_RECORD_V2 record
1504  */
1505 static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
1506         struct bios_parser *bp,
1507         ATOM_OBJECT *object)
1508 {
1509         ATOM_COMMON_RECORD_HEADER *header;
1510         uint32_t offset;
1511
1512         if (!object) {
1513                 BREAK_TO_DEBUGGER(); /* Invalid object */
1514                 return NULL;
1515         }
1516
1517         offset = le16_to_cpu(object->usRecordOffset)
1518                                         + bp->object_info_tbl_offset;
1519
1520         for (;;) {
1521                 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
1522
1523                 if (!header)
1524                         return NULL;
1525
1526                 offset += header->ucRecordSize;
1527
1528                 if (LAST_RECORD_TYPE == header->ucRecordType ||
1529                                 !header->ucRecordSize)
1530                         break;
1531
1532                 if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType)
1533                         continue;
1534
1535                 if (sizeof(ATOM_ENCODER_CAP_RECORD_V2) <= header->ucRecordSize)
1536                         return (ATOM_ENCODER_CAP_RECORD_V2 *)header;
1537         }
1538
1539         return NULL;
1540 }
1541
1542 static uint32_t get_ss_entry_number(
1543         struct bios_parser *bp,
1544         uint32_t id);
1545 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
1546         struct bios_parser *bp,
1547         uint32_t id);
1548 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1549         struct bios_parser *bp,
1550         uint32_t id);
1551 static uint32_t get_ss_entry_number_from_ss_info_tbl(
1552         struct bios_parser *bp,
1553         uint32_t id);
1554
1555 /**
1556  * BiosParserObject::GetNumberofSpreadSpectrumEntry
1557  * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from
1558  * the VBIOS that match the SSid (to be converted from signal)
1559  *
1560  * @param[in] signal, ASSignalType to be converted to SSid
1561  * @return number of SS Entry that match the signal
1562  */
1563 static uint32_t bios_parser_get_ss_entry_number(
1564         struct dc_bios *dcb,
1565         enum as_signal_type signal)
1566 {
1567         struct bios_parser *bp = BP_FROM_DCB(dcb);
1568         uint32_t ss_id = 0;
1569         ATOM_COMMON_TABLE_HEADER *header;
1570         struct atom_data_revision revision;
1571
1572         ss_id = signal_to_ss_id(signal);
1573
1574         if (!DATA_TABLES(ASIC_InternalSS_Info))
1575                 return get_ss_entry_number_from_ss_info_tbl(bp, ss_id);
1576
1577         header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
1578                         DATA_TABLES(ASIC_InternalSS_Info));
1579         get_atom_data_table_revision(header, &revision);
1580
1581         switch (revision.major) {
1582         case 2:
1583                 switch (revision.minor) {
1584                 case 1:
1585                         return get_ss_entry_number(bp, ss_id);
1586                 default:
1587                         break;
1588                 }
1589                 break;
1590         case 3:
1591                 switch (revision.minor) {
1592                 case 1:
1593                         return
1594                                 get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1595                                                 bp, ss_id);
1596                 default:
1597                         break;
1598                 }
1599                 break;
1600         default:
1601                 break;
1602         }
1603
1604         return 0;
1605 }
1606
1607 /**
1608  * get_ss_entry_number_from_ss_info_tbl
1609  * Get Number of spread spectrum entry from the SS_Info table from the VBIOS.
1610  *
1611  * @note There can only be one entry for each id for SS_Info Table
1612  *
1613  * @param [in] id, spread spectrum id
1614  * @return number of SS Entry that match the id
1615  */
1616 static uint32_t get_ss_entry_number_from_ss_info_tbl(
1617         struct bios_parser *bp,
1618         uint32_t id)
1619 {
1620         ATOM_SPREAD_SPECTRUM_INFO *tbl;
1621         ATOM_COMMON_TABLE_HEADER *header;
1622         uint32_t table_size;
1623         uint32_t i;
1624         uint32_t number = 0;
1625         uint32_t id_local = SS_ID_UNKNOWN;
1626         struct atom_data_revision revision;
1627
1628         /* SS_Info table exist */
1629         if (!DATA_TABLES(SS_Info))
1630                 return number;
1631
1632         header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
1633                         DATA_TABLES(SS_Info));
1634         get_atom_data_table_revision(header, &revision);
1635
1636         tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO,
1637                         DATA_TABLES(SS_Info));
1638
1639         if (1 != revision.major || 2 > revision.minor)
1640                 return number;
1641
1642         /* have to convert from Internal_SS format to SS_Info format */
1643         switch (id) {
1644         case ASIC_INTERNAL_SS_ON_DP:
1645                 id_local = SS_ID_DP1;
1646                 break;
1647         case ASIC_INTERNAL_SS_ON_LVDS: {
1648                 struct embedded_panel_info panel_info;
1649
1650                 if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
1651                                 == BP_RESULT_OK)
1652                         id_local = panel_info.ss_id;
1653                 break;
1654         }
1655         default:
1656                 break;
1657         }
1658
1659         if (id_local == SS_ID_UNKNOWN)
1660                 return number;
1661
1662         table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
1663                         sizeof(ATOM_COMMON_TABLE_HEADER)) /
1664                                         sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
1665
1666         for (i = 0; i < table_size; i++)
1667                 if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) {
1668                         number = 1;
1669                         break;
1670                 }
1671
1672         return number;
1673 }
1674
1675 /**
1676  * get_ss_entry_number
1677  * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
1678  * SS_Info table from the VBIOS
1679  * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or
1680  * SS_Info.
1681  *
1682  * @param id, spread sprectrum info index
1683  * @return Bios parser result code
1684  */
1685 static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id)
1686 {
1687         if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
1688                 return get_ss_entry_number_from_ss_info_tbl(bp, id);
1689
1690         return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id);
1691 }
1692
1693 /**
1694  * get_ss_entry_number_from_internal_ss_info_tbl_v2_1
1695  * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table
1696  * Ver 2.1 from the VBIOS
1697  * There will not be multiple entry for Ver 2.1
1698  *
1699  * @param id, spread sprectrum info index
1700  * @return number of SS Entry that match the id
1701  */
1702 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
1703         struct bios_parser *bp,
1704         uint32_t id)
1705 {
1706         ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include;
1707         ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
1708         uint32_t size;
1709         uint32_t i;
1710
1711         if (!DATA_TABLES(ASIC_InternalSS_Info))
1712                 return 0;
1713
1714         header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
1715                         DATA_TABLES(ASIC_InternalSS_Info));
1716
1717         size = (le16_to_cpu(header_include->sHeader.usStructureSize)
1718                         - sizeof(ATOM_COMMON_TABLE_HEADER))
1719                                                 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
1720
1721         tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
1722                                 &header_include->asSpreadSpectrum[0];
1723         for (i = 0; i < size; i++)
1724                 if (tbl[i].ucClockIndication == (uint8_t)id)
1725                         return 1;
1726
1727         return 0;
1728 }
1729 /**
1730  * get_ss_entry_number_from_internal_ss_info_table_V3_1
1731  * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of
1732  * the VBIOS that matches id
1733  *
1734  * @param[in]  id, spread sprectrum id
1735  * @return number of SS Entry that match the id
1736  */
1737 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1738         struct bios_parser *bp,
1739         uint32_t id)
1740 {
1741         uint32_t number = 0;
1742         ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include;
1743         ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
1744         uint32_t size;
1745         uint32_t i;
1746
1747         if (!DATA_TABLES(ASIC_InternalSS_Info))
1748                 return number;
1749
1750         header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
1751                         DATA_TABLES(ASIC_InternalSS_Info));
1752         size = (le16_to_cpu(header_include->sHeader.usStructureSize) -
1753                         sizeof(ATOM_COMMON_TABLE_HEADER)) /
1754                                         sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
1755
1756         tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
1757                                 &header_include->asSpreadSpectrum[0];
1758
1759         for (i = 0; i < size; i++)
1760                 if (tbl[i].ucClockIndication == (uint8_t)id)
1761                         number++;
1762
1763         return number;
1764 }
1765
1766 /**
1767  * bios_parser_get_gpio_pin_info
1768  * Get GpioPin information of input gpio id
1769  *
1770  * @param gpio_id, GPIO ID
1771  * @param info, GpioPin information structure
1772  * @return Bios parser result code
1773  * @note
1774  *  to get the GPIO PIN INFO, we need:
1775  *  1. get the GPIO_ID from other object table, see GetHPDInfo()
1776  *  2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA
1777  *  offset/mask
1778  */
1779 static enum bp_result bios_parser_get_gpio_pin_info(
1780         struct dc_bios *dcb,
1781         uint32_t gpio_id,
1782         struct gpio_pin_info *info)
1783 {
1784         struct bios_parser *bp = BP_FROM_DCB(dcb);
1785         ATOM_GPIO_PIN_LUT *header;
1786         uint32_t count = 0;
1787         uint32_t i = 0;
1788
1789         if (!DATA_TABLES(GPIO_Pin_LUT))
1790                 return BP_RESULT_BADBIOSTABLE;
1791
1792         header = GET_IMAGE(ATOM_GPIO_PIN_LUT, DATA_TABLES(GPIO_Pin_LUT));
1793         if (!header)
1794                 return BP_RESULT_BADBIOSTABLE;
1795
1796         if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_PIN_LUT)
1797                         > le16_to_cpu(header->sHeader.usStructureSize))
1798                 return BP_RESULT_BADBIOSTABLE;
1799
1800         if (1 != header->sHeader.ucTableContentRevision)
1801                 return BP_RESULT_UNSUPPORTED;
1802
1803         count = (le16_to_cpu(header->sHeader.usStructureSize)
1804                         - sizeof(ATOM_COMMON_TABLE_HEADER))
1805                                 / sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
1806         for (i = 0; i < count; ++i) {
1807                 if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id)
1808                         continue;
1809
1810                 info->offset =
1811                         (uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex);
1812                 info->offset_y = info->offset + 2;
1813                 info->offset_en = info->offset + 1;
1814                 info->offset_mask = info->offset - 1;
1815
1816                 info->mask = (uint32_t) (1 <<
1817                         header->asGPIO_Pin[i].ucGpioPinBitShift);
1818                 info->mask_y = info->mask + 2;
1819                 info->mask_en = info->mask + 1;
1820                 info->mask_mask = info->mask - 1;
1821
1822                 return BP_RESULT_OK;
1823         }
1824
1825         return BP_RESULT_NORECORD;
1826 }
1827
1828 static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
1829         ATOM_I2C_RECORD *record,
1830         struct graphics_object_i2c_info *info)
1831 {
1832         ATOM_GPIO_I2C_INFO *header;
1833         uint32_t count = 0;
1834
1835         if (!info)
1836                 return BP_RESULT_BADINPUT;
1837
1838         /* get the GPIO_I2C info */
1839         if (!DATA_TABLES(GPIO_I2C_Info))
1840                 return BP_RESULT_BADBIOSTABLE;
1841
1842         header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info));
1843         if (!header)
1844                 return BP_RESULT_BADBIOSTABLE;
1845
1846         if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT)
1847                         > le16_to_cpu(header->sHeader.usStructureSize))
1848                 return BP_RESULT_BADBIOSTABLE;
1849
1850         if (1 != header->sHeader.ucTableContentRevision)
1851                 return BP_RESULT_UNSUPPORTED;
1852
1853         /* get data count */
1854         count = (le16_to_cpu(header->sHeader.usStructureSize)
1855                         - sizeof(ATOM_COMMON_TABLE_HEADER))
1856                                 / sizeof(ATOM_GPIO_I2C_ASSIGMENT);
1857         if (count < record->sucI2cId.bfI2C_LineMux)
1858                 return BP_RESULT_BADBIOSTABLE;
1859
1860         /* get the GPIO_I2C_INFO */
1861         info->i2c_hw_assist = record->sucI2cId.bfHW_Capable;
1862         info->i2c_line = record->sucI2cId.bfI2C_LineMux;
1863         info->i2c_engine_id = record->sucI2cId.bfHW_EngineID;
1864         info->i2c_slave_address = record->ucI2CAddr;
1865
1866         info->gpio_info.clk_mask_register_index =
1867                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex);
1868         info->gpio_info.clk_en_register_index =
1869                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex);
1870         info->gpio_info.clk_y_register_index =
1871                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex);
1872         info->gpio_info.clk_a_register_index =
1873                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex);
1874         info->gpio_info.data_mask_register_index =
1875                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex);
1876         info->gpio_info.data_en_register_index =
1877                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex);
1878         info->gpio_info.data_y_register_index =
1879                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex);
1880         info->gpio_info.data_a_register_index =
1881                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex);
1882
1883         info->gpio_info.clk_mask_shift =
1884                         header->asGPIO_Info[info->i2c_line].ucClkMaskShift;
1885         info->gpio_info.clk_en_shift =
1886                         header->asGPIO_Info[info->i2c_line].ucClkEnShift;
1887         info->gpio_info.clk_y_shift =
1888                         header->asGPIO_Info[info->i2c_line].ucClkY_Shift;
1889         info->gpio_info.clk_a_shift =
1890                         header->asGPIO_Info[info->i2c_line].ucClkA_Shift;
1891         info->gpio_info.data_mask_shift =
1892                         header->asGPIO_Info[info->i2c_line].ucDataMaskShift;
1893         info->gpio_info.data_en_shift =
1894                         header->asGPIO_Info[info->i2c_line].ucDataEnShift;
1895         info->gpio_info.data_y_shift =
1896                         header->asGPIO_Info[info->i2c_line].ucDataY_Shift;
1897         info->gpio_info.data_a_shift =
1898                         header->asGPIO_Info[info->i2c_line].ucDataA_Shift;
1899
1900         return BP_RESULT_OK;
1901 }
1902
1903 static bool dal_graphics_object_id_is_valid(struct graphics_object_id id)
1904 {
1905         bool rc = true;
1906
1907         switch (id.type) {
1908         case OBJECT_TYPE_UNKNOWN:
1909                 rc = false;
1910                 break;
1911         case OBJECT_TYPE_GPU:
1912         case OBJECT_TYPE_ENGINE:
1913                 /* do NOT check for id.id == 0 */
1914                 if (id.enum_id == ENUM_ID_UNKNOWN)
1915                         rc = false;
1916                 break;
1917         default:
1918                 if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN)
1919                         rc = false;
1920                 break;
1921         }
1922
1923         return rc;
1924 }
1925
1926 static bool dal_graphics_object_id_is_equal(
1927         struct graphics_object_id id1,
1928         struct graphics_object_id id2)
1929 {
1930         if (false == dal_graphics_object_id_is_valid(id1)) {
1931                 dm_output_to_console(
1932                 "%s: Warning: comparing invalid object 'id1'!\n", __func__);
1933                 return false;
1934         }
1935
1936         if (false == dal_graphics_object_id_is_valid(id2)) {
1937                 dm_output_to_console(
1938                 "%s: Warning: comparing invalid object 'id2'!\n", __func__);
1939                 return false;
1940         }
1941
1942         if (id1.id == id2.id && id1.enum_id == id2.enum_id
1943                 && id1.type == id2.type)
1944                 return true;
1945
1946         return false;
1947 }
1948
1949 static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
1950         struct graphics_object_id id)
1951 {
1952         uint32_t offset;
1953         ATOM_OBJECT_TABLE *tbl;
1954         uint32_t i;
1955
1956         switch (id.type) {
1957         case OBJECT_TYPE_ENCODER:
1958                 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
1959                 break;
1960
1961         case OBJECT_TYPE_CONNECTOR:
1962                 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
1963                 break;
1964
1965         case OBJECT_TYPE_ROUTER:
1966                 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset);
1967                 break;
1968
1969         case OBJECT_TYPE_GENERIC:
1970                 if (bp->object_info_tbl.revision.minor < 3)
1971                         return NULL;
1972                 offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset);
1973                 break;
1974
1975         default:
1976                 return NULL;
1977         }
1978
1979         offset += bp->object_info_tbl_offset;
1980
1981         tbl = GET_IMAGE(ATOM_OBJECT_TABLE, offset);
1982         if (!tbl)
1983                 return NULL;
1984
1985         for (i = 0; i < tbl->ucNumberOfObjects; i++)
1986                 if (dal_graphics_object_id_is_equal(id,
1987                                 object_id_from_bios_object_id(
1988                                                 le16_to_cpu(tbl->asObjects[i].usObjectID))))
1989                         return &tbl->asObjects[i];
1990
1991         return NULL;
1992 }
1993
1994 static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
1995         uint16_t **id_list)
1996 {
1997         uint32_t offset;
1998         uint8_t *number;
1999
2000         if (!object) {
2001                 BREAK_TO_DEBUGGER(); /* Invalid object id */
2002                 return 0;
2003         }
2004
2005         offset = le16_to_cpu(object->usSrcDstTableOffset)
2006                                         + bp->object_info_tbl_offset;
2007
2008         number = GET_IMAGE(uint8_t, offset);
2009         if (!number)
2010                 return 0;
2011
2012         offset += sizeof(uint8_t);
2013         *id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t));
2014
2015         if (!*id_list)
2016                 return 0;
2017
2018         return *number;
2019 }
2020
2021 static struct device_id device_type_from_device_id(uint16_t device_id)
2022 {
2023
2024         struct device_id result_device_id = {0};
2025
2026         switch (device_id) {
2027         case ATOM_DEVICE_LCD1_SUPPORT:
2028                 result_device_id.device_type = DEVICE_TYPE_LCD;
2029                 result_device_id.enum_id = 1;
2030                 break;
2031
2032         case ATOM_DEVICE_LCD2_SUPPORT:
2033                 result_device_id.device_type = DEVICE_TYPE_LCD;
2034                 result_device_id.enum_id = 2;
2035                 break;
2036
2037         case ATOM_DEVICE_CRT1_SUPPORT:
2038                 result_device_id.device_type = DEVICE_TYPE_CRT;
2039                 result_device_id.enum_id = 1;
2040                 break;
2041
2042         case ATOM_DEVICE_CRT2_SUPPORT:
2043                 result_device_id.device_type = DEVICE_TYPE_CRT;
2044                 result_device_id.enum_id = 2;
2045                 break;
2046
2047         case ATOM_DEVICE_DFP1_SUPPORT:
2048                 result_device_id.device_type = DEVICE_TYPE_DFP;
2049                 result_device_id.enum_id = 1;
2050                 break;
2051
2052         case ATOM_DEVICE_DFP2_SUPPORT:
2053                 result_device_id.device_type = DEVICE_TYPE_DFP;
2054                 result_device_id.enum_id = 2;
2055                 break;
2056
2057         case ATOM_DEVICE_DFP3_SUPPORT:
2058                 result_device_id.device_type = DEVICE_TYPE_DFP;
2059                 result_device_id.enum_id = 3;
2060                 break;
2061
2062         case ATOM_DEVICE_DFP4_SUPPORT:
2063                 result_device_id.device_type = DEVICE_TYPE_DFP;
2064                 result_device_id.enum_id = 4;
2065                 break;
2066
2067         case ATOM_DEVICE_DFP5_SUPPORT:
2068                 result_device_id.device_type = DEVICE_TYPE_DFP;
2069                 result_device_id.enum_id = 5;
2070                 break;
2071
2072         case ATOM_DEVICE_DFP6_SUPPORT:
2073                 result_device_id.device_type = DEVICE_TYPE_DFP;
2074                 result_device_id.enum_id = 6;
2075                 break;
2076
2077         default:
2078                 BREAK_TO_DEBUGGER(); /* Invalid device Id */
2079                 result_device_id.device_type = DEVICE_TYPE_UNKNOWN;
2080                 result_device_id.enum_id = 0;
2081         }
2082         return result_device_id;
2083 }
2084
2085 static void get_atom_data_table_revision(
2086         ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
2087         struct atom_data_revision *tbl_revision)
2088 {
2089         if (!tbl_revision)
2090                 return;
2091
2092         /* initialize the revision to 0 which is invalid revision */
2093         tbl_revision->major = 0;
2094         tbl_revision->minor = 0;
2095
2096         if (!atom_data_tbl)
2097                 return;
2098
2099         tbl_revision->major =
2100                         (uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl);
2101         tbl_revision->minor =
2102                         (uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl);
2103 }
2104
2105 static uint32_t signal_to_ss_id(enum as_signal_type signal)
2106 {
2107         uint32_t clk_id_ss = 0;
2108
2109         switch (signal) {
2110         case AS_SIGNAL_TYPE_DVI:
2111                 clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS;
2112                 break;
2113         case AS_SIGNAL_TYPE_HDMI:
2114                 clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI;
2115                 break;
2116         case AS_SIGNAL_TYPE_LVDS:
2117                 clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS;
2118                 break;
2119         case AS_SIGNAL_TYPE_DISPLAY_PORT:
2120                 clk_id_ss = ASIC_INTERNAL_SS_ON_DP;
2121                 break;
2122         case AS_SIGNAL_TYPE_GPU_PLL:
2123                 clk_id_ss = ASIC_INTERNAL_GPUPLL_SS;
2124                 break;
2125         default:
2126                 break;
2127         }
2128         return clk_id_ss;
2129 }
2130
2131 static uint32_t get_support_mask_for_device_id(struct device_id device_id)
2132 {
2133         enum dal_device_type device_type = device_id.device_type;
2134         uint32_t enum_id = device_id.enum_id;
2135
2136         switch (device_type) {
2137         case DEVICE_TYPE_LCD:
2138                 switch (enum_id) {
2139                 case 1:
2140                         return ATOM_DEVICE_LCD1_SUPPORT;
2141                 case 2:
2142                         return ATOM_DEVICE_LCD2_SUPPORT;
2143                 default:
2144                         break;
2145                 }
2146                 break;
2147         case DEVICE_TYPE_CRT:
2148                 switch (enum_id) {
2149                 case 1:
2150                         return ATOM_DEVICE_CRT1_SUPPORT;
2151                 case 2:
2152                         return ATOM_DEVICE_CRT2_SUPPORT;
2153                 default:
2154                         break;
2155                 }
2156                 break;
2157         case DEVICE_TYPE_DFP:
2158                 switch (enum_id) {
2159                 case 1:
2160                         return ATOM_DEVICE_DFP1_SUPPORT;
2161                 case 2:
2162                         return ATOM_DEVICE_DFP2_SUPPORT;
2163                 case 3:
2164                         return ATOM_DEVICE_DFP3_SUPPORT;
2165                 case 4:
2166                         return ATOM_DEVICE_DFP4_SUPPORT;
2167                 case 5:
2168                         return ATOM_DEVICE_DFP5_SUPPORT;
2169                 case 6:
2170                         return ATOM_DEVICE_DFP6_SUPPORT;
2171                 default:
2172                         break;
2173                 }
2174                 break;
2175         case DEVICE_TYPE_CV:
2176                 switch (enum_id) {
2177                 case 1:
2178                         return ATOM_DEVICE_CV_SUPPORT;
2179                 default:
2180                         break;
2181                 }
2182                 break;
2183         case DEVICE_TYPE_TV:
2184                 switch (enum_id) {
2185                 case 1:
2186                         return ATOM_DEVICE_TV1_SUPPORT;
2187                 default:
2188                         break;
2189                 }
2190                 break;
2191         default:
2192                 break;
2193         }
2194
2195         /* Unidentified device ID, return empty support mask. */
2196         return 0;
2197 }
2198
2199 /**
2200  * bios_parser_set_scratch_critical_state
2201  *
2202  * @brief
2203  *  update critical state bit in VBIOS scratch register
2204  *
2205  * @param
2206  *  bool - to set or reset state
2207  */
2208 static void bios_parser_set_scratch_critical_state(
2209         struct dc_bios *dcb,
2210         bool state)
2211 {
2212         bios_set_scratch_critical_state(dcb, state);
2213 }
2214
2215 /*
2216  * get_integrated_info_v8
2217  *
2218  * @brief
2219  * Get V8 integrated BIOS information
2220  *
2221  * @param
2222  * bios_parser *bp - [in]BIOS parser handler to get master data table
2223  * integrated_info *info - [out] store and output integrated info
2224  *
2225  * @return
2226  * enum bp_result - BP_RESULT_OK if information is available,
2227  *                  BP_RESULT_BADBIOSTABLE otherwise.
2228  */
2229 static enum bp_result get_integrated_info_v8(
2230         struct bios_parser *bp,
2231         struct integrated_info *info)
2232 {
2233         ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8;
2234         uint32_t i;
2235
2236         info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8,
2237                         bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
2238
2239         if (info_v8 == NULL)
2240                 return BP_RESULT_BADBIOSTABLE;
2241         info->boot_up_engine_clock = le32_to_cpu(info_v8->ulBootUpEngineClock) * 10;
2242         info->dentist_vco_freq = le32_to_cpu(info_v8->ulDentistVCOFreq) * 10;
2243         info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
2244
2245         for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2246                 /* Convert [10KHz] into [KHz] */
2247                 info->disp_clk_voltage[i].max_supported_clk =
2248                         le32_to_cpu(info_v8->sDISPCLK_Voltage[i].
2249                                     ulMaximumSupportedCLK) * 10;
2250                 info->disp_clk_voltage[i].voltage_index =
2251                         le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex);
2252         }
2253
2254         info->boot_up_req_display_vector =
2255                 le32_to_cpu(info_v8->ulBootUpReqDisplayVector);
2256         info->gpu_cap_info =
2257                 le32_to_cpu(info_v8->ulGPUCapInfo);
2258
2259         /*
2260          * system_config: Bit[0] = 0 : PCIE power gating disabled
2261          *                       = 1 : PCIE power gating enabled
2262          *                Bit[1] = 0 : DDR-PLL shut down disabled
2263          *                       = 1 : DDR-PLL shut down enabled
2264          *                Bit[2] = 0 : DDR-PLL power down disabled
2265          *                       = 1 : DDR-PLL power down enabled
2266          */
2267         info->system_config = le32_to_cpu(info_v8->ulSystemConfig);
2268         info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo);
2269         info->boot_up_nb_voltage =
2270                 le16_to_cpu(info_v8->usBootUpNBVoltage);
2271         info->ext_disp_conn_info_offset =
2272                 le16_to_cpu(info_v8->usExtDispConnInfoOffset);
2273         info->memory_type = info_v8->ucMemoryType;
2274         info->ma_channel_number = info_v8->ucUMAChannelNumber;
2275         info->gmc_restore_reset_time =
2276                 le32_to_cpu(info_v8->ulGMCRestoreResetTime);
2277
2278         info->minimum_n_clk =
2279                 le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]);
2280         for (i = 1; i < 4; ++i)
2281                 info->minimum_n_clk =
2282                         info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ?
2283                         info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]);
2284
2285         info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk);
2286         info->ddr_dll_power_up_time =
2287                 le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime);
2288         info->ddr_pll_power_up_time =
2289                 le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime);
2290         info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType);
2291         info->lvds_ss_percentage =
2292                 le16_to_cpu(info_v8->usLvdsSSPercentage);
2293         info->lvds_sspread_rate_in_10hz =
2294                 le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz);
2295         info->hdmi_ss_percentage =
2296                 le16_to_cpu(info_v8->usHDMISSPercentage);
2297         info->hdmi_sspread_rate_in_10hz =
2298                 le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz);
2299         info->dvi_ss_percentage =
2300                 le16_to_cpu(info_v8->usDVISSPercentage);
2301         info->dvi_sspread_rate_in_10_hz =
2302                 le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz);
2303
2304         info->max_lvds_pclk_freq_in_single_link =
2305                 le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink);
2306         info->lvds_misc = info_v8->ucLvdsMisc;
2307         info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
2308                 info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
2309         info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
2310                 info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
2311         info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
2312                 info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
2313         info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
2314                 info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
2315         info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
2316                 info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
2317         info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
2318                 info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
2319         info->lvds_off_to_on_delay_in_4ms =
2320                 info_v8->ucLVDSOffToOnDelay_in4Ms;
2321         info->lvds_bit_depth_control_val =
2322                 le32_to_cpu(info_v8->ulLCDBitDepthControlVal);
2323
2324         for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
2325                 /* Convert [10KHz] into [KHz] */
2326                 info->avail_s_clk[i].supported_s_clk =
2327                         le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10;
2328                 info->avail_s_clk[i].voltage_index =
2329                         le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex);
2330                 info->avail_s_clk[i].voltage_id =
2331                         le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID);
2332         }
2333
2334         for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2335                 info->ext_disp_conn_info.gu_id[i] =
2336                         info_v8->sExtDispConnInfo.ucGuid[i];
2337         }
2338
2339         for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2340                 info->ext_disp_conn_info.path[i].device_connector_id =
2341                         object_id_from_bios_object_id(
2342                                 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector));
2343
2344                 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2345                         object_id_from_bios_object_id(
2346                                 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
2347
2348                 info->ext_disp_conn_info.path[i].device_tag =
2349                         le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag);
2350                 info->ext_disp_conn_info.path[i].device_acpi_enum =
2351                         le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
2352                 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2353                         info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
2354                 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2355                         info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
2356                 info->ext_disp_conn_info.path[i].channel_mapping.raw =
2357                         info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping;
2358         }
2359         info->ext_disp_conn_info.checksum =
2360                 info_v8->sExtDispConnInfo.ucChecksum;
2361
2362         return BP_RESULT_OK;
2363 }
2364
2365 /*
2366  * get_integrated_info_v8
2367  *
2368  * @brief
2369  * Get V8 integrated BIOS information
2370  *
2371  * @param
2372  * bios_parser *bp - [in]BIOS parser handler to get master data table
2373  * integrated_info *info - [out] store and output integrated info
2374  *
2375  * @return
2376  * enum bp_result - BP_RESULT_OK if information is available,
2377  *                  BP_RESULT_BADBIOSTABLE otherwise.
2378  */
2379 static enum bp_result get_integrated_info_v9(
2380         struct bios_parser *bp,
2381         struct integrated_info *info)
2382 {
2383         ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9;
2384         uint32_t i;
2385
2386         info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9,
2387                         bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
2388
2389         if (!info_v9)
2390                 return BP_RESULT_BADBIOSTABLE;
2391
2392         info->boot_up_engine_clock = le32_to_cpu(info_v9->ulBootUpEngineClock) * 10;
2393         info->dentist_vco_freq = le32_to_cpu(info_v9->ulDentistVCOFreq) * 10;
2394         info->boot_up_uma_clock = le32_to_cpu(info_v9->ulBootUpUMAClock) * 10;
2395
2396         for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2397                 /* Convert [10KHz] into [KHz] */
2398                 info->disp_clk_voltage[i].max_supported_clk =
2399                         le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10;
2400                 info->disp_clk_voltage[i].voltage_index =
2401                         le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex);
2402         }
2403
2404         info->boot_up_req_display_vector =
2405                 le32_to_cpu(info_v9->ulBootUpReqDisplayVector);
2406         info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo);
2407
2408         /*
2409          * system_config: Bit[0] = 0 : PCIE power gating disabled
2410          *                       = 1 : PCIE power gating enabled
2411          *                Bit[1] = 0 : DDR-PLL shut down disabled
2412          *                       = 1 : DDR-PLL shut down enabled
2413          *                Bit[2] = 0 : DDR-PLL power down disabled
2414          *                       = 1 : DDR-PLL power down enabled
2415          */
2416         info->system_config = le32_to_cpu(info_v9->ulSystemConfig);
2417         info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo);
2418         info->boot_up_nb_voltage = le16_to_cpu(info_v9->usBootUpNBVoltage);
2419         info->ext_disp_conn_info_offset = le16_to_cpu(info_v9->usExtDispConnInfoOffset);
2420         info->memory_type = info_v9->ucMemoryType;
2421         info->ma_channel_number = info_v9->ucUMAChannelNumber;
2422         info->gmc_restore_reset_time = le32_to_cpu(info_v9->ulGMCRestoreResetTime);
2423
2424         info->minimum_n_clk = le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]);
2425         for (i = 1; i < 4; ++i)
2426                 info->minimum_n_clk =
2427                         info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ?
2428                         info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]);
2429
2430         info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk);
2431         info->ddr_dll_power_up_time = le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime);
2432         info->ddr_pll_power_up_time = le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime);
2433         info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType);
2434         info->lvds_ss_percentage = le16_to_cpu(info_v9->usLvdsSSPercentage);
2435         info->lvds_sspread_rate_in_10hz = le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz);
2436         info->hdmi_ss_percentage = le16_to_cpu(info_v9->usHDMISSPercentage);
2437         info->hdmi_sspread_rate_in_10hz = le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz);
2438         info->dvi_ss_percentage = le16_to_cpu(info_v9->usDVISSPercentage);
2439         info->dvi_sspread_rate_in_10_hz = le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz);
2440
2441         info->max_lvds_pclk_freq_in_single_link =
2442                 le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink);
2443         info->lvds_misc = info_v9->ucLvdsMisc;
2444         info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
2445                 info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
2446         info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
2447                 info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
2448         info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
2449                 info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
2450         info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
2451                 info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
2452         info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
2453                 info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
2454         info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
2455                 info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
2456         info->lvds_off_to_on_delay_in_4ms =
2457                 info_v9->ucLVDSOffToOnDelay_in4Ms;
2458         info->lvds_bit_depth_control_val =
2459                 le32_to_cpu(info_v9->ulLCDBitDepthControlVal);
2460
2461         for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
2462                 /* Convert [10KHz] into [KHz] */
2463                 info->avail_s_clk[i].supported_s_clk =
2464                         le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10;
2465                 info->avail_s_clk[i].voltage_index =
2466                         le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex);
2467                 info->avail_s_clk[i].voltage_id =
2468                         le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID);
2469         }
2470
2471         for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2472                 info->ext_disp_conn_info.gu_id[i] =
2473                         info_v9->sExtDispConnInfo.ucGuid[i];
2474         }
2475
2476         for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2477                 info->ext_disp_conn_info.path[i].device_connector_id =
2478                         object_id_from_bios_object_id(
2479                                 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector));
2480
2481                 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2482                         object_id_from_bios_object_id(
2483                                 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
2484
2485                 info->ext_disp_conn_info.path[i].device_tag =
2486                         le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag);
2487                 info->ext_disp_conn_info.path[i].device_acpi_enum =
2488                         le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
2489                 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2490                         info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
2491                 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2492                         info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
2493                 info->ext_disp_conn_info.path[i].channel_mapping.raw =
2494                         info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping;
2495         }
2496         info->ext_disp_conn_info.checksum =
2497                 info_v9->sExtDispConnInfo.ucChecksum;
2498
2499         return BP_RESULT_OK;
2500 }
2501
2502 /*
2503  * construct_integrated_info
2504  *
2505  * @brief
2506  * Get integrated BIOS information based on table revision
2507  *
2508  * @param
2509  * bios_parser *bp - [in]BIOS parser handler to get master data table
2510  * integrated_info *info - [out] store and output integrated info
2511  *
2512  * @return
2513  * enum bp_result - BP_RESULT_OK if information is available,
2514  *                  BP_RESULT_BADBIOSTABLE otherwise.
2515  */
2516 static enum bp_result construct_integrated_info(
2517         struct bios_parser *bp,
2518         struct integrated_info *info)
2519 {
2520         enum bp_result result = BP_RESULT_BADBIOSTABLE;
2521
2522         ATOM_COMMON_TABLE_HEADER *header;
2523         struct atom_data_revision revision;
2524
2525         if (bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) {
2526                 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
2527                                 bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
2528
2529                 get_atom_data_table_revision(header, &revision);
2530
2531                 /* Don't need to check major revision as they are all 1 */
2532                 switch (revision.minor) {
2533                 case 8:
2534                         result = get_integrated_info_v8(bp, info);
2535                         break;
2536                 case 9:
2537                         result = get_integrated_info_v9(bp, info);
2538                         break;
2539                 default:
2540                         return result;
2541
2542                 }
2543         }
2544
2545         /* Sort voltage table from low to high*/
2546         if (result == BP_RESULT_OK) {
2547                 uint32_t i;
2548                 uint32_t j;
2549
2550                 for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2551                         for (j = i; j > 0; --j) {
2552                                 if (
2553                                                 info->disp_clk_voltage[j].max_supported_clk <
2554                                                 info->disp_clk_voltage[j-1].max_supported_clk) {
2555                                         /* swap j and j - 1*/
2556                                         swap(info->disp_clk_voltage[j - 1],
2557                                              info->disp_clk_voltage[j]);
2558                                 }
2559                         }
2560                 }
2561
2562         }
2563
2564         return result;
2565 }
2566
2567 static struct integrated_info *bios_parser_create_integrated_info(
2568         struct dc_bios *dcb)
2569 {
2570         struct bios_parser *bp = BP_FROM_DCB(dcb);
2571         struct integrated_info *info = NULL;
2572
2573         info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL);
2574
2575         if (info == NULL) {
2576                 ASSERT_CRITICAL(0);
2577                 return NULL;
2578         }
2579
2580         if (construct_integrated_info(bp, info) == BP_RESULT_OK)
2581                 return info;
2582
2583         kfree(info);
2584
2585         return NULL;
2586 }
2587
2588 enum bp_result update_slot_layout_info(
2589         struct dc_bios *dcb,
2590         unsigned int i,
2591         struct slot_layout_info *slot_layout_info,
2592         unsigned int record_offset)
2593 {
2594         unsigned int j;
2595         struct bios_parser *bp;
2596         ATOM_BRACKET_LAYOUT_RECORD *record;
2597         ATOM_COMMON_RECORD_HEADER *record_header;
2598         enum bp_result result = BP_RESULT_NORECORD;
2599
2600         bp = BP_FROM_DCB(dcb);
2601         record = NULL;
2602         record_header = NULL;
2603
2604         for (;;) {
2605
2606                 record_header = (ATOM_COMMON_RECORD_HEADER *)
2607                         GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);
2608                 if (record_header == NULL) {
2609                         result = BP_RESULT_BADBIOSTABLE;
2610                         break;
2611                 }
2612
2613                 /* the end of the list */
2614                 if (record_header->ucRecordType == 0xff ||
2615                         record_header->ucRecordSize == 0)       {
2616                         break;
2617                 }
2618
2619                 if (record_header->ucRecordType ==
2620                         ATOM_BRACKET_LAYOUT_RECORD_TYPE &&
2621                         sizeof(ATOM_BRACKET_LAYOUT_RECORD)
2622                         <= record_header->ucRecordSize) {
2623                         record = (ATOM_BRACKET_LAYOUT_RECORD *)
2624                                 (record_header);
2625                         result = BP_RESULT_OK;
2626                         break;
2627                 }
2628
2629                 record_offset += record_header->ucRecordSize;
2630         }
2631
2632         /* return if the record not found */
2633         if (result != BP_RESULT_OK)
2634                 return result;
2635
2636         /* get slot sizes */
2637         slot_layout_info->length = record->ucLength;
2638         slot_layout_info->width = record->ucWidth;
2639
2640         /* get info for each connector in the slot */
2641         slot_layout_info->num_of_connectors = record->ucConnNum;
2642         for (j = 0; j < slot_layout_info->num_of_connectors; ++j) {
2643                 slot_layout_info->connectors[j].connector_type =
2644                         (enum connector_layout_type)
2645                         (record->asConnInfo[j].ucConnectorType);
2646                 switch (record->asConnInfo[j].ucConnectorType) {
2647                 case CONNECTOR_TYPE_DVI_D:
2648                         slot_layout_info->connectors[j].connector_type =
2649                                 CONNECTOR_LAYOUT_TYPE_DVI_D;
2650                         slot_layout_info->connectors[j].length =
2651                                 CONNECTOR_SIZE_DVI;
2652                         break;
2653
2654                 case CONNECTOR_TYPE_HDMI:
2655                         slot_layout_info->connectors[j].connector_type =
2656                                 CONNECTOR_LAYOUT_TYPE_HDMI;
2657                         slot_layout_info->connectors[j].length =
2658                                 CONNECTOR_SIZE_HDMI;
2659                         break;
2660
2661                 case CONNECTOR_TYPE_DISPLAY_PORT:
2662                         slot_layout_info->connectors[j].connector_type =
2663                                 CONNECTOR_LAYOUT_TYPE_DP;
2664                         slot_layout_info->connectors[j].length =
2665                                 CONNECTOR_SIZE_DP;
2666                         break;
2667
2668                 case CONNECTOR_TYPE_MINI_DISPLAY_PORT:
2669                         slot_layout_info->connectors[j].connector_type =
2670                                 CONNECTOR_LAYOUT_TYPE_MINI_DP;
2671                         slot_layout_info->connectors[j].length =
2672                                 CONNECTOR_SIZE_MINI_DP;
2673                         break;
2674
2675                 default:
2676                         slot_layout_info->connectors[j].connector_type =
2677                                 CONNECTOR_LAYOUT_TYPE_UNKNOWN;
2678                         slot_layout_info->connectors[j].length =
2679                                 CONNECTOR_SIZE_UNKNOWN;
2680                 }
2681
2682                 slot_layout_info->connectors[j].position =
2683                         record->asConnInfo[j].ucPosition;
2684                 slot_layout_info->connectors[j].connector_id =
2685                         object_id_from_bios_object_id(
2686                                 record->asConnInfo[j].usConnectorObjectId);
2687         }
2688         return result;
2689 }
2690
2691
2692 enum bp_result get_bracket_layout_record(
2693         struct dc_bios *dcb,
2694         unsigned int bracket_layout_id,
2695         struct slot_layout_info *slot_layout_info)
2696 {
2697         unsigned int i;
2698         unsigned int record_offset;
2699         struct bios_parser *bp;
2700         enum bp_result result;
2701         ATOM_OBJECT *object;
2702         ATOM_OBJECT_TABLE *object_table;
2703         unsigned int genericTableOffset;
2704
2705         bp = BP_FROM_DCB(dcb);
2706         object = NULL;
2707         if (slot_layout_info == NULL) {
2708                 DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");
2709                 return BP_RESULT_BADINPUT;
2710         }
2711
2712
2713         genericTableOffset = bp->object_info_tbl_offset +
2714                 bp->object_info_tbl.v1_3->usMiscObjectTableOffset;
2715         object_table = (ATOM_OBJECT_TABLE *)
2716                 GET_IMAGE(ATOM_OBJECT_TABLE, genericTableOffset);
2717         if (!object_table)
2718                 return BP_RESULT_FAILURE;
2719
2720         result = BP_RESULT_NORECORD;
2721         for (i = 0; i < object_table->ucNumberOfObjects; ++i) {
2722
2723                 if (bracket_layout_id ==
2724                         object_table->asObjects[i].usObjectID) {
2725
2726                         object = &object_table->asObjects[i];
2727                         record_offset = object->usRecordOffset +
2728                                 bp->object_info_tbl_offset;
2729
2730                         result = update_slot_layout_info(dcb, i,
2731                                 slot_layout_info, record_offset);
2732                         break;
2733                 }
2734         }
2735         return result;
2736 }
2737
2738 static enum bp_result bios_get_board_layout_info(
2739         struct dc_bios *dcb,
2740         struct board_layout_info *board_layout_info)
2741 {
2742         unsigned int i;
2743         enum bp_result record_result;
2744
2745         const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {
2746                 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1,
2747                 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2,
2748                 0, 0
2749         };
2750
2751         if (board_layout_info == NULL) {
2752                 DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");
2753                 return BP_RESULT_BADINPUT;
2754         }
2755
2756         board_layout_info->num_of_slots = 0;
2757
2758         for (i = 0; i < MAX_BOARD_SLOTS; ++i) {
2759                 record_result = get_bracket_layout_record(dcb,
2760                         slot_index_to_vbios_id[i],
2761                         &board_layout_info->slots[i]);
2762
2763                 if (record_result == BP_RESULT_NORECORD && i > 0)
2764                         break; /* no more slots present in bios */
2765                 else if (record_result != BP_RESULT_OK)
2766                         return record_result;  /* fail */
2767
2768                 ++board_layout_info->num_of_slots;
2769         }
2770
2771         /* all data is valid */
2772         board_layout_info->is_number_of_slots_valid = 1;
2773         board_layout_info->is_slots_size_valid = 1;
2774         board_layout_info->is_connector_offsets_valid = 1;
2775         board_layout_info->is_connector_lengths_valid = 1;
2776
2777         return BP_RESULT_OK;
2778 }
2779
2780 /******************************************************************************/
2781
2782 static const struct dc_vbios_funcs vbios_funcs = {
2783         .get_connectors_number = bios_parser_get_connectors_number,
2784
2785         .get_connector_id = bios_parser_get_connector_id,
2786
2787         .get_src_obj = bios_parser_get_src_obj,
2788
2789         .get_i2c_info = bios_parser_get_i2c_info,
2790
2791         .get_hpd_info = bios_parser_get_hpd_info,
2792
2793         .get_device_tag = bios_parser_get_device_tag,
2794
2795         .get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
2796
2797         .get_ss_entry_number = bios_parser_get_ss_entry_number,
2798
2799         .get_embedded_panel_info = bios_parser_get_embedded_panel_info,
2800
2801         .get_gpio_pin_info = bios_parser_get_gpio_pin_info,
2802
2803         .get_encoder_cap_info = bios_parser_get_encoder_cap_info,
2804
2805         /* bios scratch register communication */
2806         .is_accelerated_mode = bios_is_accelerated_mode,
2807
2808         .set_scratch_critical_state = bios_parser_set_scratch_critical_state,
2809
2810         .is_device_id_supported = bios_parser_is_device_id_supported,
2811
2812         /* COMMANDS */
2813         .encoder_control = bios_parser_encoder_control,
2814
2815         .transmitter_control = bios_parser_transmitter_control,
2816
2817         .enable_crtc = bios_parser_enable_crtc,
2818
2819         .adjust_pixel_clock = bios_parser_adjust_pixel_clock,
2820
2821         .set_pixel_clock = bios_parser_set_pixel_clock,
2822
2823         .set_dce_clock = bios_parser_set_dce_clock,
2824
2825         .enable_spread_spectrum_on_ppll = bios_parser_enable_spread_spectrum_on_ppll,
2826
2827         .program_crtc_timing = bios_parser_program_crtc_timing, /* still use.  should probably retire and program directly */
2828
2829         .program_display_engine_pll = bios_parser_program_display_engine_pll,
2830
2831         .enable_disp_power_gating = bios_parser_enable_disp_power_gating,
2832
2833         /* SW init and patch */
2834
2835         .bios_parser_destroy = bios_parser_destroy,
2836
2837         .get_board_layout_info = bios_get_board_layout_info,
2838
2839         .get_atom_dc_golden_table = NULL
2840 };
2841
2842 static bool bios_parser_construct(
2843         struct bios_parser *bp,
2844         struct bp_init_data *init,
2845         enum dce_version dce_version)
2846 {
2847         uint16_t *rom_header_offset = NULL;
2848         ATOM_ROM_HEADER *rom_header = NULL;
2849         ATOM_OBJECT_HEADER *object_info_tbl;
2850         struct atom_data_revision tbl_rev = {0};
2851
2852         if (!init)
2853                 return false;
2854
2855         if (!init->bios)
2856                 return false;
2857
2858         bp->base.funcs = &vbios_funcs;
2859         bp->base.bios = init->bios;
2860         bp->base.bios_size = bp->base.bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT;
2861
2862         bp->base.ctx = init->ctx;
2863         bp->base.bios_local_image = NULL;
2864
2865         rom_header_offset =
2866         GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER);
2867
2868         if (!rom_header_offset)
2869                 return false;
2870
2871         rom_header = GET_IMAGE(ATOM_ROM_HEADER, *rom_header_offset);
2872
2873         if (!rom_header)
2874                 return false;
2875
2876         get_atom_data_table_revision(&rom_header->sHeader, &tbl_rev);
2877         if (tbl_rev.major >= 2 && tbl_rev.minor >= 2)
2878                 return false;
2879
2880         bp->master_data_tbl =
2881         GET_IMAGE(ATOM_MASTER_DATA_TABLE,
2882                 rom_header->usMasterDataTableOffset);
2883
2884         if (!bp->master_data_tbl)
2885                 return false;
2886
2887         bp->object_info_tbl_offset = DATA_TABLES(Object_Header);
2888
2889         if (!bp->object_info_tbl_offset)
2890                 return false;
2891
2892         object_info_tbl =
2893         GET_IMAGE(ATOM_OBJECT_HEADER, bp->object_info_tbl_offset);
2894
2895         if (!object_info_tbl)
2896                 return false;
2897
2898         get_atom_data_table_revision(&object_info_tbl->sHeader,
2899                 &bp->object_info_tbl.revision);
2900
2901         if (bp->object_info_tbl.revision.major == 1
2902                 && bp->object_info_tbl.revision.minor >= 3) {
2903                 ATOM_OBJECT_HEADER_V3 *tbl_v3;
2904
2905                 tbl_v3 = GET_IMAGE(ATOM_OBJECT_HEADER_V3,
2906                         bp->object_info_tbl_offset);
2907                 if (!tbl_v3)
2908                         return false;
2909
2910                 bp->object_info_tbl.v1_3 = tbl_v3;
2911         } else if (bp->object_info_tbl.revision.major == 1
2912                 && bp->object_info_tbl.revision.minor >= 1)
2913                 bp->object_info_tbl.v1_1 = object_info_tbl;
2914         else
2915                 return false;
2916
2917         dal_bios_parser_init_cmd_tbl(bp);
2918         dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version);
2919
2920         bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);
2921         bp->base.fw_info_valid = bios_parser_get_firmware_info(&bp->base, &bp->base.fw_info) == BP_RESULT_OK;
2922
2923         return true;
2924 }
2925
2926 /******************************************************************************/
This page took 0.213443 seconds and 4 git commands to generate.