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