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