1 /* 2 * Copyright 2012-15 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: AMD 23 * 24 */ 25 26 #include <linux/slab.h> 27 28 #include "dm_services.h" 29 30 #include "atom.h" 31 32 #include "dc_bios_types.h" 33 #include "include/gpio_service_interface.h" 34 #include "include/grph_object_ctrl_defs.h" 35 #include "include/bios_parser_interface.h" 36 #include "include/logger_interface.h" 37 38 #include "command_table.h" 39 #include "bios_parser_helper.h" 40 #include "command_table_helper.h" 41 #include "bios_parser.h" 42 #include "bios_parser_types_internal.h" 43 #include "bios_parser_interface.h" 44 45 #include "bios_parser_common.h" 46 47 #define THREE_PERCENT_OF_10000 300 48 49 #define LAST_RECORD_TYPE 0xff 50 51 #define DC_LOGGER \ 52 bp->base.ctx->logger 53 54 #define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table) 55 56 static void get_atom_data_table_revision( 57 ATOM_COMMON_TABLE_HEADER *atom_data_tbl, 58 struct atom_data_revision *tbl_revision); 59 static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object, 60 uint16_t **id_list); 61 static ATOM_OBJECT *get_bios_object(struct bios_parser *bp, 62 struct graphics_object_id id); 63 static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, 64 ATOM_I2C_RECORD *record, 65 struct graphics_object_i2c_info *info); 66 static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, 67 ATOM_OBJECT *object); 68 static struct device_id device_type_from_device_id(uint16_t device_id); 69 static uint32_t signal_to_ss_id(enum as_signal_type signal); 70 static uint32_t get_support_mask_for_device_id( 71 enum dal_device_type device_type, 72 uint32_t enum_id); 73 static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record( 74 struct bios_parser *bp, 75 ATOM_OBJECT *object); 76 77 #define BIOS_IMAGE_SIZE_OFFSET 2 78 #define BIOS_IMAGE_SIZE_UNIT 512 79 80 /*****************************************************************************/ 81 static bool bios_parser_construct( 82 struct bios_parser *bp, 83 struct bp_init_data *init, 84 enum dce_version dce_version); 85 86 static uint8_t bios_parser_get_connectors_number( 87 struct dc_bios *dcb); 88 89 static enum bp_result bios_parser_get_embedded_panel_info( 90 struct dc_bios *dcb, 91 struct embedded_panel_info *info); 92 93 /*****************************************************************************/ 94 95 struct dc_bios *bios_parser_create( 96 struct bp_init_data *init, 97 enum dce_version dce_version) 98 { 99 struct bios_parser *bp; 100 101 bp = kzalloc_obj(struct bios_parser); 102 if (!bp) 103 return NULL; 104 105 if (bios_parser_construct(bp, init, dce_version)) 106 return &bp->base; 107 108 kfree(bp); 109 BREAK_TO_DEBUGGER(); 110 return NULL; 111 } 112 113 static void bios_parser_destruct(struct bios_parser *bp) 114 { 115 kfree(bp->base.bios_local_image); 116 kfree(bp->base.integrated_info); 117 } 118 119 static void bios_parser_destroy(struct dc_bios **dcb) 120 { 121 struct bios_parser *bp = BP_FROM_DCB(*dcb); 122 123 if (!bp) { 124 BREAK_TO_DEBUGGER(); 125 return; 126 } 127 128 bios_parser_destruct(bp); 129 130 kfree(bp); 131 *dcb = NULL; 132 } 133 134 static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset) 135 { 136 ATOM_OBJECT_TABLE *table; 137 138 uint32_t object_table_offset = bp->object_info_tbl_offset + offset; 139 140 table = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base, 141 object_table_offset, 142 struct_size(table, asObjects, 1))); 143 144 if (!table) 145 return 0; 146 else 147 return table->ucNumberOfObjects; 148 } 149 150 static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb) 151 { 152 struct bios_parser *bp = BP_FROM_DCB(dcb); 153 154 return get_number_of_objects(bp, 155 le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset)); 156 } 157 158 static struct graphics_object_id bios_parser_get_connector_id( 159 struct dc_bios *dcb, 160 uint8_t i) 161 { 162 struct bios_parser *bp = BP_FROM_DCB(dcb); 163 struct graphics_object_id object_id = dal_graphics_object_id_init( 164 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN); 165 uint16_t id; 166 167 uint32_t connector_table_offset = bp->object_info_tbl_offset 168 + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); 169 170 ATOM_OBJECT_TABLE *tbl = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base, 171 connector_table_offset, 172 struct_size(tbl, asObjects, 1))); 173 174 if (!tbl) { 175 dm_error("Can't get connector table from atom bios.\n"); 176 return object_id; 177 } 178 179 if (tbl->ucNumberOfObjects <= i) 180 return object_id; 181 182 id = le16_to_cpu(tbl->asObjects[i].usObjectID); 183 object_id = object_id_from_bios_object_id(id); 184 return object_id; 185 } 186 187 static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb, 188 struct graphics_object_id object_id, uint32_t index, 189 struct graphics_object_id *src_object_id) 190 { 191 uint32_t number; 192 uint16_t *id; 193 ATOM_OBJECT *object; 194 struct bios_parser *bp = BP_FROM_DCB(dcb); 195 196 if (!src_object_id) 197 return BP_RESULT_BADINPUT; 198 199 object = get_bios_object(bp, object_id); 200 201 if (!object) { 202 BREAK_TO_DEBUGGER(); /* Invalid object id */ 203 return BP_RESULT_BADINPUT; 204 } 205 206 number = get_src_obj_list(bp, object, &id); 207 208 if (number <= index) 209 return BP_RESULT_BADINPUT; 210 211 *src_object_id = object_id_from_bios_object_id(id[index]); 212 213 return BP_RESULT_OK; 214 } 215 216 static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb, 217 struct graphics_object_id id, 218 struct graphics_object_i2c_info *info) 219 { 220 uint32_t offset; 221 ATOM_OBJECT *object; 222 ATOM_COMMON_RECORD_HEADER *header; 223 ATOM_I2C_RECORD *record; 224 struct bios_parser *bp = BP_FROM_DCB(dcb); 225 226 if (!info) 227 return BP_RESULT_BADINPUT; 228 229 object = get_bios_object(bp, id); 230 231 if (!object) 232 return BP_RESULT_BADINPUT; 233 234 offset = le16_to_cpu(object->usRecordOffset) 235 + bp->object_info_tbl_offset; 236 237 for (;;) { 238 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); 239 240 if (!header) 241 return BP_RESULT_BADBIOSTABLE; 242 243 if (LAST_RECORD_TYPE == header->ucRecordType || 244 !header->ucRecordSize) 245 break; 246 247 if (ATOM_I2C_RECORD_TYPE == header->ucRecordType 248 && sizeof(ATOM_I2C_RECORD) <= header->ucRecordSize) { 249 /* get the I2C info */ 250 record = (ATOM_I2C_RECORD *) header; 251 252 if (get_gpio_i2c_info(bp, record, info) == BP_RESULT_OK) 253 return BP_RESULT_OK; 254 } 255 256 offset += header->ucRecordSize; 257 } 258 259 return BP_RESULT_NORECORD; 260 } 261 262 static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb, 263 struct graphics_object_id id, 264 struct graphics_object_hpd_info *info) 265 { 266 struct bios_parser *bp = BP_FROM_DCB(dcb); 267 ATOM_OBJECT *object; 268 ATOM_HPD_INT_RECORD *record = NULL; 269 270 if (!info) 271 return BP_RESULT_BADINPUT; 272 273 object = get_bios_object(bp, id); 274 275 if (!object) 276 return BP_RESULT_BADINPUT; 277 278 record = get_hpd_record(bp, object); 279 280 if (record != NULL) { 281 info->hpd_int_gpio_uid = record->ucHPDIntGPIOID; 282 info->hpd_active = record->ucPlugged_PinState; 283 return BP_RESULT_OK; 284 } 285 286 return BP_RESULT_NORECORD; 287 } 288 289 static enum bp_result bios_parser_get_device_tag_record( 290 struct bios_parser *bp, 291 ATOM_OBJECT *object, 292 ATOM_CONNECTOR_DEVICE_TAG_RECORD **record) 293 { 294 ATOM_COMMON_RECORD_HEADER *header; 295 uint32_t offset; 296 297 offset = le16_to_cpu(object->usRecordOffset) 298 + bp->object_info_tbl_offset; 299 300 for (;;) { 301 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); 302 303 if (!header) 304 return BP_RESULT_BADBIOSTABLE; 305 306 offset += header->ucRecordSize; 307 308 if (LAST_RECORD_TYPE == header->ucRecordType || 309 !header->ucRecordSize) 310 break; 311 312 if (ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE != 313 header->ucRecordType) 314 continue; 315 316 if (sizeof(ATOM_CONNECTOR_DEVICE_TAG) > header->ucRecordSize) 317 continue; 318 319 *record = (ATOM_CONNECTOR_DEVICE_TAG_RECORD *) header; 320 return BP_RESULT_OK; 321 } 322 323 return BP_RESULT_NORECORD; 324 } 325 326 static enum bp_result bios_parser_get_device_tag( 327 struct dc_bios *dcb, 328 struct graphics_object_id connector_object_id, 329 uint32_t device_tag_index, 330 struct connector_device_tag_info *info) 331 { 332 struct bios_parser *bp = BP_FROM_DCB(dcb); 333 ATOM_OBJECT *object; 334 ATOM_CONNECTOR_DEVICE_TAG_RECORD *record = NULL; 335 ATOM_CONNECTOR_DEVICE_TAG *device_tag; 336 337 if (!info) 338 return BP_RESULT_BADINPUT; 339 340 /* getBiosObject will return MXM object */ 341 object = get_bios_object(bp, connector_object_id); 342 343 if (!object) { 344 BREAK_TO_DEBUGGER(); /* Invalid object id */ 345 return BP_RESULT_BADINPUT; 346 } 347 348 if (bios_parser_get_device_tag_record(bp, object, &record) 349 != BP_RESULT_OK) 350 return BP_RESULT_NORECORD; 351 352 if (device_tag_index >= record->ucNumberOfDevice) 353 return BP_RESULT_NORECORD; 354 355 device_tag = &record->asDeviceTag[device_tag_index]; 356 357 info->acpi_device = le32_to_cpu(device_tag->ulACPIDeviceEnum); 358 info->dev_id = 359 device_type_from_device_id(le16_to_cpu(device_tag->usDeviceID)); 360 361 return BP_RESULT_OK; 362 } 363 364 static enum bp_result get_firmware_info_v1_4( 365 struct bios_parser *bp, 366 struct dc_firmware_info *info); 367 static enum bp_result get_firmware_info_v2_1( 368 struct bios_parser *bp, 369 struct dc_firmware_info *info); 370 static enum bp_result get_firmware_info_v2_2( 371 struct bios_parser *bp, 372 struct dc_firmware_info *info); 373 374 static enum bp_result bios_parser_get_firmware_info( 375 struct dc_bios *dcb, 376 struct dc_firmware_info *info) 377 { 378 struct bios_parser *bp = BP_FROM_DCB(dcb); 379 enum bp_result result = BP_RESULT_BADBIOSTABLE; 380 ATOM_COMMON_TABLE_HEADER *header; 381 struct atom_data_revision revision; 382 383 if (info && DATA_TABLES(FirmwareInfo)) { 384 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, 385 DATA_TABLES(FirmwareInfo)); 386 get_atom_data_table_revision(header, &revision); 387 switch (revision.major) { 388 case 1: 389 switch (revision.minor) { 390 case 4: 391 result = get_firmware_info_v1_4(bp, info); 392 break; 393 default: 394 break; 395 } 396 break; 397 398 case 2: 399 switch (revision.minor) { 400 case 1: 401 result = get_firmware_info_v2_1(bp, info); 402 break; 403 case 2: 404 result = get_firmware_info_v2_2(bp, info); 405 break; 406 default: 407 break; 408 } 409 break; 410 default: 411 break; 412 } 413 } 414 415 return result; 416 } 417 418 static enum bp_result get_firmware_info_v1_4( 419 struct bios_parser *bp, 420 struct dc_firmware_info *info) 421 { 422 ATOM_FIRMWARE_INFO_V1_4 *firmware_info = 423 GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4, 424 DATA_TABLES(FirmwareInfo)); 425 426 if (!info) 427 return BP_RESULT_BADINPUT; 428 429 if (!firmware_info) 430 return BP_RESULT_BADBIOSTABLE; 431 432 memset(info, 0, sizeof(*info)); 433 434 /* Pixel clock pll information. We need to convert from 10KHz units into 435 * KHz units */ 436 info->pll_info.crystal_frequency = 437 le16_to_cpu(firmware_info->usReferenceClock) * 10; 438 info->pll_info.min_input_pxl_clk_pll_frequency = 439 le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10; 440 info->pll_info.max_input_pxl_clk_pll_frequency = 441 le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10; 442 info->pll_info.min_output_pxl_clk_pll_frequency = 443 le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10; 444 info->pll_info.max_output_pxl_clk_pll_frequency = 445 le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10; 446 info->max_pixel_clock = le16_to_cpu(firmware_info->usMaxPixelClock) * 10; 447 448 if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support) 449 /* Since there is no information on the SS, report conservative 450 * value 3% for bandwidth calculation */ 451 /* unit of 0.01% */ 452 info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000; 453 454 if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support) 455 /* Since there is no information on the SS,report conservative 456 * value 3% for bandwidth calculation */ 457 /* unit of 0.01% */ 458 info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000; 459 460 return BP_RESULT_OK; 461 } 462 463 static enum bp_result get_ss_info_v3_1( 464 struct bios_parser *bp, 465 uint32_t id, 466 uint32_t index, 467 struct spread_spectrum_info *ss_info); 468 469 static enum bp_result get_firmware_info_v2_1( 470 struct bios_parser *bp, 471 struct dc_firmware_info *info) 472 { 473 ATOM_FIRMWARE_INFO_V2_1 *firmwareInfo = 474 GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1, DATA_TABLES(FirmwareInfo)); 475 struct spread_spectrum_info internalSS; 476 uint32_t index; 477 478 if (!info) 479 return BP_RESULT_BADINPUT; 480 481 if (!firmwareInfo) 482 return BP_RESULT_BADBIOSTABLE; 483 484 memset(info, 0, sizeof(*info)); 485 486 /* Pixel clock pll information. We need to convert from 10KHz units into 487 * KHz units */ 488 info->pll_info.crystal_frequency = 489 le16_to_cpu(firmwareInfo->usCoreReferenceClock) * 10; 490 info->pll_info.min_input_pxl_clk_pll_frequency = 491 le16_to_cpu(firmwareInfo->usMinPixelClockPLL_Input) * 10; 492 info->pll_info.max_input_pxl_clk_pll_frequency = 493 le16_to_cpu(firmwareInfo->usMaxPixelClockPLL_Input) * 10; 494 info->pll_info.min_output_pxl_clk_pll_frequency = 495 le32_to_cpu(firmwareInfo->ulMinPixelClockPLL_Output) * 10; 496 info->pll_info.max_output_pxl_clk_pll_frequency = 497 le32_to_cpu(firmwareInfo->ulMaxPixelClockPLL_Output) * 10; 498 info->default_display_engine_pll_frequency = 499 le32_to_cpu(firmwareInfo->ulDefaultDispEngineClkFreq) * 10; 500 info->external_clock_source_frequency_for_dp = 501 le16_to_cpu(firmwareInfo->usUniphyDPModeExtClkFreq) * 10; 502 info->min_allowed_bl_level = firmwareInfo->ucMinAllowedBL_Level; 503 info->max_pixel_clock = le16_to_cpu(firmwareInfo->usMaxPixelClock) * 10; 504 505 /* There should be only one entry in the SS info table for Memory Clock 506 */ 507 index = 0; 508 if (firmwareInfo->usFirmwareCapability.sbfAccess.MemoryClockSS_Support) 509 /* Since there is no information for external SS, report 510 * conservative value 3% for bandwidth calculation */ 511 /* unit of 0.01% */ 512 info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000; 513 else if (get_ss_info_v3_1(bp, 514 ASIC_INTERNAL_MEMORY_SS, index, &internalSS) == BP_RESULT_OK) { 515 if (internalSS.spread_spectrum_percentage) { 516 info->feature.memory_clk_ss_percentage = 517 internalSS.spread_spectrum_percentage; 518 if (internalSS.type.CENTER_MODE) { 519 /* if it is centermode, the exact SS Percentage 520 * will be round up of half of the percentage 521 * reported in the SS table */ 522 ++info->feature.memory_clk_ss_percentage; 523 info->feature.memory_clk_ss_percentage /= 2; 524 } 525 } 526 } 527 528 /* There should be only one entry in the SS info table for Engine Clock 529 */ 530 index = 1; 531 if (firmwareInfo->usFirmwareCapability.sbfAccess.EngineClockSS_Support) 532 /* Since there is no information for external SS, report 533 * conservative value 3% for bandwidth calculation */ 534 /* unit of 0.01% */ 535 info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000; 536 else if (get_ss_info_v3_1(bp, 537 ASIC_INTERNAL_ENGINE_SS, index, &internalSS) == BP_RESULT_OK) { 538 if (internalSS.spread_spectrum_percentage) { 539 info->feature.engine_clk_ss_percentage = 540 internalSS.spread_spectrum_percentage; 541 if (internalSS.type.CENTER_MODE) { 542 /* if it is centermode, the exact SS Percentage 543 * will be round up of half of the percentage 544 * reported in the SS table */ 545 ++info->feature.engine_clk_ss_percentage; 546 info->feature.engine_clk_ss_percentage /= 2; 547 } 548 } 549 } 550 551 return BP_RESULT_OK; 552 } 553 554 static enum bp_result get_firmware_info_v2_2( 555 struct bios_parser *bp, 556 struct dc_firmware_info *info) 557 { 558 ATOM_FIRMWARE_INFO_V2_2 *firmware_info; 559 struct spread_spectrum_info internal_ss; 560 uint32_t index; 561 562 if (!info) 563 return BP_RESULT_BADINPUT; 564 565 firmware_info = GET_IMAGE(ATOM_FIRMWARE_INFO_V2_2, 566 DATA_TABLES(FirmwareInfo)); 567 568 if (!firmware_info) 569 return BP_RESULT_BADBIOSTABLE; 570 571 memset(info, 0, sizeof(*info)); 572 573 /* Pixel clock pll information. We need to convert from 10KHz units into 574 * KHz units */ 575 info->pll_info.crystal_frequency = 576 le16_to_cpu(firmware_info->usCoreReferenceClock) * 10; 577 info->pll_info.min_input_pxl_clk_pll_frequency = 578 le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10; 579 info->pll_info.max_input_pxl_clk_pll_frequency = 580 le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10; 581 info->pll_info.min_output_pxl_clk_pll_frequency = 582 le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10; 583 info->pll_info.max_output_pxl_clk_pll_frequency = 584 le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10; 585 info->default_display_engine_pll_frequency = 586 le32_to_cpu(firmware_info->ulDefaultDispEngineClkFreq) * 10; 587 info->external_clock_source_frequency_for_dp = 588 le16_to_cpu(firmware_info->usUniphyDPModeExtClkFreq) * 10; 589 590 /* There should be only one entry in the SS info table for Memory Clock 591 */ 592 index = 0; 593 if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support) 594 /* Since there is no information for external SS, report 595 * conservative value 3% for bandwidth calculation */ 596 /* unit of 0.01% */ 597 info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000; 598 else if (get_ss_info_v3_1(bp, 599 ASIC_INTERNAL_MEMORY_SS, index, &internal_ss) == BP_RESULT_OK) { 600 if (internal_ss.spread_spectrum_percentage) { 601 info->feature.memory_clk_ss_percentage = 602 internal_ss.spread_spectrum_percentage; 603 if (internal_ss.type.CENTER_MODE) { 604 /* if it is centermode, the exact SS Percentage 605 * will be round up of half of the percentage 606 * reported in the SS table */ 607 ++info->feature.memory_clk_ss_percentage; 608 info->feature.memory_clk_ss_percentage /= 2; 609 } 610 } 611 } 612 613 /* There should be only one entry in the SS info table for Engine Clock 614 */ 615 index = 1; 616 if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support) 617 /* Since there is no information for external SS, report 618 * conservative value 3% for bandwidth calculation */ 619 /* unit of 0.01% */ 620 info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000; 621 else if (get_ss_info_v3_1(bp, 622 ASIC_INTERNAL_ENGINE_SS, index, &internal_ss) == BP_RESULT_OK) { 623 if (internal_ss.spread_spectrum_percentage) { 624 info->feature.engine_clk_ss_percentage = 625 internal_ss.spread_spectrum_percentage; 626 if (internal_ss.type.CENTER_MODE) { 627 /* if it is centermode, the exact SS Percentage 628 * will be round up of half of the percentage 629 * reported in the SS table */ 630 ++info->feature.engine_clk_ss_percentage; 631 info->feature.engine_clk_ss_percentage /= 2; 632 } 633 } 634 } 635 636 /* Remote Display */ 637 info->remote_display_config = firmware_info->ucRemoteDisplayConfig; 638 639 /* Is allowed minimum BL level */ 640 info->min_allowed_bl_level = firmware_info->ucMinAllowedBL_Level; 641 /* Used starting from CI */ 642 info->smu_gpu_pll_output_freq = 643 (uint32_t) (le32_to_cpu(firmware_info->ulGPUPLL_OutputFreq) * 10); 644 645 return BP_RESULT_OK; 646 } 647 648 static enum bp_result get_ss_info_v3_1( 649 struct bios_parser *bp, 650 uint32_t id, 651 uint32_t index, 652 struct spread_spectrum_info *ss_info) 653 { 654 ATOM_ASIC_INTERNAL_SS_INFO_V3 *ss_table_header_include; 655 ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl; 656 uint32_t table_size; 657 uint32_t i; 658 uint32_t table_index = 0; 659 660 if (!ss_info) 661 return BP_RESULT_BADINPUT; 662 663 if (!DATA_TABLES(ASIC_InternalSS_Info)) 664 return BP_RESULT_UNSUPPORTED; 665 666 ss_table_header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V3 *) bios_get_image(&bp->base, 667 DATA_TABLES(ASIC_InternalSS_Info), 668 struct_size(ss_table_header_include, asSpreadSpectrum, 1))); 669 if (!ss_table_header_include) 670 return BP_RESULT_UNSUPPORTED; 671 672 table_size = 673 (le16_to_cpu(ss_table_header_include->sHeader.usStructureSize) 674 - sizeof(ATOM_COMMON_TABLE_HEADER)) 675 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3); 676 677 tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *) 678 &ss_table_header_include->asSpreadSpectrum[0]; 679 680 memset(ss_info, 0, sizeof(struct spread_spectrum_info)); 681 682 for (i = 0; i < table_size; i++) { 683 if (tbl[i].ucClockIndication != (uint8_t) id) 684 continue; 685 686 if (table_index != index) { 687 table_index++; 688 continue; 689 } 690 /* VBIOS introduced new defines for Version 3, same values as 691 * before, so now use these new ones for Version 3. 692 * Shouldn't affect field VBIOS's V3 as define values are still 693 * same. 694 * #define SS_MODE_V3_CENTRE_SPREAD_MASK 0x01 695 * #define SS_MODE_V3_EXTERNAL_SS_MASK 0x02 696 697 * Old VBIOS defines: 698 * #define ATOM_SS_CENTRE_SPREAD_MODE_MASK 0x00000001 699 * #define ATOM_EXTERNAL_SS_MASK 0x00000002 700 */ 701 702 if (SS_MODE_V3_EXTERNAL_SS_MASK & tbl[i].ucSpreadSpectrumMode) 703 ss_info->type.EXTERNAL = true; 704 705 if (SS_MODE_V3_CENTRE_SPREAD_MASK & tbl[i].ucSpreadSpectrumMode) 706 ss_info->type.CENTER_MODE = true; 707 708 /* Older VBIOS (in field) always provides SS percentage in 0.01% 709 * units set Divider to 100 */ 710 ss_info->spread_percentage_divider = 100; 711 712 /* #define SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 0x10 */ 713 if (SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 714 & tbl[i].ucSpreadSpectrumMode) 715 ss_info->spread_percentage_divider = 1000; 716 717 ss_info->type.STEP_AND_DELAY_INFO = false; 718 /* convert [10KHz] into [KHz] */ 719 ss_info->target_clock_range = 720 le32_to_cpu(tbl[i].ulTargetClockRange) * 10; 721 ss_info->spread_spectrum_percentage = 722 (uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage); 723 ss_info->spread_spectrum_range = 724 (uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10); 725 726 return BP_RESULT_OK; 727 } 728 return BP_RESULT_NORECORD; 729 } 730 731 static enum bp_result bios_parser_transmitter_control( 732 struct dc_bios *dcb, 733 struct bp_transmitter_control *cntl) 734 { 735 struct bios_parser *bp = BP_FROM_DCB(dcb); 736 737 if (!bp->cmd_tbl.transmitter_control) 738 return BP_RESULT_FAILURE; 739 740 return bp->cmd_tbl.transmitter_control(bp, cntl); 741 } 742 743 static enum bp_result bios_parser_select_crtc_source( 744 struct dc_bios *dcb, 745 struct bp_crtc_source_select *bp_params) 746 { 747 struct bios_parser *bp = BP_FROM_DCB(dcb); 748 749 if (!bp->cmd_tbl.select_crtc_source) 750 return BP_RESULT_FAILURE; 751 752 return bp->cmd_tbl.select_crtc_source(bp, bp_params); 753 } 754 755 static enum bp_result bios_parser_encoder_control( 756 struct dc_bios *dcb, 757 struct bp_encoder_control *cntl) 758 { 759 struct bios_parser *bp = BP_FROM_DCB(dcb); 760 761 if (cntl->engine_id == ENGINE_ID_DACA) { 762 if (!bp->cmd_tbl.dac1_encoder_control) 763 return BP_RESULT_FAILURE; 764 765 return bp->cmd_tbl.dac1_encoder_control( 766 bp, cntl->action, 767 cntl->pixel_clock, ATOM_DAC1_PS2); 768 } else if (cntl->engine_id == ENGINE_ID_DACB) { 769 if (!bp->cmd_tbl.dac2_encoder_control) 770 return BP_RESULT_FAILURE; 771 772 return bp->cmd_tbl.dac2_encoder_control( 773 bp, cntl->action, 774 cntl->pixel_clock, ATOM_DAC1_PS2); 775 } 776 777 if (!bp->cmd_tbl.dig_encoder_control) 778 return BP_RESULT_FAILURE; 779 780 return bp->cmd_tbl.dig_encoder_control(bp, cntl); 781 } 782 783 static enum bp_result bios_parser_external_encoder_control( 784 struct dc_bios *dcb, 785 struct bp_external_encoder_control *cntl) 786 { 787 struct bios_parser *bp = BP_FROM_DCB(dcb); 788 789 if (!bp->cmd_tbl.external_encoder_control) 790 return BP_RESULT_UNSUPPORTED; 791 792 return bp->cmd_tbl.external_encoder_control(bp, cntl); 793 } 794 795 static enum bp_result bios_parser_dac_load_detection( 796 struct dc_bios *dcb, 797 enum engine_id engine_id) 798 { 799 struct bios_parser *bp = BP_FROM_DCB(dcb); 800 struct dc_context *ctx = dcb->ctx; 801 struct bp_load_detection_parameters bp_params = {0}; 802 enum bp_result bp_result = BP_RESULT_UNSUPPORTED; 803 uint32_t bios_0_scratch; 804 uint32_t device_id_mask = 0; 805 806 bp_params.device_id = get_support_mask_for_device_id( 807 DEVICE_TYPE_CRT, engine_id == ENGINE_ID_DACB ? 2 : 1); 808 809 if (bp_params.device_id == ATOM_DEVICE_CRT1_SUPPORT) 810 device_id_mask = ATOM_S0_CRT1_MASK; 811 else if (bp_params.device_id == ATOM_DEVICE_CRT2_SUPPORT) 812 device_id_mask = ATOM_S0_CRT2_MASK; 813 else 814 return BP_RESULT_UNSUPPORTED; 815 816 /* BIOS will write the detected devices to BIOS_SCRATCH_0, clear corresponding bit */ 817 bios_0_scratch = dm_read_reg(ctx, bp->base.regs->BIOS_SCRATCH_0); 818 bios_0_scratch &= ~device_id_mask; 819 dm_write_reg(ctx, bp->base.regs->BIOS_SCRATCH_0, bios_0_scratch); 820 821 if (engine_id == ENGINE_ID_DACA || engine_id == ENGINE_ID_DACB) { 822 if (!bp->cmd_tbl.dac_load_detection) 823 return BP_RESULT_UNSUPPORTED; 824 825 bp_params.engine_id = engine_id; 826 bp_result = bp->cmd_tbl.dac_load_detection(bp, &bp_params); 827 } 828 829 if (bp_result != BP_RESULT_OK) 830 return bp_result; 831 832 bios_0_scratch = dm_read_reg(ctx, bp->base.regs->BIOS_SCRATCH_0); 833 834 if (bios_0_scratch & device_id_mask) 835 return BP_RESULT_OK; 836 837 return BP_RESULT_FAILURE; 838 } 839 840 static enum bp_result bios_parser_adjust_pixel_clock( 841 struct dc_bios *dcb, 842 struct bp_adjust_pixel_clock_parameters *bp_params) 843 { 844 struct bios_parser *bp = BP_FROM_DCB(dcb); 845 846 if (!bp->cmd_tbl.adjust_display_pll) 847 return BP_RESULT_FAILURE; 848 849 return bp->cmd_tbl.adjust_display_pll(bp, bp_params); 850 } 851 852 static enum bp_result bios_parser_set_pixel_clock( 853 struct dc_bios *dcb, 854 struct bp_pixel_clock_parameters *bp_params) 855 { 856 struct bios_parser *bp = BP_FROM_DCB(dcb); 857 858 if (!bp->cmd_tbl.set_pixel_clock) 859 return BP_RESULT_FAILURE; 860 861 return bp->cmd_tbl.set_pixel_clock(bp, bp_params); 862 } 863 864 static enum bp_result bios_parser_set_dce_clock( 865 struct dc_bios *dcb, 866 struct bp_set_dce_clock_parameters *bp_params) 867 { 868 struct bios_parser *bp = BP_FROM_DCB(dcb); 869 870 if (!bp->cmd_tbl.set_dce_clock) 871 return BP_RESULT_FAILURE; 872 873 return bp->cmd_tbl.set_dce_clock(bp, bp_params); 874 } 875 876 static enum bp_result bios_parser_enable_spread_spectrum_on_ppll( 877 struct dc_bios *dcb, 878 struct bp_spread_spectrum_parameters *bp_params, 879 bool enable) 880 { 881 struct bios_parser *bp = BP_FROM_DCB(dcb); 882 883 if (!bp->cmd_tbl.enable_spread_spectrum_on_ppll) 884 return BP_RESULT_FAILURE; 885 886 return bp->cmd_tbl.enable_spread_spectrum_on_ppll( 887 bp, bp_params, enable); 888 889 } 890 891 static enum bp_result bios_parser_program_crtc_timing( 892 struct dc_bios *dcb, 893 struct bp_hw_crtc_timing_parameters *bp_params) 894 { 895 struct bios_parser *bp = BP_FROM_DCB(dcb); 896 897 if (!bp->cmd_tbl.set_crtc_timing) 898 return BP_RESULT_FAILURE; 899 900 return bp->cmd_tbl.set_crtc_timing(bp, bp_params); 901 } 902 903 static enum bp_result bios_parser_program_display_engine_pll( 904 struct dc_bios *dcb, 905 struct bp_pixel_clock_parameters *bp_params) 906 { 907 struct bios_parser *bp = BP_FROM_DCB(dcb); 908 909 if (!bp->cmd_tbl.program_clock) 910 return BP_RESULT_FAILURE; 911 912 return bp->cmd_tbl.program_clock(bp, bp_params); 913 914 } 915 916 917 static enum bp_result bios_parser_enable_crtc( 918 struct dc_bios *dcb, 919 enum controller_id id, 920 bool enable) 921 { 922 struct bios_parser *bp = BP_FROM_DCB(dcb); 923 924 if (!bp->cmd_tbl.enable_crtc) 925 return BP_RESULT_FAILURE; 926 927 return bp->cmd_tbl.enable_crtc(bp, id, enable); 928 } 929 930 static enum bp_result bios_parser_enable_disp_power_gating( 931 struct dc_bios *dcb, 932 enum controller_id controller_id, 933 enum bp_pipe_control_action action) 934 { 935 struct bios_parser *bp = BP_FROM_DCB(dcb); 936 937 if (!bp->cmd_tbl.enable_disp_power_gating) 938 return BP_RESULT_FAILURE; 939 940 return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id, 941 action); 942 } 943 944 static bool bios_parser_is_device_id_supported( 945 struct dc_bios *dcb, 946 struct device_id id) 947 { 948 struct bios_parser *bp = BP_FROM_DCB(dcb); 949 950 uint32_t mask = get_support_mask_for_device_id(id.device_type, id.enum_id); 951 952 return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0; 953 } 954 955 static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, 956 ATOM_OBJECT *object) 957 { 958 ATOM_COMMON_RECORD_HEADER *header; 959 uint32_t offset; 960 961 if (!object) { 962 BREAK_TO_DEBUGGER(); /* Invalid object */ 963 return NULL; 964 } 965 966 offset = le16_to_cpu(object->usRecordOffset) 967 + bp->object_info_tbl_offset; 968 969 for (;;) { 970 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); 971 972 if (!header) 973 return NULL; 974 975 if (LAST_RECORD_TYPE == header->ucRecordType || 976 !header->ucRecordSize) 977 break; 978 979 if (ATOM_HPD_INT_RECORD_TYPE == header->ucRecordType 980 && sizeof(ATOM_HPD_INT_RECORD) <= header->ucRecordSize) 981 return (ATOM_HPD_INT_RECORD *) header; 982 983 offset += header->ucRecordSize; 984 } 985 986 return NULL; 987 } 988 989 static enum bp_result get_ss_info_from_ss_info_table( 990 struct bios_parser *bp, 991 uint32_t id, 992 struct spread_spectrum_info *ss_info); 993 static enum bp_result get_ss_info_from_tbl( 994 struct bios_parser *bp, 995 uint32_t id, 996 struct spread_spectrum_info *ss_info); 997 /** 998 * bios_parser_get_spread_spectrum_info 999 * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or 1000 * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info 1001 * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info ver 3.1, 1002 * there is only one entry for each signal /ss id. However, there is 1003 * no planning of supporting multiple spread Sprectum entry for EverGreen 1004 * @dcb: pointer to the DC BIOS 1005 * @signal: ASSignalType to be converted to info index 1006 * @index: number of entries that match the converted info index 1007 * @ss_info: sprectrum information structure, 1008 * return: Bios parser result code 1009 */ 1010 static enum bp_result bios_parser_get_spread_spectrum_info( 1011 struct dc_bios *dcb, 1012 enum as_signal_type signal, 1013 uint32_t index, 1014 struct spread_spectrum_info *ss_info) 1015 { 1016 struct bios_parser *bp = BP_FROM_DCB(dcb); 1017 enum bp_result result = BP_RESULT_UNSUPPORTED; 1018 uint32_t clk_id_ss = 0; 1019 ATOM_COMMON_TABLE_HEADER *header; 1020 struct atom_data_revision tbl_revision; 1021 1022 if (!ss_info) /* check for bad input */ 1023 return BP_RESULT_BADINPUT; 1024 /* signal translation */ 1025 clk_id_ss = signal_to_ss_id(signal); 1026 1027 if (!DATA_TABLES(ASIC_InternalSS_Info)) 1028 if (!index) 1029 return get_ss_info_from_ss_info_table(bp, clk_id_ss, 1030 ss_info); 1031 1032 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, 1033 DATA_TABLES(ASIC_InternalSS_Info)); 1034 get_atom_data_table_revision(header, &tbl_revision); 1035 1036 switch (tbl_revision.major) { 1037 case 2: 1038 switch (tbl_revision.minor) { 1039 case 1: 1040 /* there can not be more then one entry for Internal 1041 * SS Info table version 2.1 */ 1042 if (!index) 1043 return get_ss_info_from_tbl(bp, clk_id_ss, 1044 ss_info); 1045 break; 1046 default: 1047 break; 1048 } 1049 break; 1050 1051 case 3: 1052 switch (tbl_revision.minor) { 1053 case 1: 1054 return get_ss_info_v3_1(bp, clk_id_ss, index, ss_info); 1055 default: 1056 break; 1057 } 1058 break; 1059 default: 1060 break; 1061 } 1062 /* there can not be more then one entry for SS Info table */ 1063 return result; 1064 } 1065 1066 static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1( 1067 struct bios_parser *bp, 1068 uint32_t id, 1069 struct spread_spectrum_info *info); 1070 1071 /** 1072 * get_ss_info_from_tbl 1073 * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or 1074 * SS_Info table from the VBIOS 1075 * There can not be more than 1 entry for ASIC_InternalSS_Info Ver 2.1 or 1076 * SS_Info. 1077 * 1078 * @bp: pointer to the BIOS parser 1079 * @id: spread sprectrum info index 1080 * @ss_info: sprectrum information structure, 1081 * return: BIOS parser result code 1082 */ 1083 static enum bp_result get_ss_info_from_tbl( 1084 struct bios_parser *bp, 1085 uint32_t id, 1086 struct spread_spectrum_info *ss_info) 1087 { 1088 if (!ss_info) /* check for bad input, if ss_info is not NULL */ 1089 return BP_RESULT_BADINPUT; 1090 /* for SS_Info table only support DP and LVDS */ 1091 if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS) 1092 return get_ss_info_from_ss_info_table(bp, id, ss_info); 1093 else 1094 return get_ss_info_from_internal_ss_info_tbl_V2_1(bp, id, 1095 ss_info); 1096 } 1097 1098 /** 1099 * get_ss_info_from_internal_ss_info_tbl_V2_1 1100 * Get spread sprectrum information from the ASIC_InternalSS_Info table Ver 2.1 1101 * from the VBIOS 1102 * There will not be multiple entry for Ver 2.1 1103 * 1104 * @bp: pointer to the Bios parser 1105 * @id: spread sprectrum info index 1106 * @info: sprectrum information structure, 1107 * return: Bios parser result code 1108 */ 1109 static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1( 1110 struct bios_parser *bp, 1111 uint32_t id, 1112 struct spread_spectrum_info *info) 1113 { 1114 enum bp_result result = BP_RESULT_UNSUPPORTED; 1115 ATOM_ASIC_INTERNAL_SS_INFO_V2 *header; 1116 ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl; 1117 uint32_t tbl_size, i; 1118 1119 if (!DATA_TABLES(ASIC_InternalSS_Info)) 1120 return result; 1121 1122 header = ((ATOM_ASIC_INTERNAL_SS_INFO_V2 *) bios_get_image( 1123 &bp->base, 1124 DATA_TABLES(ASIC_InternalSS_Info), 1125 struct_size(header, asSpreadSpectrum, 1))); 1126 if (!header) 1127 return result; 1128 1129 memset(info, 0, sizeof(struct spread_spectrum_info)); 1130 1131 tbl_size = (le16_to_cpu(header->sHeader.usStructureSize) 1132 - sizeof(ATOM_COMMON_TABLE_HEADER)) 1133 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2); 1134 1135 tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *) 1136 &(header->asSpreadSpectrum[0]); 1137 for (i = 0; i < tbl_size; i++) { 1138 result = BP_RESULT_NORECORD; 1139 1140 if (tbl[i].ucClockIndication != (uint8_t)id) 1141 continue; 1142 1143 if (ATOM_EXTERNAL_SS_MASK 1144 & tbl[i].ucSpreadSpectrumMode) { 1145 info->type.EXTERNAL = true; 1146 } 1147 if (ATOM_SS_CENTRE_SPREAD_MODE_MASK 1148 & tbl[i].ucSpreadSpectrumMode) { 1149 info->type.CENTER_MODE = true; 1150 } 1151 info->type.STEP_AND_DELAY_INFO = false; 1152 /* convert [10KHz] into [KHz] */ 1153 info->target_clock_range = 1154 le32_to_cpu(tbl[i].ulTargetClockRange) * 10; 1155 info->spread_spectrum_percentage = 1156 (uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage); 1157 info->spread_spectrum_range = 1158 (uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10); 1159 result = BP_RESULT_OK; 1160 break; 1161 } 1162 1163 return result; 1164 1165 } 1166 1167 /** 1168 * get_ss_info_from_ss_info_table 1169 * Get spread sprectrum information from the SS_Info table from the VBIOS 1170 * if the pointer to info is NULL, indicate the caller what to know the number 1171 * of entries that matches the id 1172 * for, the SS_Info table, there should not be more than 1 entry match. 1173 * 1174 * @bp: pointer to the Bios parser 1175 * @id: spread sprectrum id 1176 * @ss_info: sprectrum information structure, 1177 * return: Bios parser result code 1178 */ 1179 static enum bp_result get_ss_info_from_ss_info_table( 1180 struct bios_parser *bp, 1181 uint32_t id, 1182 struct spread_spectrum_info *ss_info) 1183 { 1184 enum bp_result result = BP_RESULT_UNSUPPORTED; 1185 ATOM_SPREAD_SPECTRUM_INFO *tbl; 1186 ATOM_COMMON_TABLE_HEADER *header; 1187 uint32_t table_size; 1188 uint32_t i; 1189 uint32_t id_local = SS_ID_UNKNOWN; 1190 struct atom_data_revision revision; 1191 1192 /* exist of the SS_Info table */ 1193 /* check for bad input, pSSinfo can not be NULL */ 1194 if (!DATA_TABLES(SS_Info) || !ss_info) 1195 return result; 1196 1197 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(SS_Info)); 1198 get_atom_data_table_revision(header, &revision); 1199 1200 tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, DATA_TABLES(SS_Info)); 1201 if (!tbl) 1202 return result; 1203 1204 if (1 != revision.major || 2 > revision.minor) 1205 return result; 1206 1207 /* have to convert from Internal_SS format to SS_Info format */ 1208 switch (id) { 1209 case ASIC_INTERNAL_SS_ON_DP: 1210 id_local = SS_ID_DP1; 1211 break; 1212 case ASIC_INTERNAL_SS_ON_LVDS: 1213 { 1214 struct embedded_panel_info panel_info; 1215 1216 if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info) 1217 == BP_RESULT_OK) 1218 id_local = panel_info.ss_id; 1219 break; 1220 } 1221 default: 1222 break; 1223 } 1224 1225 if (id_local == SS_ID_UNKNOWN) 1226 return result; 1227 1228 table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) - 1229 sizeof(ATOM_COMMON_TABLE_HEADER)) / 1230 sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT); 1231 1232 for (i = 0; i < table_size; i++) { 1233 if (id_local != (uint32_t)tbl->asSS_Info[i].ucSS_Id) 1234 continue; 1235 1236 memset(ss_info, 0, sizeof(struct spread_spectrum_info)); 1237 1238 if (ATOM_EXTERNAL_SS_MASK & 1239 tbl->asSS_Info[i].ucSpreadSpectrumType) 1240 ss_info->type.EXTERNAL = true; 1241 1242 if (ATOM_SS_CENTRE_SPREAD_MODE_MASK & 1243 tbl->asSS_Info[i].ucSpreadSpectrumType) 1244 ss_info->type.CENTER_MODE = true; 1245 1246 ss_info->type.STEP_AND_DELAY_INFO = true; 1247 ss_info->spread_spectrum_percentage = 1248 (uint32_t)le16_to_cpu(tbl->asSS_Info[i].usSpreadSpectrumPercentage); 1249 ss_info->step_and_delay_info.step = tbl->asSS_Info[i].ucSS_Step; 1250 ss_info->step_and_delay_info.delay = 1251 tbl->asSS_Info[i].ucSS_Delay; 1252 ss_info->step_and_delay_info.recommended_ref_div = 1253 tbl->asSS_Info[i].ucRecommendedRef_Div; 1254 ss_info->spread_spectrum_range = 1255 (uint32_t)tbl->asSS_Info[i].ucSS_Range * 10000; 1256 1257 /* there will be only one entry for each display type in SS_info 1258 * table */ 1259 result = BP_RESULT_OK; 1260 break; 1261 } 1262 1263 return result; 1264 } 1265 static enum bp_result get_embedded_panel_info_v1_2( 1266 struct bios_parser *bp, 1267 struct embedded_panel_info *info); 1268 static enum bp_result get_embedded_panel_info_v1_3( 1269 struct bios_parser *bp, 1270 struct embedded_panel_info *info); 1271 1272 static enum bp_result bios_parser_get_embedded_panel_info( 1273 struct dc_bios *dcb, 1274 struct embedded_panel_info *info) 1275 { 1276 struct bios_parser *bp = BP_FROM_DCB(dcb); 1277 ATOM_COMMON_TABLE_HEADER *hdr; 1278 1279 if (!DATA_TABLES(LCD_Info)) 1280 return BP_RESULT_FAILURE; 1281 1282 hdr = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(LCD_Info)); 1283 1284 if (!hdr) 1285 return BP_RESULT_BADBIOSTABLE; 1286 1287 switch (hdr->ucTableFormatRevision) { 1288 case 1: 1289 switch (hdr->ucTableContentRevision) { 1290 case 0: 1291 case 1: 1292 case 2: 1293 return get_embedded_panel_info_v1_2(bp, info); 1294 case 3: 1295 return get_embedded_panel_info_v1_3(bp, info); 1296 default: 1297 break; 1298 } 1299 break; 1300 default: 1301 break; 1302 } 1303 1304 return BP_RESULT_FAILURE; 1305 } 1306 1307 static enum bp_result get_embedded_panel_info_v1_2( 1308 struct bios_parser *bp, 1309 struct embedded_panel_info *info) 1310 { 1311 ATOM_LVDS_INFO_V12 *lvds; 1312 1313 if (!info) 1314 return BP_RESULT_BADINPUT; 1315 1316 if (!DATA_TABLES(LVDS_Info)) 1317 return BP_RESULT_UNSUPPORTED; 1318 1319 lvds = 1320 GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info)); 1321 1322 if (!lvds) 1323 return BP_RESULT_BADBIOSTABLE; 1324 1325 if (1 != lvds->sHeader.ucTableFormatRevision 1326 || 2 > lvds->sHeader.ucTableContentRevision) 1327 return BP_RESULT_UNSUPPORTED; 1328 1329 memset(info, 0, sizeof(struct embedded_panel_info)); 1330 1331 /* We need to convert from 10KHz units into KHz units*/ 1332 info->lcd_timing.pixel_clk = 1333 le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10; 1334 /* usHActive does not include borders, according to VBIOS team*/ 1335 info->lcd_timing.horizontal_addressable = 1336 le16_to_cpu(lvds->sLCDTiming.usHActive); 1337 /* usHBlanking_Time includes borders, so we should really be subtracting 1338 * borders duing this translation, but LVDS generally*/ 1339 /* doesn't have borders, so we should be okay leaving this as is for 1340 * now. May need to revisit if we ever have LVDS with borders*/ 1341 info->lcd_timing.horizontal_blanking_time = 1342 le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time); 1343 /* usVActive does not include borders, according to VBIOS team*/ 1344 info->lcd_timing.vertical_addressable = 1345 le16_to_cpu(lvds->sLCDTiming.usVActive); 1346 /* usVBlanking_Time includes borders, so we should really be subtracting 1347 * borders duing this translation, but LVDS generally*/ 1348 /* doesn't have borders, so we should be okay leaving this as is for 1349 * now. May need to revisit if we ever have LVDS with borders*/ 1350 info->lcd_timing.vertical_blanking_time = 1351 le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time); 1352 info->lcd_timing.horizontal_sync_offset = 1353 le16_to_cpu(lvds->sLCDTiming.usHSyncOffset); 1354 info->lcd_timing.horizontal_sync_width = 1355 le16_to_cpu(lvds->sLCDTiming.usHSyncWidth); 1356 info->lcd_timing.vertical_sync_offset = 1357 le16_to_cpu(lvds->sLCDTiming.usVSyncOffset); 1358 info->lcd_timing.vertical_sync_width = 1359 le16_to_cpu(lvds->sLCDTiming.usVSyncWidth); 1360 info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder; 1361 info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder; 1362 info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 1363 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff; 1364 info->lcd_timing.misc_info.H_SYNC_POLARITY = 1365 ~(uint32_t) 1366 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity; 1367 info->lcd_timing.misc_info.V_SYNC_POLARITY = 1368 ~(uint32_t) 1369 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity; 1370 info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 1371 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff; 1372 info->lcd_timing.misc_info.H_REPLICATION_BY2 = 1373 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2; 1374 info->lcd_timing.misc_info.V_REPLICATION_BY2 = 1375 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2; 1376 info->lcd_timing.misc_info.COMPOSITE_SYNC = 1377 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync; 1378 info->lcd_timing.misc_info.INTERLACE = 1379 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace; 1380 info->lcd_timing.misc_info.DOUBLE_CLOCK = 1381 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock; 1382 info->ss_id = lvds->ucSS_Id; 1383 1384 { 1385 uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate); 1386 /* Get minimum supported refresh rate*/ 1387 if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr) 1388 info->supported_rr.REFRESH_RATE_30HZ = 1; 1389 else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr) 1390 info->supported_rr.REFRESH_RATE_40HZ = 1; 1391 else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr) 1392 info->supported_rr.REFRESH_RATE_48HZ = 1; 1393 else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr) 1394 info->supported_rr.REFRESH_RATE_50HZ = 1; 1395 else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr) 1396 info->supported_rr.REFRESH_RATE_60HZ = 1; 1397 } 1398 1399 /*Drr panel support can be reported by VBIOS*/ 1400 if (LCDPANEL_CAP_DRR_SUPPORTED 1401 & lvds->ucLCDPanel_SpecialHandlingCap) 1402 info->drr_enabled = 1; 1403 1404 if (ATOM_PANEL_MISC_DUAL & lvds->ucLVDS_Misc) 1405 info->lcd_timing.misc_info.DOUBLE_CLOCK = true; 1406 1407 if (ATOM_PANEL_MISC_888RGB & lvds->ucLVDS_Misc) 1408 info->lcd_timing.misc_info.RGB888 = true; 1409 1410 info->lcd_timing.misc_info.GREY_LEVEL = 1411 (uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL & 1412 lvds->ucLVDS_Misc) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT; 1413 1414 if (ATOM_PANEL_MISC_SPATIAL & lvds->ucLVDS_Misc) 1415 info->lcd_timing.misc_info.SPATIAL = true; 1416 1417 if (ATOM_PANEL_MISC_TEMPORAL & lvds->ucLVDS_Misc) 1418 info->lcd_timing.misc_info.TEMPORAL = true; 1419 1420 if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc) 1421 info->lcd_timing.misc_info.API_ENABLED = true; 1422 1423 return BP_RESULT_OK; 1424 } 1425 1426 static enum bp_result get_embedded_panel_info_v1_3( 1427 struct bios_parser *bp, 1428 struct embedded_panel_info *info) 1429 { 1430 ATOM_LCD_INFO_V13 *lvds; 1431 1432 if (!info) 1433 return BP_RESULT_BADINPUT; 1434 1435 if (!DATA_TABLES(LCD_Info)) 1436 return BP_RESULT_UNSUPPORTED; 1437 1438 lvds = GET_IMAGE(ATOM_LCD_INFO_V13, DATA_TABLES(LCD_Info)); 1439 1440 if (!lvds) 1441 return BP_RESULT_BADBIOSTABLE; 1442 1443 if (!((1 == lvds->sHeader.ucTableFormatRevision) 1444 && (3 <= lvds->sHeader.ucTableContentRevision))) 1445 return BP_RESULT_UNSUPPORTED; 1446 1447 memset(info, 0, sizeof(struct embedded_panel_info)); 1448 1449 /* We need to convert from 10KHz units into KHz units */ 1450 info->lcd_timing.pixel_clk = 1451 le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10; 1452 /* usHActive does not include borders, according to VBIOS team */ 1453 info->lcd_timing.horizontal_addressable = 1454 le16_to_cpu(lvds->sLCDTiming.usHActive); 1455 /* usHBlanking_Time includes borders, so we should really be subtracting 1456 * borders duing this translation, but LVDS generally*/ 1457 /* doesn't have borders, so we should be okay leaving this as is for 1458 * now. May need to revisit if we ever have LVDS with borders*/ 1459 info->lcd_timing.horizontal_blanking_time = 1460 le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time); 1461 /* usVActive does not include borders, according to VBIOS team*/ 1462 info->lcd_timing.vertical_addressable = 1463 le16_to_cpu(lvds->sLCDTiming.usVActive); 1464 /* usVBlanking_Time includes borders, so we should really be subtracting 1465 * borders duing this translation, but LVDS generally*/ 1466 /* doesn't have borders, so we should be okay leaving this as is for 1467 * now. May need to revisit if we ever have LVDS with borders*/ 1468 info->lcd_timing.vertical_blanking_time = 1469 le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time); 1470 info->lcd_timing.horizontal_sync_offset = 1471 le16_to_cpu(lvds->sLCDTiming.usHSyncOffset); 1472 info->lcd_timing.horizontal_sync_width = 1473 le16_to_cpu(lvds->sLCDTiming.usHSyncWidth); 1474 info->lcd_timing.vertical_sync_offset = 1475 le16_to_cpu(lvds->sLCDTiming.usVSyncOffset); 1476 info->lcd_timing.vertical_sync_width = 1477 le16_to_cpu(lvds->sLCDTiming.usVSyncWidth); 1478 info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder; 1479 info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder; 1480 info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 1481 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff; 1482 info->lcd_timing.misc_info.H_SYNC_POLARITY = 1483 ~(uint32_t) 1484 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity; 1485 info->lcd_timing.misc_info.V_SYNC_POLARITY = 1486 ~(uint32_t) 1487 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity; 1488 info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 1489 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff; 1490 info->lcd_timing.misc_info.H_REPLICATION_BY2 = 1491 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2; 1492 info->lcd_timing.misc_info.V_REPLICATION_BY2 = 1493 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2; 1494 info->lcd_timing.misc_info.COMPOSITE_SYNC = 1495 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync; 1496 info->lcd_timing.misc_info.INTERLACE = 1497 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace; 1498 info->lcd_timing.misc_info.DOUBLE_CLOCK = 1499 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock; 1500 info->ss_id = lvds->ucSS_Id; 1501 1502 /* Drr panel support can be reported by VBIOS*/ 1503 if (LCDPANEL_CAP_V13_DRR_SUPPORTED 1504 & lvds->ucLCDPanel_SpecialHandlingCap) 1505 info->drr_enabled = 1; 1506 1507 /* Get supported refresh rate*/ 1508 if (info->drr_enabled == 1) { 1509 uint8_t min_rr = 1510 lvds->sRefreshRateSupport.ucMinRefreshRateForDRR; 1511 uint8_t rr = lvds->sRefreshRateSupport.ucSupportedRefreshRate; 1512 1513 if (min_rr != 0) { 1514 if (SUPPORTED_LCD_REFRESHRATE_30Hz & min_rr) 1515 info->supported_rr.REFRESH_RATE_30HZ = 1; 1516 else if (SUPPORTED_LCD_REFRESHRATE_40Hz & min_rr) 1517 info->supported_rr.REFRESH_RATE_40HZ = 1; 1518 else if (SUPPORTED_LCD_REFRESHRATE_48Hz & min_rr) 1519 info->supported_rr.REFRESH_RATE_48HZ = 1; 1520 else if (SUPPORTED_LCD_REFRESHRATE_50Hz & min_rr) 1521 info->supported_rr.REFRESH_RATE_50HZ = 1; 1522 else if (SUPPORTED_LCD_REFRESHRATE_60Hz & min_rr) 1523 info->supported_rr.REFRESH_RATE_60HZ = 1; 1524 } else { 1525 if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr) 1526 info->supported_rr.REFRESH_RATE_30HZ = 1; 1527 else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr) 1528 info->supported_rr.REFRESH_RATE_40HZ = 1; 1529 else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr) 1530 info->supported_rr.REFRESH_RATE_48HZ = 1; 1531 else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr) 1532 info->supported_rr.REFRESH_RATE_50HZ = 1; 1533 else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr) 1534 info->supported_rr.REFRESH_RATE_60HZ = 1; 1535 } 1536 } 1537 1538 if (ATOM_PANEL_MISC_V13_DUAL & lvds->ucLCD_Misc) 1539 info->lcd_timing.misc_info.DOUBLE_CLOCK = true; 1540 1541 if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR & lvds->ucLCD_Misc) 1542 info->lcd_timing.misc_info.RGB888 = true; 1543 1544 info->lcd_timing.misc_info.GREY_LEVEL = 1545 (uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL & 1546 lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT; 1547 1548 return BP_RESULT_OK; 1549 } 1550 1551 /** 1552 * bios_parser_get_encoder_cap_info - get encoder capability 1553 * information of input object id 1554 * 1555 * @dcb: pointer to the DC BIOS 1556 * @object_id: object id 1557 * @info: encoder cap information structure 1558 * 1559 * return: Bios parser result code 1560 */ 1561 static enum bp_result bios_parser_get_encoder_cap_info( 1562 struct dc_bios *dcb, 1563 struct graphics_object_id object_id, 1564 struct bp_encoder_cap_info *info) 1565 { 1566 struct bios_parser *bp = BP_FROM_DCB(dcb); 1567 ATOM_OBJECT *object; 1568 ATOM_ENCODER_CAP_RECORD_V2 *record = NULL; 1569 1570 if (!info) 1571 return BP_RESULT_BADINPUT; 1572 1573 object = get_bios_object(bp, object_id); 1574 1575 if (!object) 1576 return BP_RESULT_BADINPUT; 1577 1578 record = get_encoder_cap_record(bp, object); 1579 if (!record) 1580 return BP_RESULT_NORECORD; 1581 1582 info->DP_HBR2_EN = record->usHBR2En; 1583 info->DP_HBR3_EN = record->usHBR3En; 1584 info->HDMI_6GB_EN = record->usHDMI6GEn; 1585 return BP_RESULT_OK; 1586 } 1587 1588 /** 1589 * get_encoder_cap_record - Get encoder cap record for the object 1590 * 1591 * @bp: pointer to the BIOS parser 1592 * @object: ATOM object 1593 * return: atom encoder cap record 1594 * note: search all records to find the ATOM_ENCODER_CAP_RECORD_V2 record 1595 */ 1596 static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record( 1597 struct bios_parser *bp, 1598 ATOM_OBJECT *object) 1599 { 1600 ATOM_COMMON_RECORD_HEADER *header; 1601 uint32_t offset; 1602 1603 if (!object) { 1604 BREAK_TO_DEBUGGER(); /* Invalid object */ 1605 return NULL; 1606 } 1607 1608 offset = le16_to_cpu(object->usRecordOffset) 1609 + bp->object_info_tbl_offset; 1610 1611 for (;;) { 1612 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); 1613 1614 if (!header) 1615 return NULL; 1616 1617 offset += header->ucRecordSize; 1618 1619 if (LAST_RECORD_TYPE == header->ucRecordType || 1620 !header->ucRecordSize) 1621 break; 1622 1623 if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType) 1624 continue; 1625 1626 if (sizeof(ATOM_ENCODER_CAP_RECORD_V2) <= header->ucRecordSize) 1627 return (ATOM_ENCODER_CAP_RECORD_V2 *)header; 1628 } 1629 1630 return NULL; 1631 } 1632 1633 static uint32_t get_ss_entry_number( 1634 struct bios_parser *bp, 1635 uint32_t id); 1636 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1( 1637 struct bios_parser *bp, 1638 uint32_t id); 1639 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1( 1640 struct bios_parser *bp, 1641 uint32_t id); 1642 static uint32_t get_ss_entry_number_from_ss_info_tbl( 1643 struct bios_parser *bp, 1644 uint32_t id); 1645 1646 /** 1647 * bios_parser_get_ss_entry_number 1648 * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from 1649 * the VBIOS that match the SSid (to be converted from signal) 1650 * 1651 * @dcb: pointer to the DC BIOS 1652 * @signal: ASSignalType to be converted to SSid 1653 * return: number of SS Entry that match the signal 1654 */ 1655 static uint32_t bios_parser_get_ss_entry_number( 1656 struct dc_bios *dcb, 1657 enum as_signal_type signal) 1658 { 1659 struct bios_parser *bp = BP_FROM_DCB(dcb); 1660 uint32_t ss_id = 0; 1661 ATOM_COMMON_TABLE_HEADER *header; 1662 struct atom_data_revision revision; 1663 1664 ss_id = signal_to_ss_id(signal); 1665 1666 if (!DATA_TABLES(ASIC_InternalSS_Info)) 1667 return get_ss_entry_number_from_ss_info_tbl(bp, ss_id); 1668 1669 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, 1670 DATA_TABLES(ASIC_InternalSS_Info)); 1671 get_atom_data_table_revision(header, &revision); 1672 1673 switch (revision.major) { 1674 case 2: 1675 switch (revision.minor) { 1676 case 1: 1677 return get_ss_entry_number(bp, ss_id); 1678 default: 1679 break; 1680 } 1681 break; 1682 case 3: 1683 switch (revision.minor) { 1684 case 1: 1685 return 1686 get_ss_entry_number_from_internal_ss_info_tbl_V3_1( 1687 bp, ss_id); 1688 default: 1689 break; 1690 } 1691 break; 1692 default: 1693 break; 1694 } 1695 1696 return 0; 1697 } 1698 1699 /** 1700 * get_ss_entry_number_from_ss_info_tbl 1701 * Get Number of spread spectrum entry from the SS_Info table from the VBIOS. 1702 * 1703 * @bp: pointer to the BIOS parser 1704 * @id: spread spectrum id 1705 * return: number of SS Entry that match the id 1706 * note: There can only be one entry for each id for SS_Info Table 1707 */ 1708 static uint32_t get_ss_entry_number_from_ss_info_tbl( 1709 struct bios_parser *bp, 1710 uint32_t id) 1711 { 1712 ATOM_SPREAD_SPECTRUM_INFO *tbl; 1713 ATOM_COMMON_TABLE_HEADER *header; 1714 uint32_t table_size; 1715 uint32_t i; 1716 uint32_t number = 0; 1717 uint32_t id_local = SS_ID_UNKNOWN; 1718 struct atom_data_revision revision; 1719 1720 /* SS_Info table exist */ 1721 if (!DATA_TABLES(SS_Info)) 1722 return number; 1723 1724 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, 1725 DATA_TABLES(SS_Info)); 1726 get_atom_data_table_revision(header, &revision); 1727 1728 tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, 1729 DATA_TABLES(SS_Info)); 1730 if (!tbl) 1731 return number; 1732 1733 if (1 != revision.major || 2 > revision.minor) 1734 return number; 1735 1736 /* have to convert from Internal_SS format to SS_Info format */ 1737 switch (id) { 1738 case ASIC_INTERNAL_SS_ON_DP: 1739 id_local = SS_ID_DP1; 1740 break; 1741 case ASIC_INTERNAL_SS_ON_LVDS: { 1742 struct embedded_panel_info panel_info; 1743 1744 if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info) 1745 == BP_RESULT_OK) 1746 id_local = panel_info.ss_id; 1747 break; 1748 } 1749 default: 1750 break; 1751 } 1752 1753 if (id_local == SS_ID_UNKNOWN) 1754 return number; 1755 1756 table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) - 1757 sizeof(ATOM_COMMON_TABLE_HEADER)) / 1758 sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT); 1759 1760 for (i = 0; i < table_size; i++) 1761 if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) { 1762 number = 1; 1763 break; 1764 } 1765 1766 return number; 1767 } 1768 1769 /** 1770 * get_ss_entry_number 1771 * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or 1772 * SS_Info table from the VBIOS 1773 * There can not be more than 1 entry for ASIC_InternalSS_Info Ver 2.1 or 1774 * SS_Info. 1775 * 1776 * @bp: pointer to the BIOS parser 1777 * @id: spread sprectrum info index 1778 * return: Bios parser result code 1779 */ 1780 static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id) 1781 { 1782 if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS) 1783 return get_ss_entry_number_from_ss_info_tbl(bp, id); 1784 1785 return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id); 1786 } 1787 1788 /** 1789 * get_ss_entry_number_from_internal_ss_info_tbl_v2_1 1790 * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table 1791 * Ver 2.1 from the VBIOS 1792 * There will not be multiple entry for Ver 2.1 1793 * 1794 * @bp: pointer to the BIOS parser 1795 * @id: spread sprectrum info index 1796 * return: number of SS Entry that match the id 1797 */ 1798 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1( 1799 struct bios_parser *bp, 1800 uint32_t id) 1801 { 1802 ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include; 1803 ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl; 1804 uint32_t size; 1805 uint32_t i; 1806 1807 if (!DATA_TABLES(ASIC_InternalSS_Info)) 1808 return 0; 1809 1810 header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V2 *) bios_get_image( 1811 &bp->base, 1812 DATA_TABLES(ASIC_InternalSS_Info), 1813 struct_size(header_include, asSpreadSpectrum, 1))); 1814 if (!header_include) 1815 return 0; 1816 1817 size = (le16_to_cpu(header_include->sHeader.usStructureSize) 1818 - sizeof(ATOM_COMMON_TABLE_HEADER)) 1819 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2); 1820 1821 tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *) 1822 &header_include->asSpreadSpectrum[0]; 1823 for (i = 0; i < size; i++) 1824 if (tbl[i].ucClockIndication == (uint8_t)id) 1825 return 1; 1826 1827 return 0; 1828 } 1829 1830 /** 1831 * get_ss_entry_number_from_internal_ss_info_tbl_V3_1 1832 * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of 1833 * the VBIOS that matches id 1834 * 1835 * @bp: pointer to the BIOS parser 1836 * @id: spread sprectrum id 1837 * return: number of SS Entry that match the id 1838 */ 1839 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1( 1840 struct bios_parser *bp, 1841 uint32_t id) 1842 { 1843 uint32_t number = 0; 1844 ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include; 1845 ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl; 1846 uint32_t size; 1847 uint32_t i; 1848 1849 if (!DATA_TABLES(ASIC_InternalSS_Info)) 1850 return number; 1851 1852 header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V3 *) bios_get_image(&bp->base, 1853 DATA_TABLES(ASIC_InternalSS_Info), 1854 struct_size(header_include, asSpreadSpectrum, 1))); 1855 if (!header_include) 1856 return number; 1857 1858 size = (le16_to_cpu(header_include->sHeader.usStructureSize) - 1859 sizeof(ATOM_COMMON_TABLE_HEADER)) / 1860 sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3); 1861 1862 tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *) 1863 &header_include->asSpreadSpectrum[0]; 1864 1865 for (i = 0; i < size; i++) 1866 if (tbl[i].ucClockIndication == (uint8_t)id) 1867 number++; 1868 1869 return number; 1870 } 1871 1872 /** 1873 * bios_parser_get_gpio_pin_info 1874 * Get GpioPin information of input gpio id 1875 * 1876 * @dcb: pointer to the DC BIOS 1877 * @gpio_id: GPIO ID 1878 * @info: GpioPin information structure 1879 * return: Bios parser result code 1880 * note: 1881 * to get the GPIO PIN INFO, we need: 1882 * 1. get the GPIO_ID from other object table, see GetHPDInfo() 1883 * 2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA 1884 * offset/mask 1885 */ 1886 static enum bp_result bios_parser_get_gpio_pin_info( 1887 struct dc_bios *dcb, 1888 uint32_t gpio_id, 1889 struct gpio_pin_info *info) 1890 { 1891 struct bios_parser *bp = BP_FROM_DCB(dcb); 1892 ATOM_GPIO_PIN_LUT *header; 1893 uint32_t count = 0; 1894 uint32_t i = 0; 1895 1896 if (!DATA_TABLES(GPIO_Pin_LUT)) 1897 return BP_RESULT_BADBIOSTABLE; 1898 1899 header = ((ATOM_GPIO_PIN_LUT *) bios_get_image(&bp->base, 1900 DATA_TABLES(GPIO_Pin_LUT), 1901 struct_size(header, asGPIO_Pin, 1))); 1902 if (!header) 1903 return BP_RESULT_BADBIOSTABLE; 1904 1905 if (sizeof(ATOM_COMMON_TABLE_HEADER) + struct_size(header, asGPIO_Pin, 1) 1906 > le16_to_cpu(header->sHeader.usStructureSize)) 1907 return BP_RESULT_BADBIOSTABLE; 1908 1909 if (1 != header->sHeader.ucTableContentRevision) 1910 return BP_RESULT_UNSUPPORTED; 1911 1912 count = (le16_to_cpu(header->sHeader.usStructureSize) 1913 - sizeof(ATOM_COMMON_TABLE_HEADER)) 1914 / sizeof(ATOM_GPIO_PIN_ASSIGNMENT); 1915 for (i = 0; i < count; ++i) { 1916 if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id) 1917 continue; 1918 1919 info->offset = 1920 (uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex); 1921 info->offset_y = info->offset + 2; 1922 info->offset_en = info->offset + 1; 1923 info->offset_mask = info->offset - 1; 1924 1925 info->mask = (uint32_t) (1 << 1926 header->asGPIO_Pin[i].ucGpioPinBitShift); 1927 info->mask_y = info->mask + 2; 1928 info->mask_en = info->mask + 1; 1929 info->mask_mask = info->mask - 1; 1930 1931 return BP_RESULT_OK; 1932 } 1933 1934 return BP_RESULT_NORECORD; 1935 } 1936 1937 static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, 1938 ATOM_I2C_RECORD *record, 1939 struct graphics_object_i2c_info *info) 1940 { 1941 ATOM_GPIO_I2C_INFO *header; 1942 uint32_t count = 0; 1943 1944 if (!info) 1945 return BP_RESULT_BADINPUT; 1946 1947 /* get the GPIO_I2C info */ 1948 if (!DATA_TABLES(GPIO_I2C_Info)) 1949 return BP_RESULT_BADBIOSTABLE; 1950 1951 header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info)); 1952 if (!header) 1953 return BP_RESULT_BADBIOSTABLE; 1954 1955 if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT) 1956 > le16_to_cpu(header->sHeader.usStructureSize)) 1957 return BP_RESULT_BADBIOSTABLE; 1958 1959 if (1 != header->sHeader.ucTableContentRevision) 1960 return BP_RESULT_UNSUPPORTED; 1961 1962 /* get data count */ 1963 count = (le16_to_cpu(header->sHeader.usStructureSize) 1964 - sizeof(ATOM_COMMON_TABLE_HEADER)) 1965 / sizeof(ATOM_GPIO_I2C_ASSIGMENT); 1966 if (count <= record->sucI2cId.bfI2C_LineMux) 1967 return BP_RESULT_BADBIOSTABLE; 1968 1969 /* get the GPIO_I2C_INFO */ 1970 info->i2c_hw_assist = record->sucI2cId.bfHW_Capable; 1971 info->i2c_line = record->sucI2cId.bfI2C_LineMux; 1972 info->i2c_engine_id = record->sucI2cId.bfHW_EngineID; 1973 info->i2c_slave_address = record->ucI2CAddr; 1974 1975 info->gpio_info.clk_mask_register_index = 1976 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex); 1977 info->gpio_info.clk_en_register_index = 1978 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex); 1979 info->gpio_info.clk_y_register_index = 1980 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex); 1981 info->gpio_info.clk_a_register_index = 1982 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex); 1983 info->gpio_info.data_mask_register_index = 1984 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex); 1985 info->gpio_info.data_en_register_index = 1986 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex); 1987 info->gpio_info.data_y_register_index = 1988 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex); 1989 info->gpio_info.data_a_register_index = 1990 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex); 1991 1992 info->gpio_info.clk_mask_shift = 1993 header->asGPIO_Info[info->i2c_line].ucClkMaskShift; 1994 info->gpio_info.clk_en_shift = 1995 header->asGPIO_Info[info->i2c_line].ucClkEnShift; 1996 info->gpio_info.clk_y_shift = 1997 header->asGPIO_Info[info->i2c_line].ucClkY_Shift; 1998 info->gpio_info.clk_a_shift = 1999 header->asGPIO_Info[info->i2c_line].ucClkA_Shift; 2000 info->gpio_info.data_mask_shift = 2001 header->asGPIO_Info[info->i2c_line].ucDataMaskShift; 2002 info->gpio_info.data_en_shift = 2003 header->asGPIO_Info[info->i2c_line].ucDataEnShift; 2004 info->gpio_info.data_y_shift = 2005 header->asGPIO_Info[info->i2c_line].ucDataY_Shift; 2006 info->gpio_info.data_a_shift = 2007 header->asGPIO_Info[info->i2c_line].ucDataA_Shift; 2008 2009 return BP_RESULT_OK; 2010 } 2011 2012 static bool dal_graphics_object_id_is_valid(struct graphics_object_id id) 2013 { 2014 bool rc = true; 2015 2016 switch (id.type) { 2017 case OBJECT_TYPE_UNKNOWN: 2018 rc = false; 2019 break; 2020 case OBJECT_TYPE_GPU: 2021 case OBJECT_TYPE_ENGINE: 2022 /* do NOT check for id.id == 0 */ 2023 if (id.enum_id == ENUM_ID_UNKNOWN) 2024 rc = false; 2025 break; 2026 default: 2027 if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN) 2028 rc = false; 2029 break; 2030 } 2031 2032 return rc; 2033 } 2034 2035 static bool dal_graphics_object_id_is_equal( 2036 struct graphics_object_id id1, 2037 struct graphics_object_id id2) 2038 { 2039 if (false == dal_graphics_object_id_is_valid(id1)) { 2040 dm_output_to_console( 2041 "%s: Warning: comparing invalid object 'id1'!\n", __func__); 2042 return false; 2043 } 2044 2045 if (false == dal_graphics_object_id_is_valid(id2)) { 2046 dm_output_to_console( 2047 "%s: Warning: comparing invalid object 'id2'!\n", __func__); 2048 return false; 2049 } 2050 2051 if (id1.id == id2.id && id1.enum_id == id2.enum_id 2052 && id1.type == id2.type) 2053 return true; 2054 2055 return false; 2056 } 2057 2058 static ATOM_OBJECT *get_bios_object(struct bios_parser *bp, 2059 struct graphics_object_id id) 2060 { 2061 uint32_t offset; 2062 ATOM_OBJECT_TABLE *tbl; 2063 uint32_t i; 2064 2065 switch (id.type) { 2066 case OBJECT_TYPE_ENCODER: 2067 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset); 2068 break; 2069 2070 case OBJECT_TYPE_CONNECTOR: 2071 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); 2072 break; 2073 2074 case OBJECT_TYPE_ROUTER: 2075 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset); 2076 break; 2077 2078 case OBJECT_TYPE_GENERIC: 2079 if (bp->object_info_tbl.revision.minor < 3) 2080 return NULL; 2081 offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset); 2082 break; 2083 2084 default: 2085 return NULL; 2086 } 2087 2088 offset += bp->object_info_tbl_offset; 2089 2090 tbl = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base, offset, 2091 struct_size(tbl, asObjects, 1))); 2092 if (!tbl) 2093 return NULL; 2094 2095 for (i = 0; i < tbl->ucNumberOfObjects; i++) 2096 if (dal_graphics_object_id_is_equal(id, 2097 object_id_from_bios_object_id( 2098 le16_to_cpu(tbl->asObjects[i].usObjectID)))) 2099 return &tbl->asObjects[i]; 2100 2101 return NULL; 2102 } 2103 2104 static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object, 2105 uint16_t **id_list) 2106 { 2107 uint32_t offset; 2108 uint8_t *number; 2109 2110 if (!object) { 2111 BREAK_TO_DEBUGGER(); /* Invalid object id */ 2112 return 0; 2113 } 2114 2115 offset = le16_to_cpu(object->usSrcDstTableOffset) 2116 + bp->object_info_tbl_offset; 2117 2118 number = GET_IMAGE(uint8_t, offset); 2119 if (!number) 2120 return 0; 2121 2122 offset += sizeof(uint8_t); 2123 *id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t)); 2124 2125 if (!*id_list) 2126 return 0; 2127 2128 return *number; 2129 } 2130 2131 static struct device_id device_type_from_device_id(uint16_t device_id) 2132 { 2133 2134 struct device_id result_device_id = {0}; 2135 2136 switch (device_id) { 2137 case ATOM_DEVICE_LCD1_SUPPORT: 2138 result_device_id.device_type = DEVICE_TYPE_LCD; 2139 result_device_id.enum_id = 1; 2140 break; 2141 2142 case ATOM_DEVICE_LCD2_SUPPORT: 2143 result_device_id.device_type = DEVICE_TYPE_LCD; 2144 result_device_id.enum_id = 2; 2145 break; 2146 2147 case ATOM_DEVICE_CRT1_SUPPORT: 2148 result_device_id.device_type = DEVICE_TYPE_CRT; 2149 result_device_id.enum_id = 1; 2150 break; 2151 2152 case ATOM_DEVICE_CRT2_SUPPORT: 2153 result_device_id.device_type = DEVICE_TYPE_CRT; 2154 result_device_id.enum_id = 2; 2155 break; 2156 2157 case ATOM_DEVICE_DFP1_SUPPORT: 2158 result_device_id.device_type = DEVICE_TYPE_DFP; 2159 result_device_id.enum_id = 1; 2160 break; 2161 2162 case ATOM_DEVICE_DFP2_SUPPORT: 2163 result_device_id.device_type = DEVICE_TYPE_DFP; 2164 result_device_id.enum_id = 2; 2165 break; 2166 2167 case ATOM_DEVICE_DFP3_SUPPORT: 2168 result_device_id.device_type = DEVICE_TYPE_DFP; 2169 result_device_id.enum_id = 3; 2170 break; 2171 2172 case ATOM_DEVICE_DFP4_SUPPORT: 2173 result_device_id.device_type = DEVICE_TYPE_DFP; 2174 result_device_id.enum_id = 4; 2175 break; 2176 2177 case ATOM_DEVICE_DFP5_SUPPORT: 2178 result_device_id.device_type = DEVICE_TYPE_DFP; 2179 result_device_id.enum_id = 5; 2180 break; 2181 2182 case ATOM_DEVICE_DFP6_SUPPORT: 2183 result_device_id.device_type = DEVICE_TYPE_DFP; 2184 result_device_id.enum_id = 6; 2185 break; 2186 2187 default: 2188 BREAK_TO_DEBUGGER(); /* Invalid device Id */ 2189 result_device_id.device_type = DEVICE_TYPE_UNKNOWN; 2190 result_device_id.enum_id = 0; 2191 } 2192 return result_device_id; 2193 } 2194 2195 static void get_atom_data_table_revision( 2196 ATOM_COMMON_TABLE_HEADER *atom_data_tbl, 2197 struct atom_data_revision *tbl_revision) 2198 { 2199 if (!tbl_revision) 2200 return; 2201 2202 /* initialize the revision to 0 which is invalid revision */ 2203 tbl_revision->major = 0; 2204 tbl_revision->minor = 0; 2205 2206 if (!atom_data_tbl) 2207 return; 2208 2209 tbl_revision->major = 2210 (uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl); 2211 tbl_revision->minor = 2212 (uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl); 2213 } 2214 2215 static uint32_t signal_to_ss_id(enum as_signal_type signal) 2216 { 2217 uint32_t clk_id_ss = 0; 2218 2219 switch (signal) { 2220 case AS_SIGNAL_TYPE_DVI: 2221 clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS; 2222 break; 2223 case AS_SIGNAL_TYPE_HDMI: 2224 clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI; 2225 break; 2226 case AS_SIGNAL_TYPE_LVDS: 2227 clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS; 2228 break; 2229 case AS_SIGNAL_TYPE_DISPLAY_PORT: 2230 clk_id_ss = ASIC_INTERNAL_SS_ON_DP; 2231 break; 2232 case AS_SIGNAL_TYPE_GPU_PLL: 2233 clk_id_ss = ASIC_INTERNAL_GPUPLL_SS; 2234 break; 2235 default: 2236 break; 2237 } 2238 return clk_id_ss; 2239 } 2240 2241 static uint32_t get_support_mask_for_device_id( 2242 enum dal_device_type device_type, 2243 uint32_t enum_id) 2244 { 2245 switch (device_type) { 2246 case DEVICE_TYPE_LCD: 2247 switch (enum_id) { 2248 case 1: 2249 return ATOM_DEVICE_LCD1_SUPPORT; 2250 case 2: 2251 return ATOM_DEVICE_LCD2_SUPPORT; 2252 default: 2253 break; 2254 } 2255 break; 2256 case DEVICE_TYPE_CRT: 2257 switch (enum_id) { 2258 case 1: 2259 return ATOM_DEVICE_CRT1_SUPPORT; 2260 case 2: 2261 return ATOM_DEVICE_CRT2_SUPPORT; 2262 default: 2263 break; 2264 } 2265 break; 2266 case DEVICE_TYPE_DFP: 2267 switch (enum_id) { 2268 case 1: 2269 return ATOM_DEVICE_DFP1_SUPPORT; 2270 case 2: 2271 return ATOM_DEVICE_DFP2_SUPPORT; 2272 case 3: 2273 return ATOM_DEVICE_DFP3_SUPPORT; 2274 case 4: 2275 return ATOM_DEVICE_DFP4_SUPPORT; 2276 case 5: 2277 return ATOM_DEVICE_DFP5_SUPPORT; 2278 case 6: 2279 return ATOM_DEVICE_DFP6_SUPPORT; 2280 default: 2281 break; 2282 } 2283 break; 2284 case DEVICE_TYPE_CV: 2285 switch (enum_id) { 2286 case 1: 2287 return ATOM_DEVICE_CV_SUPPORT; 2288 default: 2289 break; 2290 } 2291 break; 2292 case DEVICE_TYPE_TV: 2293 switch (enum_id) { 2294 case 1: 2295 return ATOM_DEVICE_TV1_SUPPORT; 2296 default: 2297 break; 2298 } 2299 break; 2300 default: 2301 break; 2302 } 2303 2304 /* Unidentified device ID, return empty support mask. */ 2305 return 0; 2306 } 2307 2308 /** 2309 * bios_parser_set_scratch_critical_state - update critical state 2310 * bit in VBIOS scratch register 2311 * @dcb: pointer to the DC BIOS 2312 * @state: set or reset state 2313 */ 2314 static void bios_parser_set_scratch_critical_state( 2315 struct dc_bios *dcb, 2316 bool state) 2317 { 2318 bios_set_scratch_critical_state(dcb, state); 2319 } 2320 2321 /* 2322 * get_integrated_info_v8 2323 * 2324 * @brief 2325 * Get V8 integrated BIOS information 2326 * 2327 * @param 2328 * bios_parser *bp - [in]BIOS parser handler to get master data table 2329 * integrated_info *info - [out] store and output integrated info 2330 * 2331 * return: 2332 * enum bp_result - BP_RESULT_OK if information is available, 2333 * BP_RESULT_BADBIOSTABLE otherwise. 2334 */ 2335 static enum bp_result get_integrated_info_v8( 2336 struct bios_parser *bp, 2337 struct integrated_info *info) 2338 { 2339 ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8; 2340 uint32_t i; 2341 2342 info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8, 2343 bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); 2344 2345 if (info_v8 == NULL) 2346 return BP_RESULT_BADBIOSTABLE; 2347 info->boot_up_engine_clock = le32_to_cpu(info_v8->ulBootUpEngineClock) * 10; 2348 info->dentist_vco_freq = le32_to_cpu(info_v8->ulDentistVCOFreq) * 10; 2349 info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10; 2350 2351 for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { 2352 /* Convert [10KHz] into [KHz] */ 2353 info->disp_clk_voltage[i].max_supported_clk = 2354 le32_to_cpu(info_v8->sDISPCLK_Voltage[i]. 2355 ulMaximumSupportedCLK) * 10; 2356 info->disp_clk_voltage[i].voltage_index = 2357 le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex); 2358 } 2359 2360 info->boot_up_req_display_vector = 2361 le32_to_cpu(info_v8->ulBootUpReqDisplayVector); 2362 info->gpu_cap_info = 2363 le32_to_cpu(info_v8->ulGPUCapInfo); 2364 2365 /* 2366 * system_config: Bit[0] = 0 : PCIE power gating disabled 2367 * = 1 : PCIE power gating enabled 2368 * Bit[1] = 0 : DDR-PLL shut down disabled 2369 * = 1 : DDR-PLL shut down enabled 2370 * Bit[2] = 0 : DDR-PLL power down disabled 2371 * = 1 : DDR-PLL power down enabled 2372 */ 2373 info->system_config = le32_to_cpu(info_v8->ulSystemConfig); 2374 info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo); 2375 info->boot_up_nb_voltage = 2376 le16_to_cpu(info_v8->usBootUpNBVoltage); 2377 info->ext_disp_conn_info_offset = 2378 le16_to_cpu(info_v8->usExtDispConnInfoOffset); 2379 info->memory_type = info_v8->ucMemoryType; 2380 info->ma_channel_number = info_v8->ucUMAChannelNumber; 2381 info->gmc_restore_reset_time = 2382 le32_to_cpu(info_v8->ulGMCRestoreResetTime); 2383 2384 info->minimum_n_clk = 2385 le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]); 2386 for (i = 1; i < 4; ++i) 2387 info->minimum_n_clk = 2388 info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ? 2389 info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]); 2390 2391 info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk); 2392 info->ddr_dll_power_up_time = 2393 le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime); 2394 info->ddr_pll_power_up_time = 2395 le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime); 2396 info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType); 2397 info->lvds_ss_percentage = 2398 le16_to_cpu(info_v8->usLvdsSSPercentage); 2399 info->lvds_sspread_rate_in_10hz = 2400 le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz); 2401 info->hdmi_ss_percentage = 2402 le16_to_cpu(info_v8->usHDMISSPercentage); 2403 info->hdmi_sspread_rate_in_10hz = 2404 le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz); 2405 info->dvi_ss_percentage = 2406 le16_to_cpu(info_v8->usDVISSPercentage); 2407 info->dvi_sspread_rate_in_10_hz = 2408 le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz); 2409 2410 info->max_lvds_pclk_freq_in_single_link = 2411 le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink); 2412 info->lvds_misc = info_v8->ucLvdsMisc; 2413 info->lvds_pwr_on_seq_dig_on_to_de_in_4ms = 2414 info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms; 2415 info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms = 2416 info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms; 2417 info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms = 2418 info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms; 2419 info->lvds_pwr_off_seq_vary_bl_to_de_in4ms = 2420 info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms; 2421 info->lvds_pwr_off_seq_de_to_dig_on_in4ms = 2422 info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms; 2423 info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms = 2424 info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; 2425 info->lvds_off_to_on_delay_in_4ms = 2426 info_v8->ucLVDSOffToOnDelay_in4Ms; 2427 info->lvds_bit_depth_control_val = 2428 le32_to_cpu(info_v8->ulLCDBitDepthControlVal); 2429 2430 for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) { 2431 /* Convert [10KHz] into [KHz] */ 2432 info->avail_s_clk[i].supported_s_clk = 2433 le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10; 2434 info->avail_s_clk[i].voltage_index = 2435 le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex); 2436 info->avail_s_clk[i].voltage_id = 2437 le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID); 2438 } 2439 2440 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) { 2441 info->ext_disp_conn_info.gu_id[i] = 2442 info_v8->sExtDispConnInfo.ucGuid[i]; 2443 } 2444 2445 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) { 2446 info->ext_disp_conn_info.path[i].device_connector_id = 2447 object_id_from_bios_object_id( 2448 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector)); 2449 2450 info->ext_disp_conn_info.path[i].ext_encoder_obj_id = 2451 object_id_from_bios_object_id( 2452 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId)); 2453 2454 info->ext_disp_conn_info.path[i].device_tag = 2455 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag); 2456 info->ext_disp_conn_info.path[i].device_acpi_enum = 2457 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum); 2458 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index = 2459 info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex; 2460 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index = 2461 info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex; 2462 info->ext_disp_conn_info.path[i].channel_mapping.raw = 2463 info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping; 2464 } 2465 info->ext_disp_conn_info.checksum = 2466 info_v8->sExtDispConnInfo.ucChecksum; 2467 2468 return BP_RESULT_OK; 2469 } 2470 2471 /* 2472 * get_integrated_info_v9 2473 * 2474 * @brief 2475 * Get V9 integrated BIOS information 2476 * 2477 * @param 2478 * bios_parser *bp - [in]BIOS parser handler to get master data table 2479 * integrated_info *info - [out] store and output integrated info 2480 * 2481 * return: 2482 * enum bp_result - BP_RESULT_OK if information is available, 2483 * BP_RESULT_BADBIOSTABLE otherwise. 2484 */ 2485 static enum bp_result get_integrated_info_v9( 2486 struct bios_parser *bp, 2487 struct integrated_info *info) 2488 { 2489 ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9; 2490 uint32_t i; 2491 2492 info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9, 2493 bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); 2494 2495 if (!info_v9) 2496 return BP_RESULT_BADBIOSTABLE; 2497 2498 info->boot_up_engine_clock = le32_to_cpu(info_v9->ulBootUpEngineClock) * 10; 2499 info->dentist_vco_freq = le32_to_cpu(info_v9->ulDentistVCOFreq) * 10; 2500 info->boot_up_uma_clock = le32_to_cpu(info_v9->ulBootUpUMAClock) * 10; 2501 2502 for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { 2503 /* Convert [10KHz] into [KHz] */ 2504 info->disp_clk_voltage[i].max_supported_clk = 2505 le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10; 2506 info->disp_clk_voltage[i].voltage_index = 2507 le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex); 2508 } 2509 2510 info->boot_up_req_display_vector = 2511 le32_to_cpu(info_v9->ulBootUpReqDisplayVector); 2512 info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo); 2513 2514 /* 2515 * system_config: Bit[0] = 0 : PCIE power gating disabled 2516 * = 1 : PCIE power gating enabled 2517 * Bit[1] = 0 : DDR-PLL shut down disabled 2518 * = 1 : DDR-PLL shut down enabled 2519 * Bit[2] = 0 : DDR-PLL power down disabled 2520 * = 1 : DDR-PLL power down enabled 2521 */ 2522 info->system_config = le32_to_cpu(info_v9->ulSystemConfig); 2523 info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo); 2524 info->boot_up_nb_voltage = le16_to_cpu(info_v9->usBootUpNBVoltage); 2525 info->ext_disp_conn_info_offset = le16_to_cpu(info_v9->usExtDispConnInfoOffset); 2526 info->memory_type = info_v9->ucMemoryType; 2527 info->ma_channel_number = info_v9->ucUMAChannelNumber; 2528 info->gmc_restore_reset_time = le32_to_cpu(info_v9->ulGMCRestoreResetTime); 2529 2530 info->minimum_n_clk = le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]); 2531 for (i = 1; i < 4; ++i) 2532 info->minimum_n_clk = 2533 info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ? 2534 info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]); 2535 2536 info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk); 2537 info->ddr_dll_power_up_time = le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime); 2538 info->ddr_pll_power_up_time = le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime); 2539 info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType); 2540 info->lvds_ss_percentage = le16_to_cpu(info_v9->usLvdsSSPercentage); 2541 info->lvds_sspread_rate_in_10hz = le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz); 2542 info->hdmi_ss_percentage = le16_to_cpu(info_v9->usHDMISSPercentage); 2543 info->hdmi_sspread_rate_in_10hz = le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz); 2544 info->dvi_ss_percentage = le16_to_cpu(info_v9->usDVISSPercentage); 2545 info->dvi_sspread_rate_in_10_hz = le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz); 2546 2547 info->max_lvds_pclk_freq_in_single_link = 2548 le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink); 2549 info->lvds_misc = info_v9->ucLvdsMisc; 2550 info->lvds_pwr_on_seq_dig_on_to_de_in_4ms = 2551 info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms; 2552 info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms = 2553 info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms; 2554 info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms = 2555 info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms; 2556 info->lvds_pwr_off_seq_vary_bl_to_de_in4ms = 2557 info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms; 2558 info->lvds_pwr_off_seq_de_to_dig_on_in4ms = 2559 info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms; 2560 info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms = 2561 info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; 2562 info->lvds_off_to_on_delay_in_4ms = 2563 info_v9->ucLVDSOffToOnDelay_in4Ms; 2564 info->lvds_bit_depth_control_val = 2565 le32_to_cpu(info_v9->ulLCDBitDepthControlVal); 2566 2567 for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) { 2568 /* Convert [10KHz] into [KHz] */ 2569 info->avail_s_clk[i].supported_s_clk = 2570 le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10; 2571 info->avail_s_clk[i].voltage_index = 2572 le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex); 2573 info->avail_s_clk[i].voltage_id = 2574 le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID); 2575 } 2576 2577 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) { 2578 info->ext_disp_conn_info.gu_id[i] = 2579 info_v9->sExtDispConnInfo.ucGuid[i]; 2580 } 2581 2582 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) { 2583 info->ext_disp_conn_info.path[i].device_connector_id = 2584 object_id_from_bios_object_id( 2585 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector)); 2586 2587 info->ext_disp_conn_info.path[i].ext_encoder_obj_id = 2588 object_id_from_bios_object_id( 2589 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId)); 2590 2591 info->ext_disp_conn_info.path[i].device_tag = 2592 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag); 2593 info->ext_disp_conn_info.path[i].device_acpi_enum = 2594 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum); 2595 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index = 2596 info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex; 2597 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index = 2598 info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex; 2599 info->ext_disp_conn_info.path[i].channel_mapping.raw = 2600 info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping; 2601 } 2602 info->ext_disp_conn_info.checksum = 2603 info_v9->sExtDispConnInfo.ucChecksum; 2604 2605 return BP_RESULT_OK; 2606 } 2607 2608 /* 2609 * construct_integrated_info 2610 * 2611 * @brief 2612 * Get integrated BIOS information based on table revision 2613 * 2614 * @param 2615 * bios_parser *bp - [in]BIOS parser handler to get master data table 2616 * integrated_info *info - [out] store and output integrated info 2617 * 2618 * return: 2619 * enum bp_result - BP_RESULT_OK if information is available, 2620 * BP_RESULT_BADBIOSTABLE otherwise. 2621 */ 2622 static enum bp_result construct_integrated_info( 2623 struct bios_parser *bp, 2624 struct integrated_info *info) 2625 { 2626 enum bp_result result = BP_RESULT_BADBIOSTABLE; 2627 2628 ATOM_COMMON_TABLE_HEADER *header; 2629 struct atom_data_revision revision; 2630 2631 if (bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) { 2632 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, 2633 bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); 2634 2635 get_atom_data_table_revision(header, &revision); 2636 2637 /* Don't need to check major revision as they are all 1 */ 2638 switch (revision.minor) { 2639 case 8: 2640 result = get_integrated_info_v8(bp, info); 2641 break; 2642 case 9: 2643 result = get_integrated_info_v9(bp, info); 2644 break; 2645 default: 2646 return result; 2647 2648 } 2649 } 2650 2651 /* Sort voltage table from low to high*/ 2652 if (result == BP_RESULT_OK) { 2653 int32_t i; 2654 int32_t j; 2655 2656 for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { 2657 for (j = i; j > 0; --j) { 2658 if ( 2659 info->disp_clk_voltage[j].max_supported_clk < 2660 info->disp_clk_voltage[j-1].max_supported_clk) { 2661 /* swap j and j - 1*/ 2662 swap(info->disp_clk_voltage[j - 1], 2663 info->disp_clk_voltage[j]); 2664 } 2665 } 2666 } 2667 2668 } 2669 2670 return result; 2671 } 2672 2673 static struct integrated_info *bios_parser_create_integrated_info( 2674 struct dc_bios *dcb) 2675 { 2676 struct bios_parser *bp = BP_FROM_DCB(dcb); 2677 struct integrated_info *info; 2678 2679 info = kzalloc_obj(struct integrated_info); 2680 2681 if (info == NULL) { 2682 ASSERT_CRITICAL(0); 2683 return NULL; 2684 } 2685 2686 if (construct_integrated_info(bp, info) == BP_RESULT_OK) 2687 return info; 2688 2689 kfree(info); 2690 2691 return NULL; 2692 } 2693 2694 static enum bp_result update_slot_layout_info(struct dc_bios *dcb, 2695 unsigned int i, 2696 struct slot_layout_info *slot_layout_info, 2697 unsigned int record_offset) 2698 { 2699 (void)i; 2700 unsigned int j; 2701 struct bios_parser *bp; 2702 ATOM_BRACKET_LAYOUT_RECORD *record; 2703 ATOM_COMMON_RECORD_HEADER *record_header; 2704 enum bp_result result = BP_RESULT_NORECORD; 2705 2706 bp = BP_FROM_DCB(dcb); 2707 record = NULL; 2708 record_header = NULL; 2709 2710 for (;;) { 2711 2712 record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset); 2713 if (record_header == NULL) { 2714 result = BP_RESULT_BADBIOSTABLE; 2715 break; 2716 } 2717 2718 /* the end of the list */ 2719 if (record_header->ucRecordType == 0xff || 2720 record_header->ucRecordSize == 0) { 2721 break; 2722 } 2723 2724 if (record_header->ucRecordType == 2725 ATOM_BRACKET_LAYOUT_RECORD_TYPE && 2726 struct_size(record, asConnInfo, 1) 2727 <= record_header->ucRecordSize) { 2728 record = (ATOM_BRACKET_LAYOUT_RECORD *) 2729 (record_header); 2730 result = BP_RESULT_OK; 2731 break; 2732 } 2733 2734 record_offset += record_header->ucRecordSize; 2735 } 2736 2737 /* return if the record not found */ 2738 if (result != BP_RESULT_OK) 2739 return result; 2740 2741 /* get slot sizes */ 2742 slot_layout_info->length = record->ucLength; 2743 slot_layout_info->width = record->ucWidth; 2744 2745 /* get info for each connector in the slot */ 2746 slot_layout_info->num_of_connectors = record->ucConnNum; 2747 for (j = 0; j < slot_layout_info->num_of_connectors; ++j) { 2748 slot_layout_info->connectors[j].connector_type = 2749 (enum connector_layout_type) 2750 (record->asConnInfo[j].ucConnectorType); 2751 switch (record->asConnInfo[j].ucConnectorType) { 2752 case CONNECTOR_TYPE_DVI_D: 2753 slot_layout_info->connectors[j].connector_type = 2754 CONNECTOR_LAYOUT_TYPE_DVI_D; 2755 slot_layout_info->connectors[j].length = 2756 CONNECTOR_SIZE_DVI; 2757 break; 2758 2759 case CONNECTOR_TYPE_HDMI: 2760 slot_layout_info->connectors[j].connector_type = 2761 CONNECTOR_LAYOUT_TYPE_HDMI; 2762 slot_layout_info->connectors[j].length = 2763 CONNECTOR_SIZE_HDMI; 2764 break; 2765 2766 case CONNECTOR_TYPE_DISPLAY_PORT: 2767 slot_layout_info->connectors[j].connector_type = 2768 CONNECTOR_LAYOUT_TYPE_DP; 2769 slot_layout_info->connectors[j].length = 2770 CONNECTOR_SIZE_DP; 2771 break; 2772 2773 case CONNECTOR_TYPE_MINI_DISPLAY_PORT: 2774 slot_layout_info->connectors[j].connector_type = 2775 CONNECTOR_LAYOUT_TYPE_MINI_DP; 2776 slot_layout_info->connectors[j].length = 2777 CONNECTOR_SIZE_MINI_DP; 2778 break; 2779 2780 default: 2781 slot_layout_info->connectors[j].connector_type = 2782 CONNECTOR_LAYOUT_TYPE_UNKNOWN; 2783 slot_layout_info->connectors[j].length = 2784 CONNECTOR_SIZE_UNKNOWN; 2785 } 2786 2787 slot_layout_info->connectors[j].position = 2788 record->asConnInfo[j].ucPosition; 2789 slot_layout_info->connectors[j].connector_id = 2790 object_id_from_bios_object_id( 2791 record->asConnInfo[j].usConnectorObjectId); 2792 } 2793 return result; 2794 } 2795 2796 2797 static enum bp_result get_bracket_layout_record(struct dc_bios *dcb, 2798 unsigned int bracket_layout_id, 2799 struct slot_layout_info *slot_layout_info) 2800 { 2801 unsigned int i; 2802 unsigned int record_offset; 2803 struct bios_parser *bp; 2804 enum bp_result result; 2805 ATOM_OBJECT *object; 2806 ATOM_OBJECT_TABLE *object_table; 2807 unsigned int genericTableOffset; 2808 2809 bp = BP_FROM_DCB(dcb); 2810 object = NULL; 2811 if (slot_layout_info == NULL) { 2812 DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n"); 2813 return BP_RESULT_BADINPUT; 2814 } 2815 2816 2817 genericTableOffset = bp->object_info_tbl_offset + 2818 bp->object_info_tbl.v1_3->usMiscObjectTableOffset; 2819 object_table = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base, 2820 genericTableOffset, 2821 struct_size(object_table, asObjects, 1))); 2822 if (!object_table) 2823 return BP_RESULT_FAILURE; 2824 2825 result = BP_RESULT_NORECORD; 2826 for (i = 0; i < object_table->ucNumberOfObjects; ++i) { 2827 2828 if (bracket_layout_id == 2829 object_table->asObjects[i].usObjectID) { 2830 2831 object = &object_table->asObjects[i]; 2832 record_offset = object->usRecordOffset + 2833 bp->object_info_tbl_offset; 2834 2835 result = update_slot_layout_info(dcb, i, 2836 slot_layout_info, record_offset); 2837 break; 2838 } 2839 } 2840 return result; 2841 } 2842 2843 static enum bp_result bios_get_board_layout_info( 2844 struct dc_bios *dcb, 2845 struct board_layout_info *board_layout_info) 2846 { 2847 unsigned int i; 2848 struct bios_parser *bp; 2849 enum bp_result record_result; 2850 2851 const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = { 2852 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1, 2853 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2, 2854 0, 0 2855 }; 2856 2857 bp = BP_FROM_DCB(dcb); 2858 2859 if (board_layout_info == NULL) { 2860 DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n"); 2861 return BP_RESULT_BADINPUT; 2862 } 2863 2864 board_layout_info->num_of_slots = 0; 2865 2866 for (i = 0; i < MAX_BOARD_SLOTS; ++i) { 2867 record_result = get_bracket_layout_record(dcb, 2868 slot_index_to_vbios_id[i], 2869 &board_layout_info->slots[i]); 2870 2871 if (record_result == BP_RESULT_NORECORD && i > 0) 2872 break; /* no more slots present in bios */ 2873 else if (record_result != BP_RESULT_OK) 2874 return record_result; /* fail */ 2875 2876 ++board_layout_info->num_of_slots; 2877 } 2878 2879 /* all data is valid */ 2880 board_layout_info->is_number_of_slots_valid = 1; 2881 board_layout_info->is_slots_size_valid = 1; 2882 board_layout_info->is_connector_offsets_valid = 1; 2883 board_layout_info->is_connector_lengths_valid = 1; 2884 2885 return BP_RESULT_OK; 2886 } 2887 2888 /******************************************************************************/ 2889 2890 static const struct dc_vbios_funcs vbios_funcs = { 2891 .get_connectors_number = bios_parser_get_connectors_number, 2892 2893 .get_connector_id = bios_parser_get_connector_id, 2894 2895 .get_src_obj = bios_parser_get_src_obj, 2896 2897 .get_i2c_info = bios_parser_get_i2c_info, 2898 2899 .get_hpd_info = bios_parser_get_hpd_info, 2900 2901 .get_device_tag = bios_parser_get_device_tag, 2902 2903 .get_spread_spectrum_info = bios_parser_get_spread_spectrum_info, 2904 2905 .get_ss_entry_number = bios_parser_get_ss_entry_number, 2906 2907 .get_embedded_panel_info = bios_parser_get_embedded_panel_info, 2908 2909 .get_gpio_pin_info = bios_parser_get_gpio_pin_info, 2910 2911 .get_encoder_cap_info = bios_parser_get_encoder_cap_info, 2912 2913 /* bios scratch register communication */ 2914 .is_accelerated_mode = bios_is_accelerated_mode, 2915 2916 .set_scratch_critical_state = bios_parser_set_scratch_critical_state, 2917 2918 .is_device_id_supported = bios_parser_is_device_id_supported, 2919 2920 /* COMMANDS */ 2921 .select_crtc_source = bios_parser_select_crtc_source, 2922 2923 .encoder_control = bios_parser_encoder_control, 2924 2925 .external_encoder_control = bios_parser_external_encoder_control, 2926 2927 .dac_load_detection = bios_parser_dac_load_detection, 2928 2929 .transmitter_control = bios_parser_transmitter_control, 2930 2931 .enable_crtc = bios_parser_enable_crtc, 2932 2933 .adjust_pixel_clock = bios_parser_adjust_pixel_clock, 2934 2935 .set_pixel_clock = bios_parser_set_pixel_clock, 2936 2937 .set_dce_clock = bios_parser_set_dce_clock, 2938 2939 .enable_spread_spectrum_on_ppll = bios_parser_enable_spread_spectrum_on_ppll, 2940 2941 .program_crtc_timing = bios_parser_program_crtc_timing, /* still use. should probably retire and program directly */ 2942 2943 .program_display_engine_pll = bios_parser_program_display_engine_pll, 2944 2945 .enable_disp_power_gating = bios_parser_enable_disp_power_gating, 2946 2947 /* SW init and patch */ 2948 2949 .bios_parser_destroy = bios_parser_destroy, 2950 2951 .get_board_layout_info = bios_get_board_layout_info, 2952 2953 .get_atom_dc_golden_table = NULL 2954 }; 2955 2956 static bool bios_parser_construct( 2957 struct bios_parser *bp, 2958 struct bp_init_data *init, 2959 enum dce_version dce_version) 2960 { 2961 uint16_t *rom_header_offset = NULL; 2962 ATOM_ROM_HEADER *rom_header = NULL; 2963 ATOM_OBJECT_HEADER *object_info_tbl; 2964 struct atom_data_revision tbl_rev = {0}; 2965 2966 if (!init) 2967 return false; 2968 2969 if (!init->bios) 2970 return false; 2971 2972 bp->base.funcs = &vbios_funcs; 2973 bp->base.bios = init->bios; 2974 bp->base.bios_size = bp->base.bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT; 2975 2976 bp->base.ctx = init->ctx; 2977 bp->base.bios_local_image = NULL; 2978 2979 rom_header_offset = 2980 GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER); 2981 2982 if (!rom_header_offset) 2983 return false; 2984 2985 rom_header = GET_IMAGE(ATOM_ROM_HEADER, *rom_header_offset); 2986 2987 if (!rom_header) 2988 return false; 2989 2990 get_atom_data_table_revision(&rom_header->sHeader, &tbl_rev); 2991 if (tbl_rev.major >= 2 && tbl_rev.minor >= 2) 2992 return false; 2993 2994 bp->master_data_tbl = 2995 GET_IMAGE(ATOM_MASTER_DATA_TABLE, 2996 rom_header->usMasterDataTableOffset); 2997 2998 if (!bp->master_data_tbl) 2999 return false; 3000 3001 bp->object_info_tbl_offset = DATA_TABLES(Object_Header); 3002 3003 if (!bp->object_info_tbl_offset) 3004 return false; 3005 3006 object_info_tbl = 3007 GET_IMAGE(ATOM_OBJECT_HEADER, bp->object_info_tbl_offset); 3008 3009 if (!object_info_tbl) 3010 return false; 3011 3012 get_atom_data_table_revision(&object_info_tbl->sHeader, 3013 &bp->object_info_tbl.revision); 3014 3015 if (bp->object_info_tbl.revision.major == 1 3016 && bp->object_info_tbl.revision.minor >= 3) { 3017 ATOM_OBJECT_HEADER_V3 *tbl_v3; 3018 3019 tbl_v3 = GET_IMAGE(ATOM_OBJECT_HEADER_V3, 3020 bp->object_info_tbl_offset); 3021 if (!tbl_v3) 3022 return false; 3023 3024 bp->object_info_tbl.v1_3 = tbl_v3; 3025 } else if (bp->object_info_tbl.revision.major == 1 3026 && bp->object_info_tbl.revision.minor >= 1) 3027 bp->object_info_tbl.v1_1 = object_info_tbl; 3028 else 3029 return false; 3030 3031 dal_bios_parser_init_cmd_tbl(bp); 3032 dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version); 3033 3034 bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base); 3035 bp->base.fw_info_valid = bios_parser_get_firmware_info(&bp->base, &bp->base.fw_info) == BP_RESULT_OK; 3036 3037 return true; 3038 } 3039 3040 /******************************************************************************/ 3041