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