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