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 struct graphics_object_id ext_enc_id) 799 { 800 struct bios_parser *bp = BP_FROM_DCB(dcb); 801 struct dc_context *ctx = dcb->ctx; 802 struct bp_load_detection_parameters bp_params = {0}; 803 struct bp_external_encoder_control ext_cntl = {0}; 804 enum bp_result bp_result = BP_RESULT_UNSUPPORTED; 805 uint32_t bios_0_scratch; 806 uint32_t device_id_mask = 0; 807 808 bp_params.device_id = get_support_mask_for_device_id( 809 DEVICE_TYPE_CRT, engine_id == ENGINE_ID_DACB ? 2 : 1); 810 811 if (bp_params.device_id == ATOM_DEVICE_CRT1_SUPPORT) 812 device_id_mask = ATOM_S0_CRT1_MASK; 813 else if (bp_params.device_id == ATOM_DEVICE_CRT2_SUPPORT) 814 device_id_mask = ATOM_S0_CRT2_MASK; 815 else 816 return BP_RESULT_UNSUPPORTED; 817 818 /* BIOS will write the detected devices to BIOS_SCRATCH_0, clear corresponding bit */ 819 bios_0_scratch = dm_read_reg(ctx, bp->base.regs->BIOS_SCRATCH_0); 820 bios_0_scratch &= ~device_id_mask; 821 dm_write_reg(ctx, bp->base.regs->BIOS_SCRATCH_0, bios_0_scratch); 822 823 if (engine_id == ENGINE_ID_DACA || engine_id == ENGINE_ID_DACB) { 824 if (!bp->cmd_tbl.dac_load_detection) 825 return BP_RESULT_UNSUPPORTED; 826 827 bp_params.engine_id = engine_id; 828 bp_result = bp->cmd_tbl.dac_load_detection(bp, &bp_params); 829 } else if (ext_enc_id.id) { 830 if (!bp->cmd_tbl.external_encoder_control) 831 return BP_RESULT_UNSUPPORTED; 832 833 ext_cntl.action = EXTERNAL_ENCODER_CONTROL_DAC_LOAD_DETECT; 834 ext_cntl.encoder_id = ext_enc_id; 835 bp_result = bp->cmd_tbl.external_encoder_control(bp, &ext_cntl); 836 } 837 838 if (bp_result != BP_RESULT_OK) 839 return bp_result; 840 841 bios_0_scratch = dm_read_reg(ctx, bp->base.regs->BIOS_SCRATCH_0); 842 843 if (bios_0_scratch & device_id_mask) 844 return BP_RESULT_OK; 845 846 return BP_RESULT_FAILURE; 847 } 848 849 static enum bp_result bios_parser_adjust_pixel_clock( 850 struct dc_bios *dcb, 851 struct bp_adjust_pixel_clock_parameters *bp_params) 852 { 853 struct bios_parser *bp = BP_FROM_DCB(dcb); 854 855 if (!bp->cmd_tbl.adjust_display_pll) 856 return BP_RESULT_FAILURE; 857 858 return bp->cmd_tbl.adjust_display_pll(bp, bp_params); 859 } 860 861 static enum bp_result bios_parser_set_pixel_clock( 862 struct dc_bios *dcb, 863 struct bp_pixel_clock_parameters *bp_params) 864 { 865 struct bios_parser *bp = BP_FROM_DCB(dcb); 866 867 if (!bp->cmd_tbl.set_pixel_clock) 868 return BP_RESULT_FAILURE; 869 870 return bp->cmd_tbl.set_pixel_clock(bp, bp_params); 871 } 872 873 static enum bp_result bios_parser_set_dce_clock( 874 struct dc_bios *dcb, 875 struct bp_set_dce_clock_parameters *bp_params) 876 { 877 struct bios_parser *bp = BP_FROM_DCB(dcb); 878 879 if (!bp->cmd_tbl.set_dce_clock) 880 return BP_RESULT_FAILURE; 881 882 return bp->cmd_tbl.set_dce_clock(bp, bp_params); 883 } 884 885 static enum bp_result bios_parser_enable_spread_spectrum_on_ppll( 886 struct dc_bios *dcb, 887 struct bp_spread_spectrum_parameters *bp_params, 888 bool enable) 889 { 890 struct bios_parser *bp = BP_FROM_DCB(dcb); 891 892 if (!bp->cmd_tbl.enable_spread_spectrum_on_ppll) 893 return BP_RESULT_FAILURE; 894 895 return bp->cmd_tbl.enable_spread_spectrum_on_ppll( 896 bp, bp_params, enable); 897 898 } 899 900 static enum bp_result bios_parser_program_crtc_timing( 901 struct dc_bios *dcb, 902 struct bp_hw_crtc_timing_parameters *bp_params) 903 { 904 struct bios_parser *bp = BP_FROM_DCB(dcb); 905 906 if (!bp->cmd_tbl.set_crtc_timing) 907 return BP_RESULT_FAILURE; 908 909 return bp->cmd_tbl.set_crtc_timing(bp, bp_params); 910 } 911 912 static enum bp_result bios_parser_program_display_engine_pll( 913 struct dc_bios *dcb, 914 struct bp_pixel_clock_parameters *bp_params) 915 { 916 struct bios_parser *bp = BP_FROM_DCB(dcb); 917 918 if (!bp->cmd_tbl.program_clock) 919 return BP_RESULT_FAILURE; 920 921 return bp->cmd_tbl.program_clock(bp, bp_params); 922 923 } 924 925 926 static enum bp_result bios_parser_enable_crtc( 927 struct dc_bios *dcb, 928 enum controller_id id, 929 bool enable) 930 { 931 struct bios_parser *bp = BP_FROM_DCB(dcb); 932 933 if (!bp->cmd_tbl.enable_crtc) 934 return BP_RESULT_FAILURE; 935 936 return bp->cmd_tbl.enable_crtc(bp, id, enable); 937 } 938 939 static enum bp_result bios_parser_enable_disp_power_gating( 940 struct dc_bios *dcb, 941 enum controller_id controller_id, 942 enum bp_pipe_control_action action) 943 { 944 struct bios_parser *bp = BP_FROM_DCB(dcb); 945 946 if (!bp->cmd_tbl.enable_disp_power_gating) 947 return BP_RESULT_FAILURE; 948 949 return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id, 950 action); 951 } 952 953 static bool bios_parser_is_device_id_supported( 954 struct dc_bios *dcb, 955 struct device_id id) 956 { 957 struct bios_parser *bp = BP_FROM_DCB(dcb); 958 959 uint32_t mask = get_support_mask_for_device_id(id.device_type, id.enum_id); 960 961 return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0; 962 } 963 964 static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, 965 ATOM_OBJECT *object) 966 { 967 ATOM_COMMON_RECORD_HEADER *header; 968 uint32_t offset; 969 970 if (!object) { 971 BREAK_TO_DEBUGGER(); /* Invalid object */ 972 return NULL; 973 } 974 975 offset = le16_to_cpu(object->usRecordOffset) 976 + bp->object_info_tbl_offset; 977 978 for (;;) { 979 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); 980 981 if (!header) 982 return NULL; 983 984 if (LAST_RECORD_TYPE == header->ucRecordType || 985 !header->ucRecordSize) 986 break; 987 988 if (ATOM_HPD_INT_RECORD_TYPE == header->ucRecordType 989 && sizeof(ATOM_HPD_INT_RECORD) <= header->ucRecordSize) 990 return (ATOM_HPD_INT_RECORD *) header; 991 992 offset += header->ucRecordSize; 993 } 994 995 return NULL; 996 } 997 998 static enum bp_result get_ss_info_from_ss_info_table( 999 struct bios_parser *bp, 1000 uint32_t id, 1001 struct spread_spectrum_info *ss_info); 1002 static enum bp_result get_ss_info_from_tbl( 1003 struct bios_parser *bp, 1004 uint32_t id, 1005 struct spread_spectrum_info *ss_info); 1006 /** 1007 * bios_parser_get_spread_spectrum_info 1008 * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or 1009 * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info 1010 * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info ver 3.1, 1011 * there is only one entry for each signal /ss id. However, there is 1012 * no planning of supporting multiple spread Sprectum entry for EverGreen 1013 * @dcb: pointer to the DC BIOS 1014 * @signal: ASSignalType to be converted to info index 1015 * @index: number of entries that match the converted info index 1016 * @ss_info: sprectrum information structure, 1017 * return: Bios parser result code 1018 */ 1019 static enum bp_result bios_parser_get_spread_spectrum_info( 1020 struct dc_bios *dcb, 1021 enum as_signal_type signal, 1022 uint32_t index, 1023 struct spread_spectrum_info *ss_info) 1024 { 1025 struct bios_parser *bp = BP_FROM_DCB(dcb); 1026 enum bp_result result = BP_RESULT_UNSUPPORTED; 1027 uint32_t clk_id_ss = 0; 1028 ATOM_COMMON_TABLE_HEADER *header; 1029 struct atom_data_revision tbl_revision; 1030 1031 if (!ss_info) /* check for bad input */ 1032 return BP_RESULT_BADINPUT; 1033 /* signal translation */ 1034 clk_id_ss = signal_to_ss_id(signal); 1035 1036 if (!DATA_TABLES(ASIC_InternalSS_Info)) 1037 if (!index) 1038 return get_ss_info_from_ss_info_table(bp, clk_id_ss, 1039 ss_info); 1040 1041 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, 1042 DATA_TABLES(ASIC_InternalSS_Info)); 1043 get_atom_data_table_revision(header, &tbl_revision); 1044 1045 switch (tbl_revision.major) { 1046 case 2: 1047 switch (tbl_revision.minor) { 1048 case 1: 1049 /* there can not be more then one entry for Internal 1050 * SS Info table version 2.1 */ 1051 if (!index) 1052 return get_ss_info_from_tbl(bp, clk_id_ss, 1053 ss_info); 1054 break; 1055 default: 1056 break; 1057 } 1058 break; 1059 1060 case 3: 1061 switch (tbl_revision.minor) { 1062 case 1: 1063 return get_ss_info_v3_1(bp, clk_id_ss, index, ss_info); 1064 default: 1065 break; 1066 } 1067 break; 1068 default: 1069 break; 1070 } 1071 /* there can not be more then one entry for SS Info table */ 1072 return result; 1073 } 1074 1075 static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1( 1076 struct bios_parser *bp, 1077 uint32_t id, 1078 struct spread_spectrum_info *info); 1079 1080 /** 1081 * get_ss_info_from_tbl 1082 * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or 1083 * SS_Info table from the VBIOS 1084 * There can not be more than 1 entry for ASIC_InternalSS_Info Ver 2.1 or 1085 * SS_Info. 1086 * 1087 * @bp: pointer to the BIOS parser 1088 * @id: spread sprectrum info index 1089 * @ss_info: sprectrum information structure, 1090 * return: BIOS parser result code 1091 */ 1092 static enum bp_result get_ss_info_from_tbl( 1093 struct bios_parser *bp, 1094 uint32_t id, 1095 struct spread_spectrum_info *ss_info) 1096 { 1097 if (!ss_info) /* check for bad input, if ss_info is not NULL */ 1098 return BP_RESULT_BADINPUT; 1099 /* for SS_Info table only support DP and LVDS */ 1100 if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS) 1101 return get_ss_info_from_ss_info_table(bp, id, ss_info); 1102 else 1103 return get_ss_info_from_internal_ss_info_tbl_V2_1(bp, id, 1104 ss_info); 1105 } 1106 1107 /** 1108 * get_ss_info_from_internal_ss_info_tbl_V2_1 1109 * Get spread sprectrum information from the ASIC_InternalSS_Info table Ver 2.1 1110 * from the VBIOS 1111 * There will not be multiple entry for Ver 2.1 1112 * 1113 * @bp: pointer to the Bios parser 1114 * @id: spread sprectrum info index 1115 * @info: sprectrum information structure, 1116 * return: Bios parser result code 1117 */ 1118 static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1( 1119 struct bios_parser *bp, 1120 uint32_t id, 1121 struct spread_spectrum_info *info) 1122 { 1123 enum bp_result result = BP_RESULT_UNSUPPORTED; 1124 ATOM_ASIC_INTERNAL_SS_INFO_V2 *header; 1125 ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl; 1126 uint32_t tbl_size, i; 1127 1128 if (!DATA_TABLES(ASIC_InternalSS_Info)) 1129 return result; 1130 1131 header = ((ATOM_ASIC_INTERNAL_SS_INFO_V2 *) bios_get_image( 1132 &bp->base, 1133 DATA_TABLES(ASIC_InternalSS_Info), 1134 struct_size(header, asSpreadSpectrum, 1))); 1135 if (!header) 1136 return result; 1137 1138 memset(info, 0, sizeof(struct spread_spectrum_info)); 1139 1140 tbl_size = (le16_to_cpu(header->sHeader.usStructureSize) 1141 - sizeof(ATOM_COMMON_TABLE_HEADER)) 1142 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2); 1143 1144 tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *) 1145 &(header->asSpreadSpectrum[0]); 1146 for (i = 0; i < tbl_size; i++) { 1147 result = BP_RESULT_NORECORD; 1148 1149 if (tbl[i].ucClockIndication != (uint8_t)id) 1150 continue; 1151 1152 if (ATOM_EXTERNAL_SS_MASK 1153 & tbl[i].ucSpreadSpectrumMode) { 1154 info->type.EXTERNAL = true; 1155 } 1156 if (ATOM_SS_CENTRE_SPREAD_MODE_MASK 1157 & tbl[i].ucSpreadSpectrumMode) { 1158 info->type.CENTER_MODE = true; 1159 } 1160 info->type.STEP_AND_DELAY_INFO = false; 1161 /* convert [10KHz] into [KHz] */ 1162 info->target_clock_range = 1163 le32_to_cpu(tbl[i].ulTargetClockRange) * 10; 1164 info->spread_spectrum_percentage = 1165 (uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage); 1166 info->spread_spectrum_range = 1167 (uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10); 1168 result = BP_RESULT_OK; 1169 break; 1170 } 1171 1172 return result; 1173 1174 } 1175 1176 /** 1177 * get_ss_info_from_ss_info_table 1178 * Get spread sprectrum information from the SS_Info table from the VBIOS 1179 * if the pointer to info is NULL, indicate the caller what to know the number 1180 * of entries that matches the id 1181 * for, the SS_Info table, there should not be more than 1 entry match. 1182 * 1183 * @bp: pointer to the Bios parser 1184 * @id: spread sprectrum id 1185 * @ss_info: sprectrum information structure, 1186 * return: Bios parser result code 1187 */ 1188 static enum bp_result get_ss_info_from_ss_info_table( 1189 struct bios_parser *bp, 1190 uint32_t id, 1191 struct spread_spectrum_info *ss_info) 1192 { 1193 enum bp_result result = BP_RESULT_UNSUPPORTED; 1194 ATOM_SPREAD_SPECTRUM_INFO *tbl; 1195 ATOM_COMMON_TABLE_HEADER *header; 1196 uint32_t table_size; 1197 uint32_t i; 1198 uint32_t id_local = SS_ID_UNKNOWN; 1199 struct atom_data_revision revision; 1200 1201 /* exist of the SS_Info table */ 1202 /* check for bad input, pSSinfo can not be NULL */ 1203 if (!DATA_TABLES(SS_Info) || !ss_info) 1204 return result; 1205 1206 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(SS_Info)); 1207 get_atom_data_table_revision(header, &revision); 1208 1209 tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, DATA_TABLES(SS_Info)); 1210 if (!tbl) 1211 return result; 1212 1213 if (1 != revision.major || 2 > revision.minor) 1214 return result; 1215 1216 /* have to convert from Internal_SS format to SS_Info format */ 1217 switch (id) { 1218 case ASIC_INTERNAL_SS_ON_DP: 1219 id_local = SS_ID_DP1; 1220 break; 1221 case ASIC_INTERNAL_SS_ON_LVDS: 1222 { 1223 struct embedded_panel_info panel_info; 1224 1225 if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info) 1226 == BP_RESULT_OK) 1227 id_local = panel_info.ss_id; 1228 break; 1229 } 1230 default: 1231 break; 1232 } 1233 1234 if (id_local == SS_ID_UNKNOWN) 1235 return result; 1236 1237 table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) - 1238 sizeof(ATOM_COMMON_TABLE_HEADER)) / 1239 sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT); 1240 1241 for (i = 0; i < table_size; i++) { 1242 if (id_local != (uint32_t)tbl->asSS_Info[i].ucSS_Id) 1243 continue; 1244 1245 memset(ss_info, 0, sizeof(struct spread_spectrum_info)); 1246 1247 if (ATOM_EXTERNAL_SS_MASK & 1248 tbl->asSS_Info[i].ucSpreadSpectrumType) 1249 ss_info->type.EXTERNAL = true; 1250 1251 if (ATOM_SS_CENTRE_SPREAD_MODE_MASK & 1252 tbl->asSS_Info[i].ucSpreadSpectrumType) 1253 ss_info->type.CENTER_MODE = true; 1254 1255 ss_info->type.STEP_AND_DELAY_INFO = true; 1256 ss_info->spread_spectrum_percentage = 1257 (uint32_t)le16_to_cpu(tbl->asSS_Info[i].usSpreadSpectrumPercentage); 1258 ss_info->step_and_delay_info.step = tbl->asSS_Info[i].ucSS_Step; 1259 ss_info->step_and_delay_info.delay = 1260 tbl->asSS_Info[i].ucSS_Delay; 1261 ss_info->step_and_delay_info.recommended_ref_div = 1262 tbl->asSS_Info[i].ucRecommendedRef_Div; 1263 ss_info->spread_spectrum_range = 1264 (uint32_t)tbl->asSS_Info[i].ucSS_Range * 10000; 1265 1266 /* there will be only one entry for each display type in SS_info 1267 * table */ 1268 result = BP_RESULT_OK; 1269 break; 1270 } 1271 1272 return result; 1273 } 1274 static enum bp_result get_embedded_panel_info_v1_2( 1275 struct bios_parser *bp, 1276 struct embedded_panel_info *info); 1277 static enum bp_result get_embedded_panel_info_v1_3( 1278 struct bios_parser *bp, 1279 struct embedded_panel_info *info); 1280 1281 static enum bp_result bios_parser_get_embedded_panel_info( 1282 struct dc_bios *dcb, 1283 struct embedded_panel_info *info) 1284 { 1285 struct bios_parser *bp = BP_FROM_DCB(dcb); 1286 ATOM_COMMON_TABLE_HEADER *hdr; 1287 1288 if (!DATA_TABLES(LCD_Info)) 1289 return BP_RESULT_FAILURE; 1290 1291 hdr = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(LCD_Info)); 1292 1293 if (!hdr) 1294 return BP_RESULT_BADBIOSTABLE; 1295 1296 switch (hdr->ucTableFormatRevision) { 1297 case 1: 1298 switch (hdr->ucTableContentRevision) { 1299 case 0: 1300 case 1: 1301 case 2: 1302 return get_embedded_panel_info_v1_2(bp, info); 1303 case 3: 1304 return get_embedded_panel_info_v1_3(bp, info); 1305 default: 1306 break; 1307 } 1308 break; 1309 default: 1310 break; 1311 } 1312 1313 return BP_RESULT_FAILURE; 1314 } 1315 1316 static enum bp_result get_embedded_panel_extra_info( 1317 struct bios_parser *bp, 1318 struct embedded_panel_info *info, 1319 const uint32_t table_offset) 1320 { 1321 uint8_t *record = bios_get_image(&bp->base, table_offset, 1); 1322 ATOM_PANEL_RESOLUTION_PATCH_RECORD *panel_res_record; 1323 ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record; 1324 1325 while (*record != ATOM_RECORD_END_TYPE) { 1326 switch (*record) { 1327 case LCD_MODE_PATCH_RECORD_MODE_TYPE: 1328 record += sizeof(ATOM_PATCH_RECORD_MODE); 1329 break; 1330 case LCD_RTS_RECORD_TYPE: 1331 record += sizeof(ATOM_LCD_RTS_RECORD); 1332 break; 1333 case LCD_CAP_RECORD_TYPE: 1334 record += sizeof(ATOM_LCD_MODE_CONTROL_CAP); 1335 break; 1336 case LCD_FAKE_EDID_PATCH_RECORD_TYPE: 1337 fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record; 1338 if (fake_edid_record->ucFakeEDIDLength) { 1339 if (fake_edid_record->ucFakeEDIDLength == 128) 1340 info->fake_edid_size = 1341 fake_edid_record->ucFakeEDIDLength; 1342 else 1343 info->fake_edid_size = 1344 fake_edid_record->ucFakeEDIDLength * 128; 1345 1346 info->fake_edid = fake_edid_record->ucFakeEDIDString; 1347 1348 record += struct_size(fake_edid_record, 1349 ucFakeEDIDString, 1350 info->fake_edid_size); 1351 } else { 1352 /* empty fake edid record must be 3 bytes long */ 1353 record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1; 1354 } 1355 break; 1356 case LCD_PANEL_RESOLUTION_RECORD_TYPE: 1357 panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record; 1358 info->panel_width_mm = panel_res_record->usHSize; 1359 info->panel_height_mm = panel_res_record->usVSize; 1360 record += sizeof(ATOM_PANEL_RESOLUTION_PATCH_RECORD); 1361 break; 1362 default: 1363 return BP_RESULT_BADBIOSTABLE; 1364 } 1365 } 1366 1367 return BP_RESULT_OK; 1368 } 1369 1370 static enum bp_result get_embedded_panel_info_v1_2( 1371 struct bios_parser *bp, 1372 struct embedded_panel_info *info) 1373 { 1374 ATOM_LVDS_INFO_V12 *lvds; 1375 1376 if (!info) 1377 return BP_RESULT_BADINPUT; 1378 1379 if (!DATA_TABLES(LVDS_Info)) 1380 return BP_RESULT_UNSUPPORTED; 1381 1382 lvds = 1383 GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info)); 1384 1385 if (!lvds) 1386 return BP_RESULT_BADBIOSTABLE; 1387 1388 if (1 != lvds->sHeader.ucTableFormatRevision 1389 || 2 > lvds->sHeader.ucTableContentRevision) 1390 return BP_RESULT_UNSUPPORTED; 1391 1392 memset(info, 0, sizeof(struct embedded_panel_info)); 1393 1394 /* We need to convert from 10KHz units into KHz units*/ 1395 info->lcd_timing.pixel_clk = 1396 le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10; 1397 /* usHActive does not include borders, according to VBIOS team*/ 1398 info->lcd_timing.horizontal_addressable = 1399 le16_to_cpu(lvds->sLCDTiming.usHActive); 1400 /* usHBlanking_Time includes borders, so we should really be subtracting 1401 * borders duing this translation, but LVDS generally*/ 1402 /* doesn't have borders, so we should be okay leaving this as is for 1403 * now. May need to revisit if we ever have LVDS with borders*/ 1404 info->lcd_timing.horizontal_blanking_time = 1405 le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time); 1406 /* usVActive does not include borders, according to VBIOS team*/ 1407 info->lcd_timing.vertical_addressable = 1408 le16_to_cpu(lvds->sLCDTiming.usVActive); 1409 /* usVBlanking_Time includes borders, so we should really be subtracting 1410 * borders duing this translation, but LVDS generally*/ 1411 /* doesn't have borders, so we should be okay leaving this as is for 1412 * now. May need to revisit if we ever have LVDS with borders*/ 1413 info->lcd_timing.vertical_blanking_time = 1414 le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time); 1415 info->lcd_timing.horizontal_sync_offset = 1416 le16_to_cpu(lvds->sLCDTiming.usHSyncOffset); 1417 info->lcd_timing.horizontal_sync_width = 1418 le16_to_cpu(lvds->sLCDTiming.usHSyncWidth); 1419 info->lcd_timing.vertical_sync_offset = 1420 le16_to_cpu(lvds->sLCDTiming.usVSyncOffset); 1421 info->lcd_timing.vertical_sync_width = 1422 le16_to_cpu(lvds->sLCDTiming.usVSyncWidth); 1423 info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder; 1424 info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder; 1425 info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 1426 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff; 1427 info->lcd_timing.misc_info.H_SYNC_POLARITY = 1428 ~(uint32_t) 1429 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity; 1430 info->lcd_timing.misc_info.V_SYNC_POLARITY = 1431 ~(uint32_t) 1432 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity; 1433 info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 1434 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff; 1435 info->lcd_timing.misc_info.H_REPLICATION_BY2 = 1436 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2; 1437 info->lcd_timing.misc_info.V_REPLICATION_BY2 = 1438 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2; 1439 info->lcd_timing.misc_info.COMPOSITE_SYNC = 1440 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync; 1441 info->lcd_timing.misc_info.INTERLACE = 1442 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace; 1443 info->lcd_timing.misc_info.DOUBLE_CLOCK = 1444 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock; 1445 info->ss_id = lvds->ucSS_Id; 1446 1447 { 1448 uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate); 1449 /* Get minimum supported refresh rate*/ 1450 if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr) 1451 info->supported_rr.REFRESH_RATE_30HZ = 1; 1452 else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr) 1453 info->supported_rr.REFRESH_RATE_40HZ = 1; 1454 else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr) 1455 info->supported_rr.REFRESH_RATE_48HZ = 1; 1456 else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr) 1457 info->supported_rr.REFRESH_RATE_50HZ = 1; 1458 else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr) 1459 info->supported_rr.REFRESH_RATE_60HZ = 1; 1460 } 1461 1462 /*Drr panel support can be reported by VBIOS*/ 1463 if (LCDPANEL_CAP_DRR_SUPPORTED 1464 & lvds->ucLCDPanel_SpecialHandlingCap) 1465 info->drr_enabled = 1; 1466 1467 if (ATOM_PANEL_MISC_DUAL & lvds->ucLVDS_Misc) 1468 info->lcd_timing.misc_info.DOUBLE_CLOCK = true; 1469 1470 if (ATOM_PANEL_MISC_888RGB & lvds->ucLVDS_Misc) 1471 info->lcd_timing.misc_info.RGB888 = true; 1472 1473 info->lcd_timing.misc_info.GREY_LEVEL = 1474 (uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL & 1475 lvds->ucLVDS_Misc) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT; 1476 1477 if (ATOM_PANEL_MISC_SPATIAL & lvds->ucLVDS_Misc) 1478 info->lcd_timing.misc_info.SPATIAL = true; 1479 1480 if (ATOM_PANEL_MISC_TEMPORAL & lvds->ucLVDS_Misc) 1481 info->lcd_timing.misc_info.TEMPORAL = true; 1482 1483 if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc) 1484 info->lcd_timing.misc_info.API_ENABLED = true; 1485 1486 if (lvds->usExtInfoTableOffset) 1487 return get_embedded_panel_extra_info(bp, info, 1488 le16_to_cpu(lvds->usExtInfoTableOffset) + DATA_TABLES(LCD_Info)); 1489 1490 return BP_RESULT_OK; 1491 } 1492 1493 static enum bp_result get_embedded_panel_info_v1_3( 1494 struct bios_parser *bp, 1495 struct embedded_panel_info *info) 1496 { 1497 ATOM_LCD_INFO_V13 *lvds; 1498 1499 if (!info) 1500 return BP_RESULT_BADINPUT; 1501 1502 if (!DATA_TABLES(LCD_Info)) 1503 return BP_RESULT_UNSUPPORTED; 1504 1505 lvds = GET_IMAGE(ATOM_LCD_INFO_V13, DATA_TABLES(LCD_Info)); 1506 1507 if (!lvds) 1508 return BP_RESULT_BADBIOSTABLE; 1509 1510 if (!((1 == lvds->sHeader.ucTableFormatRevision) 1511 && (3 <= lvds->sHeader.ucTableContentRevision))) 1512 return BP_RESULT_UNSUPPORTED; 1513 1514 memset(info, 0, sizeof(struct embedded_panel_info)); 1515 1516 /* We need to convert from 10KHz units into KHz units */ 1517 info->lcd_timing.pixel_clk = 1518 le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10; 1519 /* usHActive does not include borders, according to VBIOS team */ 1520 info->lcd_timing.horizontal_addressable = 1521 le16_to_cpu(lvds->sLCDTiming.usHActive); 1522 /* usHBlanking_Time includes borders, so we should really be subtracting 1523 * borders duing this translation, but LVDS generally*/ 1524 /* doesn't have borders, so we should be okay leaving this as is for 1525 * now. May need to revisit if we ever have LVDS with borders*/ 1526 info->lcd_timing.horizontal_blanking_time = 1527 le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time); 1528 /* usVActive does not include borders, according to VBIOS team*/ 1529 info->lcd_timing.vertical_addressable = 1530 le16_to_cpu(lvds->sLCDTiming.usVActive); 1531 /* usVBlanking_Time includes borders, so we should really be subtracting 1532 * borders duing this translation, but LVDS generally*/ 1533 /* doesn't have borders, so we should be okay leaving this as is for 1534 * now. May need to revisit if we ever have LVDS with borders*/ 1535 info->lcd_timing.vertical_blanking_time = 1536 le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time); 1537 info->lcd_timing.horizontal_sync_offset = 1538 le16_to_cpu(lvds->sLCDTiming.usHSyncOffset); 1539 info->lcd_timing.horizontal_sync_width = 1540 le16_to_cpu(lvds->sLCDTiming.usHSyncWidth); 1541 info->lcd_timing.vertical_sync_offset = 1542 le16_to_cpu(lvds->sLCDTiming.usVSyncOffset); 1543 info->lcd_timing.vertical_sync_width = 1544 le16_to_cpu(lvds->sLCDTiming.usVSyncWidth); 1545 info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder; 1546 info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder; 1547 info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 1548 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff; 1549 info->lcd_timing.misc_info.H_SYNC_POLARITY = 1550 ~(uint32_t) 1551 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity; 1552 info->lcd_timing.misc_info.V_SYNC_POLARITY = 1553 ~(uint32_t) 1554 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity; 1555 info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 1556 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff; 1557 info->lcd_timing.misc_info.H_REPLICATION_BY2 = 1558 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2; 1559 info->lcd_timing.misc_info.V_REPLICATION_BY2 = 1560 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2; 1561 info->lcd_timing.misc_info.COMPOSITE_SYNC = 1562 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync; 1563 info->lcd_timing.misc_info.INTERLACE = 1564 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace; 1565 info->lcd_timing.misc_info.DOUBLE_CLOCK = 1566 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock; 1567 info->ss_id = lvds->ucSS_Id; 1568 1569 /* Drr panel support can be reported by VBIOS*/ 1570 if (LCDPANEL_CAP_V13_DRR_SUPPORTED 1571 & lvds->ucLCDPanel_SpecialHandlingCap) 1572 info->drr_enabled = 1; 1573 1574 /* Get supported refresh rate*/ 1575 if (info->drr_enabled == 1) { 1576 uint8_t min_rr = 1577 lvds->sRefreshRateSupport.ucMinRefreshRateForDRR; 1578 uint8_t rr = lvds->sRefreshRateSupport.ucSupportedRefreshRate; 1579 1580 if (min_rr != 0) { 1581 if (SUPPORTED_LCD_REFRESHRATE_30Hz & min_rr) 1582 info->supported_rr.REFRESH_RATE_30HZ = 1; 1583 else if (SUPPORTED_LCD_REFRESHRATE_40Hz & min_rr) 1584 info->supported_rr.REFRESH_RATE_40HZ = 1; 1585 else if (SUPPORTED_LCD_REFRESHRATE_48Hz & min_rr) 1586 info->supported_rr.REFRESH_RATE_48HZ = 1; 1587 else if (SUPPORTED_LCD_REFRESHRATE_50Hz & min_rr) 1588 info->supported_rr.REFRESH_RATE_50HZ = 1; 1589 else if (SUPPORTED_LCD_REFRESHRATE_60Hz & min_rr) 1590 info->supported_rr.REFRESH_RATE_60HZ = 1; 1591 } else { 1592 if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr) 1593 info->supported_rr.REFRESH_RATE_30HZ = 1; 1594 else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr) 1595 info->supported_rr.REFRESH_RATE_40HZ = 1; 1596 else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr) 1597 info->supported_rr.REFRESH_RATE_48HZ = 1; 1598 else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr) 1599 info->supported_rr.REFRESH_RATE_50HZ = 1; 1600 else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr) 1601 info->supported_rr.REFRESH_RATE_60HZ = 1; 1602 } 1603 } 1604 1605 if (ATOM_PANEL_MISC_V13_DUAL & lvds->ucLCD_Misc) 1606 info->lcd_timing.misc_info.DOUBLE_CLOCK = true; 1607 1608 if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR & lvds->ucLCD_Misc) 1609 info->lcd_timing.misc_info.RGB888 = true; 1610 1611 info->lcd_timing.misc_info.GREY_LEVEL = 1612 (uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL & 1613 lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT; 1614 1615 if (lvds->usExtInfoTableOffset) 1616 return get_embedded_panel_extra_info(bp, info, 1617 le16_to_cpu(lvds->usExtInfoTableOffset) + DATA_TABLES(LCD_Info)); 1618 1619 return BP_RESULT_OK; 1620 } 1621 1622 /** 1623 * bios_parser_get_encoder_cap_info - get encoder capability 1624 * information of input object id 1625 * 1626 * @dcb: pointer to the DC BIOS 1627 * @object_id: object id 1628 * @info: encoder cap information structure 1629 * 1630 * return: Bios parser result code 1631 */ 1632 static enum bp_result bios_parser_get_encoder_cap_info( 1633 struct dc_bios *dcb, 1634 struct graphics_object_id object_id, 1635 struct bp_encoder_cap_info *info) 1636 { 1637 struct bios_parser *bp = BP_FROM_DCB(dcb); 1638 ATOM_OBJECT *object; 1639 ATOM_ENCODER_CAP_RECORD_V2 *record = NULL; 1640 1641 if (!info) 1642 return BP_RESULT_BADINPUT; 1643 1644 object = get_bios_object(bp, object_id); 1645 1646 if (!object) 1647 return BP_RESULT_BADINPUT; 1648 1649 record = get_encoder_cap_record(bp, object); 1650 if (!record) 1651 return BP_RESULT_NORECORD; 1652 1653 info->DP_HBR2_EN = record->usHBR2En; 1654 info->DP_HBR3_EN = record->usHBR3En; 1655 info->HDMI_6GB_EN = record->usHDMI6GEn; 1656 return BP_RESULT_OK; 1657 } 1658 1659 /** 1660 * get_encoder_cap_record - Get encoder cap record for the object 1661 * 1662 * @bp: pointer to the BIOS parser 1663 * @object: ATOM object 1664 * return: atom encoder cap record 1665 * note: search all records to find the ATOM_ENCODER_CAP_RECORD_V2 record 1666 */ 1667 static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record( 1668 struct bios_parser *bp, 1669 ATOM_OBJECT *object) 1670 { 1671 ATOM_COMMON_RECORD_HEADER *header; 1672 uint32_t offset; 1673 1674 if (!object) { 1675 BREAK_TO_DEBUGGER(); /* Invalid object */ 1676 return NULL; 1677 } 1678 1679 offset = le16_to_cpu(object->usRecordOffset) 1680 + bp->object_info_tbl_offset; 1681 1682 for (;;) { 1683 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); 1684 1685 if (!header) 1686 return NULL; 1687 1688 offset += header->ucRecordSize; 1689 1690 if (LAST_RECORD_TYPE == header->ucRecordType || 1691 !header->ucRecordSize) 1692 break; 1693 1694 if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType) 1695 continue; 1696 1697 if (sizeof(ATOM_ENCODER_CAP_RECORD_V2) <= header->ucRecordSize) 1698 return (ATOM_ENCODER_CAP_RECORD_V2 *)header; 1699 } 1700 1701 return NULL; 1702 } 1703 1704 static uint32_t get_ss_entry_number( 1705 struct bios_parser *bp, 1706 uint32_t id); 1707 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1( 1708 struct bios_parser *bp, 1709 uint32_t id); 1710 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1( 1711 struct bios_parser *bp, 1712 uint32_t id); 1713 static uint32_t get_ss_entry_number_from_ss_info_tbl( 1714 struct bios_parser *bp, 1715 uint32_t id); 1716 1717 /** 1718 * bios_parser_get_ss_entry_number 1719 * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from 1720 * the VBIOS that match the SSid (to be converted from signal) 1721 * 1722 * @dcb: pointer to the DC BIOS 1723 * @signal: ASSignalType to be converted to SSid 1724 * return: number of SS Entry that match the signal 1725 */ 1726 static uint32_t bios_parser_get_ss_entry_number( 1727 struct dc_bios *dcb, 1728 enum as_signal_type signal) 1729 { 1730 struct bios_parser *bp = BP_FROM_DCB(dcb); 1731 uint32_t ss_id = 0; 1732 ATOM_COMMON_TABLE_HEADER *header; 1733 struct atom_data_revision revision; 1734 1735 ss_id = signal_to_ss_id(signal); 1736 1737 if (!DATA_TABLES(ASIC_InternalSS_Info)) 1738 return get_ss_entry_number_from_ss_info_tbl(bp, ss_id); 1739 1740 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, 1741 DATA_TABLES(ASIC_InternalSS_Info)); 1742 get_atom_data_table_revision(header, &revision); 1743 1744 switch (revision.major) { 1745 case 2: 1746 switch (revision.minor) { 1747 case 1: 1748 return get_ss_entry_number(bp, ss_id); 1749 default: 1750 break; 1751 } 1752 break; 1753 case 3: 1754 switch (revision.minor) { 1755 case 1: 1756 return 1757 get_ss_entry_number_from_internal_ss_info_tbl_V3_1( 1758 bp, ss_id); 1759 default: 1760 break; 1761 } 1762 break; 1763 default: 1764 break; 1765 } 1766 1767 return 0; 1768 } 1769 1770 /** 1771 * get_ss_entry_number_from_ss_info_tbl 1772 * Get Number of spread spectrum entry from the SS_Info table from the VBIOS. 1773 * 1774 * @bp: pointer to the BIOS parser 1775 * @id: spread spectrum id 1776 * return: number of SS Entry that match the id 1777 * note: There can only be one entry for each id for SS_Info Table 1778 */ 1779 static uint32_t get_ss_entry_number_from_ss_info_tbl( 1780 struct bios_parser *bp, 1781 uint32_t id) 1782 { 1783 ATOM_SPREAD_SPECTRUM_INFO *tbl; 1784 ATOM_COMMON_TABLE_HEADER *header; 1785 uint32_t table_size; 1786 uint32_t i; 1787 uint32_t number = 0; 1788 uint32_t id_local = SS_ID_UNKNOWN; 1789 struct atom_data_revision revision; 1790 1791 /* SS_Info table exist */ 1792 if (!DATA_TABLES(SS_Info)) 1793 return number; 1794 1795 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, 1796 DATA_TABLES(SS_Info)); 1797 get_atom_data_table_revision(header, &revision); 1798 1799 tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, 1800 DATA_TABLES(SS_Info)); 1801 if (!tbl) 1802 return number; 1803 1804 if (1 != revision.major || 2 > revision.minor) 1805 return number; 1806 1807 /* have to convert from Internal_SS format to SS_Info format */ 1808 switch (id) { 1809 case ASIC_INTERNAL_SS_ON_DP: 1810 id_local = SS_ID_DP1; 1811 break; 1812 case ASIC_INTERNAL_SS_ON_LVDS: { 1813 struct embedded_panel_info panel_info; 1814 1815 if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info) 1816 == BP_RESULT_OK) 1817 id_local = panel_info.ss_id; 1818 break; 1819 } 1820 default: 1821 break; 1822 } 1823 1824 if (id_local == SS_ID_UNKNOWN) 1825 return number; 1826 1827 table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) - 1828 sizeof(ATOM_COMMON_TABLE_HEADER)) / 1829 sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT); 1830 1831 for (i = 0; i < table_size; i++) 1832 if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) { 1833 number = 1; 1834 break; 1835 } 1836 1837 return number; 1838 } 1839 1840 /** 1841 * get_ss_entry_number 1842 * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or 1843 * SS_Info table from the VBIOS 1844 * There can not be more than 1 entry for ASIC_InternalSS_Info Ver 2.1 or 1845 * SS_Info. 1846 * 1847 * @bp: pointer to the BIOS parser 1848 * @id: spread sprectrum info index 1849 * return: Bios parser result code 1850 */ 1851 static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id) 1852 { 1853 if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS) 1854 return get_ss_entry_number_from_ss_info_tbl(bp, id); 1855 1856 return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id); 1857 } 1858 1859 /** 1860 * get_ss_entry_number_from_internal_ss_info_tbl_v2_1 1861 * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table 1862 * Ver 2.1 from the VBIOS 1863 * There will not be multiple entry for Ver 2.1 1864 * 1865 * @bp: pointer to the BIOS parser 1866 * @id: spread sprectrum info index 1867 * return: number of SS Entry that match the id 1868 */ 1869 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1( 1870 struct bios_parser *bp, 1871 uint32_t id) 1872 { 1873 ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include; 1874 ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl; 1875 uint32_t size; 1876 uint32_t i; 1877 1878 if (!DATA_TABLES(ASIC_InternalSS_Info)) 1879 return 0; 1880 1881 header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V2 *) bios_get_image( 1882 &bp->base, 1883 DATA_TABLES(ASIC_InternalSS_Info), 1884 struct_size(header_include, asSpreadSpectrum, 1))); 1885 if (!header_include) 1886 return 0; 1887 1888 size = (le16_to_cpu(header_include->sHeader.usStructureSize) 1889 - sizeof(ATOM_COMMON_TABLE_HEADER)) 1890 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2); 1891 1892 tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *) 1893 &header_include->asSpreadSpectrum[0]; 1894 for (i = 0; i < size; i++) 1895 if (tbl[i].ucClockIndication == (uint8_t)id) 1896 return 1; 1897 1898 return 0; 1899 } 1900 1901 /** 1902 * get_ss_entry_number_from_internal_ss_info_tbl_V3_1 1903 * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of 1904 * the VBIOS that matches id 1905 * 1906 * @bp: pointer to the BIOS parser 1907 * @id: spread sprectrum id 1908 * return: number of SS Entry that match the id 1909 */ 1910 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1( 1911 struct bios_parser *bp, 1912 uint32_t id) 1913 { 1914 uint32_t number = 0; 1915 ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include; 1916 ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl; 1917 uint32_t size; 1918 uint32_t i; 1919 1920 if (!DATA_TABLES(ASIC_InternalSS_Info)) 1921 return number; 1922 1923 header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V3 *) bios_get_image(&bp->base, 1924 DATA_TABLES(ASIC_InternalSS_Info), 1925 struct_size(header_include, asSpreadSpectrum, 1))); 1926 if (!header_include) 1927 return number; 1928 1929 size = (le16_to_cpu(header_include->sHeader.usStructureSize) - 1930 sizeof(ATOM_COMMON_TABLE_HEADER)) / 1931 sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3); 1932 1933 tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *) 1934 &header_include->asSpreadSpectrum[0]; 1935 1936 for (i = 0; i < size; i++) 1937 if (tbl[i].ucClockIndication == (uint8_t)id) 1938 number++; 1939 1940 return number; 1941 } 1942 1943 /** 1944 * bios_parser_get_gpio_pin_info 1945 * Get GpioPin information of input gpio id 1946 * 1947 * @dcb: pointer to the DC BIOS 1948 * @gpio_id: GPIO ID 1949 * @info: GpioPin information structure 1950 * return: Bios parser result code 1951 * note: 1952 * to get the GPIO PIN INFO, we need: 1953 * 1. get the GPIO_ID from other object table, see GetHPDInfo() 1954 * 2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA 1955 * offset/mask 1956 */ 1957 static enum bp_result bios_parser_get_gpio_pin_info( 1958 struct dc_bios *dcb, 1959 uint32_t gpio_id, 1960 struct gpio_pin_info *info) 1961 { 1962 struct bios_parser *bp = BP_FROM_DCB(dcb); 1963 ATOM_GPIO_PIN_LUT *header; 1964 uint32_t count = 0; 1965 uint32_t i = 0; 1966 1967 if (!DATA_TABLES(GPIO_Pin_LUT)) 1968 return BP_RESULT_BADBIOSTABLE; 1969 1970 header = ((ATOM_GPIO_PIN_LUT *) bios_get_image(&bp->base, 1971 DATA_TABLES(GPIO_Pin_LUT), 1972 struct_size(header, asGPIO_Pin, 1))); 1973 if (!header) 1974 return BP_RESULT_BADBIOSTABLE; 1975 1976 if (sizeof(ATOM_COMMON_TABLE_HEADER) + struct_size(header, asGPIO_Pin, 1) 1977 > le16_to_cpu(header->sHeader.usStructureSize)) 1978 return BP_RESULT_BADBIOSTABLE; 1979 1980 if (1 != header->sHeader.ucTableContentRevision) 1981 return BP_RESULT_UNSUPPORTED; 1982 1983 count = (le16_to_cpu(header->sHeader.usStructureSize) 1984 - sizeof(ATOM_COMMON_TABLE_HEADER)) 1985 / sizeof(ATOM_GPIO_PIN_ASSIGNMENT); 1986 for (i = 0; i < count; ++i) { 1987 if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id) 1988 continue; 1989 1990 info->offset = 1991 (uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex); 1992 info->offset_y = info->offset + 2; 1993 info->offset_en = info->offset + 1; 1994 info->offset_mask = info->offset - 1; 1995 1996 info->mask = (uint32_t) (1 << 1997 header->asGPIO_Pin[i].ucGpioPinBitShift); 1998 info->mask_y = info->mask + 2; 1999 info->mask_en = info->mask + 1; 2000 info->mask_mask = info->mask - 1; 2001 2002 return BP_RESULT_OK; 2003 } 2004 2005 return BP_RESULT_NORECORD; 2006 } 2007 2008 static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, 2009 ATOM_I2C_RECORD *record, 2010 struct graphics_object_i2c_info *info) 2011 { 2012 ATOM_GPIO_I2C_INFO *header; 2013 uint32_t count = 0; 2014 2015 if (!info) 2016 return BP_RESULT_BADINPUT; 2017 2018 /* get the GPIO_I2C info */ 2019 if (!DATA_TABLES(GPIO_I2C_Info)) 2020 return BP_RESULT_BADBIOSTABLE; 2021 2022 header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info)); 2023 if (!header) 2024 return BP_RESULT_BADBIOSTABLE; 2025 2026 if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT) 2027 > le16_to_cpu(header->sHeader.usStructureSize)) 2028 return BP_RESULT_BADBIOSTABLE; 2029 2030 if (1 != header->sHeader.ucTableContentRevision) 2031 return BP_RESULT_UNSUPPORTED; 2032 2033 /* get data count */ 2034 count = (le16_to_cpu(header->sHeader.usStructureSize) 2035 - sizeof(ATOM_COMMON_TABLE_HEADER)) 2036 / sizeof(ATOM_GPIO_I2C_ASSIGMENT); 2037 if (count <= record->sucI2cId.bfI2C_LineMux) 2038 return BP_RESULT_BADBIOSTABLE; 2039 2040 /* get the GPIO_I2C_INFO */ 2041 info->i2c_hw_assist = record->sucI2cId.bfHW_Capable; 2042 info->i2c_line = record->sucI2cId.bfI2C_LineMux; 2043 info->i2c_engine_id = record->sucI2cId.bfHW_EngineID; 2044 info->i2c_slave_address = record->ucI2CAddr; 2045 2046 info->gpio_info.clk_mask_register_index = 2047 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex); 2048 info->gpio_info.clk_en_register_index = 2049 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex); 2050 info->gpio_info.clk_y_register_index = 2051 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex); 2052 info->gpio_info.clk_a_register_index = 2053 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex); 2054 info->gpio_info.data_mask_register_index = 2055 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex); 2056 info->gpio_info.data_en_register_index = 2057 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex); 2058 info->gpio_info.data_y_register_index = 2059 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex); 2060 info->gpio_info.data_a_register_index = 2061 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex); 2062 2063 info->gpio_info.clk_mask_shift = 2064 header->asGPIO_Info[info->i2c_line].ucClkMaskShift; 2065 info->gpio_info.clk_en_shift = 2066 header->asGPIO_Info[info->i2c_line].ucClkEnShift; 2067 info->gpio_info.clk_y_shift = 2068 header->asGPIO_Info[info->i2c_line].ucClkY_Shift; 2069 info->gpio_info.clk_a_shift = 2070 header->asGPIO_Info[info->i2c_line].ucClkA_Shift; 2071 info->gpio_info.data_mask_shift = 2072 header->asGPIO_Info[info->i2c_line].ucDataMaskShift; 2073 info->gpio_info.data_en_shift = 2074 header->asGPIO_Info[info->i2c_line].ucDataEnShift; 2075 info->gpio_info.data_y_shift = 2076 header->asGPIO_Info[info->i2c_line].ucDataY_Shift; 2077 info->gpio_info.data_a_shift = 2078 header->asGPIO_Info[info->i2c_line].ucDataA_Shift; 2079 2080 return BP_RESULT_OK; 2081 } 2082 2083 static bool dal_graphics_object_id_is_valid(struct graphics_object_id id) 2084 { 2085 bool rc = true; 2086 2087 switch (id.type) { 2088 case OBJECT_TYPE_UNKNOWN: 2089 rc = false; 2090 break; 2091 case OBJECT_TYPE_GPU: 2092 case OBJECT_TYPE_ENGINE: 2093 /* do NOT check for id.id == 0 */ 2094 if (id.enum_id == ENUM_ID_UNKNOWN) 2095 rc = false; 2096 break; 2097 default: 2098 if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN) 2099 rc = false; 2100 break; 2101 } 2102 2103 return rc; 2104 } 2105 2106 static bool dal_graphics_object_id_is_equal( 2107 struct graphics_object_id id1, 2108 struct graphics_object_id id2) 2109 { 2110 if (false == dal_graphics_object_id_is_valid(id1)) { 2111 dm_output_to_console( 2112 "%s: Warning: comparing invalid object 'id1'!\n", __func__); 2113 return false; 2114 } 2115 2116 if (false == dal_graphics_object_id_is_valid(id2)) { 2117 dm_output_to_console( 2118 "%s: Warning: comparing invalid object 'id2'!\n", __func__); 2119 return false; 2120 } 2121 2122 if (id1.id == id2.id && id1.enum_id == id2.enum_id 2123 && id1.type == id2.type) 2124 return true; 2125 2126 return false; 2127 } 2128 2129 static ATOM_OBJECT *get_bios_object(struct bios_parser *bp, 2130 struct graphics_object_id id) 2131 { 2132 uint32_t offset; 2133 ATOM_OBJECT_TABLE *tbl; 2134 uint32_t i; 2135 2136 switch (id.type) { 2137 case OBJECT_TYPE_ENCODER: 2138 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset); 2139 break; 2140 2141 case OBJECT_TYPE_CONNECTOR: 2142 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); 2143 break; 2144 2145 case OBJECT_TYPE_ROUTER: 2146 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset); 2147 break; 2148 2149 case OBJECT_TYPE_GENERIC: 2150 if (bp->object_info_tbl.revision.minor < 3) 2151 return NULL; 2152 offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset); 2153 break; 2154 2155 default: 2156 return NULL; 2157 } 2158 2159 offset += bp->object_info_tbl_offset; 2160 2161 tbl = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base, offset, 2162 struct_size(tbl, asObjects, 1))); 2163 if (!tbl) 2164 return NULL; 2165 2166 for (i = 0; i < tbl->ucNumberOfObjects; i++) 2167 if (dal_graphics_object_id_is_equal(id, 2168 object_id_from_bios_object_id( 2169 le16_to_cpu(tbl->asObjects[i].usObjectID)))) 2170 return &tbl->asObjects[i]; 2171 2172 return NULL; 2173 } 2174 2175 static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object, 2176 uint16_t **id_list) 2177 { 2178 uint32_t offset; 2179 uint8_t *number; 2180 2181 if (!object) { 2182 BREAK_TO_DEBUGGER(); /* Invalid object id */ 2183 return 0; 2184 } 2185 2186 offset = le16_to_cpu(object->usSrcDstTableOffset) 2187 + bp->object_info_tbl_offset; 2188 2189 number = GET_IMAGE(uint8_t, offset); 2190 if (!number) 2191 return 0; 2192 2193 offset += sizeof(uint8_t); 2194 *id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t)); 2195 2196 if (!*id_list) 2197 return 0; 2198 2199 return *number; 2200 } 2201 2202 static struct device_id device_type_from_device_id(uint16_t device_id) 2203 { 2204 2205 struct device_id result_device_id = {0}; 2206 2207 switch (device_id) { 2208 case ATOM_DEVICE_LCD1_SUPPORT: 2209 result_device_id.device_type = DEVICE_TYPE_LCD; 2210 result_device_id.enum_id = 1; 2211 break; 2212 2213 case ATOM_DEVICE_LCD2_SUPPORT: 2214 result_device_id.device_type = DEVICE_TYPE_LCD; 2215 result_device_id.enum_id = 2; 2216 break; 2217 2218 case ATOM_DEVICE_CRT1_SUPPORT: 2219 result_device_id.device_type = DEVICE_TYPE_CRT; 2220 result_device_id.enum_id = 1; 2221 break; 2222 2223 case ATOM_DEVICE_CRT2_SUPPORT: 2224 result_device_id.device_type = DEVICE_TYPE_CRT; 2225 result_device_id.enum_id = 2; 2226 break; 2227 2228 case ATOM_DEVICE_DFP1_SUPPORT: 2229 result_device_id.device_type = DEVICE_TYPE_DFP; 2230 result_device_id.enum_id = 1; 2231 break; 2232 2233 case ATOM_DEVICE_DFP2_SUPPORT: 2234 result_device_id.device_type = DEVICE_TYPE_DFP; 2235 result_device_id.enum_id = 2; 2236 break; 2237 2238 case ATOM_DEVICE_DFP3_SUPPORT: 2239 result_device_id.device_type = DEVICE_TYPE_DFP; 2240 result_device_id.enum_id = 3; 2241 break; 2242 2243 case ATOM_DEVICE_DFP4_SUPPORT: 2244 result_device_id.device_type = DEVICE_TYPE_DFP; 2245 result_device_id.enum_id = 4; 2246 break; 2247 2248 case ATOM_DEVICE_DFP5_SUPPORT: 2249 result_device_id.device_type = DEVICE_TYPE_DFP; 2250 result_device_id.enum_id = 5; 2251 break; 2252 2253 case ATOM_DEVICE_DFP6_SUPPORT: 2254 result_device_id.device_type = DEVICE_TYPE_DFP; 2255 result_device_id.enum_id = 6; 2256 break; 2257 2258 default: 2259 BREAK_TO_DEBUGGER(); /* Invalid device Id */ 2260 result_device_id.device_type = DEVICE_TYPE_UNKNOWN; 2261 result_device_id.enum_id = 0; 2262 } 2263 return result_device_id; 2264 } 2265 2266 static void get_atom_data_table_revision( 2267 ATOM_COMMON_TABLE_HEADER *atom_data_tbl, 2268 struct atom_data_revision *tbl_revision) 2269 { 2270 if (!tbl_revision) 2271 return; 2272 2273 /* initialize the revision to 0 which is invalid revision */ 2274 tbl_revision->major = 0; 2275 tbl_revision->minor = 0; 2276 2277 if (!atom_data_tbl) 2278 return; 2279 2280 tbl_revision->major = 2281 (uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl); 2282 tbl_revision->minor = 2283 (uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl); 2284 } 2285 2286 static uint32_t signal_to_ss_id(enum as_signal_type signal) 2287 { 2288 uint32_t clk_id_ss = 0; 2289 2290 switch (signal) { 2291 case AS_SIGNAL_TYPE_DVI: 2292 clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS; 2293 break; 2294 case AS_SIGNAL_TYPE_HDMI: 2295 clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI; 2296 break; 2297 case AS_SIGNAL_TYPE_LVDS: 2298 clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS; 2299 break; 2300 case AS_SIGNAL_TYPE_DISPLAY_PORT: 2301 clk_id_ss = ASIC_INTERNAL_SS_ON_DP; 2302 break; 2303 case AS_SIGNAL_TYPE_GPU_PLL: 2304 clk_id_ss = ASIC_INTERNAL_GPUPLL_SS; 2305 break; 2306 default: 2307 break; 2308 } 2309 return clk_id_ss; 2310 } 2311 2312 static uint32_t get_support_mask_for_device_id( 2313 enum dal_device_type device_type, 2314 uint32_t enum_id) 2315 { 2316 switch (device_type) { 2317 case DEVICE_TYPE_LCD: 2318 switch (enum_id) { 2319 case 1: 2320 return ATOM_DEVICE_LCD1_SUPPORT; 2321 case 2: 2322 return ATOM_DEVICE_LCD2_SUPPORT; 2323 default: 2324 break; 2325 } 2326 break; 2327 case DEVICE_TYPE_CRT: 2328 switch (enum_id) { 2329 case 1: 2330 return ATOM_DEVICE_CRT1_SUPPORT; 2331 case 2: 2332 return ATOM_DEVICE_CRT2_SUPPORT; 2333 default: 2334 break; 2335 } 2336 break; 2337 case DEVICE_TYPE_DFP: 2338 switch (enum_id) { 2339 case 1: 2340 return ATOM_DEVICE_DFP1_SUPPORT; 2341 case 2: 2342 return ATOM_DEVICE_DFP2_SUPPORT; 2343 case 3: 2344 return ATOM_DEVICE_DFP3_SUPPORT; 2345 case 4: 2346 return ATOM_DEVICE_DFP4_SUPPORT; 2347 case 5: 2348 return ATOM_DEVICE_DFP5_SUPPORT; 2349 case 6: 2350 return ATOM_DEVICE_DFP6_SUPPORT; 2351 default: 2352 break; 2353 } 2354 break; 2355 case DEVICE_TYPE_CV: 2356 switch (enum_id) { 2357 case 1: 2358 return ATOM_DEVICE_CV_SUPPORT; 2359 default: 2360 break; 2361 } 2362 break; 2363 case DEVICE_TYPE_TV: 2364 switch (enum_id) { 2365 case 1: 2366 return ATOM_DEVICE_TV1_SUPPORT; 2367 default: 2368 break; 2369 } 2370 break; 2371 default: 2372 break; 2373 } 2374 2375 /* Unidentified device ID, return empty support mask. */ 2376 return 0; 2377 } 2378 2379 /** 2380 * bios_parser_set_scratch_critical_state - update critical state 2381 * bit in VBIOS scratch register 2382 * @dcb: pointer to the DC BIOS 2383 * @state: set or reset state 2384 */ 2385 static void bios_parser_set_scratch_critical_state( 2386 struct dc_bios *dcb, 2387 bool state) 2388 { 2389 bios_set_scratch_critical_state(dcb, state); 2390 } 2391 2392 /* 2393 * get_integrated_info_v8 2394 * 2395 * @brief 2396 * Get V8 integrated BIOS information 2397 * 2398 * @param 2399 * bios_parser *bp - [in]BIOS parser handler to get master data table 2400 * integrated_info *info - [out] store and output integrated info 2401 * 2402 * return: 2403 * enum bp_result - BP_RESULT_OK if information is available, 2404 * BP_RESULT_BADBIOSTABLE otherwise. 2405 */ 2406 static enum bp_result get_integrated_info_v8( 2407 struct bios_parser *bp, 2408 struct integrated_info *info) 2409 { 2410 ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8; 2411 uint32_t i; 2412 2413 info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8, 2414 bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); 2415 2416 if (info_v8 == NULL) 2417 return BP_RESULT_BADBIOSTABLE; 2418 info->boot_up_engine_clock = le32_to_cpu(info_v8->ulBootUpEngineClock) * 10; 2419 info->dentist_vco_freq = le32_to_cpu(info_v8->ulDentistVCOFreq) * 10; 2420 info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10; 2421 2422 for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { 2423 /* Convert [10KHz] into [KHz] */ 2424 info->disp_clk_voltage[i].max_supported_clk = 2425 le32_to_cpu(info_v8->sDISPCLK_Voltage[i]. 2426 ulMaximumSupportedCLK) * 10; 2427 info->disp_clk_voltage[i].voltage_index = 2428 le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex); 2429 } 2430 2431 info->boot_up_req_display_vector = 2432 le32_to_cpu(info_v8->ulBootUpReqDisplayVector); 2433 info->gpu_cap_info = 2434 le32_to_cpu(info_v8->ulGPUCapInfo); 2435 2436 /* 2437 * system_config: Bit[0] = 0 : PCIE power gating disabled 2438 * = 1 : PCIE power gating enabled 2439 * Bit[1] = 0 : DDR-PLL shut down disabled 2440 * = 1 : DDR-PLL shut down enabled 2441 * Bit[2] = 0 : DDR-PLL power down disabled 2442 * = 1 : DDR-PLL power down enabled 2443 */ 2444 info->system_config = le32_to_cpu(info_v8->ulSystemConfig); 2445 info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo); 2446 info->boot_up_nb_voltage = 2447 le16_to_cpu(info_v8->usBootUpNBVoltage); 2448 info->ext_disp_conn_info_offset = 2449 le16_to_cpu(info_v8->usExtDispConnInfoOffset); 2450 info->memory_type = info_v8->ucMemoryType; 2451 info->ma_channel_number = info_v8->ucUMAChannelNumber; 2452 info->gmc_restore_reset_time = 2453 le32_to_cpu(info_v8->ulGMCRestoreResetTime); 2454 2455 info->minimum_n_clk = 2456 le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]); 2457 for (i = 1; i < 4; ++i) 2458 info->minimum_n_clk = 2459 info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ? 2460 info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]); 2461 2462 info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk); 2463 info->ddr_dll_power_up_time = 2464 le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime); 2465 info->ddr_pll_power_up_time = 2466 le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime); 2467 info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType); 2468 info->lvds_ss_percentage = 2469 le16_to_cpu(info_v8->usLvdsSSPercentage); 2470 info->lvds_sspread_rate_in_10hz = 2471 le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz); 2472 info->hdmi_ss_percentage = 2473 le16_to_cpu(info_v8->usHDMISSPercentage); 2474 info->hdmi_sspread_rate_in_10hz = 2475 le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz); 2476 info->dvi_ss_percentage = 2477 le16_to_cpu(info_v8->usDVISSPercentage); 2478 info->dvi_sspread_rate_in_10_hz = 2479 le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz); 2480 2481 info->max_lvds_pclk_freq_in_single_link = 2482 le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink); 2483 info->lvds_misc = info_v8->ucLvdsMisc; 2484 info->lvds_pwr_on_seq_dig_on_to_de_in_4ms = 2485 info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms; 2486 info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms = 2487 info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms; 2488 info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms = 2489 info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms; 2490 info->lvds_pwr_off_seq_vary_bl_to_de_in4ms = 2491 info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms; 2492 info->lvds_pwr_off_seq_de_to_dig_on_in4ms = 2493 info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms; 2494 info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms = 2495 info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; 2496 info->lvds_off_to_on_delay_in_4ms = 2497 info_v8->ucLVDSOffToOnDelay_in4Ms; 2498 info->lvds_bit_depth_control_val = 2499 le32_to_cpu(info_v8->ulLCDBitDepthControlVal); 2500 2501 for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) { 2502 /* Convert [10KHz] into [KHz] */ 2503 info->avail_s_clk[i].supported_s_clk = 2504 le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10; 2505 info->avail_s_clk[i].voltage_index = 2506 le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex); 2507 info->avail_s_clk[i].voltage_id = 2508 le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID); 2509 } 2510 2511 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) { 2512 info->ext_disp_conn_info.gu_id[i] = 2513 info_v8->sExtDispConnInfo.ucGuid[i]; 2514 } 2515 2516 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) { 2517 info->ext_disp_conn_info.path[i].device_connector_id = 2518 object_id_from_bios_object_id( 2519 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector)); 2520 2521 info->ext_disp_conn_info.path[i].ext_encoder_obj_id = 2522 object_id_from_bios_object_id( 2523 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId)); 2524 2525 info->ext_disp_conn_info.path[i].device_tag = 2526 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag); 2527 info->ext_disp_conn_info.path[i].device_acpi_enum = 2528 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum); 2529 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index = 2530 info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex; 2531 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index = 2532 info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex; 2533 info->ext_disp_conn_info.path[i].channel_mapping.raw = 2534 info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping; 2535 } 2536 info->ext_disp_conn_info.checksum = 2537 info_v8->sExtDispConnInfo.ucChecksum; 2538 2539 return BP_RESULT_OK; 2540 } 2541 2542 /* 2543 * get_integrated_info_v9 2544 * 2545 * @brief 2546 * Get V9 integrated BIOS information 2547 * 2548 * @param 2549 * bios_parser *bp - [in]BIOS parser handler to get master data table 2550 * integrated_info *info - [out] store and output integrated info 2551 * 2552 * return: 2553 * enum bp_result - BP_RESULT_OK if information is available, 2554 * BP_RESULT_BADBIOSTABLE otherwise. 2555 */ 2556 static enum bp_result get_integrated_info_v9( 2557 struct bios_parser *bp, 2558 struct integrated_info *info) 2559 { 2560 ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9; 2561 uint32_t i; 2562 2563 info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9, 2564 bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); 2565 2566 if (!info_v9) 2567 return BP_RESULT_BADBIOSTABLE; 2568 2569 info->boot_up_engine_clock = le32_to_cpu(info_v9->ulBootUpEngineClock) * 10; 2570 info->dentist_vco_freq = le32_to_cpu(info_v9->ulDentistVCOFreq) * 10; 2571 info->boot_up_uma_clock = le32_to_cpu(info_v9->ulBootUpUMAClock) * 10; 2572 2573 for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { 2574 /* Convert [10KHz] into [KHz] */ 2575 info->disp_clk_voltage[i].max_supported_clk = 2576 le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10; 2577 info->disp_clk_voltage[i].voltage_index = 2578 le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex); 2579 } 2580 2581 info->boot_up_req_display_vector = 2582 le32_to_cpu(info_v9->ulBootUpReqDisplayVector); 2583 info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo); 2584 2585 /* 2586 * system_config: Bit[0] = 0 : PCIE power gating disabled 2587 * = 1 : PCIE power gating enabled 2588 * Bit[1] = 0 : DDR-PLL shut down disabled 2589 * = 1 : DDR-PLL shut down enabled 2590 * Bit[2] = 0 : DDR-PLL power down disabled 2591 * = 1 : DDR-PLL power down enabled 2592 */ 2593 info->system_config = le32_to_cpu(info_v9->ulSystemConfig); 2594 info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo); 2595 info->boot_up_nb_voltage = le16_to_cpu(info_v9->usBootUpNBVoltage); 2596 info->ext_disp_conn_info_offset = le16_to_cpu(info_v9->usExtDispConnInfoOffset); 2597 info->memory_type = info_v9->ucMemoryType; 2598 info->ma_channel_number = info_v9->ucUMAChannelNumber; 2599 info->gmc_restore_reset_time = le32_to_cpu(info_v9->ulGMCRestoreResetTime); 2600 2601 info->minimum_n_clk = le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]); 2602 for (i = 1; i < 4; ++i) 2603 info->minimum_n_clk = 2604 info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ? 2605 info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]); 2606 2607 info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk); 2608 info->ddr_dll_power_up_time = le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime); 2609 info->ddr_pll_power_up_time = le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime); 2610 info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType); 2611 info->lvds_ss_percentage = le16_to_cpu(info_v9->usLvdsSSPercentage); 2612 info->lvds_sspread_rate_in_10hz = le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz); 2613 info->hdmi_ss_percentage = le16_to_cpu(info_v9->usHDMISSPercentage); 2614 info->hdmi_sspread_rate_in_10hz = le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz); 2615 info->dvi_ss_percentage = le16_to_cpu(info_v9->usDVISSPercentage); 2616 info->dvi_sspread_rate_in_10_hz = le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz); 2617 2618 info->max_lvds_pclk_freq_in_single_link = 2619 le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink); 2620 info->lvds_misc = info_v9->ucLvdsMisc; 2621 info->lvds_pwr_on_seq_dig_on_to_de_in_4ms = 2622 info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms; 2623 info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms = 2624 info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms; 2625 info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms = 2626 info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms; 2627 info->lvds_pwr_off_seq_vary_bl_to_de_in4ms = 2628 info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms; 2629 info->lvds_pwr_off_seq_de_to_dig_on_in4ms = 2630 info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms; 2631 info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms = 2632 info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; 2633 info->lvds_off_to_on_delay_in_4ms = 2634 info_v9->ucLVDSOffToOnDelay_in4Ms; 2635 info->lvds_bit_depth_control_val = 2636 le32_to_cpu(info_v9->ulLCDBitDepthControlVal); 2637 2638 for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) { 2639 /* Convert [10KHz] into [KHz] */ 2640 info->avail_s_clk[i].supported_s_clk = 2641 le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10; 2642 info->avail_s_clk[i].voltage_index = 2643 le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex); 2644 info->avail_s_clk[i].voltage_id = 2645 le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID); 2646 } 2647 2648 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) { 2649 info->ext_disp_conn_info.gu_id[i] = 2650 info_v9->sExtDispConnInfo.ucGuid[i]; 2651 } 2652 2653 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) { 2654 info->ext_disp_conn_info.path[i].device_connector_id = 2655 object_id_from_bios_object_id( 2656 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector)); 2657 2658 info->ext_disp_conn_info.path[i].ext_encoder_obj_id = 2659 object_id_from_bios_object_id( 2660 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId)); 2661 2662 info->ext_disp_conn_info.path[i].device_tag = 2663 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag); 2664 info->ext_disp_conn_info.path[i].device_acpi_enum = 2665 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum); 2666 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index = 2667 info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex; 2668 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index = 2669 info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex; 2670 info->ext_disp_conn_info.path[i].channel_mapping.raw = 2671 info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping; 2672 } 2673 info->ext_disp_conn_info.checksum = 2674 info_v9->sExtDispConnInfo.ucChecksum; 2675 2676 return BP_RESULT_OK; 2677 } 2678 2679 /* 2680 * construct_integrated_info 2681 * 2682 * @brief 2683 * Get integrated BIOS information based on table revision 2684 * 2685 * @param 2686 * bios_parser *bp - [in]BIOS parser handler to get master data table 2687 * integrated_info *info - [out] store and output integrated info 2688 * 2689 * return: 2690 * enum bp_result - BP_RESULT_OK if information is available, 2691 * BP_RESULT_BADBIOSTABLE otherwise. 2692 */ 2693 static enum bp_result construct_integrated_info( 2694 struct bios_parser *bp, 2695 struct integrated_info *info) 2696 { 2697 enum bp_result result = BP_RESULT_BADBIOSTABLE; 2698 2699 ATOM_COMMON_TABLE_HEADER *header; 2700 struct atom_data_revision revision; 2701 2702 if (bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) { 2703 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, 2704 bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); 2705 2706 get_atom_data_table_revision(header, &revision); 2707 2708 /* Don't need to check major revision as they are all 1 */ 2709 switch (revision.minor) { 2710 case 8: 2711 result = get_integrated_info_v8(bp, info); 2712 break; 2713 case 9: 2714 result = get_integrated_info_v9(bp, info); 2715 break; 2716 default: 2717 return result; 2718 2719 } 2720 } 2721 2722 /* Sort voltage table from low to high*/ 2723 if (result == BP_RESULT_OK) { 2724 int32_t i; 2725 int32_t j; 2726 2727 for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { 2728 for (j = i; j > 0; --j) { 2729 if ( 2730 info->disp_clk_voltage[j].max_supported_clk < 2731 info->disp_clk_voltage[j-1].max_supported_clk) { 2732 /* swap j and j - 1*/ 2733 swap(info->disp_clk_voltage[j - 1], 2734 info->disp_clk_voltage[j]); 2735 } 2736 } 2737 } 2738 2739 } 2740 2741 return result; 2742 } 2743 2744 static struct integrated_info *bios_parser_create_integrated_info( 2745 struct dc_bios *dcb) 2746 { 2747 struct bios_parser *bp = BP_FROM_DCB(dcb); 2748 struct integrated_info *info; 2749 2750 info = kzalloc_obj(struct integrated_info); 2751 2752 if (info == NULL) { 2753 ASSERT_CRITICAL(0); 2754 return NULL; 2755 } 2756 2757 if (construct_integrated_info(bp, info) == BP_RESULT_OK) 2758 return info; 2759 2760 kfree(info); 2761 2762 return NULL; 2763 } 2764 2765 static enum bp_result update_slot_layout_info(struct dc_bios *dcb, 2766 unsigned int i, 2767 struct slot_layout_info *slot_layout_info, 2768 unsigned int record_offset) 2769 { 2770 (void)i; 2771 unsigned int j; 2772 struct bios_parser *bp; 2773 ATOM_BRACKET_LAYOUT_RECORD *record; 2774 ATOM_COMMON_RECORD_HEADER *record_header; 2775 enum bp_result result = BP_RESULT_NORECORD; 2776 2777 bp = BP_FROM_DCB(dcb); 2778 record = NULL; 2779 record_header = NULL; 2780 2781 for (;;) { 2782 2783 record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset); 2784 if (record_header == NULL) { 2785 result = BP_RESULT_BADBIOSTABLE; 2786 break; 2787 } 2788 2789 /* the end of the list */ 2790 if (record_header->ucRecordType == 0xff || 2791 record_header->ucRecordSize == 0) { 2792 break; 2793 } 2794 2795 if (record_header->ucRecordType == 2796 ATOM_BRACKET_LAYOUT_RECORD_TYPE && 2797 struct_size(record, asConnInfo, 1) 2798 <= record_header->ucRecordSize) { 2799 record = (ATOM_BRACKET_LAYOUT_RECORD *) 2800 (record_header); 2801 result = BP_RESULT_OK; 2802 break; 2803 } 2804 2805 record_offset += record_header->ucRecordSize; 2806 } 2807 2808 /* return if the record not found */ 2809 if (result != BP_RESULT_OK) 2810 return result; 2811 2812 /* get slot sizes */ 2813 slot_layout_info->length = record->ucLength; 2814 slot_layout_info->width = record->ucWidth; 2815 2816 /* get info for each connector in the slot */ 2817 slot_layout_info->num_of_connectors = record->ucConnNum; 2818 for (j = 0; j < slot_layout_info->num_of_connectors; ++j) { 2819 slot_layout_info->connectors[j].connector_type = 2820 (enum connector_layout_type) 2821 (record->asConnInfo[j].ucConnectorType); 2822 switch (record->asConnInfo[j].ucConnectorType) { 2823 case CONNECTOR_TYPE_DVI_D: 2824 slot_layout_info->connectors[j].connector_type = 2825 CONNECTOR_LAYOUT_TYPE_DVI_D; 2826 slot_layout_info->connectors[j].length = 2827 CONNECTOR_SIZE_DVI; 2828 break; 2829 2830 case CONNECTOR_TYPE_HDMI: 2831 slot_layout_info->connectors[j].connector_type = 2832 CONNECTOR_LAYOUT_TYPE_HDMI; 2833 slot_layout_info->connectors[j].length = 2834 CONNECTOR_SIZE_HDMI; 2835 break; 2836 2837 case CONNECTOR_TYPE_DISPLAY_PORT: 2838 slot_layout_info->connectors[j].connector_type = 2839 CONNECTOR_LAYOUT_TYPE_DP; 2840 slot_layout_info->connectors[j].length = 2841 CONNECTOR_SIZE_DP; 2842 break; 2843 2844 case CONNECTOR_TYPE_MINI_DISPLAY_PORT: 2845 slot_layout_info->connectors[j].connector_type = 2846 CONNECTOR_LAYOUT_TYPE_MINI_DP; 2847 slot_layout_info->connectors[j].length = 2848 CONNECTOR_SIZE_MINI_DP; 2849 break; 2850 2851 default: 2852 slot_layout_info->connectors[j].connector_type = 2853 CONNECTOR_LAYOUT_TYPE_UNKNOWN; 2854 slot_layout_info->connectors[j].length = 2855 CONNECTOR_SIZE_UNKNOWN; 2856 } 2857 2858 slot_layout_info->connectors[j].position = 2859 record->asConnInfo[j].ucPosition; 2860 slot_layout_info->connectors[j].connector_id = 2861 object_id_from_bios_object_id( 2862 record->asConnInfo[j].usConnectorObjectId); 2863 } 2864 return result; 2865 } 2866 2867 2868 static enum bp_result get_bracket_layout_record(struct dc_bios *dcb, 2869 unsigned int bracket_layout_id, 2870 struct slot_layout_info *slot_layout_info) 2871 { 2872 unsigned int i; 2873 unsigned int record_offset; 2874 struct bios_parser *bp; 2875 enum bp_result result; 2876 ATOM_OBJECT *object; 2877 ATOM_OBJECT_TABLE *object_table; 2878 unsigned int genericTableOffset; 2879 2880 bp = BP_FROM_DCB(dcb); 2881 object = NULL; 2882 if (slot_layout_info == NULL) { 2883 DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n"); 2884 return BP_RESULT_BADINPUT; 2885 } 2886 2887 2888 genericTableOffset = bp->object_info_tbl_offset + 2889 bp->object_info_tbl.v1_3->usMiscObjectTableOffset; 2890 object_table = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base, 2891 genericTableOffset, 2892 struct_size(object_table, asObjects, 1))); 2893 if (!object_table) 2894 return BP_RESULT_FAILURE; 2895 2896 result = BP_RESULT_NORECORD; 2897 for (i = 0; i < object_table->ucNumberOfObjects; ++i) { 2898 2899 if (bracket_layout_id == 2900 object_table->asObjects[i].usObjectID) { 2901 2902 object = &object_table->asObjects[i]; 2903 record_offset = object->usRecordOffset + 2904 bp->object_info_tbl_offset; 2905 2906 result = update_slot_layout_info(dcb, i, 2907 slot_layout_info, record_offset); 2908 break; 2909 } 2910 } 2911 return result; 2912 } 2913 2914 static enum bp_result bios_get_board_layout_info( 2915 struct dc_bios *dcb, 2916 struct board_layout_info *board_layout_info) 2917 { 2918 unsigned int i; 2919 struct bios_parser *bp; 2920 enum bp_result record_result; 2921 2922 const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = { 2923 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1, 2924 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2, 2925 0, 0 2926 }; 2927 2928 bp = BP_FROM_DCB(dcb); 2929 2930 if (board_layout_info == NULL) { 2931 DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n"); 2932 return BP_RESULT_BADINPUT; 2933 } 2934 2935 board_layout_info->num_of_slots = 0; 2936 2937 for (i = 0; i < MAX_BOARD_SLOTS; ++i) { 2938 record_result = get_bracket_layout_record(dcb, 2939 slot_index_to_vbios_id[i], 2940 &board_layout_info->slots[i]); 2941 2942 if (record_result == BP_RESULT_NORECORD && i > 0) 2943 break; /* no more slots present in bios */ 2944 else if (record_result != BP_RESULT_OK) 2945 return record_result; /* fail */ 2946 2947 ++board_layout_info->num_of_slots; 2948 } 2949 2950 /* all data is valid */ 2951 board_layout_info->is_number_of_slots_valid = 1; 2952 board_layout_info->is_slots_size_valid = 1; 2953 board_layout_info->is_connector_offsets_valid = 1; 2954 board_layout_info->is_connector_lengths_valid = 1; 2955 2956 return BP_RESULT_OK; 2957 } 2958 2959 /******************************************************************************/ 2960 2961 static const struct dc_vbios_funcs vbios_funcs = { 2962 .get_connectors_number = bios_parser_get_connectors_number, 2963 2964 .get_connector_id = bios_parser_get_connector_id, 2965 2966 .get_src_obj = bios_parser_get_src_obj, 2967 2968 .get_i2c_info = bios_parser_get_i2c_info, 2969 2970 .get_hpd_info = bios_parser_get_hpd_info, 2971 2972 .get_device_tag = bios_parser_get_device_tag, 2973 2974 .get_spread_spectrum_info = bios_parser_get_spread_spectrum_info, 2975 2976 .get_ss_entry_number = bios_parser_get_ss_entry_number, 2977 2978 .get_embedded_panel_info = bios_parser_get_embedded_panel_info, 2979 2980 .get_gpio_pin_info = bios_parser_get_gpio_pin_info, 2981 2982 .get_encoder_cap_info = bios_parser_get_encoder_cap_info, 2983 2984 /* bios scratch register communication */ 2985 .is_accelerated_mode = bios_is_accelerated_mode, 2986 2987 .set_scratch_critical_state = bios_parser_set_scratch_critical_state, 2988 2989 .is_device_id_supported = bios_parser_is_device_id_supported, 2990 2991 /* COMMANDS */ 2992 .select_crtc_source = bios_parser_select_crtc_source, 2993 2994 .encoder_control = bios_parser_encoder_control, 2995 2996 .external_encoder_control = bios_parser_external_encoder_control, 2997 2998 .dac_load_detection = bios_parser_dac_load_detection, 2999 3000 .transmitter_control = bios_parser_transmitter_control, 3001 3002 .enable_crtc = bios_parser_enable_crtc, 3003 3004 .adjust_pixel_clock = bios_parser_adjust_pixel_clock, 3005 3006 .set_pixel_clock = bios_parser_set_pixel_clock, 3007 3008 .set_dce_clock = bios_parser_set_dce_clock, 3009 3010 .enable_spread_spectrum_on_ppll = bios_parser_enable_spread_spectrum_on_ppll, 3011 3012 .program_crtc_timing = bios_parser_program_crtc_timing, /* still use. should probably retire and program directly */ 3013 3014 .program_display_engine_pll = bios_parser_program_display_engine_pll, 3015 3016 .enable_disp_power_gating = bios_parser_enable_disp_power_gating, 3017 3018 /* SW init and patch */ 3019 3020 .bios_parser_destroy = bios_parser_destroy, 3021 3022 .get_board_layout_info = bios_get_board_layout_info, 3023 3024 .get_atom_dc_golden_table = NULL 3025 }; 3026 3027 static bool bios_parser_construct( 3028 struct bios_parser *bp, 3029 struct bp_init_data *init, 3030 enum dce_version dce_version) 3031 { 3032 uint16_t *rom_header_offset = NULL; 3033 ATOM_ROM_HEADER *rom_header = NULL; 3034 ATOM_OBJECT_HEADER *object_info_tbl; 3035 struct atom_data_revision tbl_rev = {0}; 3036 3037 if (!init) 3038 return false; 3039 3040 if (!init->bios) 3041 return false; 3042 3043 bp->base.funcs = &vbios_funcs; 3044 bp->base.bios = init->bios; 3045 bp->base.bios_size = bp->base.bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT; 3046 3047 bp->base.ctx = init->ctx; 3048 bp->base.bios_local_image = NULL; 3049 3050 rom_header_offset = 3051 GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER); 3052 3053 if (!rom_header_offset) 3054 return false; 3055 3056 rom_header = GET_IMAGE(ATOM_ROM_HEADER, *rom_header_offset); 3057 3058 if (!rom_header) 3059 return false; 3060 3061 get_atom_data_table_revision(&rom_header->sHeader, &tbl_rev); 3062 if (tbl_rev.major >= 2 && tbl_rev.minor >= 2) 3063 return false; 3064 3065 bp->master_data_tbl = 3066 GET_IMAGE(ATOM_MASTER_DATA_TABLE, 3067 rom_header->usMasterDataTableOffset); 3068 3069 if (!bp->master_data_tbl) 3070 return false; 3071 3072 bp->object_info_tbl_offset = DATA_TABLES(Object_Header); 3073 3074 if (!bp->object_info_tbl_offset) 3075 return false; 3076 3077 object_info_tbl = 3078 GET_IMAGE(ATOM_OBJECT_HEADER, bp->object_info_tbl_offset); 3079 3080 if (!object_info_tbl) 3081 return false; 3082 3083 get_atom_data_table_revision(&object_info_tbl->sHeader, 3084 &bp->object_info_tbl.revision); 3085 3086 if (bp->object_info_tbl.revision.major == 1 3087 && bp->object_info_tbl.revision.minor >= 3) { 3088 ATOM_OBJECT_HEADER_V3 *tbl_v3; 3089 3090 tbl_v3 = GET_IMAGE(ATOM_OBJECT_HEADER_V3, 3091 bp->object_info_tbl_offset); 3092 if (!tbl_v3) 3093 return false; 3094 3095 bp->object_info_tbl.v1_3 = tbl_v3; 3096 } else if (bp->object_info_tbl.revision.major == 1 3097 && bp->object_info_tbl.revision.minor >= 1) 3098 bp->object_info_tbl.v1_1 = object_info_tbl; 3099 else 3100 return false; 3101 3102 dal_bios_parser_init_cmd_tbl(bp); 3103 dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version); 3104 3105 bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base); 3106 bp->base.fw_info_valid = bios_parser_get_firmware_info(&bp->base, &bp->base.fw_info) == BP_RESULT_OK; 3107 3108 return true; 3109 } 3110 3111 /******************************************************************************/ 3112