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