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