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