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