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