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