2 * Copyright 2012-15 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
26 #include <linux/slab.h>
28 #include "dm_services.h"
32 #include "dc_bios_types.h"
33 #include "include/gpio_service_interface.h"
34 #include "include/grph_object_ctrl_defs.h"
35 #include "include/bios_parser_interface.h"
36 #include "include/i2caux_interface.h"
37 #include "include/logger_interface.h"
39 #include "command_table.h"
40 #include "bios_parser_helper.h"
41 #include "command_table_helper.h"
42 #include "bios_parser.h"
43 #include "bios_parser_types_internal.h"
44 #include "bios_parser_interface.h"
46 #include "bios_parser_common.h"
50 #define THREE_PERCENT_OF_10000 300
52 #define LAST_RECORD_TYPE 0xff
57 #define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table)
59 static void get_atom_data_table_revision(
60 ATOM_COMMON_TABLE_HEADER
*atom_data_tbl
,
61 struct atom_data_revision
*tbl_revision
);
62 static uint32_t get_src_obj_list(struct bios_parser
*bp
, ATOM_OBJECT
*object
,
64 static ATOM_OBJECT
*get_bios_object(struct bios_parser
*bp
,
65 struct graphics_object_id id
);
66 static enum bp_result
get_gpio_i2c_info(struct bios_parser
*bp
,
67 ATOM_I2C_RECORD
*record
,
68 struct graphics_object_i2c_info
*info
);
69 static ATOM_HPD_INT_RECORD
*get_hpd_record(struct bios_parser
*bp
,
71 static struct device_id
device_type_from_device_id(uint16_t device_id
);
72 static uint32_t signal_to_ss_id(enum as_signal_type signal
);
73 static uint32_t get_support_mask_for_device_id(struct device_id device_id
);
74 static ATOM_ENCODER_CAP_RECORD_V2
*get_encoder_cap_record(
75 struct bios_parser
*bp
,
78 #define BIOS_IMAGE_SIZE_OFFSET 2
79 #define BIOS_IMAGE_SIZE_UNIT 512
81 /*****************************************************************************/
82 static bool bios_parser_construct(
83 struct bios_parser
*bp
,
84 struct bp_init_data
*init
,
85 enum dce_version dce_version
);
87 static uint8_t bios_parser_get_connectors_number(
90 static enum bp_result
bios_parser_get_embedded_panel_info(
92 struct embedded_panel_info
*info
);
94 /*****************************************************************************/
96 struct dc_bios
*bios_parser_create(
97 struct bp_init_data
*init
,
98 enum dce_version dce_version
)
100 struct bios_parser
*bp
= NULL
;
102 bp
= kzalloc(sizeof(struct bios_parser
), GFP_KERNEL
);
106 if (bios_parser_construct(bp
, init
, dce_version
))
114 static void bios_parser_destruct(struct bios_parser
*bp
)
116 kfree(bp
->base
.bios_local_image
);
117 kfree(bp
->base
.integrated_info
);
120 static void bios_parser_destroy(struct dc_bios
**dcb
)
122 struct bios_parser
*bp
= BP_FROM_DCB(*dcb
);
129 bios_parser_destruct(bp
);
135 static uint8_t get_number_of_objects(struct bios_parser
*bp
, uint32_t offset
)
137 ATOM_OBJECT_TABLE
*table
;
139 uint32_t object_table_offset
= bp
->object_info_tbl_offset
+ offset
;
141 table
= GET_IMAGE(ATOM_OBJECT_TABLE
, object_table_offset
);
146 return table
->ucNumberOfObjects
;
149 static uint8_t bios_parser_get_connectors_number(struct dc_bios
*dcb
)
151 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
153 return get_number_of_objects(bp
,
154 le16_to_cpu(bp
->object_info_tbl
.v1_1
->usConnectorObjectTableOffset
));
157 static struct graphics_object_id
bios_parser_get_connector_id(
161 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
162 struct graphics_object_id object_id
= dal_graphics_object_id_init(
163 0, ENUM_ID_UNKNOWN
, OBJECT_TYPE_UNKNOWN
);
166 uint32_t connector_table_offset
= bp
->object_info_tbl_offset
167 + le16_to_cpu(bp
->object_info_tbl
.v1_1
->usConnectorObjectTableOffset
);
169 ATOM_OBJECT_TABLE
*tbl
=
170 GET_IMAGE(ATOM_OBJECT_TABLE
, connector_table_offset
);
173 dm_error("Can't get connector table from atom bios.\n");
177 if (tbl
->ucNumberOfObjects
<= i
) {
178 dm_error("Can't find connector id %d in connector table of size %d.\n",
179 i
, tbl
->ucNumberOfObjects
);
183 id
= le16_to_cpu(tbl
->asObjects
[i
].usObjectID
);
184 object_id
= object_id_from_bios_object_id(id
);
188 static enum bp_result
bios_parser_get_src_obj(struct dc_bios
*dcb
,
189 struct graphics_object_id object_id
, uint32_t index
,
190 struct graphics_object_id
*src_object_id
)
195 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
198 return BP_RESULT_BADINPUT
;
200 object
= get_bios_object(bp
, object_id
);
203 BREAK_TO_DEBUGGER(); /* Invalid object id */
204 return BP_RESULT_BADINPUT
;
207 number
= get_src_obj_list(bp
, object
, &id
);
210 return BP_RESULT_BADINPUT
;
212 *src_object_id
= object_id_from_bios_object_id(id
[index
]);
217 static enum bp_result
bios_parser_get_i2c_info(struct dc_bios
*dcb
,
218 struct graphics_object_id id
,
219 struct graphics_object_i2c_info
*info
)
223 ATOM_COMMON_RECORD_HEADER
*header
;
224 ATOM_I2C_RECORD
*record
;
225 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
228 return BP_RESULT_BADINPUT
;
230 object
= get_bios_object(bp
, id
);
233 return BP_RESULT_BADINPUT
;
235 offset
= le16_to_cpu(object
->usRecordOffset
)
236 + bp
->object_info_tbl_offset
;
239 header
= GET_IMAGE(ATOM_COMMON_RECORD_HEADER
, offset
);
242 return BP_RESULT_BADBIOSTABLE
;
244 if (LAST_RECORD_TYPE
== header
->ucRecordType
||
245 !header
->ucRecordSize
)
248 if (ATOM_I2C_RECORD_TYPE
== header
->ucRecordType
249 && sizeof(ATOM_I2C_RECORD
) <= header
->ucRecordSize
) {
250 /* get the I2C info */
251 record
= (ATOM_I2C_RECORD
*) header
;
253 if (get_gpio_i2c_info(bp
, record
, info
) == BP_RESULT_OK
)
257 offset
+= header
->ucRecordSize
;
260 return BP_RESULT_NORECORD
;
263 static enum bp_result
bios_parser_get_hpd_info(struct dc_bios
*dcb
,
264 struct graphics_object_id id
,
265 struct graphics_object_hpd_info
*info
)
267 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
269 ATOM_HPD_INT_RECORD
*record
= NULL
;
272 return BP_RESULT_BADINPUT
;
274 object
= get_bios_object(bp
, id
);
277 return BP_RESULT_BADINPUT
;
279 record
= get_hpd_record(bp
, object
);
281 if (record
!= NULL
) {
282 info
->hpd_int_gpio_uid
= record
->ucHPDIntGPIOID
;
283 info
->hpd_active
= record
->ucPlugged_PinState
;
287 return BP_RESULT_NORECORD
;
290 static enum bp_result
bios_parser_get_device_tag_record(
291 struct bios_parser
*bp
,
293 ATOM_CONNECTOR_DEVICE_TAG_RECORD
**record
)
295 ATOM_COMMON_RECORD_HEADER
*header
;
298 offset
= le16_to_cpu(object
->usRecordOffset
)
299 + bp
->object_info_tbl_offset
;
302 header
= GET_IMAGE(ATOM_COMMON_RECORD_HEADER
, offset
);
305 return BP_RESULT_BADBIOSTABLE
;
307 offset
+= header
->ucRecordSize
;
309 if (LAST_RECORD_TYPE
== header
->ucRecordType
||
310 !header
->ucRecordSize
)
313 if (ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE
!=
314 header
->ucRecordType
)
317 if (sizeof(ATOM_CONNECTOR_DEVICE_TAG
) > header
->ucRecordSize
)
320 *record
= (ATOM_CONNECTOR_DEVICE_TAG_RECORD
*) header
;
324 return BP_RESULT_NORECORD
;
327 static enum bp_result
bios_parser_get_device_tag(
329 struct graphics_object_id connector_object_id
,
330 uint32_t device_tag_index
,
331 struct connector_device_tag_info
*info
)
333 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
335 ATOM_CONNECTOR_DEVICE_TAG_RECORD
*record
= NULL
;
336 ATOM_CONNECTOR_DEVICE_TAG
*device_tag
;
339 return BP_RESULT_BADINPUT
;
341 /* getBiosObject will return MXM object */
342 object
= get_bios_object(bp
, connector_object_id
);
345 BREAK_TO_DEBUGGER(); /* Invalid object id */
346 return BP_RESULT_BADINPUT
;
349 if (bios_parser_get_device_tag_record(bp
, object
, &record
)
351 return BP_RESULT_NORECORD
;
353 if (device_tag_index
>= record
->ucNumberOfDevice
)
354 return BP_RESULT_NORECORD
;
356 device_tag
= &record
->asDeviceTag
[device_tag_index
];
358 info
->acpi_device
= le32_to_cpu(device_tag
->ulACPIDeviceEnum
);
360 device_type_from_device_id(le16_to_cpu(device_tag
->usDeviceID
));
365 static enum bp_result
get_firmware_info_v1_4(
366 struct bios_parser
*bp
,
367 struct dc_firmware_info
*info
);
368 static enum bp_result
get_firmware_info_v2_1(
369 struct bios_parser
*bp
,
370 struct dc_firmware_info
*info
);
371 static enum bp_result
get_firmware_info_v2_2(
372 struct bios_parser
*bp
,
373 struct dc_firmware_info
*info
);
375 static enum bp_result
bios_parser_get_firmware_info(
377 struct dc_firmware_info
*info
)
379 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
380 enum bp_result result
= BP_RESULT_BADBIOSTABLE
;
381 ATOM_COMMON_TABLE_HEADER
*header
;
382 struct atom_data_revision revision
;
384 if (info
&& DATA_TABLES(FirmwareInfo
)) {
385 header
= GET_IMAGE(ATOM_COMMON_TABLE_HEADER
,
386 DATA_TABLES(FirmwareInfo
));
387 get_atom_data_table_revision(header
, &revision
);
388 switch (revision
.major
) {
390 switch (revision
.minor
) {
392 result
= get_firmware_info_v1_4(bp
, info
);
400 switch (revision
.minor
) {
402 result
= get_firmware_info_v2_1(bp
, info
);
405 result
= get_firmware_info_v2_2(bp
, info
);
419 static enum bp_result
get_firmware_info_v1_4(
420 struct bios_parser
*bp
,
421 struct dc_firmware_info
*info
)
423 ATOM_FIRMWARE_INFO_V1_4
*firmware_info
=
424 GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4
,
425 DATA_TABLES(FirmwareInfo
));
428 return BP_RESULT_BADINPUT
;
431 return BP_RESULT_BADBIOSTABLE
;
433 memset(info
, 0, sizeof(*info
));
435 /* Pixel clock pll information. We need to convert from 10KHz units into
437 info
->pll_info
.crystal_frequency
=
438 le16_to_cpu(firmware_info
->usReferenceClock
) * 10;
439 info
->pll_info
.min_input_pxl_clk_pll_frequency
=
440 le16_to_cpu(firmware_info
->usMinPixelClockPLL_Input
) * 10;
441 info
->pll_info
.max_input_pxl_clk_pll_frequency
=
442 le16_to_cpu(firmware_info
->usMaxPixelClockPLL_Input
) * 10;
443 info
->pll_info
.min_output_pxl_clk_pll_frequency
=
444 le32_to_cpu(firmware_info
->ulMinPixelClockPLL_Output
) * 10;
445 info
->pll_info
.max_output_pxl_clk_pll_frequency
=
446 le32_to_cpu(firmware_info
->ulMaxPixelClockPLL_Output
) * 10;
448 if (firmware_info
->usFirmwareCapability
.sbfAccess
.MemoryClockSS_Support
)
449 /* Since there is no information on the SS, report conservative
450 * value 3% for bandwidth calculation */
452 info
->feature
.memory_clk_ss_percentage
= THREE_PERCENT_OF_10000
;
454 if (firmware_info
->usFirmwareCapability
.sbfAccess
.EngineClockSS_Support
)
455 /* Since there is no information on the SS,report conservative
456 * value 3% for bandwidth calculation */
458 info
->feature
.engine_clk_ss_percentage
= THREE_PERCENT_OF_10000
;
463 static enum bp_result
get_ss_info_v3_1(
464 struct bios_parser
*bp
,
467 struct spread_spectrum_info
*ss_info
);
469 static enum bp_result
get_firmware_info_v2_1(
470 struct bios_parser
*bp
,
471 struct dc_firmware_info
*info
)
473 ATOM_FIRMWARE_INFO_V2_1
*firmwareInfo
=
474 GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1
, DATA_TABLES(FirmwareInfo
));
475 struct spread_spectrum_info internalSS
;
479 return BP_RESULT_BADINPUT
;
482 return BP_RESULT_BADBIOSTABLE
;
484 memset(info
, 0, sizeof(*info
));
486 /* Pixel clock pll information. We need to convert from 10KHz units into
488 info
->pll_info
.crystal_frequency
=
489 le16_to_cpu(firmwareInfo
->usCoreReferenceClock
) * 10;
490 info
->pll_info
.min_input_pxl_clk_pll_frequency
=
491 le16_to_cpu(firmwareInfo
->usMinPixelClockPLL_Input
) * 10;
492 info
->pll_info
.max_input_pxl_clk_pll_frequency
=
493 le16_to_cpu(firmwareInfo
->usMaxPixelClockPLL_Input
) * 10;
494 info
->pll_info
.min_output_pxl_clk_pll_frequency
=
495 le32_to_cpu(firmwareInfo
->ulMinPixelClockPLL_Output
) * 10;
496 info
->pll_info
.max_output_pxl_clk_pll_frequency
=
497 le32_to_cpu(firmwareInfo
->ulMaxPixelClockPLL_Output
) * 10;
498 info
->default_display_engine_pll_frequency
=
499 le32_to_cpu(firmwareInfo
->ulDefaultDispEngineClkFreq
) * 10;
500 info
->external_clock_source_frequency_for_dp
=
501 le16_to_cpu(firmwareInfo
->usUniphyDPModeExtClkFreq
) * 10;
502 info
->min_allowed_bl_level
= firmwareInfo
->ucMinAllowedBL_Level
;
504 /* There should be only one entry in the SS info table for Memory Clock
507 if (firmwareInfo
->usFirmwareCapability
.sbfAccess
.MemoryClockSS_Support
)
508 /* Since there is no information for external SS, report
509 * conservative value 3% for bandwidth calculation */
511 info
->feature
.memory_clk_ss_percentage
= THREE_PERCENT_OF_10000
;
512 else if (get_ss_info_v3_1(bp
,
513 ASIC_INTERNAL_MEMORY_SS
, index
, &internalSS
) == BP_RESULT_OK
) {
514 if (internalSS
.spread_spectrum_percentage
) {
515 info
->feature
.memory_clk_ss_percentage
=
516 internalSS
.spread_spectrum_percentage
;
517 if (internalSS
.type
.CENTER_MODE
) {
518 /* if it is centermode, the exact SS Percentage
519 * will be round up of half of the percentage
520 * reported in the SS table */
521 ++info
->feature
.memory_clk_ss_percentage
;
522 info
->feature
.memory_clk_ss_percentage
/= 2;
527 /* There should be only one entry in the SS info table for Engine Clock
530 if (firmwareInfo
->usFirmwareCapability
.sbfAccess
.EngineClockSS_Support
)
531 /* Since there is no information for external SS, report
532 * conservative value 3% for bandwidth calculation */
534 info
->feature
.engine_clk_ss_percentage
= THREE_PERCENT_OF_10000
;
535 else if (get_ss_info_v3_1(bp
,
536 ASIC_INTERNAL_ENGINE_SS
, index
, &internalSS
) == BP_RESULT_OK
) {
537 if (internalSS
.spread_spectrum_percentage
) {
538 info
->feature
.engine_clk_ss_percentage
=
539 internalSS
.spread_spectrum_percentage
;
540 if (internalSS
.type
.CENTER_MODE
) {
541 /* if it is centermode, the exact SS Percentage
542 * will be round up of half of the percentage
543 * reported in the SS table */
544 ++info
->feature
.engine_clk_ss_percentage
;
545 info
->feature
.engine_clk_ss_percentage
/= 2;
553 static enum bp_result
get_firmware_info_v2_2(
554 struct bios_parser
*bp
,
555 struct dc_firmware_info
*info
)
557 ATOM_FIRMWARE_INFO_V2_2
*firmware_info
;
558 struct spread_spectrum_info internal_ss
;
562 return BP_RESULT_BADINPUT
;
564 firmware_info
= GET_IMAGE(ATOM_FIRMWARE_INFO_V2_2
,
565 DATA_TABLES(FirmwareInfo
));
568 return BP_RESULT_BADBIOSTABLE
;
570 memset(info
, 0, sizeof(*info
));
572 /* Pixel clock pll information. We need to convert from 10KHz units into
574 info
->pll_info
.crystal_frequency
=
575 le16_to_cpu(firmware_info
->usCoreReferenceClock
) * 10;
576 info
->pll_info
.min_input_pxl_clk_pll_frequency
=
577 le16_to_cpu(firmware_info
->usMinPixelClockPLL_Input
) * 10;
578 info
->pll_info
.max_input_pxl_clk_pll_frequency
=
579 le16_to_cpu(firmware_info
->usMaxPixelClockPLL_Input
) * 10;
580 info
->pll_info
.min_output_pxl_clk_pll_frequency
=
581 le32_to_cpu(firmware_info
->ulMinPixelClockPLL_Output
) * 10;
582 info
->pll_info
.max_output_pxl_clk_pll_frequency
=
583 le32_to_cpu(firmware_info
->ulMaxPixelClockPLL_Output
) * 10;
584 info
->default_display_engine_pll_frequency
=
585 le32_to_cpu(firmware_info
->ulDefaultDispEngineClkFreq
) * 10;
586 info
->external_clock_source_frequency_for_dp
=
587 le16_to_cpu(firmware_info
->usUniphyDPModeExtClkFreq
) * 10;
589 /* There should be only one entry in the SS info table for Memory Clock
592 if (firmware_info
->usFirmwareCapability
.sbfAccess
.MemoryClockSS_Support
)
593 /* Since there is no information for external SS, report
594 * conservative value 3% for bandwidth calculation */
596 info
->feature
.memory_clk_ss_percentage
= THREE_PERCENT_OF_10000
;
597 else if (get_ss_info_v3_1(bp
,
598 ASIC_INTERNAL_MEMORY_SS
, index
, &internal_ss
) == BP_RESULT_OK
) {
599 if (internal_ss
.spread_spectrum_percentage
) {
600 info
->feature
.memory_clk_ss_percentage
=
601 internal_ss
.spread_spectrum_percentage
;
602 if (internal_ss
.type
.CENTER_MODE
) {
603 /* if it is centermode, the exact SS Percentage
604 * will be round up of half of the percentage
605 * reported in the SS table */
606 ++info
->feature
.memory_clk_ss_percentage
;
607 info
->feature
.memory_clk_ss_percentage
/= 2;
612 /* There should be only one entry in the SS info table for Engine Clock
615 if (firmware_info
->usFirmwareCapability
.sbfAccess
.EngineClockSS_Support
)
616 /* Since there is no information for external SS, report
617 * conservative value 3% for bandwidth calculation */
619 info
->feature
.engine_clk_ss_percentage
= THREE_PERCENT_OF_10000
;
620 else if (get_ss_info_v3_1(bp
,
621 ASIC_INTERNAL_ENGINE_SS
, index
, &internal_ss
) == BP_RESULT_OK
) {
622 if (internal_ss
.spread_spectrum_percentage
) {
623 info
->feature
.engine_clk_ss_percentage
=
624 internal_ss
.spread_spectrum_percentage
;
625 if (internal_ss
.type
.CENTER_MODE
) {
626 /* if it is centermode, the exact SS Percentage
627 * will be round up of half of the percentage
628 * reported in the SS table */
629 ++info
->feature
.engine_clk_ss_percentage
;
630 info
->feature
.engine_clk_ss_percentage
/= 2;
636 info
->remote_display_config
= firmware_info
->ucRemoteDisplayConfig
;
638 /* Is allowed minimum BL level */
639 info
->min_allowed_bl_level
= firmware_info
->ucMinAllowedBL_Level
;
640 /* Used starting from CI */
641 info
->smu_gpu_pll_output_freq
=
642 (uint32_t) (le32_to_cpu(firmware_info
->ulGPUPLL_OutputFreq
) * 10);
647 static enum bp_result
get_ss_info_v3_1(
648 struct bios_parser
*bp
,
651 struct spread_spectrum_info
*ss_info
)
653 ATOM_ASIC_INTERNAL_SS_INFO_V3
*ss_table_header_include
;
654 ATOM_ASIC_SS_ASSIGNMENT_V3
*tbl
;
657 uint32_t table_index
= 0;
660 return BP_RESULT_BADINPUT
;
662 if (!DATA_TABLES(ASIC_InternalSS_Info
))
663 return BP_RESULT_UNSUPPORTED
;
665 ss_table_header_include
= GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3
,
666 DATA_TABLES(ASIC_InternalSS_Info
));
668 (le16_to_cpu(ss_table_header_include
->sHeader
.usStructureSize
)
669 - sizeof(ATOM_COMMON_TABLE_HEADER
))
670 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3
);
672 tbl
= (ATOM_ASIC_SS_ASSIGNMENT_V3
*)
673 &ss_table_header_include
->asSpreadSpectrum
[0];
675 memset(ss_info
, 0, sizeof(struct spread_spectrum_info
));
677 for (i
= 0; i
< table_size
; i
++) {
678 if (tbl
[i
].ucClockIndication
!= (uint8_t) id
)
681 if (table_index
!= index
) {
685 /* VBIOS introduced new defines for Version 3, same values as
686 * before, so now use these new ones for Version 3.
687 * Shouldn't affect field VBIOS's V3 as define values are still
689 * #define SS_MODE_V3_CENTRE_SPREAD_MASK 0x01
690 * #define SS_MODE_V3_EXTERNAL_SS_MASK 0x02
693 * #define ATOM_SS_CENTRE_SPREAD_MODE_MASK 0x00000001
694 * #define ATOM_EXTERNAL_SS_MASK 0x00000002
697 if (SS_MODE_V3_EXTERNAL_SS_MASK
& tbl
[i
].ucSpreadSpectrumMode
)
698 ss_info
->type
.EXTERNAL
= true;
700 if (SS_MODE_V3_CENTRE_SPREAD_MASK
& tbl
[i
].ucSpreadSpectrumMode
)
701 ss_info
->type
.CENTER_MODE
= true;
703 /* Older VBIOS (in field) always provides SS percentage in 0.01%
704 * units set Divider to 100 */
705 ss_info
->spread_percentage_divider
= 100;
707 /* #define SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 0x10 */
708 if (SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK
709 & tbl
[i
].ucSpreadSpectrumMode
)
710 ss_info
->spread_percentage_divider
= 1000;
712 ss_info
->type
.STEP_AND_DELAY_INFO
= false;
713 /* convert [10KHz] into [KHz] */
714 ss_info
->target_clock_range
=
715 le32_to_cpu(tbl
[i
].ulTargetClockRange
) * 10;
716 ss_info
->spread_spectrum_percentage
=
717 (uint32_t)le16_to_cpu(tbl
[i
].usSpreadSpectrumPercentage
);
718 ss_info
->spread_spectrum_range
=
719 (uint32_t)(le16_to_cpu(tbl
[i
].usSpreadRateIn10Hz
) * 10);
723 return BP_RESULT_NORECORD
;
726 static enum bp_result
bios_parser_transmitter_control(
728 struct bp_transmitter_control
*cntl
)
730 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
732 if (!bp
->cmd_tbl
.transmitter_control
)
733 return BP_RESULT_FAILURE
;
735 return bp
->cmd_tbl
.transmitter_control(bp
, cntl
);
738 static enum bp_result
bios_parser_encoder_control(
740 struct bp_encoder_control
*cntl
)
742 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
744 if (!bp
->cmd_tbl
.dig_encoder_control
)
745 return BP_RESULT_FAILURE
;
747 return bp
->cmd_tbl
.dig_encoder_control(bp
, cntl
);
750 static enum bp_result
bios_parser_adjust_pixel_clock(
752 struct bp_adjust_pixel_clock_parameters
*bp_params
)
754 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
756 if (!bp
->cmd_tbl
.adjust_display_pll
)
757 return BP_RESULT_FAILURE
;
759 return bp
->cmd_tbl
.adjust_display_pll(bp
, bp_params
);
762 static enum bp_result
bios_parser_set_pixel_clock(
764 struct bp_pixel_clock_parameters
*bp_params
)
766 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
768 if (!bp
->cmd_tbl
.set_pixel_clock
)
769 return BP_RESULT_FAILURE
;
771 return bp
->cmd_tbl
.set_pixel_clock(bp
, bp_params
);
774 static enum bp_result
bios_parser_set_dce_clock(
776 struct bp_set_dce_clock_parameters
*bp_params
)
778 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
780 if (!bp
->cmd_tbl
.set_dce_clock
)
781 return BP_RESULT_FAILURE
;
783 return bp
->cmd_tbl
.set_dce_clock(bp
, bp_params
);
786 static enum bp_result
bios_parser_enable_spread_spectrum_on_ppll(
788 struct bp_spread_spectrum_parameters
*bp_params
,
791 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
793 if (!bp
->cmd_tbl
.enable_spread_spectrum_on_ppll
)
794 return BP_RESULT_FAILURE
;
796 return bp
->cmd_tbl
.enable_spread_spectrum_on_ppll(
797 bp
, bp_params
, enable
);
801 static enum bp_result
bios_parser_program_crtc_timing(
803 struct bp_hw_crtc_timing_parameters
*bp_params
)
805 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
807 if (!bp
->cmd_tbl
.set_crtc_timing
)
808 return BP_RESULT_FAILURE
;
810 return bp
->cmd_tbl
.set_crtc_timing(bp
, bp_params
);
813 static enum bp_result
bios_parser_program_display_engine_pll(
815 struct bp_pixel_clock_parameters
*bp_params
)
817 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
819 if (!bp
->cmd_tbl
.program_clock
)
820 return BP_RESULT_FAILURE
;
822 return bp
->cmd_tbl
.program_clock(bp
, bp_params
);
827 static enum bp_result
bios_parser_enable_crtc(
829 enum controller_id id
,
832 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
834 if (!bp
->cmd_tbl
.enable_crtc
)
835 return BP_RESULT_FAILURE
;
837 return bp
->cmd_tbl
.enable_crtc(bp
, id
, enable
);
840 static enum bp_result
bios_parser_enable_disp_power_gating(
842 enum controller_id controller_id
,
843 enum bp_pipe_control_action action
)
845 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
847 if (!bp
->cmd_tbl
.enable_disp_power_gating
)
848 return BP_RESULT_FAILURE
;
850 return bp
->cmd_tbl
.enable_disp_power_gating(bp
, controller_id
,
854 static bool bios_parser_is_device_id_supported(
858 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
860 uint32_t mask
= get_support_mask_for_device_id(id
);
862 return (le16_to_cpu(bp
->object_info_tbl
.v1_1
->usDeviceSupport
) & mask
) != 0;
865 static ATOM_HPD_INT_RECORD
*get_hpd_record(struct bios_parser
*bp
,
868 ATOM_COMMON_RECORD_HEADER
*header
;
872 BREAK_TO_DEBUGGER(); /* Invalid object */
876 offset
= le16_to_cpu(object
->usRecordOffset
)
877 + bp
->object_info_tbl_offset
;
880 header
= GET_IMAGE(ATOM_COMMON_RECORD_HEADER
, offset
);
885 if (LAST_RECORD_TYPE
== header
->ucRecordType
||
886 !header
->ucRecordSize
)
889 if (ATOM_HPD_INT_RECORD_TYPE
== header
->ucRecordType
890 && sizeof(ATOM_HPD_INT_RECORD
) <= header
->ucRecordSize
)
891 return (ATOM_HPD_INT_RECORD
*) header
;
893 offset
+= header
->ucRecordSize
;
899 static enum bp_result
get_ss_info_from_ss_info_table(
900 struct bios_parser
*bp
,
902 struct spread_spectrum_info
*ss_info
);
903 static enum bp_result
get_ss_info_from_tbl(
904 struct bios_parser
*bp
,
906 struct spread_spectrum_info
*ss_info
);
908 * bios_parser_get_spread_spectrum_info
909 * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or
910 * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info
911 * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info ver 3.1,
912 * there is only one entry for each signal /ss id. However, there is
913 * no planning of supporting multiple spread Sprectum entry for EverGreen
915 * @param [in] signal, ASSignalType to be converted to info index
916 * @param [in] index, number of entries that match the converted info index
917 * @param [out] ss_info, sprectrum information structure,
918 * @return Bios parser result code
920 static enum bp_result
bios_parser_get_spread_spectrum_info(
922 enum as_signal_type signal
,
924 struct spread_spectrum_info
*ss_info
)
926 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
927 enum bp_result result
= BP_RESULT_UNSUPPORTED
;
928 uint32_t clk_id_ss
= 0;
929 ATOM_COMMON_TABLE_HEADER
*header
;
930 struct atom_data_revision tbl_revision
;
932 if (!ss_info
) /* check for bad input */
933 return BP_RESULT_BADINPUT
;
934 /* signal translation */
935 clk_id_ss
= signal_to_ss_id(signal
);
937 if (!DATA_TABLES(ASIC_InternalSS_Info
))
939 return get_ss_info_from_ss_info_table(bp
, clk_id_ss
,
942 header
= GET_IMAGE(ATOM_COMMON_TABLE_HEADER
,
943 DATA_TABLES(ASIC_InternalSS_Info
));
944 get_atom_data_table_revision(header
, &tbl_revision
);
946 switch (tbl_revision
.major
) {
948 switch (tbl_revision
.minor
) {
950 /* there can not be more then one entry for Internal
951 * SS Info table version 2.1 */
953 return get_ss_info_from_tbl(bp
, clk_id_ss
,
962 switch (tbl_revision
.minor
) {
964 return get_ss_info_v3_1(bp
, clk_id_ss
, index
, ss_info
);
972 /* there can not be more then one entry for SS Info table */
976 static enum bp_result
get_ss_info_from_internal_ss_info_tbl_V2_1(
977 struct bios_parser
*bp
,
979 struct spread_spectrum_info
*info
);
982 * get_ss_info_from_table
983 * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
984 * SS_Info table from the VBIOS
985 * There can not be more than 1 entry for ASIC_InternalSS_Info Ver 2.1 or
989 * @param id, spread sprectrum info index
990 * @param pSSinfo, sprectrum information structure,
991 * @return Bios parser result code
993 static enum bp_result
get_ss_info_from_tbl(
994 struct bios_parser
*bp
,
996 struct spread_spectrum_info
*ss_info
)
998 if (!ss_info
) /* check for bad input, if ss_info is not NULL */
999 return BP_RESULT_BADINPUT
;
1000 /* for SS_Info table only support DP and LVDS */
1001 if (id
== ASIC_INTERNAL_SS_ON_DP
|| id
== ASIC_INTERNAL_SS_ON_LVDS
)
1002 return get_ss_info_from_ss_info_table(bp
, id
, ss_info
);
1004 return get_ss_info_from_internal_ss_info_tbl_V2_1(bp
, id
,
1009 * get_ss_info_from_internal_ss_info_tbl_V2_1
1010 * Get spread sprectrum information from the ASIC_InternalSS_Info table Ver 2.1
1012 * There will not be multiple entry for Ver 2.1
1014 * @param id, spread sprectrum info index
1015 * @param pSSinfo, sprectrum information structure,
1016 * @return Bios parser result code
1018 static enum bp_result
get_ss_info_from_internal_ss_info_tbl_V2_1(
1019 struct bios_parser
*bp
,
1021 struct spread_spectrum_info
*info
)
1023 enum bp_result result
= BP_RESULT_UNSUPPORTED
;
1024 ATOM_ASIC_INTERNAL_SS_INFO_V2
*header
;
1025 ATOM_ASIC_SS_ASSIGNMENT_V2
*tbl
;
1026 uint32_t tbl_size
, i
;
1028 if (!DATA_TABLES(ASIC_InternalSS_Info
))
1031 header
= GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2
,
1032 DATA_TABLES(ASIC_InternalSS_Info
));
1034 memset(info
, 0, sizeof(struct spread_spectrum_info
));
1036 tbl_size
= (le16_to_cpu(header
->sHeader
.usStructureSize
)
1037 - sizeof(ATOM_COMMON_TABLE_HEADER
))
1038 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2
);
1040 tbl
= (ATOM_ASIC_SS_ASSIGNMENT_V2
*)
1041 &(header
->asSpreadSpectrum
[0]);
1042 for (i
= 0; i
< tbl_size
; i
++) {
1043 result
= BP_RESULT_NORECORD
;
1045 if (tbl
[i
].ucClockIndication
!= (uint8_t)id
)
1048 if (ATOM_EXTERNAL_SS_MASK
1049 & tbl
[i
].ucSpreadSpectrumMode
) {
1050 info
->type
.EXTERNAL
= true;
1052 if (ATOM_SS_CENTRE_SPREAD_MODE_MASK
1053 & tbl
[i
].ucSpreadSpectrumMode
) {
1054 info
->type
.CENTER_MODE
= true;
1056 info
->type
.STEP_AND_DELAY_INFO
= false;
1057 /* convert [10KHz] into [KHz] */
1058 info
->target_clock_range
=
1059 le32_to_cpu(tbl
[i
].ulTargetClockRange
) * 10;
1060 info
->spread_spectrum_percentage
=
1061 (uint32_t)le16_to_cpu(tbl
[i
].usSpreadSpectrumPercentage
);
1062 info
->spread_spectrum_range
=
1063 (uint32_t)(le16_to_cpu(tbl
[i
].usSpreadRateIn10Hz
) * 10);
1064 result
= BP_RESULT_OK
;
1073 * get_ss_info_from_ss_info_table
1074 * Get spread sprectrum information from the SS_Info table from the VBIOS
1075 * if the pointer to info is NULL, indicate the caller what to know the number
1076 * of entries that matches the id
1077 * for, the SS_Info table, there should not be more than 1 entry match.
1079 * @param [in] id, spread sprectrum id
1080 * @param [out] pSSinfo, sprectrum information structure,
1081 * @return Bios parser result code
1083 static enum bp_result
get_ss_info_from_ss_info_table(
1084 struct bios_parser
*bp
,
1086 struct spread_spectrum_info
*ss_info
)
1088 enum bp_result result
= BP_RESULT_UNSUPPORTED
;
1089 ATOM_SPREAD_SPECTRUM_INFO
*tbl
;
1090 ATOM_COMMON_TABLE_HEADER
*header
;
1091 uint32_t table_size
;
1093 uint32_t id_local
= SS_ID_UNKNOWN
;
1094 struct atom_data_revision revision
;
1096 /* exist of the SS_Info table */
1097 /* check for bad input, pSSinfo can not be NULL */
1098 if (!DATA_TABLES(SS_Info
) || !ss_info
)
1101 header
= GET_IMAGE(ATOM_COMMON_TABLE_HEADER
, DATA_TABLES(SS_Info
));
1102 get_atom_data_table_revision(header
, &revision
);
1104 tbl
= GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO
, DATA_TABLES(SS_Info
));
1106 if (1 != revision
.major
|| 2 > revision
.minor
)
1109 /* have to convert from Internal_SS format to SS_Info format */
1111 case ASIC_INTERNAL_SS_ON_DP
:
1112 id_local
= SS_ID_DP1
;
1114 case ASIC_INTERNAL_SS_ON_LVDS
:
1116 struct embedded_panel_info panel_info
;
1118 if (bios_parser_get_embedded_panel_info(&bp
->base
, &panel_info
)
1120 id_local
= panel_info
.ss_id
;
1127 if (id_local
== SS_ID_UNKNOWN
)
1130 table_size
= (le16_to_cpu(tbl
->sHeader
.usStructureSize
) -
1131 sizeof(ATOM_COMMON_TABLE_HEADER
)) /
1132 sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT
);
1134 for (i
= 0; i
< table_size
; i
++) {
1135 if (id_local
!= (uint32_t)tbl
->asSS_Info
[i
].ucSS_Id
)
1138 memset(ss_info
, 0, sizeof(struct spread_spectrum_info
));
1140 if (ATOM_EXTERNAL_SS_MASK
&
1141 tbl
->asSS_Info
[i
].ucSpreadSpectrumType
)
1142 ss_info
->type
.EXTERNAL
= true;
1144 if (ATOM_SS_CENTRE_SPREAD_MODE_MASK
&
1145 tbl
->asSS_Info
[i
].ucSpreadSpectrumType
)
1146 ss_info
->type
.CENTER_MODE
= true;
1148 ss_info
->type
.STEP_AND_DELAY_INFO
= true;
1149 ss_info
->spread_spectrum_percentage
=
1150 (uint32_t)le16_to_cpu(tbl
->asSS_Info
[i
].usSpreadSpectrumPercentage
);
1151 ss_info
->step_and_delay_info
.step
= tbl
->asSS_Info
[i
].ucSS_Step
;
1152 ss_info
->step_and_delay_info
.delay
=
1153 tbl
->asSS_Info
[i
].ucSS_Delay
;
1154 ss_info
->step_and_delay_info
.recommended_ref_div
=
1155 tbl
->asSS_Info
[i
].ucRecommendedRef_Div
;
1156 ss_info
->spread_spectrum_range
=
1157 (uint32_t)tbl
->asSS_Info
[i
].ucSS_Range
* 10000;
1159 /* there will be only one entry for each display type in SS_info
1161 result
= BP_RESULT_OK
;
1167 static enum bp_result
get_embedded_panel_info_v1_2(
1168 struct bios_parser
*bp
,
1169 struct embedded_panel_info
*info
);
1170 static enum bp_result
get_embedded_panel_info_v1_3(
1171 struct bios_parser
*bp
,
1172 struct embedded_panel_info
*info
);
1174 static enum bp_result
bios_parser_get_embedded_panel_info(
1175 struct dc_bios
*dcb
,
1176 struct embedded_panel_info
*info
)
1178 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
1179 ATOM_COMMON_TABLE_HEADER
*hdr
;
1181 if (!DATA_TABLES(LCD_Info
))
1182 return BP_RESULT_FAILURE
;
1184 hdr
= GET_IMAGE(ATOM_COMMON_TABLE_HEADER
, DATA_TABLES(LCD_Info
));
1187 return BP_RESULT_BADBIOSTABLE
;
1189 switch (hdr
->ucTableFormatRevision
) {
1191 switch (hdr
->ucTableContentRevision
) {
1195 return get_embedded_panel_info_v1_2(bp
, info
);
1197 return get_embedded_panel_info_v1_3(bp
, info
);
1206 return BP_RESULT_FAILURE
;
1209 static enum bp_result
get_embedded_panel_info_v1_2(
1210 struct bios_parser
*bp
,
1211 struct embedded_panel_info
*info
)
1213 ATOM_LVDS_INFO_V12
*lvds
;
1216 return BP_RESULT_BADINPUT
;
1218 if (!DATA_TABLES(LVDS_Info
))
1219 return BP_RESULT_UNSUPPORTED
;
1222 GET_IMAGE(ATOM_LVDS_INFO_V12
, DATA_TABLES(LVDS_Info
));
1225 return BP_RESULT_BADBIOSTABLE
;
1227 if (1 != lvds
->sHeader
.ucTableFormatRevision
1228 || 2 > lvds
->sHeader
.ucTableContentRevision
)
1229 return BP_RESULT_UNSUPPORTED
;
1231 memset(info
, 0, sizeof(struct embedded_panel_info
));
1233 /* We need to convert from 10KHz units into KHz units*/
1234 info
->lcd_timing
.pixel_clk
=
1235 le16_to_cpu(lvds
->sLCDTiming
.usPixClk
) * 10;
1236 /* usHActive does not include borders, according to VBIOS team*/
1237 info
->lcd_timing
.horizontal_addressable
=
1238 le16_to_cpu(lvds
->sLCDTiming
.usHActive
);
1239 /* usHBlanking_Time includes borders, so we should really be subtracting
1240 * borders duing this translation, but LVDS generally*/
1241 /* doesn't have borders, so we should be okay leaving this as is for
1242 * now. May need to revisit if we ever have LVDS with borders*/
1243 info
->lcd_timing
.horizontal_blanking_time
=
1244 le16_to_cpu(lvds
->sLCDTiming
.usHBlanking_Time
);
1245 /* usVActive does not include borders, according to VBIOS team*/
1246 info
->lcd_timing
.vertical_addressable
=
1247 le16_to_cpu(lvds
->sLCDTiming
.usVActive
);
1248 /* usVBlanking_Time includes borders, so we should really be subtracting
1249 * borders duing this translation, but LVDS generally*/
1250 /* doesn't have borders, so we should be okay leaving this as is for
1251 * now. May need to revisit if we ever have LVDS with borders*/
1252 info
->lcd_timing
.vertical_blanking_time
=
1253 le16_to_cpu(lvds
->sLCDTiming
.usVBlanking_Time
);
1254 info
->lcd_timing
.horizontal_sync_offset
=
1255 le16_to_cpu(lvds
->sLCDTiming
.usHSyncOffset
);
1256 info
->lcd_timing
.horizontal_sync_width
=
1257 le16_to_cpu(lvds
->sLCDTiming
.usHSyncWidth
);
1258 info
->lcd_timing
.vertical_sync_offset
=
1259 le16_to_cpu(lvds
->sLCDTiming
.usVSyncOffset
);
1260 info
->lcd_timing
.vertical_sync_width
=
1261 le16_to_cpu(lvds
->sLCDTiming
.usVSyncWidth
);
1262 info
->lcd_timing
.horizontal_border
= lvds
->sLCDTiming
.ucHBorder
;
1263 info
->lcd_timing
.vertical_border
= lvds
->sLCDTiming
.ucVBorder
;
1264 info
->lcd_timing
.misc_info
.HORIZONTAL_CUT_OFF
=
1265 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.HorizontalCutOff
;
1266 info
->lcd_timing
.misc_info
.H_SYNC_POLARITY
=
1268 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.HSyncPolarity
;
1269 info
->lcd_timing
.misc_info
.V_SYNC_POLARITY
=
1271 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.VSyncPolarity
;
1272 info
->lcd_timing
.misc_info
.VERTICAL_CUT_OFF
=
1273 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.VerticalCutOff
;
1274 info
->lcd_timing
.misc_info
.H_REPLICATION_BY2
=
1275 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.H_ReplicationBy2
;
1276 info
->lcd_timing
.misc_info
.V_REPLICATION_BY2
=
1277 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.V_ReplicationBy2
;
1278 info
->lcd_timing
.misc_info
.COMPOSITE_SYNC
=
1279 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.CompositeSync
;
1280 info
->lcd_timing
.misc_info
.INTERLACE
=
1281 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.Interlace
;
1282 info
->lcd_timing
.misc_info
.DOUBLE_CLOCK
=
1283 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.DoubleClock
;
1284 info
->ss_id
= lvds
->ucSS_Id
;
1287 uint8_t rr
= le16_to_cpu(lvds
->usSupportedRefreshRate
);
1288 /* Get minimum supported refresh rate*/
1289 if (SUPPORTED_LCD_REFRESHRATE_30Hz
& rr
)
1290 info
->supported_rr
.REFRESH_RATE_30HZ
= 1;
1291 else if (SUPPORTED_LCD_REFRESHRATE_40Hz
& rr
)
1292 info
->supported_rr
.REFRESH_RATE_40HZ
= 1;
1293 else if (SUPPORTED_LCD_REFRESHRATE_48Hz
& rr
)
1294 info
->supported_rr
.REFRESH_RATE_48HZ
= 1;
1295 else if (SUPPORTED_LCD_REFRESHRATE_50Hz
& rr
)
1296 info
->supported_rr
.REFRESH_RATE_50HZ
= 1;
1297 else if (SUPPORTED_LCD_REFRESHRATE_60Hz
& rr
)
1298 info
->supported_rr
.REFRESH_RATE_60HZ
= 1;
1301 /*Drr panel support can be reported by VBIOS*/
1302 if (LCDPANEL_CAP_DRR_SUPPORTED
1303 & lvds
->ucLCDPanel_SpecialHandlingCap
)
1304 info
->drr_enabled
= 1;
1306 if (ATOM_PANEL_MISC_DUAL
& lvds
->ucLVDS_Misc
)
1307 info
->lcd_timing
.misc_info
.DOUBLE_CLOCK
= true;
1309 if (ATOM_PANEL_MISC_888RGB
& lvds
->ucLVDS_Misc
)
1310 info
->lcd_timing
.misc_info
.RGB888
= true;
1312 info
->lcd_timing
.misc_info
.GREY_LEVEL
=
1313 (uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL
&
1314 lvds
->ucLVDS_Misc
) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT
;
1316 if (ATOM_PANEL_MISC_SPATIAL
& lvds
->ucLVDS_Misc
)
1317 info
->lcd_timing
.misc_info
.SPATIAL
= true;
1319 if (ATOM_PANEL_MISC_TEMPORAL
& lvds
->ucLVDS_Misc
)
1320 info
->lcd_timing
.misc_info
.TEMPORAL
= true;
1322 if (ATOM_PANEL_MISC_API_ENABLED
& lvds
->ucLVDS_Misc
)
1323 info
->lcd_timing
.misc_info
.API_ENABLED
= true;
1325 return BP_RESULT_OK
;
1328 static enum bp_result
get_embedded_panel_info_v1_3(
1329 struct bios_parser
*bp
,
1330 struct embedded_panel_info
*info
)
1332 ATOM_LCD_INFO_V13
*lvds
;
1335 return BP_RESULT_BADINPUT
;
1337 if (!DATA_TABLES(LCD_Info
))
1338 return BP_RESULT_UNSUPPORTED
;
1340 lvds
= GET_IMAGE(ATOM_LCD_INFO_V13
, DATA_TABLES(LCD_Info
));
1343 return BP_RESULT_BADBIOSTABLE
;
1345 if (!((1 == lvds
->sHeader
.ucTableFormatRevision
)
1346 && (3 <= lvds
->sHeader
.ucTableContentRevision
)))
1347 return BP_RESULT_UNSUPPORTED
;
1349 memset(info
, 0, sizeof(struct embedded_panel_info
));
1351 /* We need to convert from 10KHz units into KHz units */
1352 info
->lcd_timing
.pixel_clk
=
1353 le16_to_cpu(lvds
->sLCDTiming
.usPixClk
) * 10;
1354 /* usHActive does not include borders, according to VBIOS team */
1355 info
->lcd_timing
.horizontal_addressable
=
1356 le16_to_cpu(lvds
->sLCDTiming
.usHActive
);
1357 /* usHBlanking_Time includes borders, so we should really be subtracting
1358 * borders duing this translation, but LVDS generally*/
1359 /* doesn't have borders, so we should be okay leaving this as is for
1360 * now. May need to revisit if we ever have LVDS with borders*/
1361 info
->lcd_timing
.horizontal_blanking_time
=
1362 le16_to_cpu(lvds
->sLCDTiming
.usHBlanking_Time
);
1363 /* usVActive does not include borders, according to VBIOS team*/
1364 info
->lcd_timing
.vertical_addressable
=
1365 le16_to_cpu(lvds
->sLCDTiming
.usVActive
);
1366 /* usVBlanking_Time includes borders, so we should really be subtracting
1367 * borders duing this translation, but LVDS generally*/
1368 /* doesn't have borders, so we should be okay leaving this as is for
1369 * now. May need to revisit if we ever have LVDS with borders*/
1370 info
->lcd_timing
.vertical_blanking_time
=
1371 le16_to_cpu(lvds
->sLCDTiming
.usVBlanking_Time
);
1372 info
->lcd_timing
.horizontal_sync_offset
=
1373 le16_to_cpu(lvds
->sLCDTiming
.usHSyncOffset
);
1374 info
->lcd_timing
.horizontal_sync_width
=
1375 le16_to_cpu(lvds
->sLCDTiming
.usHSyncWidth
);
1376 info
->lcd_timing
.vertical_sync_offset
=
1377 le16_to_cpu(lvds
->sLCDTiming
.usVSyncOffset
);
1378 info
->lcd_timing
.vertical_sync_width
=
1379 le16_to_cpu(lvds
->sLCDTiming
.usVSyncWidth
);
1380 info
->lcd_timing
.horizontal_border
= lvds
->sLCDTiming
.ucHBorder
;
1381 info
->lcd_timing
.vertical_border
= lvds
->sLCDTiming
.ucVBorder
;
1382 info
->lcd_timing
.misc_info
.HORIZONTAL_CUT_OFF
=
1383 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.HorizontalCutOff
;
1384 info
->lcd_timing
.misc_info
.H_SYNC_POLARITY
=
1386 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.HSyncPolarity
;
1387 info
->lcd_timing
.misc_info
.V_SYNC_POLARITY
=
1389 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.VSyncPolarity
;
1390 info
->lcd_timing
.misc_info
.VERTICAL_CUT_OFF
=
1391 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.VerticalCutOff
;
1392 info
->lcd_timing
.misc_info
.H_REPLICATION_BY2
=
1393 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.H_ReplicationBy2
;
1394 info
->lcd_timing
.misc_info
.V_REPLICATION_BY2
=
1395 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.V_ReplicationBy2
;
1396 info
->lcd_timing
.misc_info
.COMPOSITE_SYNC
=
1397 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.CompositeSync
;
1398 info
->lcd_timing
.misc_info
.INTERLACE
=
1399 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.Interlace
;
1400 info
->lcd_timing
.misc_info
.DOUBLE_CLOCK
=
1401 lvds
->sLCDTiming
.susModeMiscInfo
.sbfAccess
.DoubleClock
;
1402 info
->ss_id
= lvds
->ucSS_Id
;
1404 /* Drr panel support can be reported by VBIOS*/
1405 if (LCDPANEL_CAP_V13_DRR_SUPPORTED
1406 & lvds
->ucLCDPanel_SpecialHandlingCap
)
1407 info
->drr_enabled
= 1;
1409 /* Get supported refresh rate*/
1410 if (info
->drr_enabled
== 1) {
1412 lvds
->sRefreshRateSupport
.ucMinRefreshRateForDRR
;
1413 uint8_t rr
= lvds
->sRefreshRateSupport
.ucSupportedRefreshRate
;
1416 if (SUPPORTED_LCD_REFRESHRATE_30Hz
& min_rr
)
1417 info
->supported_rr
.REFRESH_RATE_30HZ
= 1;
1418 else if (SUPPORTED_LCD_REFRESHRATE_40Hz
& min_rr
)
1419 info
->supported_rr
.REFRESH_RATE_40HZ
= 1;
1420 else if (SUPPORTED_LCD_REFRESHRATE_48Hz
& min_rr
)
1421 info
->supported_rr
.REFRESH_RATE_48HZ
= 1;
1422 else if (SUPPORTED_LCD_REFRESHRATE_50Hz
& min_rr
)
1423 info
->supported_rr
.REFRESH_RATE_50HZ
= 1;
1424 else if (SUPPORTED_LCD_REFRESHRATE_60Hz
& min_rr
)
1425 info
->supported_rr
.REFRESH_RATE_60HZ
= 1;
1427 if (SUPPORTED_LCD_REFRESHRATE_30Hz
& rr
)
1428 info
->supported_rr
.REFRESH_RATE_30HZ
= 1;
1429 else if (SUPPORTED_LCD_REFRESHRATE_40Hz
& rr
)
1430 info
->supported_rr
.REFRESH_RATE_40HZ
= 1;
1431 else if (SUPPORTED_LCD_REFRESHRATE_48Hz
& rr
)
1432 info
->supported_rr
.REFRESH_RATE_48HZ
= 1;
1433 else if (SUPPORTED_LCD_REFRESHRATE_50Hz
& rr
)
1434 info
->supported_rr
.REFRESH_RATE_50HZ
= 1;
1435 else if (SUPPORTED_LCD_REFRESHRATE_60Hz
& rr
)
1436 info
->supported_rr
.REFRESH_RATE_60HZ
= 1;
1440 if (ATOM_PANEL_MISC_V13_DUAL
& lvds
->ucLCD_Misc
)
1441 info
->lcd_timing
.misc_info
.DOUBLE_CLOCK
= true;
1443 if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR
& lvds
->ucLCD_Misc
)
1444 info
->lcd_timing
.misc_info
.RGB888
= true;
1446 info
->lcd_timing
.misc_info
.GREY_LEVEL
=
1447 (uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL
&
1448 lvds
->ucLCD_Misc
) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT
;
1450 return BP_RESULT_OK
;
1454 * bios_parser_get_encoder_cap_info
1457 * Get encoder capability information of input object id
1459 * @param object_id, Object id
1460 * @param object_id, encoder cap information structure
1462 * @return Bios parser result code
1465 static enum bp_result
bios_parser_get_encoder_cap_info(
1466 struct dc_bios
*dcb
,
1467 struct graphics_object_id object_id
,
1468 struct bp_encoder_cap_info
*info
)
1470 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
1471 ATOM_OBJECT
*object
;
1472 ATOM_ENCODER_CAP_RECORD_V2
*record
= NULL
;
1475 return BP_RESULT_BADINPUT
;
1477 object
= get_bios_object(bp
, object_id
);
1480 return BP_RESULT_BADINPUT
;
1482 record
= get_encoder_cap_record(bp
, object
);
1484 return BP_RESULT_NORECORD
;
1486 info
->DP_HBR2_EN
= record
->usHBR2En
;
1487 info
->DP_HBR3_EN
= record
->usHBR3En
;
1488 info
->HDMI_6GB_EN
= record
->usHDMI6GEn
;
1489 return BP_RESULT_OK
;
1493 * get_encoder_cap_record
1496 * Get encoder cap record for the object
1498 * @param object, ATOM object
1500 * @return atom encoder cap record
1503 * search all records to find the ATOM_ENCODER_CAP_RECORD_V2 record
1505 static ATOM_ENCODER_CAP_RECORD_V2
*get_encoder_cap_record(
1506 struct bios_parser
*bp
,
1507 ATOM_OBJECT
*object
)
1509 ATOM_COMMON_RECORD_HEADER
*header
;
1513 BREAK_TO_DEBUGGER(); /* Invalid object */
1517 offset
= le16_to_cpu(object
->usRecordOffset
)
1518 + bp
->object_info_tbl_offset
;
1521 header
= GET_IMAGE(ATOM_COMMON_RECORD_HEADER
, offset
);
1526 offset
+= header
->ucRecordSize
;
1528 if (LAST_RECORD_TYPE
== header
->ucRecordType
||
1529 !header
->ucRecordSize
)
1532 if (ATOM_ENCODER_CAP_RECORD_TYPE
!= header
->ucRecordType
)
1535 if (sizeof(ATOM_ENCODER_CAP_RECORD_V2
) <= header
->ucRecordSize
)
1536 return (ATOM_ENCODER_CAP_RECORD_V2
*)header
;
1542 static uint32_t get_ss_entry_number(
1543 struct bios_parser
*bp
,
1545 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
1546 struct bios_parser
*bp
,
1548 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1549 struct bios_parser
*bp
,
1551 static uint32_t get_ss_entry_number_from_ss_info_tbl(
1552 struct bios_parser
*bp
,
1556 * BiosParserObject::GetNumberofSpreadSpectrumEntry
1557 * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from
1558 * the VBIOS that match the SSid (to be converted from signal)
1560 * @param[in] signal, ASSignalType to be converted to SSid
1561 * @return number of SS Entry that match the signal
1563 static uint32_t bios_parser_get_ss_entry_number(
1564 struct dc_bios
*dcb
,
1565 enum as_signal_type signal
)
1567 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
1569 ATOM_COMMON_TABLE_HEADER
*header
;
1570 struct atom_data_revision revision
;
1572 ss_id
= signal_to_ss_id(signal
);
1574 if (!DATA_TABLES(ASIC_InternalSS_Info
))
1575 return get_ss_entry_number_from_ss_info_tbl(bp
, ss_id
);
1577 header
= GET_IMAGE(ATOM_COMMON_TABLE_HEADER
,
1578 DATA_TABLES(ASIC_InternalSS_Info
));
1579 get_atom_data_table_revision(header
, &revision
);
1581 switch (revision
.major
) {
1583 switch (revision
.minor
) {
1585 return get_ss_entry_number(bp
, ss_id
);
1591 switch (revision
.minor
) {
1594 get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1608 * get_ss_entry_number_from_ss_info_tbl
1609 * Get Number of spread spectrum entry from the SS_Info table from the VBIOS.
1611 * @note There can only be one entry for each id for SS_Info Table
1613 * @param [in] id, spread spectrum id
1614 * @return number of SS Entry that match the id
1616 static uint32_t get_ss_entry_number_from_ss_info_tbl(
1617 struct bios_parser
*bp
,
1620 ATOM_SPREAD_SPECTRUM_INFO
*tbl
;
1621 ATOM_COMMON_TABLE_HEADER
*header
;
1622 uint32_t table_size
;
1624 uint32_t number
= 0;
1625 uint32_t id_local
= SS_ID_UNKNOWN
;
1626 struct atom_data_revision revision
;
1628 /* SS_Info table exist */
1629 if (!DATA_TABLES(SS_Info
))
1632 header
= GET_IMAGE(ATOM_COMMON_TABLE_HEADER
,
1633 DATA_TABLES(SS_Info
));
1634 get_atom_data_table_revision(header
, &revision
);
1636 tbl
= GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO
,
1637 DATA_TABLES(SS_Info
));
1639 if (1 != revision
.major
|| 2 > revision
.minor
)
1642 /* have to convert from Internal_SS format to SS_Info format */
1644 case ASIC_INTERNAL_SS_ON_DP
:
1645 id_local
= SS_ID_DP1
;
1647 case ASIC_INTERNAL_SS_ON_LVDS
: {
1648 struct embedded_panel_info panel_info
;
1650 if (bios_parser_get_embedded_panel_info(&bp
->base
, &panel_info
)
1652 id_local
= panel_info
.ss_id
;
1659 if (id_local
== SS_ID_UNKNOWN
)
1662 table_size
= (le16_to_cpu(tbl
->sHeader
.usStructureSize
) -
1663 sizeof(ATOM_COMMON_TABLE_HEADER
)) /
1664 sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT
);
1666 for (i
= 0; i
< table_size
; i
++)
1667 if (id_local
== (uint32_t)tbl
->asSS_Info
[i
].ucSS_Id
) {
1676 * get_ss_entry_number
1677 * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
1678 * SS_Info table from the VBIOS
1679 * There can not be more than 1 entry for ASIC_InternalSS_Info Ver 2.1 or
1682 * @param id, spread sprectrum info index
1683 * @return Bios parser result code
1685 static uint32_t get_ss_entry_number(struct bios_parser
*bp
, uint32_t id
)
1687 if (id
== ASIC_INTERNAL_SS_ON_DP
|| id
== ASIC_INTERNAL_SS_ON_LVDS
)
1688 return get_ss_entry_number_from_ss_info_tbl(bp
, id
);
1690 return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp
, id
);
1694 * get_ss_entry_number_from_internal_ss_info_tbl_v2_1
1695 * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table
1696 * Ver 2.1 from the VBIOS
1697 * There will not be multiple entry for Ver 2.1
1699 * @param id, spread sprectrum info index
1700 * @return number of SS Entry that match the id
1702 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
1703 struct bios_parser
*bp
,
1706 ATOM_ASIC_INTERNAL_SS_INFO_V2
*header_include
;
1707 ATOM_ASIC_SS_ASSIGNMENT_V2
*tbl
;
1711 if (!DATA_TABLES(ASIC_InternalSS_Info
))
1714 header_include
= GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2
,
1715 DATA_TABLES(ASIC_InternalSS_Info
));
1717 size
= (le16_to_cpu(header_include
->sHeader
.usStructureSize
)
1718 - sizeof(ATOM_COMMON_TABLE_HEADER
))
1719 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2
);
1721 tbl
= (ATOM_ASIC_SS_ASSIGNMENT_V2
*)
1722 &header_include
->asSpreadSpectrum
[0];
1723 for (i
= 0; i
< size
; i
++)
1724 if (tbl
[i
].ucClockIndication
== (uint8_t)id
)
1730 * get_ss_entry_number_from_internal_ss_info_table_V3_1
1731 * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of
1732 * the VBIOS that matches id
1734 * @param[in] id, spread sprectrum id
1735 * @return number of SS Entry that match the id
1737 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1738 struct bios_parser
*bp
,
1741 uint32_t number
= 0;
1742 ATOM_ASIC_INTERNAL_SS_INFO_V3
*header_include
;
1743 ATOM_ASIC_SS_ASSIGNMENT_V3
*tbl
;
1747 if (!DATA_TABLES(ASIC_InternalSS_Info
))
1750 header_include
= GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3
,
1751 DATA_TABLES(ASIC_InternalSS_Info
));
1752 size
= (le16_to_cpu(header_include
->sHeader
.usStructureSize
) -
1753 sizeof(ATOM_COMMON_TABLE_HEADER
)) /
1754 sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3
);
1756 tbl
= (ATOM_ASIC_SS_ASSIGNMENT_V3
*)
1757 &header_include
->asSpreadSpectrum
[0];
1759 for (i
= 0; i
< size
; i
++)
1760 if (tbl
[i
].ucClockIndication
== (uint8_t)id
)
1767 * bios_parser_get_gpio_pin_info
1768 * Get GpioPin information of input gpio id
1770 * @param gpio_id, GPIO ID
1771 * @param info, GpioPin information structure
1772 * @return Bios parser result code
1774 * to get the GPIO PIN INFO, we need:
1775 * 1. get the GPIO_ID from other object table, see GetHPDInfo()
1776 * 2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA
1779 static enum bp_result
bios_parser_get_gpio_pin_info(
1780 struct dc_bios
*dcb
,
1782 struct gpio_pin_info
*info
)
1784 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
1785 ATOM_GPIO_PIN_LUT
*header
;
1789 if (!DATA_TABLES(GPIO_Pin_LUT
))
1790 return BP_RESULT_BADBIOSTABLE
;
1792 header
= GET_IMAGE(ATOM_GPIO_PIN_LUT
, DATA_TABLES(GPIO_Pin_LUT
));
1794 return BP_RESULT_BADBIOSTABLE
;
1796 if (sizeof(ATOM_COMMON_TABLE_HEADER
) + sizeof(ATOM_GPIO_PIN_LUT
)
1797 > le16_to_cpu(header
->sHeader
.usStructureSize
))
1798 return BP_RESULT_BADBIOSTABLE
;
1800 if (1 != header
->sHeader
.ucTableContentRevision
)
1801 return BP_RESULT_UNSUPPORTED
;
1803 count
= (le16_to_cpu(header
->sHeader
.usStructureSize
)
1804 - sizeof(ATOM_COMMON_TABLE_HEADER
))
1805 / sizeof(ATOM_GPIO_PIN_ASSIGNMENT
);
1806 for (i
= 0; i
< count
; ++i
) {
1807 if (header
->asGPIO_Pin
[i
].ucGPIO_ID
!= gpio_id
)
1811 (uint32_t) le16_to_cpu(header
->asGPIO_Pin
[i
].usGpioPin_AIndex
);
1812 info
->offset_y
= info
->offset
+ 2;
1813 info
->offset_en
= info
->offset
+ 1;
1814 info
->offset_mask
= info
->offset
- 1;
1816 info
->mask
= (uint32_t) (1 <<
1817 header
->asGPIO_Pin
[i
].ucGpioPinBitShift
);
1818 info
->mask_y
= info
->mask
+ 2;
1819 info
->mask_en
= info
->mask
+ 1;
1820 info
->mask_mask
= info
->mask
- 1;
1822 return BP_RESULT_OK
;
1825 return BP_RESULT_NORECORD
;
1828 static enum bp_result
get_gpio_i2c_info(struct bios_parser
*bp
,
1829 ATOM_I2C_RECORD
*record
,
1830 struct graphics_object_i2c_info
*info
)
1832 ATOM_GPIO_I2C_INFO
*header
;
1836 return BP_RESULT_BADINPUT
;
1838 /* get the GPIO_I2C info */
1839 if (!DATA_TABLES(GPIO_I2C_Info
))
1840 return BP_RESULT_BADBIOSTABLE
;
1842 header
= GET_IMAGE(ATOM_GPIO_I2C_INFO
, DATA_TABLES(GPIO_I2C_Info
));
1844 return BP_RESULT_BADBIOSTABLE
;
1846 if (sizeof(ATOM_COMMON_TABLE_HEADER
) + sizeof(ATOM_GPIO_I2C_ASSIGMENT
)
1847 > le16_to_cpu(header
->sHeader
.usStructureSize
))
1848 return BP_RESULT_BADBIOSTABLE
;
1850 if (1 != header
->sHeader
.ucTableContentRevision
)
1851 return BP_RESULT_UNSUPPORTED
;
1853 /* get data count */
1854 count
= (le16_to_cpu(header
->sHeader
.usStructureSize
)
1855 - sizeof(ATOM_COMMON_TABLE_HEADER
))
1856 / sizeof(ATOM_GPIO_I2C_ASSIGMENT
);
1857 if (count
< record
->sucI2cId
.bfI2C_LineMux
)
1858 return BP_RESULT_BADBIOSTABLE
;
1860 /* get the GPIO_I2C_INFO */
1861 info
->i2c_hw_assist
= record
->sucI2cId
.bfHW_Capable
;
1862 info
->i2c_line
= record
->sucI2cId
.bfI2C_LineMux
;
1863 info
->i2c_engine_id
= record
->sucI2cId
.bfHW_EngineID
;
1864 info
->i2c_slave_address
= record
->ucI2CAddr
;
1866 info
->gpio_info
.clk_mask_register_index
=
1867 le16_to_cpu(header
->asGPIO_Info
[info
->i2c_line
].usClkMaskRegisterIndex
);
1868 info
->gpio_info
.clk_en_register_index
=
1869 le16_to_cpu(header
->asGPIO_Info
[info
->i2c_line
].usClkEnRegisterIndex
);
1870 info
->gpio_info
.clk_y_register_index
=
1871 le16_to_cpu(header
->asGPIO_Info
[info
->i2c_line
].usClkY_RegisterIndex
);
1872 info
->gpio_info
.clk_a_register_index
=
1873 le16_to_cpu(header
->asGPIO_Info
[info
->i2c_line
].usClkA_RegisterIndex
);
1874 info
->gpio_info
.data_mask_register_index
=
1875 le16_to_cpu(header
->asGPIO_Info
[info
->i2c_line
].usDataMaskRegisterIndex
);
1876 info
->gpio_info
.data_en_register_index
=
1877 le16_to_cpu(header
->asGPIO_Info
[info
->i2c_line
].usDataEnRegisterIndex
);
1878 info
->gpio_info
.data_y_register_index
=
1879 le16_to_cpu(header
->asGPIO_Info
[info
->i2c_line
].usDataY_RegisterIndex
);
1880 info
->gpio_info
.data_a_register_index
=
1881 le16_to_cpu(header
->asGPIO_Info
[info
->i2c_line
].usDataA_RegisterIndex
);
1883 info
->gpio_info
.clk_mask_shift
=
1884 header
->asGPIO_Info
[info
->i2c_line
].ucClkMaskShift
;
1885 info
->gpio_info
.clk_en_shift
=
1886 header
->asGPIO_Info
[info
->i2c_line
].ucClkEnShift
;
1887 info
->gpio_info
.clk_y_shift
=
1888 header
->asGPIO_Info
[info
->i2c_line
].ucClkY_Shift
;
1889 info
->gpio_info
.clk_a_shift
=
1890 header
->asGPIO_Info
[info
->i2c_line
].ucClkA_Shift
;
1891 info
->gpio_info
.data_mask_shift
=
1892 header
->asGPIO_Info
[info
->i2c_line
].ucDataMaskShift
;
1893 info
->gpio_info
.data_en_shift
=
1894 header
->asGPIO_Info
[info
->i2c_line
].ucDataEnShift
;
1895 info
->gpio_info
.data_y_shift
=
1896 header
->asGPIO_Info
[info
->i2c_line
].ucDataY_Shift
;
1897 info
->gpio_info
.data_a_shift
=
1898 header
->asGPIO_Info
[info
->i2c_line
].ucDataA_Shift
;
1900 return BP_RESULT_OK
;
1903 static bool dal_graphics_object_id_is_valid(struct graphics_object_id id
)
1908 case OBJECT_TYPE_UNKNOWN
:
1911 case OBJECT_TYPE_GPU
:
1912 case OBJECT_TYPE_ENGINE
:
1913 /* do NOT check for id.id == 0 */
1914 if (id
.enum_id
== ENUM_ID_UNKNOWN
)
1918 if (id
.id
== 0 || id
.enum_id
== ENUM_ID_UNKNOWN
)
1926 static bool dal_graphics_object_id_is_equal(
1927 struct graphics_object_id id1
,
1928 struct graphics_object_id id2
)
1930 if (false == dal_graphics_object_id_is_valid(id1
)) {
1931 dm_output_to_console(
1932 "%s: Warning: comparing invalid object 'id1'!\n", __func__
);
1936 if (false == dal_graphics_object_id_is_valid(id2
)) {
1937 dm_output_to_console(
1938 "%s: Warning: comparing invalid object 'id2'!\n", __func__
);
1942 if (id1
.id
== id2
.id
&& id1
.enum_id
== id2
.enum_id
1943 && id1
.type
== id2
.type
)
1949 static ATOM_OBJECT
*get_bios_object(struct bios_parser
*bp
,
1950 struct graphics_object_id id
)
1953 ATOM_OBJECT_TABLE
*tbl
;
1957 case OBJECT_TYPE_ENCODER
:
1958 offset
= le16_to_cpu(bp
->object_info_tbl
.v1_1
->usEncoderObjectTableOffset
);
1961 case OBJECT_TYPE_CONNECTOR
:
1962 offset
= le16_to_cpu(bp
->object_info_tbl
.v1_1
->usConnectorObjectTableOffset
);
1965 case OBJECT_TYPE_ROUTER
:
1966 offset
= le16_to_cpu(bp
->object_info_tbl
.v1_1
->usRouterObjectTableOffset
);
1969 case OBJECT_TYPE_GENERIC
:
1970 if (bp
->object_info_tbl
.revision
.minor
< 3)
1972 offset
= le16_to_cpu(bp
->object_info_tbl
.v1_3
->usMiscObjectTableOffset
);
1979 offset
+= bp
->object_info_tbl_offset
;
1981 tbl
= GET_IMAGE(ATOM_OBJECT_TABLE
, offset
);
1985 for (i
= 0; i
< tbl
->ucNumberOfObjects
; i
++)
1986 if (dal_graphics_object_id_is_equal(id
,
1987 object_id_from_bios_object_id(
1988 le16_to_cpu(tbl
->asObjects
[i
].usObjectID
))))
1989 return &tbl
->asObjects
[i
];
1994 static uint32_t get_src_obj_list(struct bios_parser
*bp
, ATOM_OBJECT
*object
,
2001 BREAK_TO_DEBUGGER(); /* Invalid object id */
2005 offset
= le16_to_cpu(object
->usSrcDstTableOffset
)
2006 + bp
->object_info_tbl_offset
;
2008 number
= GET_IMAGE(uint8_t, offset
);
2012 offset
+= sizeof(uint8_t);
2013 *id_list
= (uint16_t *)bios_get_image(&bp
->base
, offset
, *number
* sizeof(uint16_t));
2021 static struct device_id
device_type_from_device_id(uint16_t device_id
)
2024 struct device_id result_device_id
= {0};
2026 switch (device_id
) {
2027 case ATOM_DEVICE_LCD1_SUPPORT
:
2028 result_device_id
.device_type
= DEVICE_TYPE_LCD
;
2029 result_device_id
.enum_id
= 1;
2032 case ATOM_DEVICE_LCD2_SUPPORT
:
2033 result_device_id
.device_type
= DEVICE_TYPE_LCD
;
2034 result_device_id
.enum_id
= 2;
2037 case ATOM_DEVICE_CRT1_SUPPORT
:
2038 result_device_id
.device_type
= DEVICE_TYPE_CRT
;
2039 result_device_id
.enum_id
= 1;
2042 case ATOM_DEVICE_CRT2_SUPPORT
:
2043 result_device_id
.device_type
= DEVICE_TYPE_CRT
;
2044 result_device_id
.enum_id
= 2;
2047 case ATOM_DEVICE_DFP1_SUPPORT
:
2048 result_device_id
.device_type
= DEVICE_TYPE_DFP
;
2049 result_device_id
.enum_id
= 1;
2052 case ATOM_DEVICE_DFP2_SUPPORT
:
2053 result_device_id
.device_type
= DEVICE_TYPE_DFP
;
2054 result_device_id
.enum_id
= 2;
2057 case ATOM_DEVICE_DFP3_SUPPORT
:
2058 result_device_id
.device_type
= DEVICE_TYPE_DFP
;
2059 result_device_id
.enum_id
= 3;
2062 case ATOM_DEVICE_DFP4_SUPPORT
:
2063 result_device_id
.device_type
= DEVICE_TYPE_DFP
;
2064 result_device_id
.enum_id
= 4;
2067 case ATOM_DEVICE_DFP5_SUPPORT
:
2068 result_device_id
.device_type
= DEVICE_TYPE_DFP
;
2069 result_device_id
.enum_id
= 5;
2072 case ATOM_DEVICE_DFP6_SUPPORT
:
2073 result_device_id
.device_type
= DEVICE_TYPE_DFP
;
2074 result_device_id
.enum_id
= 6;
2078 BREAK_TO_DEBUGGER(); /* Invalid device Id */
2079 result_device_id
.device_type
= DEVICE_TYPE_UNKNOWN
;
2080 result_device_id
.enum_id
= 0;
2082 return result_device_id
;
2085 static void get_atom_data_table_revision(
2086 ATOM_COMMON_TABLE_HEADER
*atom_data_tbl
,
2087 struct atom_data_revision
*tbl_revision
)
2092 /* initialize the revision to 0 which is invalid revision */
2093 tbl_revision
->major
= 0;
2094 tbl_revision
->minor
= 0;
2099 tbl_revision
->major
=
2100 (uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl
);
2101 tbl_revision
->minor
=
2102 (uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl
);
2105 static uint32_t signal_to_ss_id(enum as_signal_type signal
)
2107 uint32_t clk_id_ss
= 0;
2110 case AS_SIGNAL_TYPE_DVI
:
2111 clk_id_ss
= ASIC_INTERNAL_SS_ON_TMDS
;
2113 case AS_SIGNAL_TYPE_HDMI
:
2114 clk_id_ss
= ASIC_INTERNAL_SS_ON_HDMI
;
2116 case AS_SIGNAL_TYPE_LVDS
:
2117 clk_id_ss
= ASIC_INTERNAL_SS_ON_LVDS
;
2119 case AS_SIGNAL_TYPE_DISPLAY_PORT
:
2120 clk_id_ss
= ASIC_INTERNAL_SS_ON_DP
;
2122 case AS_SIGNAL_TYPE_GPU_PLL
:
2123 clk_id_ss
= ASIC_INTERNAL_GPUPLL_SS
;
2131 static uint32_t get_support_mask_for_device_id(struct device_id device_id
)
2133 enum dal_device_type device_type
= device_id
.device_type
;
2134 uint32_t enum_id
= device_id
.enum_id
;
2136 switch (device_type
) {
2137 case DEVICE_TYPE_LCD
:
2140 return ATOM_DEVICE_LCD1_SUPPORT
;
2142 return ATOM_DEVICE_LCD2_SUPPORT
;
2147 case DEVICE_TYPE_CRT
:
2150 return ATOM_DEVICE_CRT1_SUPPORT
;
2152 return ATOM_DEVICE_CRT2_SUPPORT
;
2157 case DEVICE_TYPE_DFP
:
2160 return ATOM_DEVICE_DFP1_SUPPORT
;
2162 return ATOM_DEVICE_DFP2_SUPPORT
;
2164 return ATOM_DEVICE_DFP3_SUPPORT
;
2166 return ATOM_DEVICE_DFP4_SUPPORT
;
2168 return ATOM_DEVICE_DFP5_SUPPORT
;
2170 return ATOM_DEVICE_DFP6_SUPPORT
;
2175 case DEVICE_TYPE_CV
:
2178 return ATOM_DEVICE_CV_SUPPORT
;
2183 case DEVICE_TYPE_TV
:
2186 return ATOM_DEVICE_TV1_SUPPORT
;
2195 /* Unidentified device ID, return empty support mask. */
2200 * bios_parser_set_scratch_critical_state
2203 * update critical state bit in VBIOS scratch register
2206 * bool - to set or reset state
2208 static void bios_parser_set_scratch_critical_state(
2209 struct dc_bios
*dcb
,
2212 bios_set_scratch_critical_state(dcb
, state
);
2216 * get_integrated_info_v8
2219 * Get V8 integrated BIOS information
2222 * bios_parser *bp - [in]BIOS parser handler to get master data table
2223 * integrated_info *info - [out] store and output integrated info
2226 * enum bp_result - BP_RESULT_OK if information is available,
2227 * BP_RESULT_BADBIOSTABLE otherwise.
2229 static enum bp_result
get_integrated_info_v8(
2230 struct bios_parser
*bp
,
2231 struct integrated_info
*info
)
2233 ATOM_INTEGRATED_SYSTEM_INFO_V1_8
*info_v8
;
2236 info_v8
= GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8
,
2237 bp
->master_data_tbl
->ListOfDataTables
.IntegratedSystemInfo
);
2239 if (info_v8
== NULL
)
2240 return BP_RESULT_BADBIOSTABLE
;
2241 info
->boot_up_engine_clock
= le32_to_cpu(info_v8
->ulBootUpEngineClock
) * 10;
2242 info
->dentist_vco_freq
= le32_to_cpu(info_v8
->ulDentistVCOFreq
) * 10;
2243 info
->boot_up_uma_clock
= le32_to_cpu(info_v8
->ulBootUpUMAClock
) * 10;
2245 for (i
= 0; i
< NUMBER_OF_DISP_CLK_VOLTAGE
; ++i
) {
2246 /* Convert [10KHz] into [KHz] */
2247 info
->disp_clk_voltage
[i
].max_supported_clk
=
2248 le32_to_cpu(info_v8
->sDISPCLK_Voltage
[i
].
2249 ulMaximumSupportedCLK
) * 10;
2250 info
->disp_clk_voltage
[i
].voltage_index
=
2251 le32_to_cpu(info_v8
->sDISPCLK_Voltage
[i
].ulVoltageIndex
);
2254 info
->boot_up_req_display_vector
=
2255 le32_to_cpu(info_v8
->ulBootUpReqDisplayVector
);
2256 info
->gpu_cap_info
=
2257 le32_to_cpu(info_v8
->ulGPUCapInfo
);
2260 * system_config: Bit[0] = 0 : PCIE power gating disabled
2261 * = 1 : PCIE power gating enabled
2262 * Bit[1] = 0 : DDR-PLL shut down disabled
2263 * = 1 : DDR-PLL shut down enabled
2264 * Bit[2] = 0 : DDR-PLL power down disabled
2265 * = 1 : DDR-PLL power down enabled
2267 info
->system_config
= le32_to_cpu(info_v8
->ulSystemConfig
);
2268 info
->cpu_cap_info
= le32_to_cpu(info_v8
->ulCPUCapInfo
);
2269 info
->boot_up_nb_voltage
=
2270 le16_to_cpu(info_v8
->usBootUpNBVoltage
);
2271 info
->ext_disp_conn_info_offset
=
2272 le16_to_cpu(info_v8
->usExtDispConnInfoOffset
);
2273 info
->memory_type
= info_v8
->ucMemoryType
;
2274 info
->ma_channel_number
= info_v8
->ucUMAChannelNumber
;
2275 info
->gmc_restore_reset_time
=
2276 le32_to_cpu(info_v8
->ulGMCRestoreResetTime
);
2278 info
->minimum_n_clk
=
2279 le32_to_cpu(info_v8
->ulNbpStateNClkFreq
[0]);
2280 for (i
= 1; i
< 4; ++i
)
2281 info
->minimum_n_clk
=
2282 info
->minimum_n_clk
< le32_to_cpu(info_v8
->ulNbpStateNClkFreq
[i
]) ?
2283 info
->minimum_n_clk
: le32_to_cpu(info_v8
->ulNbpStateNClkFreq
[i
]);
2285 info
->idle_n_clk
= le32_to_cpu(info_v8
->ulIdleNClk
);
2286 info
->ddr_dll_power_up_time
=
2287 le32_to_cpu(info_v8
->ulDDR_DLL_PowerUpTime
);
2288 info
->ddr_pll_power_up_time
=
2289 le32_to_cpu(info_v8
->ulDDR_PLL_PowerUpTime
);
2290 info
->pcie_clk_ss_type
= le16_to_cpu(info_v8
->usPCIEClkSSType
);
2291 info
->lvds_ss_percentage
=
2292 le16_to_cpu(info_v8
->usLvdsSSPercentage
);
2293 info
->lvds_sspread_rate_in_10hz
=
2294 le16_to_cpu(info_v8
->usLvdsSSpreadRateIn10Hz
);
2295 info
->hdmi_ss_percentage
=
2296 le16_to_cpu(info_v8
->usHDMISSPercentage
);
2297 info
->hdmi_sspread_rate_in_10hz
=
2298 le16_to_cpu(info_v8
->usHDMISSpreadRateIn10Hz
);
2299 info
->dvi_ss_percentage
=
2300 le16_to_cpu(info_v8
->usDVISSPercentage
);
2301 info
->dvi_sspread_rate_in_10_hz
=
2302 le16_to_cpu(info_v8
->usDVISSpreadRateIn10Hz
);
2304 info
->max_lvds_pclk_freq_in_single_link
=
2305 le16_to_cpu(info_v8
->usMaxLVDSPclkFreqInSingleLink
);
2306 info
->lvds_misc
= info_v8
->ucLvdsMisc
;
2307 info
->lvds_pwr_on_seq_dig_on_to_de_in_4ms
=
2308 info_v8
->ucLVDSPwrOnSeqDIGONtoDE_in4Ms
;
2309 info
->lvds_pwr_on_seq_de_to_vary_bl_in_4ms
=
2310 info_v8
->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms
;
2311 info
->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms
=
2312 info_v8
->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms
;
2313 info
->lvds_pwr_off_seq_vary_bl_to_de_in4ms
=
2314 info_v8
->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms
;
2315 info
->lvds_pwr_off_seq_de_to_dig_on_in4ms
=
2316 info_v8
->ucLVDSPwrOffSeqDEtoDIGON_in4Ms
;
2317 info
->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms
=
2318 info_v8
->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms
;
2319 info
->lvds_off_to_on_delay_in_4ms
=
2320 info_v8
->ucLVDSOffToOnDelay_in4Ms
;
2321 info
->lvds_bit_depth_control_val
=
2322 le32_to_cpu(info_v8
->ulLCDBitDepthControlVal
);
2324 for (i
= 0; i
< NUMBER_OF_AVAILABLE_SCLK
; ++i
) {
2325 /* Convert [10KHz] into [KHz] */
2326 info
->avail_s_clk
[i
].supported_s_clk
=
2327 le32_to_cpu(info_v8
->sAvail_SCLK
[i
].ulSupportedSCLK
) * 10;
2328 info
->avail_s_clk
[i
].voltage_index
=
2329 le16_to_cpu(info_v8
->sAvail_SCLK
[i
].usVoltageIndex
);
2330 info
->avail_s_clk
[i
].voltage_id
=
2331 le16_to_cpu(info_v8
->sAvail_SCLK
[i
].usVoltageID
);
2334 for (i
= 0; i
< NUMBER_OF_UCHAR_FOR_GUID
; ++i
) {
2335 info
->ext_disp_conn_info
.gu_id
[i
] =
2336 info_v8
->sExtDispConnInfo
.ucGuid
[i
];
2339 for (i
= 0; i
< MAX_NUMBER_OF_EXT_DISPLAY_PATH
; ++i
) {
2340 info
->ext_disp_conn_info
.path
[i
].device_connector_id
=
2341 object_id_from_bios_object_id(
2342 le16_to_cpu(info_v8
->sExtDispConnInfo
.sPath
[i
].usDeviceConnector
));
2344 info
->ext_disp_conn_info
.path
[i
].ext_encoder_obj_id
=
2345 object_id_from_bios_object_id(
2346 le16_to_cpu(info_v8
->sExtDispConnInfo
.sPath
[i
].usExtEncoderObjId
));
2348 info
->ext_disp_conn_info
.path
[i
].device_tag
=
2349 le16_to_cpu(info_v8
->sExtDispConnInfo
.sPath
[i
].usDeviceTag
);
2350 info
->ext_disp_conn_info
.path
[i
].device_acpi_enum
=
2351 le16_to_cpu(info_v8
->sExtDispConnInfo
.sPath
[i
].usDeviceACPIEnum
);
2352 info
->ext_disp_conn_info
.path
[i
].ext_aux_ddc_lut_index
=
2353 info_v8
->sExtDispConnInfo
.sPath
[i
].ucExtAUXDDCLutIndex
;
2354 info
->ext_disp_conn_info
.path
[i
].ext_hpd_pin_lut_index
=
2355 info_v8
->sExtDispConnInfo
.sPath
[i
].ucExtHPDPINLutIndex
;
2356 info
->ext_disp_conn_info
.path
[i
].channel_mapping
.raw
=
2357 info_v8
->sExtDispConnInfo
.sPath
[i
].ucChannelMapping
;
2359 info
->ext_disp_conn_info
.checksum
=
2360 info_v8
->sExtDispConnInfo
.ucChecksum
;
2362 return BP_RESULT_OK
;
2366 * get_integrated_info_v8
2369 * Get V8 integrated BIOS information
2372 * bios_parser *bp - [in]BIOS parser handler to get master data table
2373 * integrated_info *info - [out] store and output integrated info
2376 * enum bp_result - BP_RESULT_OK if information is available,
2377 * BP_RESULT_BADBIOSTABLE otherwise.
2379 static enum bp_result
get_integrated_info_v9(
2380 struct bios_parser
*bp
,
2381 struct integrated_info
*info
)
2383 ATOM_INTEGRATED_SYSTEM_INFO_V1_9
*info_v9
;
2386 info_v9
= GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9
,
2387 bp
->master_data_tbl
->ListOfDataTables
.IntegratedSystemInfo
);
2390 return BP_RESULT_BADBIOSTABLE
;
2392 info
->boot_up_engine_clock
= le32_to_cpu(info_v9
->ulBootUpEngineClock
) * 10;
2393 info
->dentist_vco_freq
= le32_to_cpu(info_v9
->ulDentistVCOFreq
) * 10;
2394 info
->boot_up_uma_clock
= le32_to_cpu(info_v9
->ulBootUpUMAClock
) * 10;
2396 for (i
= 0; i
< NUMBER_OF_DISP_CLK_VOLTAGE
; ++i
) {
2397 /* Convert [10KHz] into [KHz] */
2398 info
->disp_clk_voltage
[i
].max_supported_clk
=
2399 le32_to_cpu(info_v9
->sDISPCLK_Voltage
[i
].ulMaximumSupportedCLK
) * 10;
2400 info
->disp_clk_voltage
[i
].voltage_index
=
2401 le32_to_cpu(info_v9
->sDISPCLK_Voltage
[i
].ulVoltageIndex
);
2404 info
->boot_up_req_display_vector
=
2405 le32_to_cpu(info_v9
->ulBootUpReqDisplayVector
);
2406 info
->gpu_cap_info
= le32_to_cpu(info_v9
->ulGPUCapInfo
);
2409 * system_config: Bit[0] = 0 : PCIE power gating disabled
2410 * = 1 : PCIE power gating enabled
2411 * Bit[1] = 0 : DDR-PLL shut down disabled
2412 * = 1 : DDR-PLL shut down enabled
2413 * Bit[2] = 0 : DDR-PLL power down disabled
2414 * = 1 : DDR-PLL power down enabled
2416 info
->system_config
= le32_to_cpu(info_v9
->ulSystemConfig
);
2417 info
->cpu_cap_info
= le32_to_cpu(info_v9
->ulCPUCapInfo
);
2418 info
->boot_up_nb_voltage
= le16_to_cpu(info_v9
->usBootUpNBVoltage
);
2419 info
->ext_disp_conn_info_offset
= le16_to_cpu(info_v9
->usExtDispConnInfoOffset
);
2420 info
->memory_type
= info_v9
->ucMemoryType
;
2421 info
->ma_channel_number
= info_v9
->ucUMAChannelNumber
;
2422 info
->gmc_restore_reset_time
= le32_to_cpu(info_v9
->ulGMCRestoreResetTime
);
2424 info
->minimum_n_clk
= le32_to_cpu(info_v9
->ulNbpStateNClkFreq
[0]);
2425 for (i
= 1; i
< 4; ++i
)
2426 info
->minimum_n_clk
=
2427 info
->minimum_n_clk
< le32_to_cpu(info_v9
->ulNbpStateNClkFreq
[i
]) ?
2428 info
->minimum_n_clk
: le32_to_cpu(info_v9
->ulNbpStateNClkFreq
[i
]);
2430 info
->idle_n_clk
= le32_to_cpu(info_v9
->ulIdleNClk
);
2431 info
->ddr_dll_power_up_time
= le32_to_cpu(info_v9
->ulDDR_DLL_PowerUpTime
);
2432 info
->ddr_pll_power_up_time
= le32_to_cpu(info_v9
->ulDDR_PLL_PowerUpTime
);
2433 info
->pcie_clk_ss_type
= le16_to_cpu(info_v9
->usPCIEClkSSType
);
2434 info
->lvds_ss_percentage
= le16_to_cpu(info_v9
->usLvdsSSPercentage
);
2435 info
->lvds_sspread_rate_in_10hz
= le16_to_cpu(info_v9
->usLvdsSSpreadRateIn10Hz
);
2436 info
->hdmi_ss_percentage
= le16_to_cpu(info_v9
->usHDMISSPercentage
);
2437 info
->hdmi_sspread_rate_in_10hz
= le16_to_cpu(info_v9
->usHDMISSpreadRateIn10Hz
);
2438 info
->dvi_ss_percentage
= le16_to_cpu(info_v9
->usDVISSPercentage
);
2439 info
->dvi_sspread_rate_in_10_hz
= le16_to_cpu(info_v9
->usDVISSpreadRateIn10Hz
);
2441 info
->max_lvds_pclk_freq_in_single_link
=
2442 le16_to_cpu(info_v9
->usMaxLVDSPclkFreqInSingleLink
);
2443 info
->lvds_misc
= info_v9
->ucLvdsMisc
;
2444 info
->lvds_pwr_on_seq_dig_on_to_de_in_4ms
=
2445 info_v9
->ucLVDSPwrOnSeqDIGONtoDE_in4Ms
;
2446 info
->lvds_pwr_on_seq_de_to_vary_bl_in_4ms
=
2447 info_v9
->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms
;
2448 info
->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms
=
2449 info_v9
->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms
;
2450 info
->lvds_pwr_off_seq_vary_bl_to_de_in4ms
=
2451 info_v9
->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms
;
2452 info
->lvds_pwr_off_seq_de_to_dig_on_in4ms
=
2453 info_v9
->ucLVDSPwrOffSeqDEtoDIGON_in4Ms
;
2454 info
->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms
=
2455 info_v9
->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms
;
2456 info
->lvds_off_to_on_delay_in_4ms
=
2457 info_v9
->ucLVDSOffToOnDelay_in4Ms
;
2458 info
->lvds_bit_depth_control_val
=
2459 le32_to_cpu(info_v9
->ulLCDBitDepthControlVal
);
2461 for (i
= 0; i
< NUMBER_OF_AVAILABLE_SCLK
; ++i
) {
2462 /* Convert [10KHz] into [KHz] */
2463 info
->avail_s_clk
[i
].supported_s_clk
=
2464 le32_to_cpu(info_v9
->sAvail_SCLK
[i
].ulSupportedSCLK
) * 10;
2465 info
->avail_s_clk
[i
].voltage_index
=
2466 le16_to_cpu(info_v9
->sAvail_SCLK
[i
].usVoltageIndex
);
2467 info
->avail_s_clk
[i
].voltage_id
=
2468 le16_to_cpu(info_v9
->sAvail_SCLK
[i
].usVoltageID
);
2471 for (i
= 0; i
< NUMBER_OF_UCHAR_FOR_GUID
; ++i
) {
2472 info
->ext_disp_conn_info
.gu_id
[i
] =
2473 info_v9
->sExtDispConnInfo
.ucGuid
[i
];
2476 for (i
= 0; i
< MAX_NUMBER_OF_EXT_DISPLAY_PATH
; ++i
) {
2477 info
->ext_disp_conn_info
.path
[i
].device_connector_id
=
2478 object_id_from_bios_object_id(
2479 le16_to_cpu(info_v9
->sExtDispConnInfo
.sPath
[i
].usDeviceConnector
));
2481 info
->ext_disp_conn_info
.path
[i
].ext_encoder_obj_id
=
2482 object_id_from_bios_object_id(
2483 le16_to_cpu(info_v9
->sExtDispConnInfo
.sPath
[i
].usExtEncoderObjId
));
2485 info
->ext_disp_conn_info
.path
[i
].device_tag
=
2486 le16_to_cpu(info_v9
->sExtDispConnInfo
.sPath
[i
].usDeviceTag
);
2487 info
->ext_disp_conn_info
.path
[i
].device_acpi_enum
=
2488 le16_to_cpu(info_v9
->sExtDispConnInfo
.sPath
[i
].usDeviceACPIEnum
);
2489 info
->ext_disp_conn_info
.path
[i
].ext_aux_ddc_lut_index
=
2490 info_v9
->sExtDispConnInfo
.sPath
[i
].ucExtAUXDDCLutIndex
;
2491 info
->ext_disp_conn_info
.path
[i
].ext_hpd_pin_lut_index
=
2492 info_v9
->sExtDispConnInfo
.sPath
[i
].ucExtHPDPINLutIndex
;
2493 info
->ext_disp_conn_info
.path
[i
].channel_mapping
.raw
=
2494 info_v9
->sExtDispConnInfo
.sPath
[i
].ucChannelMapping
;
2496 info
->ext_disp_conn_info
.checksum
=
2497 info_v9
->sExtDispConnInfo
.ucChecksum
;
2499 return BP_RESULT_OK
;
2503 * construct_integrated_info
2506 * Get integrated BIOS information based on table revision
2509 * bios_parser *bp - [in]BIOS parser handler to get master data table
2510 * integrated_info *info - [out] store and output integrated info
2513 * enum bp_result - BP_RESULT_OK if information is available,
2514 * BP_RESULT_BADBIOSTABLE otherwise.
2516 static enum bp_result
construct_integrated_info(
2517 struct bios_parser
*bp
,
2518 struct integrated_info
*info
)
2520 enum bp_result result
= BP_RESULT_BADBIOSTABLE
;
2522 ATOM_COMMON_TABLE_HEADER
*header
;
2523 struct atom_data_revision revision
;
2525 if (bp
->master_data_tbl
->ListOfDataTables
.IntegratedSystemInfo
) {
2526 header
= GET_IMAGE(ATOM_COMMON_TABLE_HEADER
,
2527 bp
->master_data_tbl
->ListOfDataTables
.IntegratedSystemInfo
);
2529 get_atom_data_table_revision(header
, &revision
);
2531 /* Don't need to check major revision as they are all 1 */
2532 switch (revision
.minor
) {
2534 result
= get_integrated_info_v8(bp
, info
);
2537 result
= get_integrated_info_v9(bp
, info
);
2545 /* Sort voltage table from low to high*/
2546 if (result
== BP_RESULT_OK
) {
2550 for (i
= 1; i
< NUMBER_OF_DISP_CLK_VOLTAGE
; ++i
) {
2551 for (j
= i
; j
> 0; --j
) {
2553 info
->disp_clk_voltage
[j
].max_supported_clk
<
2554 info
->disp_clk_voltage
[j
-1].max_supported_clk
) {
2555 /* swap j and j - 1*/
2556 swap(info
->disp_clk_voltage
[j
- 1],
2557 info
->disp_clk_voltage
[j
]);
2567 static struct integrated_info
*bios_parser_create_integrated_info(
2568 struct dc_bios
*dcb
)
2570 struct bios_parser
*bp
= BP_FROM_DCB(dcb
);
2571 struct integrated_info
*info
= NULL
;
2573 info
= kzalloc(sizeof(struct integrated_info
), GFP_KERNEL
);
2580 if (construct_integrated_info(bp
, info
) == BP_RESULT_OK
)
2588 enum bp_result
update_slot_layout_info(
2589 struct dc_bios
*dcb
,
2591 struct slot_layout_info
*slot_layout_info
,
2592 unsigned int record_offset
)
2595 struct bios_parser
*bp
;
2596 ATOM_BRACKET_LAYOUT_RECORD
*record
;
2597 ATOM_COMMON_RECORD_HEADER
*record_header
;
2598 enum bp_result result
= BP_RESULT_NORECORD
;
2600 bp
= BP_FROM_DCB(dcb
);
2602 record_header
= NULL
;
2606 record_header
= (ATOM_COMMON_RECORD_HEADER
*)
2607 GET_IMAGE(ATOM_COMMON_RECORD_HEADER
, record_offset
);
2608 if (record_header
== NULL
) {
2609 result
= BP_RESULT_BADBIOSTABLE
;
2613 /* the end of the list */
2614 if (record_header
->ucRecordType
== 0xff ||
2615 record_header
->ucRecordSize
== 0) {
2619 if (record_header
->ucRecordType
==
2620 ATOM_BRACKET_LAYOUT_RECORD_TYPE
&&
2621 sizeof(ATOM_BRACKET_LAYOUT_RECORD
)
2622 <= record_header
->ucRecordSize
) {
2623 record
= (ATOM_BRACKET_LAYOUT_RECORD
*)
2625 result
= BP_RESULT_OK
;
2629 record_offset
+= record_header
->ucRecordSize
;
2632 /* return if the record not found */
2633 if (result
!= BP_RESULT_OK
)
2636 /* get slot sizes */
2637 slot_layout_info
->length
= record
->ucLength
;
2638 slot_layout_info
->width
= record
->ucWidth
;
2640 /* get info for each connector in the slot */
2641 slot_layout_info
->num_of_connectors
= record
->ucConnNum
;
2642 for (j
= 0; j
< slot_layout_info
->num_of_connectors
; ++j
) {
2643 slot_layout_info
->connectors
[j
].connector_type
=
2644 (enum connector_layout_type
)
2645 (record
->asConnInfo
[j
].ucConnectorType
);
2646 switch (record
->asConnInfo
[j
].ucConnectorType
) {
2647 case CONNECTOR_TYPE_DVI_D
:
2648 slot_layout_info
->connectors
[j
].connector_type
=
2649 CONNECTOR_LAYOUT_TYPE_DVI_D
;
2650 slot_layout_info
->connectors
[j
].length
=
2654 case CONNECTOR_TYPE_HDMI
:
2655 slot_layout_info
->connectors
[j
].connector_type
=
2656 CONNECTOR_LAYOUT_TYPE_HDMI
;
2657 slot_layout_info
->connectors
[j
].length
=
2658 CONNECTOR_SIZE_HDMI
;
2661 case CONNECTOR_TYPE_DISPLAY_PORT
:
2662 slot_layout_info
->connectors
[j
].connector_type
=
2663 CONNECTOR_LAYOUT_TYPE_DP
;
2664 slot_layout_info
->connectors
[j
].length
=
2668 case CONNECTOR_TYPE_MINI_DISPLAY_PORT
:
2669 slot_layout_info
->connectors
[j
].connector_type
=
2670 CONNECTOR_LAYOUT_TYPE_MINI_DP
;
2671 slot_layout_info
->connectors
[j
].length
=
2672 CONNECTOR_SIZE_MINI_DP
;
2676 slot_layout_info
->connectors
[j
].connector_type
=
2677 CONNECTOR_LAYOUT_TYPE_UNKNOWN
;
2678 slot_layout_info
->connectors
[j
].length
=
2679 CONNECTOR_SIZE_UNKNOWN
;
2682 slot_layout_info
->connectors
[j
].position
=
2683 record
->asConnInfo
[j
].ucPosition
;
2684 slot_layout_info
->connectors
[j
].connector_id
=
2685 object_id_from_bios_object_id(
2686 record
->asConnInfo
[j
].usConnectorObjectId
);
2692 enum bp_result
get_bracket_layout_record(
2693 struct dc_bios
*dcb
,
2694 unsigned int bracket_layout_id
,
2695 struct slot_layout_info
*slot_layout_info
)
2698 unsigned int record_offset
;
2699 struct bios_parser
*bp
;
2700 enum bp_result result
;
2701 ATOM_OBJECT
*object
;
2702 ATOM_OBJECT_TABLE
*object_table
;
2703 unsigned int genericTableOffset
;
2705 bp
= BP_FROM_DCB(dcb
);
2707 if (slot_layout_info
== NULL
) {
2708 DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");
2709 return BP_RESULT_BADINPUT
;
2713 genericTableOffset
= bp
->object_info_tbl_offset
+
2714 bp
->object_info_tbl
.v1_3
->usMiscObjectTableOffset
;
2715 object_table
= (ATOM_OBJECT_TABLE
*)
2716 GET_IMAGE(ATOM_OBJECT_TABLE
, genericTableOffset
);
2718 return BP_RESULT_FAILURE
;
2720 result
= BP_RESULT_NORECORD
;
2721 for (i
= 0; i
< object_table
->ucNumberOfObjects
; ++i
) {
2723 if (bracket_layout_id
==
2724 object_table
->asObjects
[i
].usObjectID
) {
2726 object
= &object_table
->asObjects
[i
];
2727 record_offset
= object
->usRecordOffset
+
2728 bp
->object_info_tbl_offset
;
2730 result
= update_slot_layout_info(dcb
, i
,
2731 slot_layout_info
, record_offset
);
2738 static enum bp_result
bios_get_board_layout_info(
2739 struct dc_bios
*dcb
,
2740 struct board_layout_info
*board_layout_info
)
2743 enum bp_result record_result
;
2745 const unsigned int slot_index_to_vbios_id
[MAX_BOARD_SLOTS
] = {
2746 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1
,
2747 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2
,
2751 if (board_layout_info
== NULL
) {
2752 DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");
2753 return BP_RESULT_BADINPUT
;
2756 board_layout_info
->num_of_slots
= 0;
2758 for (i
= 0; i
< MAX_BOARD_SLOTS
; ++i
) {
2759 record_result
= get_bracket_layout_record(dcb
,
2760 slot_index_to_vbios_id
[i
],
2761 &board_layout_info
->slots
[i
]);
2763 if (record_result
== BP_RESULT_NORECORD
&& i
> 0)
2764 break; /* no more slots present in bios */
2765 else if (record_result
!= BP_RESULT_OK
)
2766 return record_result
; /* fail */
2768 ++board_layout_info
->num_of_slots
;
2771 /* all data is valid */
2772 board_layout_info
->is_number_of_slots_valid
= 1;
2773 board_layout_info
->is_slots_size_valid
= 1;
2774 board_layout_info
->is_connector_offsets_valid
= 1;
2775 board_layout_info
->is_connector_lengths_valid
= 1;
2777 return BP_RESULT_OK
;
2780 /******************************************************************************/
2782 static const struct dc_vbios_funcs vbios_funcs
= {
2783 .get_connectors_number
= bios_parser_get_connectors_number
,
2785 .get_connector_id
= bios_parser_get_connector_id
,
2787 .get_src_obj
= bios_parser_get_src_obj
,
2789 .get_i2c_info
= bios_parser_get_i2c_info
,
2791 .get_hpd_info
= bios_parser_get_hpd_info
,
2793 .get_device_tag
= bios_parser_get_device_tag
,
2795 .get_spread_spectrum_info
= bios_parser_get_spread_spectrum_info
,
2797 .get_ss_entry_number
= bios_parser_get_ss_entry_number
,
2799 .get_embedded_panel_info
= bios_parser_get_embedded_panel_info
,
2801 .get_gpio_pin_info
= bios_parser_get_gpio_pin_info
,
2803 .get_encoder_cap_info
= bios_parser_get_encoder_cap_info
,
2805 /* bios scratch register communication */
2806 .is_accelerated_mode
= bios_is_accelerated_mode
,
2808 .set_scratch_critical_state
= bios_parser_set_scratch_critical_state
,
2810 .is_device_id_supported
= bios_parser_is_device_id_supported
,
2813 .encoder_control
= bios_parser_encoder_control
,
2815 .transmitter_control
= bios_parser_transmitter_control
,
2817 .enable_crtc
= bios_parser_enable_crtc
,
2819 .adjust_pixel_clock
= bios_parser_adjust_pixel_clock
,
2821 .set_pixel_clock
= bios_parser_set_pixel_clock
,
2823 .set_dce_clock
= bios_parser_set_dce_clock
,
2825 .enable_spread_spectrum_on_ppll
= bios_parser_enable_spread_spectrum_on_ppll
,
2827 .program_crtc_timing
= bios_parser_program_crtc_timing
, /* still use. should probably retire and program directly */
2829 .program_display_engine_pll
= bios_parser_program_display_engine_pll
,
2831 .enable_disp_power_gating
= bios_parser_enable_disp_power_gating
,
2833 /* SW init and patch */
2835 .bios_parser_destroy
= bios_parser_destroy
,
2837 .get_board_layout_info
= bios_get_board_layout_info
,
2839 .get_atom_dc_golden_table
= NULL
2842 static bool bios_parser_construct(
2843 struct bios_parser
*bp
,
2844 struct bp_init_data
*init
,
2845 enum dce_version dce_version
)
2847 uint16_t *rom_header_offset
= NULL
;
2848 ATOM_ROM_HEADER
*rom_header
= NULL
;
2849 ATOM_OBJECT_HEADER
*object_info_tbl
;
2850 struct atom_data_revision tbl_rev
= {0};
2858 bp
->base
.funcs
= &vbios_funcs
;
2859 bp
->base
.bios
= init
->bios
;
2860 bp
->base
.bios_size
= bp
->base
.bios
[BIOS_IMAGE_SIZE_OFFSET
] * BIOS_IMAGE_SIZE_UNIT
;
2862 bp
->base
.ctx
= init
->ctx
;
2863 bp
->base
.bios_local_image
= NULL
;
2866 GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER
);
2868 if (!rom_header_offset
)
2871 rom_header
= GET_IMAGE(ATOM_ROM_HEADER
, *rom_header_offset
);
2876 get_atom_data_table_revision(&rom_header
->sHeader
, &tbl_rev
);
2877 if (tbl_rev
.major
>= 2 && tbl_rev
.minor
>= 2)
2880 bp
->master_data_tbl
=
2881 GET_IMAGE(ATOM_MASTER_DATA_TABLE
,
2882 rom_header
->usMasterDataTableOffset
);
2884 if (!bp
->master_data_tbl
)
2887 bp
->object_info_tbl_offset
= DATA_TABLES(Object_Header
);
2889 if (!bp
->object_info_tbl_offset
)
2893 GET_IMAGE(ATOM_OBJECT_HEADER
, bp
->object_info_tbl_offset
);
2895 if (!object_info_tbl
)
2898 get_atom_data_table_revision(&object_info_tbl
->sHeader
,
2899 &bp
->object_info_tbl
.revision
);
2901 if (bp
->object_info_tbl
.revision
.major
== 1
2902 && bp
->object_info_tbl
.revision
.minor
>= 3) {
2903 ATOM_OBJECT_HEADER_V3
*tbl_v3
;
2905 tbl_v3
= GET_IMAGE(ATOM_OBJECT_HEADER_V3
,
2906 bp
->object_info_tbl_offset
);
2910 bp
->object_info_tbl
.v1_3
= tbl_v3
;
2911 } else if (bp
->object_info_tbl
.revision
.major
== 1
2912 && bp
->object_info_tbl
.revision
.minor
>= 1)
2913 bp
->object_info_tbl
.v1_1
= object_info_tbl
;
2917 dal_bios_parser_init_cmd_tbl(bp
);
2918 dal_bios_parser_init_cmd_tbl_helper(&bp
->cmd_helper
, dce_version
);
2920 bp
->base
.integrated_info
= bios_parser_create_integrated_info(&bp
->base
);
2921 bp
->base
.fw_info_valid
= bios_parser_get_firmware_info(&bp
->base
, &bp
->base
.fw_info
) == BP_RESULT_OK
;
2926 /******************************************************************************/