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