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