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