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