GNU Linux-libre 4.19.268-gnu1
[releases.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 "dm_services.h"
27
28 #include "atom.h"
29
30 #include "dc_bios_types.h"
31 #include "include/gpio_service_interface.h"
32 #include "include/grph_object_ctrl_defs.h"
33 #include "include/bios_parser_interface.h"
34 #include "include/i2caux_interface.h"
35 #include "include/logger_interface.h"
36
37 #include "command_table.h"
38 #include "bios_parser_helper.h"
39 #include "command_table_helper.h"
40 #include "bios_parser.h"
41 #include "bios_parser_types_internal.h"
42 #include "bios_parser_interface.h"
43
44 #include "bios_parser_common.h"
45 /* TODO remove - only needed for default i2c speed */
46 #include "dc.h"
47
48 #define THREE_PERCENT_OF_10000 300
49
50 #define LAST_RECORD_TYPE 0xff
51
52 #define DC_LOGGER \
53         bp->base.ctx->logger
54
55 /* GUID to validate external display connection info table (aka OPM module) */
56 static const uint8_t ext_display_connection_guid[NUMBER_OF_UCHAR_FOR_GUID] = {
57         0x91, 0x6E, 0x57, 0x09,
58         0x3F, 0x6D, 0xD2, 0x11,
59         0x39, 0x8E, 0x00, 0xA0,
60         0xC9, 0x69, 0x72, 0x3B};
61
62 #define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table)
63
64 static void get_atom_data_table_revision(
65         ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
66         struct atom_data_revision *tbl_revision);
67 static uint32_t get_dst_number_from_object(struct bios_parser *bp,
68         ATOM_OBJECT *object);
69 static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
70         uint16_t **id_list);
71 static uint32_t get_dest_obj_list(struct bios_parser *bp,
72         ATOM_OBJECT *object, uint16_t **id_list);
73 static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
74         struct graphics_object_id id);
75 static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
76         ATOM_I2C_RECORD *record,
77         struct graphics_object_i2c_info *info);
78 static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
79         ATOM_OBJECT *object);
80 static struct device_id device_type_from_device_id(uint16_t device_id);
81 static uint32_t signal_to_ss_id(enum as_signal_type signal);
82 static uint32_t get_support_mask_for_device_id(struct device_id device_id);
83 static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
84         struct bios_parser *bp,
85         ATOM_OBJECT *object);
86
87 #define BIOS_IMAGE_SIZE_OFFSET 2
88 #define BIOS_IMAGE_SIZE_UNIT 512
89
90 /*****************************************************************************/
91 static bool bios_parser_construct(
92         struct bios_parser *bp,
93         struct bp_init_data *init,
94         enum dce_version dce_version);
95
96 static uint8_t bios_parser_get_connectors_number(
97         struct dc_bios *dcb);
98
99 static enum bp_result bios_parser_get_embedded_panel_info(
100         struct dc_bios *dcb,
101         struct embedded_panel_info *info);
102
103 /*****************************************************************************/
104
105 struct dc_bios *bios_parser_create(
106         struct bp_init_data *init,
107         enum dce_version dce_version)
108 {
109         struct bios_parser *bp = NULL;
110
111         bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL);
112         if (!bp)
113                 return NULL;
114
115         if (bios_parser_construct(bp, init, dce_version))
116                 return &bp->base;
117
118         kfree(bp);
119         BREAK_TO_DEBUGGER();
120         return NULL;
121 }
122
123 static void destruct(struct bios_parser *bp)
124 {
125         kfree(bp->base.bios_local_image);
126         kfree(bp->base.integrated_info);
127 }
128
129 static void bios_parser_destroy(struct dc_bios **dcb)
130 {
131         struct bios_parser *bp = BP_FROM_DCB(*dcb);
132
133         if (!bp) {
134                 BREAK_TO_DEBUGGER();
135                 return;
136         }
137
138         destruct(bp);
139
140         kfree(bp);
141         *dcb = NULL;
142 }
143
144 static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset)
145 {
146         ATOM_OBJECT_TABLE *table;
147
148         uint32_t object_table_offset = bp->object_info_tbl_offset + offset;
149
150         table = GET_IMAGE(ATOM_OBJECT_TABLE, object_table_offset);
151
152         if (!table)
153                 return 0;
154         else
155                 return table->ucNumberOfObjects;
156 }
157
158 static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)
159 {
160         struct bios_parser *bp = BP_FROM_DCB(dcb);
161
162         return get_number_of_objects(bp,
163                 le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset));
164 }
165
166 static struct graphics_object_id bios_parser_get_encoder_id(
167         struct dc_bios *dcb,
168         uint32_t i)
169 {
170         struct bios_parser *bp = BP_FROM_DCB(dcb);
171         struct graphics_object_id object_id = dal_graphics_object_id_init(
172                 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
173
174         uint32_t encoder_table_offset = bp->object_info_tbl_offset
175                 + le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
176
177         ATOM_OBJECT_TABLE *tbl =
178                 GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset);
179
180         if (tbl && tbl->ucNumberOfObjects > i) {
181                 const uint16_t id = le16_to_cpu(tbl->asObjects[i].usObjectID);
182
183                 object_id = object_id_from_bios_object_id(id);
184         }
185
186         return object_id;
187 }
188
189 static struct graphics_object_id bios_parser_get_connector_id(
190         struct dc_bios *dcb,
191         uint8_t i)
192 {
193         struct bios_parser *bp = BP_FROM_DCB(dcb);
194         struct graphics_object_id object_id = dal_graphics_object_id_init(
195                 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
196         uint16_t id;
197
198         uint32_t connector_table_offset = bp->object_info_tbl_offset
199                 + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
200
201         ATOM_OBJECT_TABLE *tbl =
202                 GET_IMAGE(ATOM_OBJECT_TABLE, connector_table_offset);
203
204         if (!tbl) {
205                 dm_error("Can't get connector table from atom bios.\n");
206                 return object_id;
207         }
208
209         if (tbl->ucNumberOfObjects <= i) {
210                 dm_error("Can't find connector id %d in connector table of size %d.\n",
211                          i, tbl->ucNumberOfObjects);
212                 return object_id;
213         }
214
215         id = le16_to_cpu(tbl->asObjects[i].usObjectID);
216         object_id = object_id_from_bios_object_id(id);
217         return object_id;
218 }
219
220 static uint32_t bios_parser_get_dst_number(struct dc_bios *dcb,
221         struct graphics_object_id id)
222 {
223         struct bios_parser *bp = BP_FROM_DCB(dcb);
224         ATOM_OBJECT *object = get_bios_object(bp, id);
225
226         return get_dst_number_from_object(bp, object);
227 }
228
229 static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
230         struct graphics_object_id object_id, uint32_t index,
231         struct graphics_object_id *src_object_id)
232 {
233         uint32_t number;
234         uint16_t *id;
235         ATOM_OBJECT *object;
236         struct bios_parser *bp = BP_FROM_DCB(dcb);
237
238         if (!src_object_id)
239                 return BP_RESULT_BADINPUT;
240
241         object = get_bios_object(bp, object_id);
242
243         if (!object) {
244                 BREAK_TO_DEBUGGER(); /* Invalid object id */
245                 return BP_RESULT_BADINPUT;
246         }
247
248         number = get_src_obj_list(bp, object, &id);
249
250         if (number <= index)
251                 return BP_RESULT_BADINPUT;
252
253         *src_object_id = object_id_from_bios_object_id(id[index]);
254
255         return BP_RESULT_OK;
256 }
257
258 static enum bp_result bios_parser_get_dst_obj(struct dc_bios *dcb,
259         struct graphics_object_id object_id, uint32_t index,
260         struct graphics_object_id *dest_object_id)
261 {
262         uint32_t number;
263         uint16_t *id = NULL;
264         ATOM_OBJECT *object;
265         struct bios_parser *bp = BP_FROM_DCB(dcb);
266
267         if (!dest_object_id)
268                 return BP_RESULT_BADINPUT;
269
270         object = get_bios_object(bp, object_id);
271
272         number = get_dest_obj_list(bp, object, &id);
273
274         if (number <= index || !id)
275                 return BP_RESULT_BADINPUT;
276
277         *dest_object_id = object_id_from_bios_object_id(id[index]);
278
279         return BP_RESULT_OK;
280 }
281
282 static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
283         struct graphics_object_id id,
284         struct graphics_object_i2c_info *info)
285 {
286         uint32_t offset;
287         ATOM_OBJECT *object;
288         ATOM_COMMON_RECORD_HEADER *header;
289         ATOM_I2C_RECORD *record;
290         struct bios_parser *bp = BP_FROM_DCB(dcb);
291
292         if (!info)
293                 return BP_RESULT_BADINPUT;
294
295         object = get_bios_object(bp, id);
296
297         if (!object)
298                 return BP_RESULT_BADINPUT;
299
300         offset = le16_to_cpu(object->usRecordOffset)
301                         + bp->object_info_tbl_offset;
302
303         for (;;) {
304                 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
305
306                 if (!header)
307                         return BP_RESULT_BADBIOSTABLE;
308
309                 if (LAST_RECORD_TYPE == header->ucRecordType ||
310                         !header->ucRecordSize)
311                         break;
312
313                 if (ATOM_I2C_RECORD_TYPE == header->ucRecordType
314                         && sizeof(ATOM_I2C_RECORD) <= header->ucRecordSize) {
315                         /* get the I2C info */
316                         record = (ATOM_I2C_RECORD *) header;
317
318                         if (get_gpio_i2c_info(bp, record, info) == BP_RESULT_OK)
319                                 return BP_RESULT_OK;
320                 }
321
322                 offset += header->ucRecordSize;
323         }
324
325         return BP_RESULT_NORECORD;
326 }
327
328 static enum bp_result get_voltage_ddc_info_v1(uint8_t *i2c_line,
329         ATOM_COMMON_TABLE_HEADER *header,
330         uint8_t *address)
331 {
332         enum bp_result result = BP_RESULT_NORECORD;
333         ATOM_VOLTAGE_OBJECT_INFO *info =
334                 (ATOM_VOLTAGE_OBJECT_INFO *) address;
335
336         uint8_t *voltage_current_object = (uint8_t *) &info->asVoltageObj[0];
337
338         while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) {
339                 ATOM_VOLTAGE_OBJECT *object =
340                         (ATOM_VOLTAGE_OBJECT *) voltage_current_object;
341
342                 if ((object->ucVoltageType == SET_VOLTAGE_INIT_MODE) &&
343                         (object->ucVoltageType &
344                                 VOLTAGE_CONTROLLED_BY_I2C_MASK)) {
345
346                         *i2c_line = object->asControl.ucVoltageControlI2cLine
347                                         ^ 0x90;
348                         result = BP_RESULT_OK;
349                         break;
350                 }
351
352                 voltage_current_object += object->ucSize;
353         }
354         return result;
355 }
356
357 static enum bp_result get_voltage_ddc_info_v3(uint8_t *i2c_line,
358         uint32_t index,
359         ATOM_COMMON_TABLE_HEADER *header,
360         uint8_t *address)
361 {
362         enum bp_result result = BP_RESULT_NORECORD;
363         ATOM_VOLTAGE_OBJECT_INFO_V3_1 *info =
364                 (ATOM_VOLTAGE_OBJECT_INFO_V3_1 *) address;
365
366         uint8_t *voltage_current_object =
367                 (uint8_t *) (&(info->asVoltageObj[0]));
368
369         while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) {
370                 ATOM_I2C_VOLTAGE_OBJECT_V3 *object =
371                         (ATOM_I2C_VOLTAGE_OBJECT_V3 *) voltage_current_object;
372
373                 if (object->sHeader.ucVoltageMode ==
374                         ATOM_INIT_VOLTAGE_REGULATOR) {
375                         if (object->sHeader.ucVoltageType == index) {
376                                 *i2c_line = object->ucVoltageControlI2cLine
377                                                 ^ 0x90;
378                                 result = BP_RESULT_OK;
379                                 break;
380                         }
381                 }
382
383                 voltage_current_object += le16_to_cpu(object->sHeader.usSize);
384         }
385         return result;
386 }
387
388 static enum bp_result bios_parser_get_thermal_ddc_info(
389         struct dc_bios *dcb,
390         uint32_t i2c_channel_id,
391         struct graphics_object_i2c_info *info)
392 {
393         struct bios_parser *bp = BP_FROM_DCB(dcb);
394         ATOM_I2C_ID_CONFIG_ACCESS *config;
395         ATOM_I2C_RECORD record;
396
397         if (!info)
398                 return BP_RESULT_BADINPUT;
399
400         config = (ATOM_I2C_ID_CONFIG_ACCESS *) &i2c_channel_id;
401
402         record.sucI2cId.bfHW_Capable = config->sbfAccess.bfHW_Capable;
403         record.sucI2cId.bfI2C_LineMux = config->sbfAccess.bfI2C_LineMux;
404         record.sucI2cId.bfHW_EngineID = config->sbfAccess.bfHW_EngineID;
405
406         return get_gpio_i2c_info(bp, &record, info);
407 }
408
409 static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb,
410         uint32_t index,
411         struct graphics_object_i2c_info *info)
412 {
413         uint8_t i2c_line = 0;
414         enum bp_result result = BP_RESULT_NORECORD;
415         uint8_t *voltage_info_address;
416         ATOM_COMMON_TABLE_HEADER *header;
417         struct atom_data_revision revision = {0};
418         struct bios_parser *bp = BP_FROM_DCB(dcb);
419
420         if (!DATA_TABLES(VoltageObjectInfo))
421                 return result;
422
423         voltage_info_address = bios_get_image(&bp->base, DATA_TABLES(VoltageObjectInfo), sizeof(ATOM_COMMON_TABLE_HEADER));
424
425         header = (ATOM_COMMON_TABLE_HEADER *) voltage_info_address;
426
427         get_atom_data_table_revision(header, &revision);
428
429         switch (revision.major) {
430         case 1:
431         case 2:
432                 result = get_voltage_ddc_info_v1(&i2c_line, header,
433                         voltage_info_address);
434                 break;
435         case 3:
436                 if (revision.minor != 1)
437                         break;
438                 result = get_voltage_ddc_info_v3(&i2c_line, index, header,
439                         voltage_info_address);
440                 break;
441         }
442
443         if (result == BP_RESULT_OK)
444                 result = bios_parser_get_thermal_ddc_info(dcb,
445                         i2c_line, info);
446
447         return result;
448 }
449
450 /* TODO: temporary commented out to suppress 'defined but not used' warning */
451 #if 0
452 static enum bp_result bios_parser_get_ddc_info_for_i2c_line(
453         struct bios_parser *bp,
454         uint8_t i2c_line, struct graphics_object_i2c_info *info)
455 {
456         uint32_t offset;
457         ATOM_OBJECT *object;
458         ATOM_OBJECT_TABLE *table;
459         uint32_t i;
460
461         if (!info)
462                 return BP_RESULT_BADINPUT;
463
464         offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
465
466         offset += bp->object_info_tbl_offset;
467
468         table = GET_IMAGE(ATOM_OBJECT_TABLE, offset);
469
470         if (!table)
471                 return BP_RESULT_BADBIOSTABLE;
472
473         for (i = 0; i < table->ucNumberOfObjects; i++) {
474                 object = &table->asObjects[i];
475
476                 if (!object) {
477                         BREAK_TO_DEBUGGER(); /* Invalid object id */
478                         return BP_RESULT_BADINPUT;
479                 }
480
481                 offset = le16_to_cpu(object->usRecordOffset)
482                                 + bp->object_info_tbl_offset;
483
484                 for (;;) {
485                         ATOM_COMMON_RECORD_HEADER *header =
486                                 GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
487
488                         if (!header)
489                                 return BP_RESULT_BADBIOSTABLE;
490
491                         offset += header->ucRecordSize;
492
493                         if (LAST_RECORD_TYPE == header->ucRecordType ||
494                                 !header->ucRecordSize)
495                                 break;
496
497                         if (ATOM_I2C_RECORD_TYPE == header->ucRecordType
498                                 && sizeof(ATOM_I2C_RECORD) <=
499                                 header->ucRecordSize) {
500                                 ATOM_I2C_RECORD *record =
501                                         (ATOM_I2C_RECORD *) header;
502
503                                 if (i2c_line != record->sucI2cId.bfI2C_LineMux)
504                                         continue;
505
506                                 /* get the I2C info */
507                                 if (get_gpio_i2c_info(bp, record, info) ==
508                                         BP_RESULT_OK)
509                                         return BP_RESULT_OK;
510                         }
511                 }
512         }
513
514         return BP_RESULT_NORECORD;
515 }
516 #endif
517
518 static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb,
519         struct graphics_object_id id,
520         struct graphics_object_hpd_info *info)
521 {
522         struct bios_parser *bp = BP_FROM_DCB(dcb);
523         ATOM_OBJECT *object;
524         ATOM_HPD_INT_RECORD *record = NULL;
525
526         if (!info)
527                 return BP_RESULT_BADINPUT;
528
529         object = get_bios_object(bp, id);
530
531         if (!object)
532                 return BP_RESULT_BADINPUT;
533
534         record = get_hpd_record(bp, object);
535
536         if (record != NULL) {
537                 info->hpd_int_gpio_uid = record->ucHPDIntGPIOID;
538                 info->hpd_active = record->ucPlugged_PinState;
539                 return BP_RESULT_OK;
540         }
541
542         return BP_RESULT_NORECORD;
543 }
544
545 static enum bp_result bios_parser_get_device_tag_record(
546         struct bios_parser *bp,
547         ATOM_OBJECT *object,
548         ATOM_CONNECTOR_DEVICE_TAG_RECORD **record)
549 {
550         ATOM_COMMON_RECORD_HEADER *header;
551         uint32_t offset;
552
553         offset = le16_to_cpu(object->usRecordOffset)
554                         + bp->object_info_tbl_offset;
555
556         for (;;) {
557                 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
558
559                 if (!header)
560                         return BP_RESULT_BADBIOSTABLE;
561
562                 offset += header->ucRecordSize;
563
564                 if (LAST_RECORD_TYPE == header->ucRecordType ||
565                         !header->ucRecordSize)
566                         break;
567
568                 if (ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE !=
569                         header->ucRecordType)
570                         continue;
571
572                 if (sizeof(ATOM_CONNECTOR_DEVICE_TAG) > header->ucRecordSize)
573                         continue;
574
575                 *record = (ATOM_CONNECTOR_DEVICE_TAG_RECORD *) header;
576                 return BP_RESULT_OK;
577         }
578
579         return BP_RESULT_NORECORD;
580 }
581
582 static enum bp_result bios_parser_get_device_tag(
583         struct dc_bios *dcb,
584         struct graphics_object_id connector_object_id,
585         uint32_t device_tag_index,
586         struct connector_device_tag_info *info)
587 {
588         struct bios_parser *bp = BP_FROM_DCB(dcb);
589         ATOM_OBJECT *object;
590         ATOM_CONNECTOR_DEVICE_TAG_RECORD *record = NULL;
591         ATOM_CONNECTOR_DEVICE_TAG *device_tag;
592
593         if (!info)
594                 return BP_RESULT_BADINPUT;
595
596         /* getBiosObject will return MXM object */
597         object = get_bios_object(bp, connector_object_id);
598
599         if (!object) {
600                 BREAK_TO_DEBUGGER(); /* Invalid object id */
601                 return BP_RESULT_BADINPUT;
602         }
603
604         if (bios_parser_get_device_tag_record(bp, object, &record)
605                 != BP_RESULT_OK)
606                 return BP_RESULT_NORECORD;
607
608         if (device_tag_index >= record->ucNumberOfDevice)
609                 return BP_RESULT_NORECORD;
610
611         device_tag = &record->asDeviceTag[device_tag_index];
612
613         info->acpi_device = le32_to_cpu(device_tag->ulACPIDeviceEnum);
614         info->dev_id =
615                 device_type_from_device_id(le16_to_cpu(device_tag->usDeviceID));
616
617         return BP_RESULT_OK;
618 }
619
620 static enum bp_result get_firmware_info_v1_4(
621         struct bios_parser *bp,
622         struct dc_firmware_info *info);
623 static enum bp_result get_firmware_info_v2_1(
624         struct bios_parser *bp,
625         struct dc_firmware_info *info);
626 static enum bp_result get_firmware_info_v2_2(
627         struct bios_parser *bp,
628         struct dc_firmware_info *info);
629
630 static enum bp_result bios_parser_get_firmware_info(
631         struct dc_bios *dcb,
632         struct dc_firmware_info *info)
633 {
634         struct bios_parser *bp = BP_FROM_DCB(dcb);
635         enum bp_result result = BP_RESULT_BADBIOSTABLE;
636         ATOM_COMMON_TABLE_HEADER *header;
637         struct atom_data_revision revision;
638
639         if (info && DATA_TABLES(FirmwareInfo)) {
640                 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
641                         DATA_TABLES(FirmwareInfo));
642                 get_atom_data_table_revision(header, &revision);
643                 switch (revision.major) {
644                 case 1:
645                         switch (revision.minor) {
646                         case 4:
647                                 result = get_firmware_info_v1_4(bp, info);
648                                 break;
649                         default:
650                                 break;
651                         }
652                         break;
653
654                 case 2:
655                         switch (revision.minor) {
656                         case 1:
657                                 result = get_firmware_info_v2_1(bp, info);
658                                 break;
659                         case 2:
660                                 result = get_firmware_info_v2_2(bp, info);
661                                 break;
662                         default:
663                                 break;
664                         }
665                         break;
666                 default:
667                         break;
668                 }
669         }
670
671         return result;
672 }
673
674 static enum bp_result get_firmware_info_v1_4(
675         struct bios_parser *bp,
676         struct dc_firmware_info *info)
677 {
678         ATOM_FIRMWARE_INFO_V1_4 *firmware_info =
679                 GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4,
680                         DATA_TABLES(FirmwareInfo));
681
682         if (!info)
683                 return BP_RESULT_BADINPUT;
684
685         if (!firmware_info)
686                 return BP_RESULT_BADBIOSTABLE;
687
688         memset(info, 0, sizeof(*info));
689
690         /* Pixel clock pll information. We need to convert from 10KHz units into
691          * KHz units */
692         info->pll_info.crystal_frequency =
693                 le16_to_cpu(firmware_info->usReferenceClock) * 10;
694         info->pll_info.min_input_pxl_clk_pll_frequency =
695                 le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
696         info->pll_info.max_input_pxl_clk_pll_frequency =
697                 le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
698         info->pll_info.min_output_pxl_clk_pll_frequency =
699                 le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
700         info->pll_info.max_output_pxl_clk_pll_frequency =
701                 le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
702
703         if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
704                 /* Since there is no information on the SS, report conservative
705                  * value 3% for bandwidth calculation */
706                 /* unit of 0.01% */
707                 info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
708
709         if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
710                 /* Since there is no information on the SS,report conservative
711                  * value 3% for bandwidth calculation */
712                 /* unit of 0.01% */
713                 info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
714
715         return BP_RESULT_OK;
716 }
717
718 static enum bp_result get_ss_info_v3_1(
719         struct bios_parser *bp,
720         uint32_t id,
721         uint32_t index,
722         struct spread_spectrum_info *ss_info);
723
724 static enum bp_result get_firmware_info_v2_1(
725         struct bios_parser *bp,
726         struct dc_firmware_info *info)
727 {
728         ATOM_FIRMWARE_INFO_V2_1 *firmwareInfo =
729                 GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1, DATA_TABLES(FirmwareInfo));
730         struct spread_spectrum_info internalSS;
731         uint32_t index;
732
733         if (!info)
734                 return BP_RESULT_BADINPUT;
735
736         if (!firmwareInfo)
737                 return BP_RESULT_BADBIOSTABLE;
738
739         memset(info, 0, sizeof(*info));
740
741         /* Pixel clock pll information. We need to convert from 10KHz units into
742          * KHz units */
743         info->pll_info.crystal_frequency =
744                 le16_to_cpu(firmwareInfo->usCoreReferenceClock) * 10;
745         info->pll_info.min_input_pxl_clk_pll_frequency =
746                 le16_to_cpu(firmwareInfo->usMinPixelClockPLL_Input) * 10;
747         info->pll_info.max_input_pxl_clk_pll_frequency =
748                 le16_to_cpu(firmwareInfo->usMaxPixelClockPLL_Input) * 10;
749         info->pll_info.min_output_pxl_clk_pll_frequency =
750                 le32_to_cpu(firmwareInfo->ulMinPixelClockPLL_Output) * 10;
751         info->pll_info.max_output_pxl_clk_pll_frequency =
752                 le32_to_cpu(firmwareInfo->ulMaxPixelClockPLL_Output) * 10;
753         info->default_display_engine_pll_frequency =
754                 le32_to_cpu(firmwareInfo->ulDefaultDispEngineClkFreq) * 10;
755         info->external_clock_source_frequency_for_dp =
756                 le16_to_cpu(firmwareInfo->usUniphyDPModeExtClkFreq) * 10;
757         info->min_allowed_bl_level = firmwareInfo->ucMinAllowedBL_Level;
758
759         /* There should be only one entry in the SS info table for Memory Clock
760          */
761         index = 0;
762         if (firmwareInfo->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
763                 /* Since there is no information for external SS, report
764                  *  conservative value 3% for bandwidth calculation */
765                 /* unit of 0.01% */
766                 info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
767         else if (get_ss_info_v3_1(bp,
768                 ASIC_INTERNAL_MEMORY_SS, index, &internalSS) == BP_RESULT_OK) {
769                 if (internalSS.spread_spectrum_percentage) {
770                         info->feature.memory_clk_ss_percentage =
771                                 internalSS.spread_spectrum_percentage;
772                         if (internalSS.type.CENTER_MODE) {
773                                 /* if it is centermode, the exact SS Percentage
774                                  * will be round up of half of the percentage
775                                  * reported in the SS table */
776                                 ++info->feature.memory_clk_ss_percentage;
777                                 info->feature.memory_clk_ss_percentage /= 2;
778                         }
779                 }
780         }
781
782         /* There should be only one entry in the SS info table for Engine Clock
783          */
784         index = 1;
785         if (firmwareInfo->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
786                 /* Since there is no information for external SS, report
787                  * conservative value 3% for bandwidth calculation */
788                 /* unit of 0.01% */
789                 info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
790         else if (get_ss_info_v3_1(bp,
791                 ASIC_INTERNAL_ENGINE_SS, index, &internalSS) == BP_RESULT_OK) {
792                 if (internalSS.spread_spectrum_percentage) {
793                         info->feature.engine_clk_ss_percentage =
794                                 internalSS.spread_spectrum_percentage;
795                         if (internalSS.type.CENTER_MODE) {
796                                 /* if it is centermode, the exact SS Percentage
797                                  * will be round up of half of the percentage
798                                  * reported in the SS table */
799                                 ++info->feature.engine_clk_ss_percentage;
800                                 info->feature.engine_clk_ss_percentage /= 2;
801                         }
802                 }
803         }
804
805         return BP_RESULT_OK;
806 }
807
808 static enum bp_result get_firmware_info_v2_2(
809         struct bios_parser *bp,
810         struct dc_firmware_info *info)
811 {
812         ATOM_FIRMWARE_INFO_V2_2 *firmware_info;
813         struct spread_spectrum_info internal_ss;
814         uint32_t index;
815
816         if (!info)
817                 return BP_RESULT_BADINPUT;
818
819         firmware_info = GET_IMAGE(ATOM_FIRMWARE_INFO_V2_2,
820                 DATA_TABLES(FirmwareInfo));
821
822         if (!firmware_info)
823                 return BP_RESULT_BADBIOSTABLE;
824
825         memset(info, 0, sizeof(*info));
826
827         /* Pixel clock pll information. We need to convert from 10KHz units into
828          * KHz units */
829         info->pll_info.crystal_frequency =
830                 le16_to_cpu(firmware_info->usCoreReferenceClock) * 10;
831         info->pll_info.min_input_pxl_clk_pll_frequency =
832                 le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
833         info->pll_info.max_input_pxl_clk_pll_frequency =
834                 le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
835         info->pll_info.min_output_pxl_clk_pll_frequency =
836                 le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
837         info->pll_info.max_output_pxl_clk_pll_frequency =
838                 le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
839         info->default_display_engine_pll_frequency =
840                 le32_to_cpu(firmware_info->ulDefaultDispEngineClkFreq) * 10;
841         info->external_clock_source_frequency_for_dp =
842                 le16_to_cpu(firmware_info->usUniphyDPModeExtClkFreq) * 10;
843
844         /* There should be only one entry in the SS info table for Memory Clock
845          */
846         index = 0;
847         if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
848                 /* Since there is no information for external SS, report
849                  *  conservative value 3% for bandwidth calculation */
850                 /* unit of 0.01% */
851                 info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
852         else if (get_ss_info_v3_1(bp,
853                         ASIC_INTERNAL_MEMORY_SS, index, &internal_ss) == BP_RESULT_OK) {
854                 if (internal_ss.spread_spectrum_percentage) {
855                         info->feature.memory_clk_ss_percentage =
856                                         internal_ss.spread_spectrum_percentage;
857                         if (internal_ss.type.CENTER_MODE) {
858                                 /* if it is centermode, the exact SS Percentage
859                                  * will be round up of half of the percentage
860                                  * reported in the SS table */
861                                 ++info->feature.memory_clk_ss_percentage;
862                                 info->feature.memory_clk_ss_percentage /= 2;
863                         }
864                 }
865         }
866
867         /* There should be only one entry in the SS info table for Engine Clock
868          */
869         index = 1;
870         if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
871                 /* Since there is no information for external SS, report
872                  * conservative value 3% for bandwidth calculation */
873                 /* unit of 0.01% */
874                 info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
875         else if (get_ss_info_v3_1(bp,
876                         ASIC_INTERNAL_ENGINE_SS, index, &internal_ss) == BP_RESULT_OK) {
877                 if (internal_ss.spread_spectrum_percentage) {
878                         info->feature.engine_clk_ss_percentage =
879                                         internal_ss.spread_spectrum_percentage;
880                         if (internal_ss.type.CENTER_MODE) {
881                                 /* if it is centermode, the exact SS Percentage
882                                  * will be round up of half of the percentage
883                                  * reported in the SS table */
884                                 ++info->feature.engine_clk_ss_percentage;
885                                 info->feature.engine_clk_ss_percentage /= 2;
886                         }
887                 }
888         }
889
890         /* Remote Display */
891         info->remote_display_config = firmware_info->ucRemoteDisplayConfig;
892
893         /* Is allowed minimum BL level */
894         info->min_allowed_bl_level = firmware_info->ucMinAllowedBL_Level;
895         /* Used starting from CI */
896         info->smu_gpu_pll_output_freq =
897                         (uint32_t) (le32_to_cpu(firmware_info->ulGPUPLL_OutputFreq) * 10);
898
899         return BP_RESULT_OK;
900 }
901
902 static enum bp_result get_ss_info_v3_1(
903         struct bios_parser *bp,
904         uint32_t id,
905         uint32_t index,
906         struct spread_spectrum_info *ss_info)
907 {
908         ATOM_ASIC_INTERNAL_SS_INFO_V3 *ss_table_header_include;
909         ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
910         uint32_t table_size;
911         uint32_t i;
912         uint32_t table_index = 0;
913
914         if (!ss_info)
915                 return BP_RESULT_BADINPUT;
916
917         if (!DATA_TABLES(ASIC_InternalSS_Info))
918                 return BP_RESULT_UNSUPPORTED;
919
920         ss_table_header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
921                 DATA_TABLES(ASIC_InternalSS_Info));
922         table_size =
923                 (le16_to_cpu(ss_table_header_include->sHeader.usStructureSize)
924                                 - sizeof(ATOM_COMMON_TABLE_HEADER))
925                                 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
926
927         tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
928                                 &ss_table_header_include->asSpreadSpectrum[0];
929
930         memset(ss_info, 0, sizeof(struct spread_spectrum_info));
931
932         for (i = 0; i < table_size; i++) {
933                 if (tbl[i].ucClockIndication != (uint8_t) id)
934                         continue;
935
936                 if (table_index != index) {
937                         table_index++;
938                         continue;
939                 }
940                 /* VBIOS introduced new defines for Version 3, same values as
941                  *  before, so now use these new ones for Version 3.
942                  * Shouldn't affect field VBIOS's V3 as define values are still
943                  *  same.
944                  * #define SS_MODE_V3_CENTRE_SPREAD_MASK                0x01
945                  * #define SS_MODE_V3_EXTERNAL_SS_MASK                  0x02
946
947                  * Old VBIOS defines:
948                  * #define ATOM_SS_CENTRE_SPREAD_MODE_MASK        0x00000001
949                  * #define ATOM_EXTERNAL_SS_MASK                  0x00000002
950                  */
951
952                 if (SS_MODE_V3_EXTERNAL_SS_MASK & tbl[i].ucSpreadSpectrumMode)
953                         ss_info->type.EXTERNAL = true;
954
955                 if (SS_MODE_V3_CENTRE_SPREAD_MASK & tbl[i].ucSpreadSpectrumMode)
956                         ss_info->type.CENTER_MODE = true;
957
958                 /* Older VBIOS (in field) always provides SS percentage in 0.01%
959                  * units set Divider to 100 */
960                 ss_info->spread_percentage_divider = 100;
961
962                 /* #define SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 0x10 */
963                 if (SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK
964                                 & tbl[i].ucSpreadSpectrumMode)
965                         ss_info->spread_percentage_divider = 1000;
966
967                 ss_info->type.STEP_AND_DELAY_INFO = false;
968                 /* convert [10KHz] into [KHz] */
969                 ss_info->target_clock_range =
970                                 le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
971                 ss_info->spread_spectrum_percentage =
972                                 (uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
973                 ss_info->spread_spectrum_range =
974                                 (uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
975
976                 return BP_RESULT_OK;
977         }
978         return BP_RESULT_NORECORD;
979 }
980
981 static enum bp_result bios_parser_transmitter_control(
982         struct dc_bios *dcb,
983         struct bp_transmitter_control *cntl)
984 {
985         struct bios_parser *bp = BP_FROM_DCB(dcb);
986
987         if (!bp->cmd_tbl.transmitter_control)
988                 return BP_RESULT_FAILURE;
989
990         return bp->cmd_tbl.transmitter_control(bp, cntl);
991 }
992
993 static enum bp_result bios_parser_encoder_control(
994         struct dc_bios *dcb,
995         struct bp_encoder_control *cntl)
996 {
997         struct bios_parser *bp = BP_FROM_DCB(dcb);
998
999         if (!bp->cmd_tbl.dig_encoder_control)
1000                 return BP_RESULT_FAILURE;
1001
1002         return bp->cmd_tbl.dig_encoder_control(bp, cntl);
1003 }
1004
1005 static enum bp_result bios_parser_adjust_pixel_clock(
1006         struct dc_bios *dcb,
1007         struct bp_adjust_pixel_clock_parameters *bp_params)
1008 {
1009         struct bios_parser *bp = BP_FROM_DCB(dcb);
1010
1011         if (!bp->cmd_tbl.adjust_display_pll)
1012                 return BP_RESULT_FAILURE;
1013
1014         return bp->cmd_tbl.adjust_display_pll(bp, bp_params);
1015 }
1016
1017 static enum bp_result bios_parser_set_pixel_clock(
1018         struct dc_bios *dcb,
1019         struct bp_pixel_clock_parameters *bp_params)
1020 {
1021         struct bios_parser *bp = BP_FROM_DCB(dcb);
1022
1023         if (!bp->cmd_tbl.set_pixel_clock)
1024                 return BP_RESULT_FAILURE;
1025
1026         return bp->cmd_tbl.set_pixel_clock(bp, bp_params);
1027 }
1028
1029 static enum bp_result bios_parser_set_dce_clock(
1030         struct dc_bios *dcb,
1031         struct bp_set_dce_clock_parameters *bp_params)
1032 {
1033         struct bios_parser *bp = BP_FROM_DCB(dcb);
1034
1035         if (!bp->cmd_tbl.set_dce_clock)
1036                 return BP_RESULT_FAILURE;
1037
1038         return bp->cmd_tbl.set_dce_clock(bp, bp_params);
1039 }
1040
1041 static enum bp_result bios_parser_enable_spread_spectrum_on_ppll(
1042         struct dc_bios *dcb,
1043         struct bp_spread_spectrum_parameters *bp_params,
1044         bool enable)
1045 {
1046         struct bios_parser *bp = BP_FROM_DCB(dcb);
1047
1048         if (!bp->cmd_tbl.enable_spread_spectrum_on_ppll)
1049                 return BP_RESULT_FAILURE;
1050
1051         return bp->cmd_tbl.enable_spread_spectrum_on_ppll(
1052                         bp, bp_params, enable);
1053
1054 }
1055
1056 static enum bp_result bios_parser_program_crtc_timing(
1057         struct dc_bios *dcb,
1058         struct bp_hw_crtc_timing_parameters *bp_params)
1059 {
1060         struct bios_parser *bp = BP_FROM_DCB(dcb);
1061
1062         if (!bp->cmd_tbl.set_crtc_timing)
1063                 return BP_RESULT_FAILURE;
1064
1065         return bp->cmd_tbl.set_crtc_timing(bp, bp_params);
1066 }
1067
1068 static enum bp_result bios_parser_program_display_engine_pll(
1069         struct dc_bios *dcb,
1070         struct bp_pixel_clock_parameters *bp_params)
1071 {
1072         struct bios_parser *bp = BP_FROM_DCB(dcb);
1073
1074         if (!bp->cmd_tbl.program_clock)
1075                 return BP_RESULT_FAILURE;
1076
1077         return bp->cmd_tbl.program_clock(bp, bp_params);
1078
1079 }
1080
1081
1082 static enum bp_result bios_parser_enable_crtc(
1083         struct dc_bios *dcb,
1084         enum controller_id id,
1085         bool enable)
1086 {
1087         struct bios_parser *bp = BP_FROM_DCB(dcb);
1088
1089         if (!bp->cmd_tbl.enable_crtc)
1090                 return BP_RESULT_FAILURE;
1091
1092         return bp->cmd_tbl.enable_crtc(bp, id, enable);
1093 }
1094
1095 static enum bp_result bios_parser_crtc_source_select(
1096         struct dc_bios *dcb,
1097         struct bp_crtc_source_select *bp_params)
1098 {
1099         struct bios_parser *bp = BP_FROM_DCB(dcb);
1100
1101         if (!bp->cmd_tbl.select_crtc_source)
1102                 return BP_RESULT_FAILURE;
1103
1104         return bp->cmd_tbl.select_crtc_source(bp, bp_params);
1105 }
1106
1107 static enum bp_result bios_parser_enable_disp_power_gating(
1108         struct dc_bios *dcb,
1109         enum controller_id controller_id,
1110         enum bp_pipe_control_action action)
1111 {
1112         struct bios_parser *bp = BP_FROM_DCB(dcb);
1113
1114         if (!bp->cmd_tbl.enable_disp_power_gating)
1115                 return BP_RESULT_FAILURE;
1116
1117         return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id,
1118                 action);
1119 }
1120
1121 static bool bios_parser_is_device_id_supported(
1122         struct dc_bios *dcb,
1123         struct device_id id)
1124 {
1125         struct bios_parser *bp = BP_FROM_DCB(dcb);
1126
1127         uint32_t mask = get_support_mask_for_device_id(id);
1128
1129         return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0;
1130 }
1131
1132 static enum bp_result bios_parser_crt_control(
1133         struct dc_bios *dcb,
1134         enum engine_id engine_id,
1135         bool enable,
1136         uint32_t pixel_clock)
1137 {
1138         struct bios_parser *bp = BP_FROM_DCB(dcb);
1139         uint8_t standard;
1140
1141         if (!bp->cmd_tbl.dac1_encoder_control &&
1142                 engine_id == ENGINE_ID_DACA)
1143                 return BP_RESULT_FAILURE;
1144         if (!bp->cmd_tbl.dac2_encoder_control &&
1145                 engine_id == ENGINE_ID_DACB)
1146                 return BP_RESULT_FAILURE;
1147         /* validate params */
1148         switch (engine_id) {
1149         case ENGINE_ID_DACA:
1150         case ENGINE_ID_DACB:
1151                 break;
1152         default:
1153                 /* unsupported engine */
1154                 return BP_RESULT_FAILURE;
1155         }
1156
1157         standard = ATOM_DAC1_PS2; /* == ATOM_DAC2_PS2 */
1158
1159         if (enable) {
1160                 if (engine_id == ENGINE_ID_DACA) {
1161                         bp->cmd_tbl.dac1_encoder_control(bp, enable,
1162                                 pixel_clock, standard);
1163                         if (bp->cmd_tbl.dac1_output_control != NULL)
1164                                 bp->cmd_tbl.dac1_output_control(bp, enable);
1165                 } else {
1166                         bp->cmd_tbl.dac2_encoder_control(bp, enable,
1167                                 pixel_clock, standard);
1168                         if (bp->cmd_tbl.dac2_output_control != NULL)
1169                                 bp->cmd_tbl.dac2_output_control(bp, enable);
1170                 }
1171         } else {
1172                 if (engine_id == ENGINE_ID_DACA) {
1173                         if (bp->cmd_tbl.dac1_output_control != NULL)
1174                                 bp->cmd_tbl.dac1_output_control(bp, enable);
1175                         bp->cmd_tbl.dac1_encoder_control(bp, enable,
1176                                 pixel_clock, standard);
1177                 } else {
1178                         if (bp->cmd_tbl.dac2_output_control != NULL)
1179                                 bp->cmd_tbl.dac2_output_control(bp, enable);
1180                         bp->cmd_tbl.dac2_encoder_control(bp, enable,
1181                                 pixel_clock, standard);
1182                 }
1183         }
1184
1185         return BP_RESULT_OK;
1186 }
1187
1188 static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
1189         ATOM_OBJECT *object)
1190 {
1191         ATOM_COMMON_RECORD_HEADER *header;
1192         uint32_t offset;
1193
1194         if (!object) {
1195                 BREAK_TO_DEBUGGER(); /* Invalid object */
1196                 return NULL;
1197         }
1198
1199         offset = le16_to_cpu(object->usRecordOffset)
1200                         + bp->object_info_tbl_offset;
1201
1202         for (;;) {
1203                 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
1204
1205                 if (!header)
1206                         return NULL;
1207
1208                 if (LAST_RECORD_TYPE == header->ucRecordType ||
1209                         !header->ucRecordSize)
1210                         break;
1211
1212                 if (ATOM_HPD_INT_RECORD_TYPE == header->ucRecordType
1213                         && sizeof(ATOM_HPD_INT_RECORD) <= header->ucRecordSize)
1214                         return (ATOM_HPD_INT_RECORD *) header;
1215
1216                 offset += header->ucRecordSize;
1217         }
1218
1219         return NULL;
1220 }
1221
1222 /**
1223  * Get I2C information of input object id
1224  *
1225  * search all records to find the ATOM_I2C_RECORD_TYPE record IR
1226  */
1227 static ATOM_I2C_RECORD *get_i2c_record(
1228         struct bios_parser *bp,
1229         ATOM_OBJECT *object)
1230 {
1231         uint32_t offset;
1232         ATOM_COMMON_RECORD_HEADER *record_header;
1233
1234         if (!object) {
1235                 BREAK_TO_DEBUGGER();
1236                 /* Invalid object */
1237                 return NULL;
1238         }
1239
1240         offset = le16_to_cpu(object->usRecordOffset)
1241                         + bp->object_info_tbl_offset;
1242
1243         for (;;) {
1244                 record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
1245
1246                 if (!record_header)
1247                         return NULL;
1248
1249                 if (LAST_RECORD_TYPE == record_header->ucRecordType ||
1250                         0 == record_header->ucRecordSize)
1251                         break;
1252
1253                 if (ATOM_I2C_RECORD_TYPE == record_header->ucRecordType &&
1254                         sizeof(ATOM_I2C_RECORD) <=
1255                         record_header->ucRecordSize) {
1256                         return (ATOM_I2C_RECORD *)record_header;
1257                 }
1258
1259                 offset += record_header->ucRecordSize;
1260         }
1261
1262         return NULL;
1263 }
1264
1265 static enum bp_result get_ss_info_from_ss_info_table(
1266         struct bios_parser *bp,
1267         uint32_t id,
1268         struct spread_spectrum_info *ss_info);
1269 static enum bp_result get_ss_info_from_tbl(
1270         struct bios_parser *bp,
1271         uint32_t id,
1272         struct spread_spectrum_info *ss_info);
1273 /**
1274  * bios_parser_get_spread_spectrum_info
1275  * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or
1276  * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info
1277  * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info ver 3.1,
1278  * there is only one entry for each signal /ss id.  However, there is
1279  * no planning of supporting multiple spread Sprectum entry for EverGreen
1280  * @param [in] this
1281  * @param [in] signal, ASSignalType to be converted to info index
1282  * @param [in] index, number of entries that match the converted info index
1283  * @param [out] ss_info, sprectrum information structure,
1284  * @return Bios parser result code
1285  */
1286 static enum bp_result bios_parser_get_spread_spectrum_info(
1287         struct dc_bios *dcb,
1288         enum as_signal_type signal,
1289         uint32_t index,
1290         struct spread_spectrum_info *ss_info)
1291 {
1292         struct bios_parser *bp = BP_FROM_DCB(dcb);
1293         enum bp_result result = BP_RESULT_UNSUPPORTED;
1294         uint32_t clk_id_ss = 0;
1295         ATOM_COMMON_TABLE_HEADER *header;
1296         struct atom_data_revision tbl_revision;
1297
1298         if (!ss_info) /* check for bad input */
1299                 return BP_RESULT_BADINPUT;
1300         /* signal translation */
1301         clk_id_ss = signal_to_ss_id(signal);
1302
1303         if (!DATA_TABLES(ASIC_InternalSS_Info))
1304                 if (!index)
1305                         return get_ss_info_from_ss_info_table(bp, clk_id_ss,
1306                                 ss_info);
1307
1308         header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
1309                 DATA_TABLES(ASIC_InternalSS_Info));
1310         get_atom_data_table_revision(header, &tbl_revision);
1311
1312         switch (tbl_revision.major) {
1313         case 2:
1314                 switch (tbl_revision.minor) {
1315                 case 1:
1316                         /* there can not be more then one entry for Internal
1317                          * SS Info table version 2.1 */
1318                         if (!index)
1319                                 return get_ss_info_from_tbl(bp, clk_id_ss,
1320                                                 ss_info);
1321                         break;
1322                 default:
1323                         break;
1324                 }
1325                 break;
1326
1327         case 3:
1328                 switch (tbl_revision.minor) {
1329                 case 1:
1330                         return get_ss_info_v3_1(bp, clk_id_ss, index, ss_info);
1331                 default:
1332                         break;
1333                 }
1334                 break;
1335         default:
1336                 break;
1337         }
1338         /* there can not be more then one entry for SS Info table */
1339         return result;
1340 }
1341
1342 static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
1343         struct bios_parser *bp,
1344         uint32_t id,
1345         struct spread_spectrum_info *info);
1346
1347 /**
1348  * get_ss_info_from_table
1349  * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
1350  * SS_Info table from the VBIOS
1351  * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or
1352  * SS_Info.
1353  *
1354  * @param this
1355  * @param id, spread sprectrum info index
1356  * @param pSSinfo, sprectrum information structure,
1357  * @return Bios parser result code
1358  */
1359 static enum bp_result get_ss_info_from_tbl(
1360         struct bios_parser *bp,
1361         uint32_t id,
1362         struct spread_spectrum_info *ss_info)
1363 {
1364         if (!ss_info) /* check for bad input, if ss_info is not NULL */
1365                 return BP_RESULT_BADINPUT;
1366         /* for SS_Info table only support DP and LVDS */
1367         if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
1368                 return get_ss_info_from_ss_info_table(bp, id, ss_info);
1369         else
1370                 return get_ss_info_from_internal_ss_info_tbl_V2_1(bp, id,
1371                         ss_info);
1372 }
1373
1374 /**
1375  * get_ss_info_from_internal_ss_info_tbl_V2_1
1376  * Get spread sprectrum information from the ASIC_InternalSS_Info table Ver 2.1
1377  * from the VBIOS
1378  * There will not be multiple entry for Ver 2.1
1379  *
1380  * @param id, spread sprectrum info index
1381  * @param pSSinfo, sprectrum information structure,
1382  * @return Bios parser result code
1383  */
1384 static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
1385         struct bios_parser *bp,
1386         uint32_t id,
1387         struct spread_spectrum_info *info)
1388 {
1389         enum bp_result result = BP_RESULT_UNSUPPORTED;
1390         ATOM_ASIC_INTERNAL_SS_INFO_V2 *header;
1391         ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
1392         uint32_t tbl_size, i;
1393
1394         if (!DATA_TABLES(ASIC_InternalSS_Info))
1395                 return result;
1396
1397         header = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
1398                 DATA_TABLES(ASIC_InternalSS_Info));
1399
1400         memset(info, 0, sizeof(struct spread_spectrum_info));
1401
1402         tbl_size = (le16_to_cpu(header->sHeader.usStructureSize)
1403                         - sizeof(ATOM_COMMON_TABLE_HEADER))
1404                                         / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
1405
1406         tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
1407                                         &(header->asSpreadSpectrum[0]);
1408         for (i = 0; i < tbl_size; i++) {
1409                 result = BP_RESULT_NORECORD;
1410
1411                 if (tbl[i].ucClockIndication != (uint8_t)id)
1412                         continue;
1413
1414                 if (ATOM_EXTERNAL_SS_MASK
1415                         & tbl[i].ucSpreadSpectrumMode) {
1416                         info->type.EXTERNAL = true;
1417                 }
1418                 if (ATOM_SS_CENTRE_SPREAD_MODE_MASK
1419                         & tbl[i].ucSpreadSpectrumMode) {
1420                         info->type.CENTER_MODE = true;
1421                 }
1422                 info->type.STEP_AND_DELAY_INFO = false;
1423                 /* convert [10KHz] into [KHz] */
1424                 info->target_clock_range =
1425                         le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
1426                 info->spread_spectrum_percentage =
1427                         (uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
1428                 info->spread_spectrum_range =
1429                         (uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
1430                 result = BP_RESULT_OK;
1431                 break;
1432         }
1433
1434         return result;
1435
1436 }
1437
1438 /**
1439  * get_ss_info_from_ss_info_table
1440  * Get spread sprectrum information from the SS_Info table from the VBIOS
1441  * if the pointer to info is NULL, indicate the caller what to know the number
1442  * of entries that matches the id
1443  * for, the SS_Info table, there should not be more than 1 entry match.
1444  *
1445  * @param [in] id, spread sprectrum id
1446  * @param [out] pSSinfo, sprectrum information structure,
1447  * @return Bios parser result code
1448  */
1449 static enum bp_result get_ss_info_from_ss_info_table(
1450         struct bios_parser *bp,
1451         uint32_t id,
1452         struct spread_spectrum_info *ss_info)
1453 {
1454         enum bp_result result = BP_RESULT_UNSUPPORTED;
1455         ATOM_SPREAD_SPECTRUM_INFO *tbl;
1456         ATOM_COMMON_TABLE_HEADER *header;
1457         uint32_t table_size;
1458         uint32_t i;
1459         uint32_t id_local = SS_ID_UNKNOWN;
1460         struct atom_data_revision revision;
1461
1462         /* exist of the SS_Info table */
1463         /* check for bad input, pSSinfo can not be NULL */
1464         if (!DATA_TABLES(SS_Info) || !ss_info)
1465                 return result;
1466
1467         header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(SS_Info));
1468         get_atom_data_table_revision(header, &revision);
1469
1470         tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, DATA_TABLES(SS_Info));
1471
1472         if (1 != revision.major || 2 > revision.minor)
1473                 return result;
1474
1475         /* have to convert from Internal_SS format to SS_Info format */
1476         switch (id) {
1477         case ASIC_INTERNAL_SS_ON_DP:
1478                 id_local = SS_ID_DP1;
1479                 break;
1480         case ASIC_INTERNAL_SS_ON_LVDS:
1481         {
1482                 struct embedded_panel_info panel_info;
1483
1484                 if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
1485                                 == BP_RESULT_OK)
1486                         id_local = panel_info.ss_id;
1487                 break;
1488         }
1489         default:
1490                 break;
1491         }
1492
1493         if (id_local == SS_ID_UNKNOWN)
1494                 return result;
1495
1496         table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
1497                         sizeof(ATOM_COMMON_TABLE_HEADER)) /
1498                                         sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
1499
1500         for (i = 0; i < table_size; i++) {
1501                 if (id_local != (uint32_t)tbl->asSS_Info[i].ucSS_Id)
1502                         continue;
1503
1504                 memset(ss_info, 0, sizeof(struct spread_spectrum_info));
1505
1506                 if (ATOM_EXTERNAL_SS_MASK &
1507                                 tbl->asSS_Info[i].ucSpreadSpectrumType)
1508                         ss_info->type.EXTERNAL = true;
1509
1510                 if (ATOM_SS_CENTRE_SPREAD_MODE_MASK &
1511                                 tbl->asSS_Info[i].ucSpreadSpectrumType)
1512                         ss_info->type.CENTER_MODE = true;
1513
1514                 ss_info->type.STEP_AND_DELAY_INFO = true;
1515                 ss_info->spread_spectrum_percentage =
1516                         (uint32_t)le16_to_cpu(tbl->asSS_Info[i].usSpreadSpectrumPercentage);
1517                 ss_info->step_and_delay_info.step = tbl->asSS_Info[i].ucSS_Step;
1518                 ss_info->step_and_delay_info.delay =
1519                         tbl->asSS_Info[i].ucSS_Delay;
1520                 ss_info->step_and_delay_info.recommended_ref_div =
1521                         tbl->asSS_Info[i].ucRecommendedRef_Div;
1522                 ss_info->spread_spectrum_range =
1523                         (uint32_t)tbl->asSS_Info[i].ucSS_Range * 10000;
1524
1525                 /* there will be only one entry for each display type in SS_info
1526                  * table */
1527                 result = BP_RESULT_OK;
1528                 break;
1529         }
1530
1531         return result;
1532 }
1533 static enum bp_result get_embedded_panel_info_v1_2(
1534         struct bios_parser *bp,
1535         struct embedded_panel_info *info);
1536 static enum bp_result get_embedded_panel_info_v1_3(
1537         struct bios_parser *bp,
1538         struct embedded_panel_info *info);
1539
1540 static enum bp_result bios_parser_get_embedded_panel_info(
1541         struct dc_bios *dcb,
1542         struct embedded_panel_info *info)
1543 {
1544         struct bios_parser *bp = BP_FROM_DCB(dcb);
1545         ATOM_COMMON_TABLE_HEADER *hdr;
1546
1547         if (!DATA_TABLES(LCD_Info))
1548                 return BP_RESULT_FAILURE;
1549
1550         hdr = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(LCD_Info));
1551
1552         if (!hdr)
1553                 return BP_RESULT_BADBIOSTABLE;
1554
1555         switch (hdr->ucTableFormatRevision) {
1556         case 1:
1557                 switch (hdr->ucTableContentRevision) {
1558                 case 0:
1559                 case 1:
1560                 case 2:
1561                         return get_embedded_panel_info_v1_2(bp, info);
1562                 case 3:
1563                         return get_embedded_panel_info_v1_3(bp, info);
1564                 default:
1565                         break;
1566                 }
1567         default:
1568                 break;
1569         }
1570
1571         return BP_RESULT_FAILURE;
1572 }
1573
1574 static enum bp_result get_embedded_panel_info_v1_2(
1575         struct bios_parser *bp,
1576         struct embedded_panel_info *info)
1577 {
1578         ATOM_LVDS_INFO_V12 *lvds;
1579
1580         if (!info)
1581                 return BP_RESULT_BADINPUT;
1582
1583         if (!DATA_TABLES(LVDS_Info))
1584                 return BP_RESULT_UNSUPPORTED;
1585
1586         lvds =
1587                 GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info));
1588
1589         if (!lvds)
1590                 return BP_RESULT_BADBIOSTABLE;
1591
1592         if (1 != lvds->sHeader.ucTableFormatRevision
1593                 || 2 > lvds->sHeader.ucTableContentRevision)
1594                 return BP_RESULT_UNSUPPORTED;
1595
1596         memset(info, 0, sizeof(struct embedded_panel_info));
1597
1598         /* We need to convert from 10KHz units into KHz units*/
1599         info->lcd_timing.pixel_clk =
1600                 le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
1601         /* usHActive does not include borders, according to VBIOS team*/
1602         info->lcd_timing.horizontal_addressable =
1603                 le16_to_cpu(lvds->sLCDTiming.usHActive);
1604         /* usHBlanking_Time includes borders, so we should really be subtracting
1605          * borders duing this translation, but LVDS generally*/
1606         /* doesn't have borders, so we should be okay leaving this as is for
1607          * now.  May need to revisit if we ever have LVDS with borders*/
1608         info->lcd_timing.horizontal_blanking_time =
1609                         le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
1610         /* usVActive does not include borders, according to VBIOS team*/
1611         info->lcd_timing.vertical_addressable =
1612                         le16_to_cpu(lvds->sLCDTiming.usVActive);
1613         /* usVBlanking_Time includes borders, so we should really be subtracting
1614          * borders duing this translation, but LVDS generally*/
1615         /* doesn't have borders, so we should be okay leaving this as is for
1616          * now. May need to revisit if we ever have LVDS with borders*/
1617         info->lcd_timing.vertical_blanking_time =
1618                 le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
1619         info->lcd_timing.horizontal_sync_offset =
1620                 le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
1621         info->lcd_timing.horizontal_sync_width =
1622                 le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
1623         info->lcd_timing.vertical_sync_offset =
1624                 le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
1625         info->lcd_timing.vertical_sync_width =
1626                 le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
1627         info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
1628         info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
1629         info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
1630                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
1631         info->lcd_timing.misc_info.H_SYNC_POLARITY =
1632                 ~(uint32_t)
1633                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
1634         info->lcd_timing.misc_info.V_SYNC_POLARITY =
1635                 ~(uint32_t)
1636                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
1637         info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
1638                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
1639         info->lcd_timing.misc_info.H_REPLICATION_BY2 =
1640                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
1641         info->lcd_timing.misc_info.V_REPLICATION_BY2 =
1642                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
1643         info->lcd_timing.misc_info.COMPOSITE_SYNC =
1644                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
1645         info->lcd_timing.misc_info.INTERLACE =
1646                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
1647         info->lcd_timing.misc_info.DOUBLE_CLOCK =
1648                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
1649         info->ss_id = lvds->ucSS_Id;
1650
1651         {
1652                 uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate);
1653                 /* Get minimum supported refresh rate*/
1654                 if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
1655                         info->supported_rr.REFRESH_RATE_30HZ = 1;
1656                 else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
1657                         info->supported_rr.REFRESH_RATE_40HZ = 1;
1658                 else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
1659                         info->supported_rr.REFRESH_RATE_48HZ = 1;
1660                 else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
1661                         info->supported_rr.REFRESH_RATE_50HZ = 1;
1662                 else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
1663                         info->supported_rr.REFRESH_RATE_60HZ = 1;
1664         }
1665
1666         /*Drr panel support can be reported by VBIOS*/
1667         if (LCDPANEL_CAP_DRR_SUPPORTED
1668                         & lvds->ucLCDPanel_SpecialHandlingCap)
1669                 info->drr_enabled = 1;
1670
1671         if (ATOM_PANEL_MISC_DUAL & lvds->ucLVDS_Misc)
1672                 info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
1673
1674         if (ATOM_PANEL_MISC_888RGB & lvds->ucLVDS_Misc)
1675                 info->lcd_timing.misc_info.RGB888 = true;
1676
1677         info->lcd_timing.misc_info.GREY_LEVEL =
1678                 (uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL &
1679                         lvds->ucLVDS_Misc) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT;
1680
1681         if (ATOM_PANEL_MISC_SPATIAL & lvds->ucLVDS_Misc)
1682                 info->lcd_timing.misc_info.SPATIAL = true;
1683
1684         if (ATOM_PANEL_MISC_TEMPORAL & lvds->ucLVDS_Misc)
1685                 info->lcd_timing.misc_info.TEMPORAL = true;
1686
1687         if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc)
1688                 info->lcd_timing.misc_info.API_ENABLED = true;
1689
1690         return BP_RESULT_OK;
1691 }
1692
1693 static enum bp_result get_embedded_panel_info_v1_3(
1694         struct bios_parser *bp,
1695         struct embedded_panel_info *info)
1696 {
1697         ATOM_LCD_INFO_V13 *lvds;
1698
1699         if (!info)
1700                 return BP_RESULT_BADINPUT;
1701
1702         if (!DATA_TABLES(LCD_Info))
1703                 return BP_RESULT_UNSUPPORTED;
1704
1705         lvds = GET_IMAGE(ATOM_LCD_INFO_V13, DATA_TABLES(LCD_Info));
1706
1707         if (!lvds)
1708                 return BP_RESULT_BADBIOSTABLE;
1709
1710         if (!((1 == lvds->sHeader.ucTableFormatRevision)
1711                         && (3 <= lvds->sHeader.ucTableContentRevision)))
1712                 return BP_RESULT_UNSUPPORTED;
1713
1714         memset(info, 0, sizeof(struct embedded_panel_info));
1715
1716         /* We need to convert from 10KHz units into KHz units */
1717         info->lcd_timing.pixel_clk =
1718                         le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
1719         /* usHActive does not include borders, according to VBIOS team */
1720         info->lcd_timing.horizontal_addressable =
1721                         le16_to_cpu(lvds->sLCDTiming.usHActive);
1722         /* usHBlanking_Time includes borders, so we should really be subtracting
1723          * borders duing this translation, but LVDS generally*/
1724         /* doesn't have borders, so we should be okay leaving this as is for
1725          * now.  May need to revisit if we ever have LVDS with borders*/
1726         info->lcd_timing.horizontal_blanking_time =
1727                 le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
1728         /* usVActive does not include borders, according to VBIOS team*/
1729         info->lcd_timing.vertical_addressable =
1730                 le16_to_cpu(lvds->sLCDTiming.usVActive);
1731         /* usVBlanking_Time includes borders, so we should really be subtracting
1732          * borders duing this translation, but LVDS generally*/
1733         /* doesn't have borders, so we should be okay leaving this as is for
1734          * now. May need to revisit if we ever have LVDS with borders*/
1735         info->lcd_timing.vertical_blanking_time =
1736                 le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
1737         info->lcd_timing.horizontal_sync_offset =
1738                 le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
1739         info->lcd_timing.horizontal_sync_width =
1740                 le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
1741         info->lcd_timing.vertical_sync_offset =
1742                 le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
1743         info->lcd_timing.vertical_sync_width =
1744                 le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
1745         info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
1746         info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
1747         info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
1748                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
1749         info->lcd_timing.misc_info.H_SYNC_POLARITY =
1750                 ~(uint32_t)
1751                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
1752         info->lcd_timing.misc_info.V_SYNC_POLARITY =
1753                 ~(uint32_t)
1754                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
1755         info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
1756                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
1757         info->lcd_timing.misc_info.H_REPLICATION_BY2 =
1758                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
1759         info->lcd_timing.misc_info.V_REPLICATION_BY2 =
1760                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
1761         info->lcd_timing.misc_info.COMPOSITE_SYNC =
1762                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
1763         info->lcd_timing.misc_info.INTERLACE =
1764                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
1765         info->lcd_timing.misc_info.DOUBLE_CLOCK =
1766                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
1767         info->ss_id = lvds->ucSS_Id;
1768
1769         /* Drr panel support can be reported by VBIOS*/
1770         if (LCDPANEL_CAP_V13_DRR_SUPPORTED
1771                         & lvds->ucLCDPanel_SpecialHandlingCap)
1772                 info->drr_enabled = 1;
1773
1774         /* Get supported refresh rate*/
1775         if (info->drr_enabled == 1) {
1776                 uint8_t min_rr =
1777                                 lvds->sRefreshRateSupport.ucMinRefreshRateForDRR;
1778                 uint8_t rr = lvds->sRefreshRateSupport.ucSupportedRefreshRate;
1779
1780                 if (min_rr != 0) {
1781                         if (SUPPORTED_LCD_REFRESHRATE_30Hz & min_rr)
1782                                 info->supported_rr.REFRESH_RATE_30HZ = 1;
1783                         else if (SUPPORTED_LCD_REFRESHRATE_40Hz & min_rr)
1784                                 info->supported_rr.REFRESH_RATE_40HZ = 1;
1785                         else if (SUPPORTED_LCD_REFRESHRATE_48Hz & min_rr)
1786                                 info->supported_rr.REFRESH_RATE_48HZ = 1;
1787                         else if (SUPPORTED_LCD_REFRESHRATE_50Hz & min_rr)
1788                                 info->supported_rr.REFRESH_RATE_50HZ = 1;
1789                         else if (SUPPORTED_LCD_REFRESHRATE_60Hz & min_rr)
1790                                 info->supported_rr.REFRESH_RATE_60HZ = 1;
1791                 } else {
1792                         if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
1793                                 info->supported_rr.REFRESH_RATE_30HZ = 1;
1794                         else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
1795                                 info->supported_rr.REFRESH_RATE_40HZ = 1;
1796                         else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
1797                                 info->supported_rr.REFRESH_RATE_48HZ = 1;
1798                         else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
1799                                 info->supported_rr.REFRESH_RATE_50HZ = 1;
1800                         else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
1801                                 info->supported_rr.REFRESH_RATE_60HZ = 1;
1802                 }
1803         }
1804
1805         if (ATOM_PANEL_MISC_V13_DUAL & lvds->ucLCD_Misc)
1806                 info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
1807
1808         if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR & lvds->ucLCD_Misc)
1809                 info->lcd_timing.misc_info.RGB888 = true;
1810
1811         info->lcd_timing.misc_info.GREY_LEVEL =
1812                         (uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL &
1813                                 lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT;
1814
1815         return BP_RESULT_OK;
1816 }
1817
1818 /**
1819  * bios_parser_get_encoder_cap_info
1820  *
1821  * @brief
1822  *  Get encoder capability information of input object id
1823  *
1824  * @param object_id, Object id
1825  * @param object_id, encoder cap information structure
1826  *
1827  * @return Bios parser result code
1828  *
1829  */
1830 static enum bp_result bios_parser_get_encoder_cap_info(
1831         struct dc_bios *dcb,
1832         struct graphics_object_id object_id,
1833         struct bp_encoder_cap_info *info)
1834 {
1835         struct bios_parser *bp = BP_FROM_DCB(dcb);
1836         ATOM_OBJECT *object;
1837         ATOM_ENCODER_CAP_RECORD_V2 *record = NULL;
1838
1839         if (!info)
1840                 return BP_RESULT_BADINPUT;
1841
1842         object = get_bios_object(bp, object_id);
1843
1844         if (!object)
1845                 return BP_RESULT_BADINPUT;
1846
1847         record = get_encoder_cap_record(bp, object);
1848         if (!record)
1849                 return BP_RESULT_NORECORD;
1850
1851         info->DP_HBR2_EN = record->usHBR2En;
1852         info->DP_HBR3_EN = record->usHBR3En;
1853         info->HDMI_6GB_EN = record->usHDMI6GEn;
1854         return BP_RESULT_OK;
1855 }
1856
1857 /**
1858  * get_encoder_cap_record
1859  *
1860  * @brief
1861  *  Get encoder cap record for the object
1862  *
1863  * @param object, ATOM object
1864  *
1865  * @return atom encoder cap record
1866  *
1867  * @note
1868  *  search all records to find the ATOM_ENCODER_CAP_RECORD_V2 record
1869  */
1870 static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
1871         struct bios_parser *bp,
1872         ATOM_OBJECT *object)
1873 {
1874         ATOM_COMMON_RECORD_HEADER *header;
1875         uint32_t offset;
1876
1877         if (!object) {
1878                 BREAK_TO_DEBUGGER(); /* Invalid object */
1879                 return NULL;
1880         }
1881
1882         offset = le16_to_cpu(object->usRecordOffset)
1883                                         + bp->object_info_tbl_offset;
1884
1885         for (;;) {
1886                 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
1887
1888                 if (!header)
1889                         return NULL;
1890
1891                 offset += header->ucRecordSize;
1892
1893                 if (LAST_RECORD_TYPE == header->ucRecordType ||
1894                                 !header->ucRecordSize)
1895                         break;
1896
1897                 if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType)
1898                         continue;
1899
1900                 if (sizeof(ATOM_ENCODER_CAP_RECORD_V2) <= header->ucRecordSize)
1901                         return (ATOM_ENCODER_CAP_RECORD_V2 *)header;
1902         }
1903
1904         return NULL;
1905 }
1906
1907 static uint32_t get_ss_entry_number(
1908         struct bios_parser *bp,
1909         uint32_t id);
1910 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
1911         struct bios_parser *bp,
1912         uint32_t id);
1913 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1914         struct bios_parser *bp,
1915         uint32_t id);
1916 static uint32_t get_ss_entry_number_from_ss_info_tbl(
1917         struct bios_parser *bp,
1918         uint32_t id);
1919
1920 /**
1921  * BiosParserObject::GetNumberofSpreadSpectrumEntry
1922  * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from
1923  * the VBIOS that match the SSid (to be converted from signal)
1924  *
1925  * @param[in] signal, ASSignalType to be converted to SSid
1926  * @return number of SS Entry that match the signal
1927  */
1928 static uint32_t bios_parser_get_ss_entry_number(
1929         struct dc_bios *dcb,
1930         enum as_signal_type signal)
1931 {
1932         struct bios_parser *bp = BP_FROM_DCB(dcb);
1933         uint32_t ss_id = 0;
1934         ATOM_COMMON_TABLE_HEADER *header;
1935         struct atom_data_revision revision;
1936
1937         ss_id = signal_to_ss_id(signal);
1938
1939         if (!DATA_TABLES(ASIC_InternalSS_Info))
1940                 return get_ss_entry_number_from_ss_info_tbl(bp, ss_id);
1941
1942         header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
1943                         DATA_TABLES(ASIC_InternalSS_Info));
1944         get_atom_data_table_revision(header, &revision);
1945
1946         switch (revision.major) {
1947         case 2:
1948                 switch (revision.minor) {
1949                 case 1:
1950                         return get_ss_entry_number(bp, ss_id);
1951                 default:
1952                         break;
1953                 }
1954                 break;
1955         case 3:
1956                 switch (revision.minor) {
1957                 case 1:
1958                         return
1959                                 get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1960                                                 bp, ss_id);
1961                 default:
1962                         break;
1963                 }
1964                 break;
1965         default:
1966                 break;
1967         }
1968
1969         return 0;
1970 }
1971
1972 /**
1973  * get_ss_entry_number_from_ss_info_tbl
1974  * Get Number of spread spectrum entry from the SS_Info table from the VBIOS.
1975  *
1976  * @note There can only be one entry for each id for SS_Info Table
1977  *
1978  * @param [in] id, spread spectrum id
1979  * @return number of SS Entry that match the id
1980  */
1981 static uint32_t get_ss_entry_number_from_ss_info_tbl(
1982         struct bios_parser *bp,
1983         uint32_t id)
1984 {
1985         ATOM_SPREAD_SPECTRUM_INFO *tbl;
1986         ATOM_COMMON_TABLE_HEADER *header;
1987         uint32_t table_size;
1988         uint32_t i;
1989         uint32_t number = 0;
1990         uint32_t id_local = SS_ID_UNKNOWN;
1991         struct atom_data_revision revision;
1992
1993         /* SS_Info table exist */
1994         if (!DATA_TABLES(SS_Info))
1995                 return number;
1996
1997         header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
1998                         DATA_TABLES(SS_Info));
1999         get_atom_data_table_revision(header, &revision);
2000
2001         tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO,
2002                         DATA_TABLES(SS_Info));
2003
2004         if (1 != revision.major || 2 > revision.minor)
2005                 return number;
2006
2007         /* have to convert from Internal_SS format to SS_Info format */
2008         switch (id) {
2009         case ASIC_INTERNAL_SS_ON_DP:
2010                 id_local = SS_ID_DP1;
2011                 break;
2012         case ASIC_INTERNAL_SS_ON_LVDS: {
2013                 struct embedded_panel_info panel_info;
2014
2015                 if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
2016                                 == BP_RESULT_OK)
2017                         id_local = panel_info.ss_id;
2018                 break;
2019         }
2020         default:
2021                 break;
2022         }
2023
2024         if (id_local == SS_ID_UNKNOWN)
2025                 return number;
2026
2027         table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
2028                         sizeof(ATOM_COMMON_TABLE_HEADER)) /
2029                                         sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
2030
2031         for (i = 0; i < table_size; i++)
2032                 if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) {
2033                         number = 1;
2034                         break;
2035                 }
2036
2037         return number;
2038 }
2039
2040 /**
2041  * get_ss_entry_number
2042  * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
2043  * SS_Info table from the VBIOS
2044  * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or
2045  * SS_Info.
2046  *
2047  * @param id, spread sprectrum info index
2048  * @return Bios parser result code
2049  */
2050 static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id)
2051 {
2052         if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
2053                 return get_ss_entry_number_from_ss_info_tbl(bp, id);
2054
2055         return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id);
2056 }
2057
2058 /**
2059  * get_ss_entry_number_from_internal_ss_info_tbl_v2_1
2060  * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table
2061  * Ver 2.1 from the VBIOS
2062  * There will not be multiple entry for Ver 2.1
2063  *
2064  * @param id, spread sprectrum info index
2065  * @return number of SS Entry that match the id
2066  */
2067 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
2068         struct bios_parser *bp,
2069         uint32_t id)
2070 {
2071         ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include;
2072         ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
2073         uint32_t size;
2074         uint32_t i;
2075
2076         if (!DATA_TABLES(ASIC_InternalSS_Info))
2077                 return 0;
2078
2079         header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
2080                         DATA_TABLES(ASIC_InternalSS_Info));
2081
2082         size = (le16_to_cpu(header_include->sHeader.usStructureSize)
2083                         - sizeof(ATOM_COMMON_TABLE_HEADER))
2084                                                 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
2085
2086         tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
2087                                 &header_include->asSpreadSpectrum[0];
2088         for (i = 0; i < size; i++)
2089                 if (tbl[i].ucClockIndication == (uint8_t)id)
2090                         return 1;
2091
2092         return 0;
2093 }
2094 /**
2095  * get_ss_entry_number_from_internal_ss_info_table_V3_1
2096  * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of
2097  * the VBIOS that matches id
2098  *
2099  * @param[in]  id, spread sprectrum id
2100  * @return number of SS Entry that match the id
2101  */
2102 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
2103         struct bios_parser *bp,
2104         uint32_t id)
2105 {
2106         uint32_t number = 0;
2107         ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include;
2108         ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
2109         uint32_t size;
2110         uint32_t i;
2111
2112         if (!DATA_TABLES(ASIC_InternalSS_Info))
2113                 return number;
2114
2115         header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
2116                         DATA_TABLES(ASIC_InternalSS_Info));
2117         size = (le16_to_cpu(header_include->sHeader.usStructureSize) -
2118                         sizeof(ATOM_COMMON_TABLE_HEADER)) /
2119                                         sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
2120
2121         tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
2122                                 &header_include->asSpreadSpectrum[0];
2123
2124         for (i = 0; i < size; i++)
2125                 if (tbl[i].ucClockIndication == (uint8_t)id)
2126                         number++;
2127
2128         return number;
2129 }
2130
2131 /**
2132  * bios_parser_get_gpio_pin_info
2133  * Get GpioPin information of input gpio id
2134  *
2135  * @param gpio_id, GPIO ID
2136  * @param info, GpioPin information structure
2137  * @return Bios parser result code
2138  * @note
2139  *  to get the GPIO PIN INFO, we need:
2140  *  1. get the GPIO_ID from other object table, see GetHPDInfo()
2141  *  2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA
2142  *  offset/mask
2143  */
2144 static enum bp_result bios_parser_get_gpio_pin_info(
2145         struct dc_bios *dcb,
2146         uint32_t gpio_id,
2147         struct gpio_pin_info *info)
2148 {
2149         struct bios_parser *bp = BP_FROM_DCB(dcb);
2150         ATOM_GPIO_PIN_LUT *header;
2151         uint32_t count = 0;
2152         uint32_t i = 0;
2153
2154         if (!DATA_TABLES(GPIO_Pin_LUT))
2155                 return BP_RESULT_BADBIOSTABLE;
2156
2157         header = GET_IMAGE(ATOM_GPIO_PIN_LUT, DATA_TABLES(GPIO_Pin_LUT));
2158         if (!header)
2159                 return BP_RESULT_BADBIOSTABLE;
2160
2161         if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_PIN_LUT)
2162                         > le16_to_cpu(header->sHeader.usStructureSize))
2163                 return BP_RESULT_BADBIOSTABLE;
2164
2165         if (1 != header->sHeader.ucTableContentRevision)
2166                 return BP_RESULT_UNSUPPORTED;
2167
2168         count = (le16_to_cpu(header->sHeader.usStructureSize)
2169                         - sizeof(ATOM_COMMON_TABLE_HEADER))
2170                                 / sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
2171         for (i = 0; i < count; ++i) {
2172                 if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id)
2173                         continue;
2174
2175                 info->offset =
2176                         (uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex);
2177                 info->offset_y = info->offset + 2;
2178                 info->offset_en = info->offset + 1;
2179                 info->offset_mask = info->offset - 1;
2180
2181                 info->mask = (uint32_t) (1 <<
2182                         header->asGPIO_Pin[i].ucGpioPinBitShift);
2183                 info->mask_y = info->mask + 2;
2184                 info->mask_en = info->mask + 1;
2185                 info->mask_mask = info->mask - 1;
2186
2187                 return BP_RESULT_OK;
2188         }
2189
2190         return BP_RESULT_NORECORD;
2191 }
2192
2193 static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
2194         ATOM_I2C_RECORD *record,
2195         struct graphics_object_i2c_info *info)
2196 {
2197         ATOM_GPIO_I2C_INFO *header;
2198         uint32_t count = 0;
2199
2200         if (!info)
2201                 return BP_RESULT_BADINPUT;
2202
2203         /* get the GPIO_I2C info */
2204         if (!DATA_TABLES(GPIO_I2C_Info))
2205                 return BP_RESULT_BADBIOSTABLE;
2206
2207         header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info));
2208         if (!header)
2209                 return BP_RESULT_BADBIOSTABLE;
2210
2211         if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT)
2212                         > le16_to_cpu(header->sHeader.usStructureSize))
2213                 return BP_RESULT_BADBIOSTABLE;
2214
2215         if (1 != header->sHeader.ucTableContentRevision)
2216                 return BP_RESULT_UNSUPPORTED;
2217
2218         /* get data count */
2219         count = (le16_to_cpu(header->sHeader.usStructureSize)
2220                         - sizeof(ATOM_COMMON_TABLE_HEADER))
2221                                 / sizeof(ATOM_GPIO_I2C_ASSIGMENT);
2222         if (count < record->sucI2cId.bfI2C_LineMux)
2223                 return BP_RESULT_BADBIOSTABLE;
2224
2225         /* get the GPIO_I2C_INFO */
2226         info->i2c_hw_assist = record->sucI2cId.bfHW_Capable;
2227         info->i2c_line = record->sucI2cId.bfI2C_LineMux;
2228         info->i2c_engine_id = record->sucI2cId.bfHW_EngineID;
2229         info->i2c_slave_address = record->ucI2CAddr;
2230
2231         info->gpio_info.clk_mask_register_index =
2232                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex);
2233         info->gpio_info.clk_en_register_index =
2234                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex);
2235         info->gpio_info.clk_y_register_index =
2236                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex);
2237         info->gpio_info.clk_a_register_index =
2238                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex);
2239         info->gpio_info.data_mask_register_index =
2240                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex);
2241         info->gpio_info.data_en_register_index =
2242                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex);
2243         info->gpio_info.data_y_register_index =
2244                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex);
2245         info->gpio_info.data_a_register_index =
2246                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex);
2247
2248         info->gpio_info.clk_mask_shift =
2249                         header->asGPIO_Info[info->i2c_line].ucClkMaskShift;
2250         info->gpio_info.clk_en_shift =
2251                         header->asGPIO_Info[info->i2c_line].ucClkEnShift;
2252         info->gpio_info.clk_y_shift =
2253                         header->asGPIO_Info[info->i2c_line].ucClkY_Shift;
2254         info->gpio_info.clk_a_shift =
2255                         header->asGPIO_Info[info->i2c_line].ucClkA_Shift;
2256         info->gpio_info.data_mask_shift =
2257                         header->asGPIO_Info[info->i2c_line].ucDataMaskShift;
2258         info->gpio_info.data_en_shift =
2259                         header->asGPIO_Info[info->i2c_line].ucDataEnShift;
2260         info->gpio_info.data_y_shift =
2261                         header->asGPIO_Info[info->i2c_line].ucDataY_Shift;
2262         info->gpio_info.data_a_shift =
2263                         header->asGPIO_Info[info->i2c_line].ucDataA_Shift;
2264
2265         return BP_RESULT_OK;
2266 }
2267
2268 static bool dal_graphics_object_id_is_valid(struct graphics_object_id id)
2269 {
2270         bool rc = true;
2271
2272         switch (id.type) {
2273         case OBJECT_TYPE_UNKNOWN:
2274                 rc = false;
2275                 break;
2276         case OBJECT_TYPE_GPU:
2277         case OBJECT_TYPE_ENGINE:
2278                 /* do NOT check for id.id == 0 */
2279                 if (id.enum_id == ENUM_ID_UNKNOWN)
2280                         rc = false;
2281                 break;
2282         default:
2283                 if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN)
2284                         rc = false;
2285                 break;
2286         }
2287
2288         return rc;
2289 }
2290
2291 static bool dal_graphics_object_id_is_equal(
2292         struct graphics_object_id id1,
2293         struct graphics_object_id id2)
2294 {
2295         if (false == dal_graphics_object_id_is_valid(id1)) {
2296                 dm_output_to_console(
2297                 "%s: Warning: comparing invalid object 'id1'!\n", __func__);
2298                 return false;
2299         }
2300
2301         if (false == dal_graphics_object_id_is_valid(id2)) {
2302                 dm_output_to_console(
2303                 "%s: Warning: comparing invalid object 'id2'!\n", __func__);
2304                 return false;
2305         }
2306
2307         if (id1.id == id2.id && id1.enum_id == id2.enum_id
2308                 && id1.type == id2.type)
2309                 return true;
2310
2311         return false;
2312 }
2313
2314 static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
2315         struct graphics_object_id id)
2316 {
2317         uint32_t offset;
2318         ATOM_OBJECT_TABLE *tbl;
2319         uint32_t i;
2320
2321         switch (id.type) {
2322         case OBJECT_TYPE_ENCODER:
2323                 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
2324                 break;
2325
2326         case OBJECT_TYPE_CONNECTOR:
2327                 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
2328                 break;
2329
2330         case OBJECT_TYPE_ROUTER:
2331                 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset);
2332                 break;
2333
2334         case OBJECT_TYPE_GENERIC:
2335                 if (bp->object_info_tbl.revision.minor < 3)
2336                         return NULL;
2337                 offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset);
2338                 break;
2339
2340         default:
2341                 return NULL;
2342         }
2343
2344         offset += bp->object_info_tbl_offset;
2345
2346         tbl = GET_IMAGE(ATOM_OBJECT_TABLE, offset);
2347         if (!tbl)
2348                 return NULL;
2349
2350         for (i = 0; i < tbl->ucNumberOfObjects; i++)
2351                 if (dal_graphics_object_id_is_equal(id,
2352                                 object_id_from_bios_object_id(
2353                                                 le16_to_cpu(tbl->asObjects[i].usObjectID))))
2354                         return &tbl->asObjects[i];
2355
2356         return NULL;
2357 }
2358
2359 static uint32_t get_dest_obj_list(struct bios_parser *bp,
2360         ATOM_OBJECT *object, uint16_t **id_list)
2361 {
2362         uint32_t offset;
2363         uint8_t *number;
2364
2365         if (!object) {
2366                 BREAK_TO_DEBUGGER(); /* Invalid object id */
2367                 return 0;
2368         }
2369
2370         offset = le16_to_cpu(object->usSrcDstTableOffset)
2371                                                 + bp->object_info_tbl_offset;
2372
2373         number = GET_IMAGE(uint8_t, offset);
2374         if (!number)
2375                 return 0;
2376
2377         offset += sizeof(uint8_t);
2378         offset += sizeof(uint16_t) * (*number);
2379
2380         number = GET_IMAGE(uint8_t, offset);
2381         if ((!number) || (!*number))
2382                 return 0;
2383
2384         offset += sizeof(uint8_t);
2385         *id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t));
2386
2387         if (!*id_list)
2388                 return 0;
2389
2390         return *number;
2391 }
2392
2393 static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
2394         uint16_t **id_list)
2395 {
2396         uint32_t offset;
2397         uint8_t *number;
2398
2399         if (!object) {
2400                 BREAK_TO_DEBUGGER(); /* Invalid object id */
2401                 return 0;
2402         }
2403
2404         offset = le16_to_cpu(object->usSrcDstTableOffset)
2405                                         + bp->object_info_tbl_offset;
2406
2407         number = GET_IMAGE(uint8_t, offset);
2408         if (!number)
2409                 return 0;
2410
2411         offset += sizeof(uint8_t);
2412         *id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t));
2413
2414         if (!*id_list)
2415                 return 0;
2416
2417         return *number;
2418 }
2419
2420 static uint32_t get_dst_number_from_object(struct bios_parser *bp,
2421         ATOM_OBJECT *object)
2422 {
2423         uint32_t offset;
2424         uint8_t *number;
2425
2426         if (!object) {
2427                 BREAK_TO_DEBUGGER(); /* Invalid encoder object id*/
2428                 return 0;
2429         }
2430
2431         offset = le16_to_cpu(object->usSrcDstTableOffset)
2432                                         + bp->object_info_tbl_offset;
2433
2434         number = GET_IMAGE(uint8_t, offset);
2435         if (!number)
2436                 return 0;
2437
2438         offset += sizeof(uint8_t);
2439         offset += sizeof(uint16_t) * (*number);
2440
2441         number = GET_IMAGE(uint8_t, offset);
2442
2443         if (!number)
2444                 return 0;
2445
2446         return *number;
2447 }
2448
2449 static struct device_id device_type_from_device_id(uint16_t device_id)
2450 {
2451
2452         struct device_id result_device_id;
2453
2454         switch (device_id) {
2455         case ATOM_DEVICE_LCD1_SUPPORT:
2456                 result_device_id.device_type = DEVICE_TYPE_LCD;
2457                 result_device_id.enum_id = 1;
2458                 break;
2459
2460         case ATOM_DEVICE_LCD2_SUPPORT:
2461                 result_device_id.device_type = DEVICE_TYPE_LCD;
2462                 result_device_id.enum_id = 2;
2463                 break;
2464
2465         case ATOM_DEVICE_CRT1_SUPPORT:
2466                 result_device_id.device_type = DEVICE_TYPE_CRT;
2467                 result_device_id.enum_id = 1;
2468                 break;
2469
2470         case ATOM_DEVICE_CRT2_SUPPORT:
2471                 result_device_id.device_type = DEVICE_TYPE_CRT;
2472                 result_device_id.enum_id = 2;
2473                 break;
2474
2475         case ATOM_DEVICE_DFP1_SUPPORT:
2476                 result_device_id.device_type = DEVICE_TYPE_DFP;
2477                 result_device_id.enum_id = 1;
2478                 break;
2479
2480         case ATOM_DEVICE_DFP2_SUPPORT:
2481                 result_device_id.device_type = DEVICE_TYPE_DFP;
2482                 result_device_id.enum_id = 2;
2483                 break;
2484
2485         case ATOM_DEVICE_DFP3_SUPPORT:
2486                 result_device_id.device_type = DEVICE_TYPE_DFP;
2487                 result_device_id.enum_id = 3;
2488                 break;
2489
2490         case ATOM_DEVICE_DFP4_SUPPORT:
2491                 result_device_id.device_type = DEVICE_TYPE_DFP;
2492                 result_device_id.enum_id = 4;
2493                 break;
2494
2495         case ATOM_DEVICE_DFP5_SUPPORT:
2496                 result_device_id.device_type = DEVICE_TYPE_DFP;
2497                 result_device_id.enum_id = 5;
2498                 break;
2499
2500         case ATOM_DEVICE_DFP6_SUPPORT:
2501                 result_device_id.device_type = DEVICE_TYPE_DFP;
2502                 result_device_id.enum_id = 6;
2503                 break;
2504
2505         default:
2506                 BREAK_TO_DEBUGGER(); /* Invalid device Id */
2507                 result_device_id.device_type = DEVICE_TYPE_UNKNOWN;
2508                 result_device_id.enum_id = 0;
2509         }
2510         return result_device_id;
2511 }
2512
2513 static void get_atom_data_table_revision(
2514         ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
2515         struct atom_data_revision *tbl_revision)
2516 {
2517         if (!tbl_revision)
2518                 return;
2519
2520         /* initialize the revision to 0 which is invalid revision */
2521         tbl_revision->major = 0;
2522         tbl_revision->minor = 0;
2523
2524         if (!atom_data_tbl)
2525                 return;
2526
2527         tbl_revision->major =
2528                         (uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl);
2529         tbl_revision->minor =
2530                         (uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl);
2531 }
2532
2533 static uint32_t signal_to_ss_id(enum as_signal_type signal)
2534 {
2535         uint32_t clk_id_ss = 0;
2536
2537         switch (signal) {
2538         case AS_SIGNAL_TYPE_DVI:
2539                 clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS;
2540                 break;
2541         case AS_SIGNAL_TYPE_HDMI:
2542                 clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI;
2543                 break;
2544         case AS_SIGNAL_TYPE_LVDS:
2545                 clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS;
2546                 break;
2547         case AS_SIGNAL_TYPE_DISPLAY_PORT:
2548                 clk_id_ss = ASIC_INTERNAL_SS_ON_DP;
2549                 break;
2550         case AS_SIGNAL_TYPE_GPU_PLL:
2551                 clk_id_ss = ASIC_INTERNAL_GPUPLL_SS;
2552                 break;
2553         default:
2554                 break;
2555         }
2556         return clk_id_ss;
2557 }
2558
2559 static uint32_t get_support_mask_for_device_id(struct device_id device_id)
2560 {
2561         enum dal_device_type device_type = device_id.device_type;
2562         uint32_t enum_id = device_id.enum_id;
2563
2564         switch (device_type) {
2565         case DEVICE_TYPE_LCD:
2566                 switch (enum_id) {
2567                 case 1:
2568                         return ATOM_DEVICE_LCD1_SUPPORT;
2569                 case 2:
2570                         return ATOM_DEVICE_LCD2_SUPPORT;
2571                 default:
2572                         break;
2573                 }
2574                 break;
2575         case DEVICE_TYPE_CRT:
2576                 switch (enum_id) {
2577                 case 1:
2578                         return ATOM_DEVICE_CRT1_SUPPORT;
2579                 case 2:
2580                         return ATOM_DEVICE_CRT2_SUPPORT;
2581                 default:
2582                         break;
2583                 }
2584                 break;
2585         case DEVICE_TYPE_DFP:
2586                 switch (enum_id) {
2587                 case 1:
2588                         return ATOM_DEVICE_DFP1_SUPPORT;
2589                 case 2:
2590                         return ATOM_DEVICE_DFP2_SUPPORT;
2591                 case 3:
2592                         return ATOM_DEVICE_DFP3_SUPPORT;
2593                 case 4:
2594                         return ATOM_DEVICE_DFP4_SUPPORT;
2595                 case 5:
2596                         return ATOM_DEVICE_DFP5_SUPPORT;
2597                 case 6:
2598                         return ATOM_DEVICE_DFP6_SUPPORT;
2599                 default:
2600                         break;
2601                 }
2602                 break;
2603         case DEVICE_TYPE_CV:
2604                 switch (enum_id) {
2605                 case 1:
2606                         return ATOM_DEVICE_CV_SUPPORT;
2607                 default:
2608                         break;
2609                 }
2610                 break;
2611         case DEVICE_TYPE_TV:
2612                 switch (enum_id) {
2613                 case 1:
2614                         return ATOM_DEVICE_TV1_SUPPORT;
2615                 default:
2616                         break;
2617                 }
2618                 break;
2619         default:
2620                 break;
2621         };
2622
2623         /* Unidentified device ID, return empty support mask. */
2624         return 0;
2625 }
2626
2627 /**
2628  *  HwContext interface for writing MM registers
2629  */
2630
2631 static bool i2c_read(
2632         struct bios_parser *bp,
2633         struct graphics_object_i2c_info *i2c_info,
2634         uint8_t *buffer,
2635         uint32_t length)
2636 {
2637         struct ddc *ddc;
2638         uint8_t offset[2] = { 0, 0 };
2639         bool result = false;
2640         struct i2c_command cmd;
2641         struct gpio_ddc_hw_info hw_info = {
2642                 i2c_info->i2c_hw_assist,
2643                 i2c_info->i2c_line };
2644
2645         ddc = dal_gpio_create_ddc(bp->base.ctx->gpio_service,
2646                 i2c_info->gpio_info.clk_a_register_index,
2647                 (1 << i2c_info->gpio_info.clk_a_shift), &hw_info);
2648
2649         if (!ddc)
2650                 return result;
2651
2652         /*Using SW engine */
2653         cmd.engine = I2C_COMMAND_ENGINE_SW;
2654         cmd.speed = ddc->ctx->dc->caps.i2c_speed_in_khz;
2655
2656         {
2657                 struct i2c_payload payloads[] = {
2658                                 {
2659                                                 .address = i2c_info->i2c_slave_address >> 1,
2660                                                 .data = offset,
2661                                                 .length = sizeof(offset),
2662                                                 .write = true
2663                                 },
2664                                 {
2665                                                 .address = i2c_info->i2c_slave_address >> 1,
2666                                                 .data = buffer,
2667                                                 .length = length,
2668                                                 .write = false
2669                                 }
2670                 };
2671
2672                 cmd.payloads = payloads;
2673                 cmd.number_of_payloads = ARRAY_SIZE(payloads);
2674
2675                 /* TODO route this through drm i2c_adapter */
2676                 result = dal_i2caux_submit_i2c_command(
2677                                 ddc->ctx->i2caux,
2678                                 ddc,
2679                                 &cmd);
2680         }
2681
2682         dal_gpio_destroy_ddc(&ddc);
2683
2684         return result;
2685 }
2686
2687 /**
2688  * Read external display connection info table through i2c.
2689  * validate the GUID and checksum.
2690  *
2691  * @return enum bp_result whether all data was sucessfully read
2692  */
2693 static enum bp_result get_ext_display_connection_info(
2694         struct bios_parser *bp,
2695         ATOM_OBJECT *opm_object,
2696         ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *ext_display_connection_info_tbl)
2697 {
2698         bool config_tbl_present = false;
2699         ATOM_I2C_RECORD *i2c_record = NULL;
2700         uint32_t i = 0;
2701
2702         if (opm_object == NULL)
2703                 return BP_RESULT_BADINPUT;
2704
2705         i2c_record = get_i2c_record(bp, opm_object);
2706
2707         if (i2c_record != NULL) {
2708                 ATOM_GPIO_I2C_INFO *gpio_i2c_header;
2709                 struct graphics_object_i2c_info i2c_info;
2710
2711                 gpio_i2c_header = GET_IMAGE(ATOM_GPIO_I2C_INFO,
2712                                 bp->master_data_tbl->ListOfDataTables.GPIO_I2C_Info);
2713
2714                 if (NULL == gpio_i2c_header)
2715                         return BP_RESULT_BADBIOSTABLE;
2716
2717                 if (get_gpio_i2c_info(bp, i2c_record, &i2c_info) !=
2718                                 BP_RESULT_OK)
2719                         return BP_RESULT_BADBIOSTABLE;
2720
2721                 if (i2c_read(bp,
2722                              &i2c_info,
2723                              (uint8_t *)ext_display_connection_info_tbl,
2724                              sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO))) {
2725                         config_tbl_present = true;
2726                 }
2727         }
2728
2729         /* Validate GUID */
2730         if (config_tbl_present)
2731                 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; i++) {
2732                         if (ext_display_connection_info_tbl->ucGuid[i]
2733                             != ext_display_connection_guid[i]) {
2734                                 config_tbl_present = false;
2735                                 break;
2736                         }
2737                 }
2738
2739         /* Validate checksum */
2740         if (config_tbl_present) {
2741                 uint8_t check_sum = 0;
2742                 uint8_t *buf =
2743                                 (uint8_t *)ext_display_connection_info_tbl;
2744
2745                 for (i = 0; i < sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO);
2746                                 i++) {
2747                         check_sum += buf[i];
2748                 }
2749
2750                 if (check_sum != 0)
2751                         config_tbl_present = false;
2752         }
2753
2754         if (config_tbl_present)
2755                 return BP_RESULT_OK;
2756         else
2757                 return BP_RESULT_FAILURE;
2758 }
2759
2760 /*
2761  * Gets the first device ID in the same group as the given ID for enumerating.
2762  * For instance, if any DFP device ID is passed, returns the device ID for DFP1.
2763  *
2764  * The first device ID in the same group as the passed device ID, or 0 if no
2765  * matching device group found.
2766  */
2767 static uint32_t enum_first_device_id(uint32_t dev_id)
2768 {
2769         /* Return the first in the group that this ID belongs to. */
2770         if (dev_id & ATOM_DEVICE_CRT_SUPPORT)
2771                 return ATOM_DEVICE_CRT1_SUPPORT;
2772         else if (dev_id & ATOM_DEVICE_DFP_SUPPORT)
2773                 return ATOM_DEVICE_DFP1_SUPPORT;
2774         else if (dev_id & ATOM_DEVICE_LCD_SUPPORT)
2775                 return ATOM_DEVICE_LCD1_SUPPORT;
2776         else if (dev_id & ATOM_DEVICE_TV_SUPPORT)
2777                 return ATOM_DEVICE_TV1_SUPPORT;
2778         else if (dev_id & ATOM_DEVICE_CV_SUPPORT)
2779                 return ATOM_DEVICE_CV_SUPPORT;
2780
2781         /* No group found for this device ID. */
2782
2783         dm_error("%s: incorrect input %d\n", __func__, dev_id);
2784         /* No matching support flag for given device ID */
2785         return 0;
2786 }
2787
2788 /*
2789  * Gets the next device ID in the group for a given device ID.
2790  *
2791  * The current device ID being enumerated on.
2792  *
2793  * The next device ID in the group, or 0 if no device exists.
2794  */
2795 static uint32_t enum_next_dev_id(uint32_t dev_id)
2796 {
2797         /* Get next device ID in the group. */
2798         switch (dev_id) {
2799         case ATOM_DEVICE_CRT1_SUPPORT:
2800                 return ATOM_DEVICE_CRT2_SUPPORT;
2801         case ATOM_DEVICE_LCD1_SUPPORT:
2802                 return ATOM_DEVICE_LCD2_SUPPORT;
2803         case ATOM_DEVICE_DFP1_SUPPORT:
2804                 return ATOM_DEVICE_DFP2_SUPPORT;
2805         case ATOM_DEVICE_DFP2_SUPPORT:
2806                 return ATOM_DEVICE_DFP3_SUPPORT;
2807         case ATOM_DEVICE_DFP3_SUPPORT:
2808                 return ATOM_DEVICE_DFP4_SUPPORT;
2809         case ATOM_DEVICE_DFP4_SUPPORT:
2810                 return ATOM_DEVICE_DFP5_SUPPORT;
2811         case ATOM_DEVICE_DFP5_SUPPORT:
2812                 return ATOM_DEVICE_DFP6_SUPPORT;
2813         }
2814
2815         /* Done enumerating through devices. */
2816         return 0;
2817 }
2818
2819 /*
2820  * Returns the new device tag record for patched BIOS object.
2821  *
2822  * [IN] pExtDisplayPath - External display path to copy device tag from.
2823  * [IN] deviceSupport - Bit vector for device ID support flags.
2824  * [OUT] pDeviceTag - Device tag structure to fill with patched data.
2825  *
2826  * True if a compatible device ID was found, false otherwise.
2827  */
2828 static bool get_patched_device_tag(
2829         struct bios_parser *bp,
2830         EXT_DISPLAY_PATH *ext_display_path,
2831         uint32_t device_support,
2832         ATOM_CONNECTOR_DEVICE_TAG *device_tag)
2833 {
2834         uint32_t dev_id;
2835         /* Use fallback behaviour if not supported. */
2836         if (!bp->remap_device_tags) {
2837                 device_tag->ulACPIDeviceEnum =
2838                                 cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum));
2839                 device_tag->usDeviceID =
2840                                 cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceTag));
2841                 return true;
2842         }
2843
2844         /* Find the first unused in the same group. */
2845         dev_id = enum_first_device_id(le16_to_cpu(ext_display_path->usDeviceTag));
2846         while (dev_id != 0) {
2847                 /* Assign this device ID if supported. */
2848                 if ((device_support & dev_id) != 0) {
2849                         device_tag->ulACPIDeviceEnum =
2850                                         cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum));
2851                         device_tag->usDeviceID = cpu_to_le16((USHORT) dev_id);
2852                         return true;
2853                 }
2854
2855                 dev_id = enum_next_dev_id(dev_id);
2856         }
2857
2858         /* No compatible device ID found. */
2859         return false;
2860 }
2861
2862 /*
2863  * Adds a device tag to a BIOS object's device tag record if there is
2864  * matching device ID supported.
2865  *
2866  * pObject - Pointer to the BIOS object to add the device tag to.
2867  * pExtDisplayPath - Display path to retrieve base device ID from.
2868  * pDeviceSupport - Pointer to bit vector for supported device IDs.
2869  */
2870 static void add_device_tag_from_ext_display_path(
2871         struct bios_parser *bp,
2872         ATOM_OBJECT *object,
2873         EXT_DISPLAY_PATH *ext_display_path,
2874         uint32_t *device_support)
2875 {
2876         /* Get device tag record for object. */
2877         ATOM_CONNECTOR_DEVICE_TAG *device_tag = NULL;
2878         ATOM_CONNECTOR_DEVICE_TAG_RECORD *device_tag_record = NULL;
2879         enum bp_result result =
2880                         bios_parser_get_device_tag_record(
2881                                         bp, object, &device_tag_record);
2882
2883         if ((le16_to_cpu(ext_display_path->usDeviceTag) != CONNECTOR_OBJECT_ID_NONE)
2884                         && (result == BP_RESULT_OK)) {
2885                 uint8_t index;
2886
2887                 if ((device_tag_record->ucNumberOfDevice == 1) &&
2888                                 (le16_to_cpu(device_tag_record->asDeviceTag[0].usDeviceID) == 0)) {
2889                         /*Workaround bug in current VBIOS releases where
2890                          * ucNumberOfDevice = 1 but there is no actual device
2891                          * tag data. This w/a is temporary until the updated
2892                          * VBIOS is distributed. */
2893                         device_tag_record->ucNumberOfDevice =
2894                                         device_tag_record->ucNumberOfDevice - 1;
2895                 }
2896
2897                 /* Attempt to find a matching device ID. */
2898                 index = device_tag_record->ucNumberOfDevice;
2899                 device_tag = &device_tag_record->asDeviceTag[index];
2900                 if (get_patched_device_tag(
2901                                 bp,
2902                                 ext_display_path,
2903                                 *device_support,
2904                                 device_tag)) {
2905                         /* Update cached device support to remove assigned ID.
2906                          */
2907                         *device_support &= ~le16_to_cpu(device_tag->usDeviceID);
2908                         device_tag_record->ucNumberOfDevice++;
2909                 }
2910         }
2911 }
2912
2913 /*
2914  * Read out a single EXT_DISPLAY_PATH from the external display connection info
2915  * table. The specific entry in the table is determined by the enum_id passed
2916  * in.
2917  *
2918  * EXT_DISPLAY_PATH describing a single Configuration table entry
2919  */
2920
2921 #define INVALID_CONNECTOR 0xffff
2922
2923 static EXT_DISPLAY_PATH *get_ext_display_path_entry(
2924         ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *config_table,
2925         uint32_t bios_object_id)
2926 {
2927         EXT_DISPLAY_PATH *ext_display_path;
2928         uint32_t ext_display_path_index =
2929                         ((bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT) - 1;
2930
2931         if (ext_display_path_index >= MAX_NUMBER_OF_EXT_DISPLAY_PATH)
2932                 return NULL;
2933
2934         ext_display_path = &config_table->sPath[ext_display_path_index];
2935
2936         if (le16_to_cpu(ext_display_path->usDeviceConnector) == INVALID_CONNECTOR)
2937                 ext_display_path->usDeviceConnector = cpu_to_le16(0);
2938
2939         return ext_display_path;
2940 }
2941
2942 /*
2943  * Get AUX/DDC information of input object id
2944  *
2945  * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record
2946  * IR
2947  */
2948 static ATOM_CONNECTOR_AUXDDC_LUT_RECORD *get_ext_connector_aux_ddc_lut_record(
2949         struct bios_parser *bp,
2950         ATOM_OBJECT *object)
2951 {
2952         uint32_t offset;
2953         ATOM_COMMON_RECORD_HEADER *header;
2954
2955         if (!object) {
2956                 BREAK_TO_DEBUGGER();
2957                 /* Invalid object */
2958                 return NULL;
2959         }
2960
2961         offset = le16_to_cpu(object->usRecordOffset)
2962                                         + bp->object_info_tbl_offset;
2963
2964         for (;;) {
2965                 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
2966
2967                 if (!header)
2968                         return NULL;
2969
2970                 if (LAST_RECORD_TYPE == header->ucRecordType ||
2971                                 0 == header->ucRecordSize)
2972                         break;
2973
2974                 if (ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE ==
2975                                 header->ucRecordType &&
2976                                 sizeof(ATOM_CONNECTOR_AUXDDC_LUT_RECORD) <=
2977                                 header->ucRecordSize)
2978                         return (ATOM_CONNECTOR_AUXDDC_LUT_RECORD *)(header);
2979
2980                 offset += header->ucRecordSize;
2981         }
2982
2983         return NULL;
2984 }
2985
2986 /*
2987  * Get AUX/DDC information of input object id
2988  *
2989  * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record
2990  * IR
2991  */
2992 static ATOM_CONNECTOR_HPDPIN_LUT_RECORD *get_ext_connector_hpd_pin_lut_record(
2993         struct bios_parser *bp,
2994         ATOM_OBJECT *object)
2995 {
2996         uint32_t offset;
2997         ATOM_COMMON_RECORD_HEADER *header;
2998
2999         if (!object) {
3000                 BREAK_TO_DEBUGGER();
3001                 /* Invalid object */
3002                 return NULL;
3003         }
3004
3005         offset = le16_to_cpu(object->usRecordOffset)
3006                                         + bp->object_info_tbl_offset;
3007
3008         for (;;) {
3009                 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
3010
3011                 if (!header)
3012                         return NULL;
3013
3014                 if (LAST_RECORD_TYPE == header->ucRecordType ||
3015                                 0 == header->ucRecordSize)
3016                         break;
3017
3018                 if (ATOM_CONNECTOR_HPDPIN_LUT_RECORD_TYPE ==
3019                                 header->ucRecordType &&
3020                                 sizeof(ATOM_CONNECTOR_HPDPIN_LUT_RECORD) <=
3021                                 header->ucRecordSize)
3022                         return (ATOM_CONNECTOR_HPDPIN_LUT_RECORD *)header;
3023
3024                 offset += header->ucRecordSize;
3025         }
3026
3027         return NULL;
3028 }
3029
3030 /*
3031  * Check whether we need to patch the VBIOS connector info table with
3032  * data from an external display connection info table.  This is
3033  * necessary to support MXM boards with an OPM (output personality
3034  * module).  With these designs, the VBIOS connector info table
3035  * specifies an MXM_CONNECTOR with a unique ID.  The driver retrieves
3036  * the external connection info table through i2c and then looks up the
3037  * connector ID to find the real connector type (e.g. DFP1).
3038  *
3039  */
3040 static enum bp_result patch_bios_image_from_ext_display_connection_info(
3041         struct bios_parser *bp)
3042 {
3043         ATOM_OBJECT_TABLE *connector_tbl;
3044         uint32_t connector_tbl_offset;
3045         struct graphics_object_id object_id;
3046         ATOM_OBJECT *object;
3047         ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO ext_display_connection_info_tbl;
3048         EXT_DISPLAY_PATH *ext_display_path;
3049         ATOM_CONNECTOR_AUXDDC_LUT_RECORD *aux_ddc_lut_record = NULL;
3050         ATOM_I2C_RECORD *i2c_record = NULL;
3051         ATOM_CONNECTOR_HPDPIN_LUT_RECORD *hpd_pin_lut_record = NULL;
3052         ATOM_HPD_INT_RECORD *hpd_record = NULL;
3053         ATOM_OBJECT_TABLE *encoder_table;
3054         uint32_t encoder_table_offset;
3055         ATOM_OBJECT *opm_object = NULL;
3056         uint32_t i = 0;
3057         struct graphics_object_id opm_object_id =
3058                         dal_graphics_object_id_init(
3059                                         GENERIC_ID_MXM_OPM,
3060                                         ENUM_ID_1,
3061                                         OBJECT_TYPE_GENERIC);
3062         ATOM_CONNECTOR_DEVICE_TAG_RECORD *dev_tag_record;
3063         uint32_t cached_device_support =
3064                         le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport);
3065
3066         uint32_t dst_number;
3067         uint16_t *dst_object_id_list;
3068
3069         opm_object = get_bios_object(bp, opm_object_id);
3070         if (!opm_object)
3071                 return BP_RESULT_UNSUPPORTED;
3072
3073         memset(&ext_display_connection_info_tbl, 0,
3074                         sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO));
3075
3076         connector_tbl_offset = bp->object_info_tbl_offset
3077                         + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
3078         connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset);
3079
3080         /* Read Connector info table from EEPROM through i2c */
3081         if (get_ext_display_connection_info(bp,
3082                                             opm_object,
3083                                             &ext_display_connection_info_tbl) != BP_RESULT_OK) {
3084
3085                 DC_LOG_WARNING("%s: Failed to read Connection Info Table", __func__);
3086                 return BP_RESULT_UNSUPPORTED;
3087         }
3088
3089         /* Get pointer to AUX/DDC and HPD LUTs */
3090         aux_ddc_lut_record =
3091                         get_ext_connector_aux_ddc_lut_record(bp, opm_object);
3092         hpd_pin_lut_record =
3093                         get_ext_connector_hpd_pin_lut_record(bp, opm_object);
3094
3095         if ((aux_ddc_lut_record == NULL) || (hpd_pin_lut_record == NULL))
3096                 return BP_RESULT_UNSUPPORTED;
3097
3098         /* Cache support bits for currently unmapped device types. */
3099         if (bp->remap_device_tags) {
3100                 for (i = 0; i < connector_tbl->ucNumberOfObjects; ++i) {
3101                         uint32_t j;
3102                         /* Remove support for all non-MXM connectors. */
3103                         object = &connector_tbl->asObjects[i];
3104                         object_id = object_id_from_bios_object_id(
3105                                         le16_to_cpu(object->usObjectID));
3106                         if ((OBJECT_TYPE_CONNECTOR != object_id.type) ||
3107                                         (CONNECTOR_ID_MXM == object_id.id))
3108                                 continue;
3109
3110                         /* Remove support for all device tags. */
3111                         if (bios_parser_get_device_tag_record(
3112                                         bp, object, &dev_tag_record) != BP_RESULT_OK)
3113                                 continue;
3114
3115                         for (j = 0; j < dev_tag_record->ucNumberOfDevice; ++j) {
3116                                 ATOM_CONNECTOR_DEVICE_TAG *device_tag =
3117                                                 &dev_tag_record->asDeviceTag[j];
3118                                 cached_device_support &=
3119                                                 ~le16_to_cpu(device_tag->usDeviceID);
3120                         }
3121                 }
3122         }
3123
3124         /* Find all MXM connector objects and patch them with connector info
3125          * from the external display connection info table. */
3126         for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) {
3127                 uint32_t j;
3128
3129                 object = &connector_tbl->asObjects[i];
3130                 object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID));
3131                 if ((OBJECT_TYPE_CONNECTOR != object_id.type) ||
3132                                 (CONNECTOR_ID_MXM != object_id.id))
3133                         continue;
3134
3135                 /* Get the correct connection info table entry based on the enum
3136                  * id. */
3137                 ext_display_path = get_ext_display_path_entry(
3138                                 &ext_display_connection_info_tbl,
3139                                 le16_to_cpu(object->usObjectID));
3140                 if (!ext_display_path)
3141                         return BP_RESULT_FAILURE;
3142
3143                 /* Patch device connector ID */
3144                 object->usObjectID =
3145                                 cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceConnector));
3146
3147                 /* Patch device tag, ulACPIDeviceEnum. */
3148                 add_device_tag_from_ext_display_path(
3149                                 bp,
3150                                 object,
3151                                 ext_display_path,
3152                                 &cached_device_support);
3153
3154                 /* Patch HPD info */
3155                 if (ext_display_path->ucExtHPDPINLutIndex <
3156                                 MAX_NUMBER_OF_EXT_HPDPIN_LUT_ENTRIES) {
3157                         hpd_record = get_hpd_record(bp, object);
3158                         if (hpd_record) {
3159                                 uint8_t index =
3160                                                 ext_display_path->ucExtHPDPINLutIndex;
3161                                 hpd_record->ucHPDIntGPIOID =
3162                                                 hpd_pin_lut_record->ucHPDPINMap[index];
3163                         } else {
3164                                 BREAK_TO_DEBUGGER();
3165                                 /* Invalid hpd record */
3166                                 return BP_RESULT_FAILURE;
3167                         }
3168                 }
3169
3170                 /* Patch I2C/AUX info */
3171                 if (ext_display_path->ucExtHPDPINLutIndex <
3172                                 MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES) {
3173                         i2c_record = get_i2c_record(bp, object);
3174                         if (i2c_record) {
3175                                 uint8_t index =
3176                                                 ext_display_path->ucExtAUXDDCLutIndex;
3177                                 i2c_record->sucI2cId =
3178                                                 aux_ddc_lut_record->ucAUXDDCMap[index];
3179                         } else {
3180                                 BREAK_TO_DEBUGGER();
3181                                 /* Invalid I2C record */
3182                                 return BP_RESULT_FAILURE;
3183                         }
3184                 }
3185
3186                 /* Merge with other MXM connectors that map to the same physical
3187                  * connector. */
3188                 for (j = i + 1;
3189                                 j < connector_tbl->ucNumberOfObjects; j++) {
3190                         ATOM_OBJECT *next_object;
3191                         struct graphics_object_id next_object_id;
3192                         EXT_DISPLAY_PATH *next_ext_display_path;
3193
3194                         next_object = &connector_tbl->asObjects[j];
3195                         next_object_id = object_id_from_bios_object_id(
3196                                         le16_to_cpu(next_object->usObjectID));
3197
3198                         if ((OBJECT_TYPE_CONNECTOR != next_object_id.type) &&
3199                                         (CONNECTOR_ID_MXM == next_object_id.id))
3200                                 continue;
3201
3202                         next_ext_display_path = get_ext_display_path_entry(
3203                                         &ext_display_connection_info_tbl,
3204                                         le16_to_cpu(next_object->usObjectID));
3205
3206                         if (next_ext_display_path == NULL)
3207                                 return BP_RESULT_FAILURE;
3208
3209                         /* Merge if using same connector. */
3210                         if ((le16_to_cpu(next_ext_display_path->usDeviceConnector) ==
3211                                         le16_to_cpu(ext_display_path->usDeviceConnector)) &&
3212                                         (le16_to_cpu(ext_display_path->usDeviceConnector) != 0)) {
3213                                 /* Clear duplicate connector from table. */
3214                                 next_object->usObjectID = cpu_to_le16(0);
3215                                 add_device_tag_from_ext_display_path(
3216                                                 bp,
3217                                                 object,
3218                                                 ext_display_path,
3219                                                 &cached_device_support);
3220                         }
3221                 }
3222         }
3223
3224         /* Find all encoders which have an MXM object as their destination.
3225          *  Replace the MXM object with the real connector Id from the external
3226          *  display connection info table */
3227
3228         encoder_table_offset = bp->object_info_tbl_offset
3229                         + le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
3230         encoder_table = GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset);
3231
3232         for (i = 0; i < encoder_table->ucNumberOfObjects; i++) {
3233                 uint32_t j;
3234
3235                 object = &encoder_table->asObjects[i];
3236
3237                 dst_number = get_dest_obj_list(bp, object, &dst_object_id_list);
3238
3239                 for (j = 0; j < dst_number; j++) {
3240                         object_id = object_id_from_bios_object_id(
3241                                         dst_object_id_list[j]);
3242
3243                         if ((OBJECT_TYPE_CONNECTOR != object_id.type) ||
3244                                         (CONNECTOR_ID_MXM != object_id.id))
3245                                 continue;
3246
3247                         /* Get the correct connection info table entry based on
3248                          * the enum id. */
3249                         ext_display_path =
3250                                         get_ext_display_path_entry(
3251                                                         &ext_display_connection_info_tbl,
3252                                                         dst_object_id_list[j]);
3253
3254                         if (ext_display_path == NULL)
3255                                 return BP_RESULT_FAILURE;
3256
3257                         dst_object_id_list[j] =
3258                                         le16_to_cpu(ext_display_path->usDeviceConnector);
3259                 }
3260         }
3261
3262         return BP_RESULT_OK;
3263 }
3264
3265 /*
3266  * Check whether we need to patch the VBIOS connector info table with
3267  * data from an external display connection info table.  This is
3268  * necessary to support MXM boards with an OPM (output personality
3269  * module).  With these designs, the VBIOS connector info table
3270  * specifies an MXM_CONNECTOR with a unique ID.  The driver retrieves
3271  * the external connection info table through i2c and then looks up the
3272  * connector ID to find the real connector type (e.g. DFP1).
3273  *
3274  */
3275
3276 static void process_ext_display_connection_info(struct bios_parser *bp)
3277 {
3278         ATOM_OBJECT_TABLE *connector_tbl;
3279         uint32_t connector_tbl_offset;
3280         struct graphics_object_id object_id;
3281         ATOM_OBJECT *object;
3282         bool mxm_connector_found = false;
3283         bool null_entry_found = false;
3284         uint32_t i = 0;
3285
3286         connector_tbl_offset = bp->object_info_tbl_offset +
3287                         le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
3288         connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset);
3289
3290         /* Look for MXM connectors to determine whether we need patch the VBIOS
3291          * connector info table. Look for null entries to determine whether we
3292          * need to compact connector table. */
3293         for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) {
3294                 object = &connector_tbl->asObjects[i];
3295                 object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID));
3296
3297                 if ((OBJECT_TYPE_CONNECTOR == object_id.type) &&
3298                                 (CONNECTOR_ID_MXM == object_id.id)) {
3299                         /* Once we found MXM connector - we can break */
3300                         mxm_connector_found = true;
3301                         break;
3302                 } else if (OBJECT_TYPE_CONNECTOR != object_id.type) {
3303                         /* We need to continue looping - to check if MXM
3304                          * connector present */
3305                         null_entry_found = true;
3306                 }
3307         }
3308
3309         /* Patch BIOS image */
3310         if (mxm_connector_found || null_entry_found) {
3311                 uint32_t connectors_num = 0;
3312                 uint8_t *original_bios;
3313                 /* Step 1: Replace bios image with the new copy which will be
3314                  * patched */
3315                 bp->base.bios_local_image = kzalloc(bp->base.bios_size,
3316                                                     GFP_KERNEL);
3317                 if (bp->base.bios_local_image == NULL) {
3318                         BREAK_TO_DEBUGGER();
3319                         /* Failed to alloc bp->base.bios_local_image */
3320                         return;
3321                 }
3322
3323                 memmove(bp->base.bios_local_image, bp->base.bios, bp->base.bios_size);
3324                 original_bios = bp->base.bios;
3325                 bp->base.bios = bp->base.bios_local_image;
3326                 connector_tbl =
3327                                 GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset);
3328
3329                 /* Step 2: (only if MXM connector found) Patch BIOS image with
3330                  * info from external module */
3331                 if (mxm_connector_found &&
3332                     patch_bios_image_from_ext_display_connection_info(bp) !=
3333                                                 BP_RESULT_OK) {
3334                         /* Patching the bios image has failed. We will copy
3335                          * again original image provided and afterwards
3336                          * only remove null entries */
3337                         memmove(
3338                                         bp->base.bios_local_image,
3339                                         original_bios,
3340                                         bp->base.bios_size);
3341                 }
3342
3343                 /* Step 3: Compact connector table (remove null entries, valid
3344                  * entries moved to beginning) */
3345                 for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) {
3346                         object = &connector_tbl->asObjects[i];
3347                         object_id = object_id_from_bios_object_id(
3348                                         le16_to_cpu(object->usObjectID));
3349
3350                         if (OBJECT_TYPE_CONNECTOR != object_id.type)
3351                                 continue;
3352
3353                         if (i != connectors_num) {
3354                                 memmove(
3355                                                 &connector_tbl->
3356                                                 asObjects[connectors_num],
3357                                                 object,
3358                                                 sizeof(ATOM_OBJECT));
3359                         }
3360                         ++connectors_num;
3361                 }
3362                 connector_tbl->ucNumberOfObjects = (uint8_t)connectors_num;
3363         }
3364 }
3365
3366 static void bios_parser_post_init(struct dc_bios *dcb)
3367 {
3368         struct bios_parser *bp = BP_FROM_DCB(dcb);
3369
3370         process_ext_display_connection_info(bp);
3371 }
3372
3373 /**
3374  * bios_parser_set_scratch_critical_state
3375  *
3376  * @brief
3377  *  update critical state bit in VBIOS scratch register
3378  *
3379  * @param
3380  *  bool - to set or reset state
3381  */
3382 static void bios_parser_set_scratch_critical_state(
3383         struct dc_bios *dcb,
3384         bool state)
3385 {
3386         bios_set_scratch_critical_state(dcb, state);
3387 }
3388
3389 /*
3390  * get_integrated_info_v8
3391  *
3392  * @brief
3393  * Get V8 integrated BIOS information
3394  *
3395  * @param
3396  * bios_parser *bp - [in]BIOS parser handler to get master data table
3397  * integrated_info *info - [out] store and output integrated info
3398  *
3399  * @return
3400  * enum bp_result - BP_RESULT_OK if information is available,
3401  *                  BP_RESULT_BADBIOSTABLE otherwise.
3402  */
3403 static enum bp_result get_integrated_info_v8(
3404         struct bios_parser *bp,
3405         struct integrated_info *info)
3406 {
3407         ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8;
3408         uint32_t i;
3409
3410         info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8,
3411                         bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
3412
3413         if (info_v8 == NULL)
3414                 return BP_RESULT_BADBIOSTABLE;
3415         info->boot_up_engine_clock = le32_to_cpu(info_v8->ulBootUpEngineClock) * 10;
3416         info->dentist_vco_freq = le32_to_cpu(info_v8->ulDentistVCOFreq) * 10;
3417         info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
3418
3419         for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
3420                 /* Convert [10KHz] into [KHz] */
3421                 info->disp_clk_voltage[i].max_supported_clk =
3422                         le32_to_cpu(info_v8->sDISPCLK_Voltage[i].
3423                                     ulMaximumSupportedCLK) * 10;
3424                 info->disp_clk_voltage[i].voltage_index =
3425                         le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex);
3426         }
3427
3428         info->boot_up_req_display_vector =
3429                 le32_to_cpu(info_v8->ulBootUpReqDisplayVector);
3430         info->gpu_cap_info =
3431                 le32_to_cpu(info_v8->ulGPUCapInfo);
3432
3433         /*
3434          * system_config: Bit[0] = 0 : PCIE power gating disabled
3435          *                       = 1 : PCIE power gating enabled
3436          *                Bit[1] = 0 : DDR-PLL shut down disabled
3437          *                       = 1 : DDR-PLL shut down enabled
3438          *                Bit[2] = 0 : DDR-PLL power down disabled
3439          *                       = 1 : DDR-PLL power down enabled
3440          */
3441         info->system_config = le32_to_cpu(info_v8->ulSystemConfig);
3442         info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo);
3443         info->boot_up_nb_voltage =
3444                 le16_to_cpu(info_v8->usBootUpNBVoltage);
3445         info->ext_disp_conn_info_offset =
3446                 le16_to_cpu(info_v8->usExtDispConnInfoOffset);
3447         info->memory_type = info_v8->ucMemoryType;
3448         info->ma_channel_number = info_v8->ucUMAChannelNumber;
3449         info->gmc_restore_reset_time =
3450                 le32_to_cpu(info_v8->ulGMCRestoreResetTime);
3451
3452         info->minimum_n_clk =
3453                 le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]);
3454         for (i = 1; i < 4; ++i)
3455                 info->minimum_n_clk =
3456                         info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ?
3457                         info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]);
3458
3459         info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk);
3460         info->ddr_dll_power_up_time =
3461                 le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime);
3462         info->ddr_pll_power_up_time =
3463                 le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime);
3464         info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType);
3465         info->lvds_ss_percentage =
3466                 le16_to_cpu(info_v8->usLvdsSSPercentage);
3467         info->lvds_sspread_rate_in_10hz =
3468                 le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz);
3469         info->hdmi_ss_percentage =
3470                 le16_to_cpu(info_v8->usHDMISSPercentage);
3471         info->hdmi_sspread_rate_in_10hz =
3472                 le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz);
3473         info->dvi_ss_percentage =
3474                 le16_to_cpu(info_v8->usDVISSPercentage);
3475         info->dvi_sspread_rate_in_10_hz =
3476                 le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz);
3477
3478         info->max_lvds_pclk_freq_in_single_link =
3479                 le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink);
3480         info->lvds_misc = info_v8->ucLvdsMisc;
3481         info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
3482                 info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
3483         info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
3484                 info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
3485         info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
3486                 info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
3487         info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
3488                 info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
3489         info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
3490                 info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
3491         info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
3492                 info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
3493         info->lvds_off_to_on_delay_in_4ms =
3494                 info_v8->ucLVDSOffToOnDelay_in4Ms;
3495         info->lvds_bit_depth_control_val =
3496                 le32_to_cpu(info_v8->ulLCDBitDepthControlVal);
3497
3498         for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
3499                 /* Convert [10KHz] into [KHz] */
3500                 info->avail_s_clk[i].supported_s_clk =
3501                         le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10;
3502                 info->avail_s_clk[i].voltage_index =
3503                         le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex);
3504                 info->avail_s_clk[i].voltage_id =
3505                         le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID);
3506         }
3507
3508         for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
3509                 info->ext_disp_conn_info.gu_id[i] =
3510                         info_v8->sExtDispConnInfo.ucGuid[i];
3511         }
3512
3513         for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
3514                 info->ext_disp_conn_info.path[i].device_connector_id =
3515                         object_id_from_bios_object_id(
3516                                 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector));
3517
3518                 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
3519                         object_id_from_bios_object_id(
3520                                 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
3521
3522                 info->ext_disp_conn_info.path[i].device_tag =
3523                         le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag);
3524                 info->ext_disp_conn_info.path[i].device_acpi_enum =
3525                         le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
3526                 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
3527                         info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
3528                 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
3529                         info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
3530                 info->ext_disp_conn_info.path[i].channel_mapping.raw =
3531                         info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping;
3532         }
3533         info->ext_disp_conn_info.checksum =
3534                 info_v8->sExtDispConnInfo.ucChecksum;
3535
3536         return BP_RESULT_OK;
3537 }
3538
3539 /*
3540  * get_integrated_info_v8
3541  *
3542  * @brief
3543  * Get V8 integrated BIOS information
3544  *
3545  * @param
3546  * bios_parser *bp - [in]BIOS parser handler to get master data table
3547  * integrated_info *info - [out] store and output integrated info
3548  *
3549  * @return
3550  * enum bp_result - BP_RESULT_OK if information is available,
3551  *                  BP_RESULT_BADBIOSTABLE otherwise.
3552  */
3553 static enum bp_result get_integrated_info_v9(
3554         struct bios_parser *bp,
3555         struct integrated_info *info)
3556 {
3557         ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9;
3558         uint32_t i;
3559
3560         info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9,
3561                         bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
3562
3563         if (!info_v9)
3564                 return BP_RESULT_BADBIOSTABLE;
3565
3566         info->boot_up_engine_clock = le32_to_cpu(info_v9->ulBootUpEngineClock) * 10;
3567         info->dentist_vco_freq = le32_to_cpu(info_v9->ulDentistVCOFreq) * 10;
3568         info->boot_up_uma_clock = le32_to_cpu(info_v9->ulBootUpUMAClock) * 10;
3569
3570         for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
3571                 /* Convert [10KHz] into [KHz] */
3572                 info->disp_clk_voltage[i].max_supported_clk =
3573                         le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10;
3574                 info->disp_clk_voltage[i].voltage_index =
3575                         le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex);
3576         }
3577
3578         info->boot_up_req_display_vector =
3579                 le32_to_cpu(info_v9->ulBootUpReqDisplayVector);
3580         info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo);
3581
3582         /*
3583          * system_config: Bit[0] = 0 : PCIE power gating disabled
3584          *                       = 1 : PCIE power gating enabled
3585          *                Bit[1] = 0 : DDR-PLL shut down disabled
3586          *                       = 1 : DDR-PLL shut down enabled
3587          *                Bit[2] = 0 : DDR-PLL power down disabled
3588          *                       = 1 : DDR-PLL power down enabled
3589          */
3590         info->system_config = le32_to_cpu(info_v9->ulSystemConfig);
3591         info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo);
3592         info->boot_up_nb_voltage = le16_to_cpu(info_v9->usBootUpNBVoltage);
3593         info->ext_disp_conn_info_offset = le16_to_cpu(info_v9->usExtDispConnInfoOffset);
3594         info->memory_type = info_v9->ucMemoryType;
3595         info->ma_channel_number = info_v9->ucUMAChannelNumber;
3596         info->gmc_restore_reset_time = le32_to_cpu(info_v9->ulGMCRestoreResetTime);
3597
3598         info->minimum_n_clk = le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]);
3599         for (i = 1; i < 4; ++i)
3600                 info->minimum_n_clk =
3601                         info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ?
3602                         info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]);
3603
3604         info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk);
3605         info->ddr_dll_power_up_time = le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime);
3606         info->ddr_pll_power_up_time = le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime);
3607         info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType);
3608         info->lvds_ss_percentage = le16_to_cpu(info_v9->usLvdsSSPercentage);
3609         info->lvds_sspread_rate_in_10hz = le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz);
3610         info->hdmi_ss_percentage = le16_to_cpu(info_v9->usHDMISSPercentage);
3611         info->hdmi_sspread_rate_in_10hz = le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz);
3612         info->dvi_ss_percentage = le16_to_cpu(info_v9->usDVISSPercentage);
3613         info->dvi_sspread_rate_in_10_hz = le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz);
3614
3615         info->max_lvds_pclk_freq_in_single_link =
3616                 le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink);
3617         info->lvds_misc = info_v9->ucLvdsMisc;
3618         info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
3619                 info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
3620         info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
3621                 info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
3622         info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
3623                 info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
3624         info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
3625                 info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
3626         info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
3627                 info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
3628         info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
3629                 info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
3630         info->lvds_off_to_on_delay_in_4ms =
3631                 info_v9->ucLVDSOffToOnDelay_in4Ms;
3632         info->lvds_bit_depth_control_val =
3633                 le32_to_cpu(info_v9->ulLCDBitDepthControlVal);
3634
3635         for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
3636                 /* Convert [10KHz] into [KHz] */
3637                 info->avail_s_clk[i].supported_s_clk =
3638                         le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10;
3639                 info->avail_s_clk[i].voltage_index =
3640                         le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex);
3641                 info->avail_s_clk[i].voltage_id =
3642                         le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID);
3643         }
3644
3645         for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
3646                 info->ext_disp_conn_info.gu_id[i] =
3647                         info_v9->sExtDispConnInfo.ucGuid[i];
3648         }
3649
3650         for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
3651                 info->ext_disp_conn_info.path[i].device_connector_id =
3652                         object_id_from_bios_object_id(
3653                                 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector));
3654
3655                 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
3656                         object_id_from_bios_object_id(
3657                                 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
3658
3659                 info->ext_disp_conn_info.path[i].device_tag =
3660                         le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag);
3661                 info->ext_disp_conn_info.path[i].device_acpi_enum =
3662                         le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
3663                 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
3664                         info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
3665                 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
3666                         info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
3667                 info->ext_disp_conn_info.path[i].channel_mapping.raw =
3668                         info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping;
3669         }
3670         info->ext_disp_conn_info.checksum =
3671                 info_v9->sExtDispConnInfo.ucChecksum;
3672
3673         return BP_RESULT_OK;
3674 }
3675
3676 /*
3677  * construct_integrated_info
3678  *
3679  * @brief
3680  * Get integrated BIOS information based on table revision
3681  *
3682  * @param
3683  * bios_parser *bp - [in]BIOS parser handler to get master data table
3684  * integrated_info *info - [out] store and output integrated info
3685  *
3686  * @return
3687  * enum bp_result - BP_RESULT_OK if information is available,
3688  *                  BP_RESULT_BADBIOSTABLE otherwise.
3689  */
3690 static enum bp_result construct_integrated_info(
3691         struct bios_parser *bp,
3692         struct integrated_info *info)
3693 {
3694         enum bp_result result = BP_RESULT_BADBIOSTABLE;
3695
3696         ATOM_COMMON_TABLE_HEADER *header;
3697         struct atom_data_revision revision;
3698
3699         if (bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) {
3700                 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
3701                                 bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
3702
3703                 get_atom_data_table_revision(header, &revision);
3704
3705                 /* Don't need to check major revision as they are all 1 */
3706                 switch (revision.minor) {
3707                 case 8:
3708                         result = get_integrated_info_v8(bp, info);
3709                         break;
3710                 case 9:
3711                         result = get_integrated_info_v9(bp, info);
3712                         break;
3713                 default:
3714                         return result;
3715
3716                 }
3717         }
3718
3719         /* Sort voltage table from low to high*/
3720         if (result == BP_RESULT_OK) {
3721                 struct clock_voltage_caps temp = {0, 0};
3722                 uint32_t i;
3723                 uint32_t j;
3724
3725                 for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
3726                         for (j = i; j > 0; --j) {
3727                                 if (
3728                                                 info->disp_clk_voltage[j].max_supported_clk <
3729                                                 info->disp_clk_voltage[j-1].max_supported_clk) {
3730                                         /* swap j and j - 1*/
3731                                         temp = info->disp_clk_voltage[j-1];
3732                                         info->disp_clk_voltage[j-1] =
3733                                                         info->disp_clk_voltage[j];
3734                                         info->disp_clk_voltage[j] = temp;
3735                                 }
3736                         }
3737                 }
3738
3739         }
3740
3741         return result;
3742 }
3743
3744 static struct integrated_info *bios_parser_create_integrated_info(
3745         struct dc_bios *dcb)
3746 {
3747         struct bios_parser *bp = BP_FROM_DCB(dcb);
3748         struct integrated_info *info = NULL;
3749
3750         info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL);
3751
3752         if (info == NULL) {
3753                 ASSERT_CRITICAL(0);
3754                 return NULL;
3755         }
3756
3757         if (construct_integrated_info(bp, info) == BP_RESULT_OK)
3758                 return info;
3759
3760         kfree(info);
3761
3762         return NULL;
3763 }
3764
3765 enum bp_result update_slot_layout_info(
3766         struct dc_bios *dcb,
3767         unsigned int i,
3768         struct slot_layout_info *slot_layout_info,
3769         unsigned int record_offset)
3770 {
3771         unsigned int j;
3772         struct bios_parser *bp;
3773         ATOM_BRACKET_LAYOUT_RECORD *record;
3774         ATOM_COMMON_RECORD_HEADER *record_header;
3775         enum bp_result result = BP_RESULT_NORECORD;
3776
3777         bp = BP_FROM_DCB(dcb);
3778         record = NULL;
3779         record_header = NULL;
3780
3781         for (;;) {
3782
3783                 record_header = (ATOM_COMMON_RECORD_HEADER *)
3784                         GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);
3785                 if (record_header == NULL) {
3786                         result = BP_RESULT_BADBIOSTABLE;
3787                         break;
3788                 }
3789
3790                 /* the end of the list */
3791                 if (record_header->ucRecordType == 0xff ||
3792                         record_header->ucRecordSize == 0)       {
3793                         break;
3794                 }
3795
3796                 if (record_header->ucRecordType ==
3797                         ATOM_BRACKET_LAYOUT_RECORD_TYPE &&
3798                         sizeof(ATOM_BRACKET_LAYOUT_RECORD)
3799                         <= record_header->ucRecordSize) {
3800                         record = (ATOM_BRACKET_LAYOUT_RECORD *)
3801                                 (record_header);
3802                         result = BP_RESULT_OK;
3803                         break;
3804                 }
3805
3806                 record_offset += record_header->ucRecordSize;
3807         }
3808
3809         /* return if the record not found */
3810         if (result != BP_RESULT_OK)
3811                 return result;
3812
3813         /* get slot sizes */
3814         slot_layout_info->length = record->ucLength;
3815         slot_layout_info->width = record->ucWidth;
3816
3817         /* get info for each connector in the slot */
3818         slot_layout_info->num_of_connectors = record->ucConnNum;
3819         for (j = 0; j < slot_layout_info->num_of_connectors; ++j) {
3820                 slot_layout_info->connectors[j].connector_type =
3821                         (enum connector_layout_type)
3822                         (record->asConnInfo[j].ucConnectorType);
3823                 switch (record->asConnInfo[j].ucConnectorType) {
3824                 case CONNECTOR_TYPE_DVI_D:
3825                         slot_layout_info->connectors[j].connector_type =
3826                                 CONNECTOR_LAYOUT_TYPE_DVI_D;
3827                         slot_layout_info->connectors[j].length =
3828                                 CONNECTOR_SIZE_DVI;
3829                         break;
3830
3831                 case CONNECTOR_TYPE_HDMI:
3832                         slot_layout_info->connectors[j].connector_type =
3833                                 CONNECTOR_LAYOUT_TYPE_HDMI;
3834                         slot_layout_info->connectors[j].length =
3835                                 CONNECTOR_SIZE_HDMI;
3836                         break;
3837
3838                 case CONNECTOR_TYPE_DISPLAY_PORT:
3839                         slot_layout_info->connectors[j].connector_type =
3840                                 CONNECTOR_LAYOUT_TYPE_DP;
3841                         slot_layout_info->connectors[j].length =
3842                                 CONNECTOR_SIZE_DP;
3843                         break;
3844
3845                 case CONNECTOR_TYPE_MINI_DISPLAY_PORT:
3846                         slot_layout_info->connectors[j].connector_type =
3847                                 CONNECTOR_LAYOUT_TYPE_MINI_DP;
3848                         slot_layout_info->connectors[j].length =
3849                                 CONNECTOR_SIZE_MINI_DP;
3850                         break;
3851
3852                 default:
3853                         slot_layout_info->connectors[j].connector_type =
3854                                 CONNECTOR_LAYOUT_TYPE_UNKNOWN;
3855                         slot_layout_info->connectors[j].length =
3856                                 CONNECTOR_SIZE_UNKNOWN;
3857                 }
3858
3859                 slot_layout_info->connectors[j].position =
3860                         record->asConnInfo[j].ucPosition;
3861                 slot_layout_info->connectors[j].connector_id =
3862                         object_id_from_bios_object_id(
3863                                 record->asConnInfo[j].usConnectorObjectId);
3864         }
3865         return result;
3866 }
3867
3868
3869 enum bp_result get_bracket_layout_record(
3870         struct dc_bios *dcb,
3871         unsigned int bracket_layout_id,
3872         struct slot_layout_info *slot_layout_info)
3873 {
3874         unsigned int i;
3875         unsigned int record_offset;
3876         struct bios_parser *bp;
3877         enum bp_result result;
3878         ATOM_OBJECT *object;
3879         ATOM_OBJECT_TABLE *object_table;
3880         unsigned int genericTableOffset;
3881
3882         bp = BP_FROM_DCB(dcb);
3883         object = NULL;
3884         if (slot_layout_info == NULL) {
3885                 DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");
3886                 return BP_RESULT_BADINPUT;
3887         }
3888
3889
3890         genericTableOffset = bp->object_info_tbl_offset +
3891                 bp->object_info_tbl.v1_3->usMiscObjectTableOffset;
3892         object_table = (ATOM_OBJECT_TABLE *)
3893                 GET_IMAGE(ATOM_OBJECT_TABLE, genericTableOffset);
3894         if (!object_table)
3895                 return BP_RESULT_FAILURE;
3896
3897         result = BP_RESULT_NORECORD;
3898         for (i = 0; i < object_table->ucNumberOfObjects; ++i) {
3899
3900                 if (bracket_layout_id ==
3901                         object_table->asObjects[i].usObjectID) {
3902
3903                         object = &object_table->asObjects[i];
3904                         record_offset = object->usRecordOffset +
3905                                 bp->object_info_tbl_offset;
3906
3907                         result = update_slot_layout_info(dcb, i,
3908                                 slot_layout_info, record_offset);
3909                         break;
3910                 }
3911         }
3912         return result;
3913 }
3914
3915 static enum bp_result bios_get_board_layout_info(
3916         struct dc_bios *dcb,
3917         struct board_layout_info *board_layout_info)
3918 {
3919         unsigned int i;
3920         struct bios_parser *bp;
3921         enum bp_result record_result;
3922
3923         const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {
3924                 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1,
3925                 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2,
3926                 0, 0
3927         };
3928
3929         bp = BP_FROM_DCB(dcb);
3930         if (board_layout_info == NULL) {
3931                 DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");
3932                 return BP_RESULT_BADINPUT;
3933         }
3934
3935         board_layout_info->num_of_slots = 0;
3936
3937         for (i = 0; i < MAX_BOARD_SLOTS; ++i) {
3938                 record_result = get_bracket_layout_record(dcb,
3939                         slot_index_to_vbios_id[i],
3940                         &board_layout_info->slots[i]);
3941
3942                 if (record_result == BP_RESULT_NORECORD && i > 0)
3943                         break; /* no more slots present in bios */
3944                 else if (record_result != BP_RESULT_OK)
3945                         return record_result;  /* fail */
3946
3947                 ++board_layout_info->num_of_slots;
3948         }
3949
3950         /* all data is valid */
3951         board_layout_info->is_number_of_slots_valid = 1;
3952         board_layout_info->is_slots_size_valid = 1;
3953         board_layout_info->is_connector_offsets_valid = 1;
3954         board_layout_info->is_connector_lengths_valid = 1;
3955
3956         return BP_RESULT_OK;
3957 }
3958
3959 /******************************************************************************/
3960
3961 static const struct dc_vbios_funcs vbios_funcs = {
3962         .get_connectors_number = bios_parser_get_connectors_number,
3963
3964         .get_encoder_id = bios_parser_get_encoder_id,
3965
3966         .get_connector_id = bios_parser_get_connector_id,
3967
3968         .get_dst_number = bios_parser_get_dst_number,
3969
3970         .get_src_obj = bios_parser_get_src_obj,
3971
3972         .get_dst_obj = bios_parser_get_dst_obj,
3973
3974         .get_i2c_info = bios_parser_get_i2c_info,
3975
3976         .get_voltage_ddc_info = bios_parser_get_voltage_ddc_info,
3977
3978         .get_thermal_ddc_info = bios_parser_get_thermal_ddc_info,
3979
3980         .get_hpd_info = bios_parser_get_hpd_info,
3981
3982         .get_device_tag = bios_parser_get_device_tag,
3983
3984         .get_firmware_info = bios_parser_get_firmware_info,
3985
3986         .get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
3987
3988         .get_ss_entry_number = bios_parser_get_ss_entry_number,
3989
3990         .get_embedded_panel_info = bios_parser_get_embedded_panel_info,
3991
3992         .get_gpio_pin_info = bios_parser_get_gpio_pin_info,
3993
3994         .get_encoder_cap_info = bios_parser_get_encoder_cap_info,
3995
3996         /* bios scratch register communication */
3997         .is_accelerated_mode = bios_is_accelerated_mode,
3998         .get_vga_enabled_displays = bios_get_vga_enabled_displays,
3999
4000         .set_scratch_critical_state = bios_parser_set_scratch_critical_state,
4001
4002         .is_device_id_supported = bios_parser_is_device_id_supported,
4003
4004         /* COMMANDS */
4005         .encoder_control = bios_parser_encoder_control,
4006
4007         .transmitter_control = bios_parser_transmitter_control,
4008
4009         .crt_control = bios_parser_crt_control,  /* not used in DAL3.  keep for now in case we need to support VGA on Bonaire */
4010
4011         .enable_crtc = bios_parser_enable_crtc,
4012
4013         .adjust_pixel_clock = bios_parser_adjust_pixel_clock,
4014
4015         .set_pixel_clock = bios_parser_set_pixel_clock,
4016
4017         .set_dce_clock = bios_parser_set_dce_clock,
4018
4019         .enable_spread_spectrum_on_ppll = bios_parser_enable_spread_spectrum_on_ppll,
4020
4021         .program_crtc_timing = bios_parser_program_crtc_timing, /* still use.  should probably retire and program directly */
4022
4023         .crtc_source_select = bios_parser_crtc_source_select,  /* still use.  should probably retire and program directly */
4024
4025         .program_display_engine_pll = bios_parser_program_display_engine_pll,
4026
4027         .enable_disp_power_gating = bios_parser_enable_disp_power_gating,
4028
4029         /* SW init and patch */
4030         .post_init = bios_parser_post_init,  /* patch vbios table for mxm module by reading i2c */
4031
4032         .bios_parser_destroy = bios_parser_destroy,
4033
4034         .get_board_layout_info = bios_get_board_layout_info,
4035 };
4036
4037 static bool bios_parser_construct(
4038         struct bios_parser *bp,
4039         struct bp_init_data *init,
4040         enum dce_version dce_version)
4041 {
4042         uint16_t *rom_header_offset = NULL;
4043         ATOM_ROM_HEADER *rom_header = NULL;
4044         ATOM_OBJECT_HEADER *object_info_tbl;
4045         struct atom_data_revision tbl_rev = {0};
4046
4047         if (!init)
4048                 return false;
4049
4050         if (!init->bios)
4051                 return false;
4052
4053         bp->base.funcs = &vbios_funcs;
4054         bp->base.bios = init->bios;
4055         bp->base.bios_size = bp->base.bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT;
4056
4057         bp->base.ctx = init->ctx;
4058         bp->base.bios_local_image = NULL;
4059
4060         rom_header_offset =
4061         GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER);
4062
4063         if (!rom_header_offset)
4064                 return false;
4065
4066         rom_header = GET_IMAGE(ATOM_ROM_HEADER, *rom_header_offset);
4067
4068         if (!rom_header)
4069                 return false;
4070
4071         get_atom_data_table_revision(&rom_header->sHeader, &tbl_rev);
4072         if (tbl_rev.major >= 2 && tbl_rev.minor >= 2)
4073                 return false;
4074
4075         bp->master_data_tbl =
4076         GET_IMAGE(ATOM_MASTER_DATA_TABLE,
4077                 rom_header->usMasterDataTableOffset);
4078
4079         if (!bp->master_data_tbl)
4080                 return false;
4081
4082         bp->object_info_tbl_offset = DATA_TABLES(Object_Header);
4083
4084         if (!bp->object_info_tbl_offset)
4085                 return false;
4086
4087         object_info_tbl =
4088         GET_IMAGE(ATOM_OBJECT_HEADER, bp->object_info_tbl_offset);
4089
4090         if (!object_info_tbl)
4091                 return false;
4092
4093         get_atom_data_table_revision(&object_info_tbl->sHeader,
4094                 &bp->object_info_tbl.revision);
4095
4096         if (bp->object_info_tbl.revision.major == 1
4097                 && bp->object_info_tbl.revision.minor >= 3) {
4098                 ATOM_OBJECT_HEADER_V3 *tbl_v3;
4099
4100                 tbl_v3 = GET_IMAGE(ATOM_OBJECT_HEADER_V3,
4101                         bp->object_info_tbl_offset);
4102                 if (!tbl_v3)
4103                         return false;
4104
4105                 bp->object_info_tbl.v1_3 = tbl_v3;
4106         } else if (bp->object_info_tbl.revision.major == 1
4107                 && bp->object_info_tbl.revision.minor >= 1)
4108                 bp->object_info_tbl.v1_1 = object_info_tbl;
4109         else
4110                 return false;
4111
4112         dal_bios_parser_init_cmd_tbl(bp);
4113         dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version);
4114
4115         bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);
4116
4117         return true;
4118 }
4119
4120 /******************************************************************************/