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 "dm_services.h" 27 28 #include "atom.h" 29 30 #include "dc_bios_types.h" 31 #include "include/gpio_service_interface.h" 32 #include "include/grph_object_ctrl_defs.h" 33 #include "include/bios_parser_interface.h" 34 #include "include/i2caux_interface.h" 35 #include "include/logger_interface.h" 36 37 #include "command_table.h" 38 #include "bios_parser_helper.h" 39 #include "command_table_helper.h" 40 #include "bios_parser.h" 41 #include "bios_parser_types_internal.h" 42 #include "bios_parser_interface.h" 43 44 #include "bios_parser_common.h" 45 /* TODO remove - only needed for default i2c speed */ 46 #include "dc.h" 47 48 #define THREE_PERCENT_OF_10000 300 49 50 #define LAST_RECORD_TYPE 0xff 51 52 /* GUID to validate external display connection info table (aka OPM module) */ 53 static const uint8_t ext_display_connection_guid[NUMBER_OF_UCHAR_FOR_GUID] = { 54 0x91, 0x6E, 0x57, 0x09, 55 0x3F, 0x6D, 0xD2, 0x11, 56 0x39, 0x8E, 0x00, 0xA0, 57 0xC9, 0x69, 0x72, 0x3B}; 58 59 #define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table) 60 61 static void get_atom_data_table_revision( 62 ATOM_COMMON_TABLE_HEADER *atom_data_tbl, 63 struct atom_data_revision *tbl_revision); 64 static uint32_t get_dst_number_from_object(struct bios_parser *bp, 65 ATOM_OBJECT *object); 66 static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object, 67 uint16_t **id_list); 68 static uint32_t get_dest_obj_list(struct bios_parser *bp, 69 ATOM_OBJECT *object, uint16_t **id_list); 70 static ATOM_OBJECT *get_bios_object(struct bios_parser *bp, 71 struct graphics_object_id id); 72 static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, 73 ATOM_I2C_RECORD *record, 74 struct graphics_object_i2c_info *info); 75 static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, 76 ATOM_OBJECT *object); 77 static struct device_id device_type_from_device_id(uint16_t device_id); 78 static uint32_t signal_to_ss_id(enum as_signal_type signal); 79 static uint32_t get_support_mask_for_device_id(struct device_id device_id); 80 static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record( 81 struct bios_parser *bp, 82 ATOM_OBJECT *object); 83 84 #define BIOS_IMAGE_SIZE_OFFSET 2 85 #define BIOS_IMAGE_SIZE_UNIT 512 86 87 /*****************************************************************************/ 88 static bool bios_parser_construct( 89 struct bios_parser *bp, 90 struct bp_init_data *init, 91 enum dce_version dce_version); 92 93 static uint8_t bios_parser_get_connectors_number( 94 struct dc_bios *dcb); 95 96 static enum bp_result bios_parser_get_embedded_panel_info( 97 struct dc_bios *dcb, 98 struct embedded_panel_info *info); 99 100 /*****************************************************************************/ 101 102 struct dc_bios *bios_parser_create( 103 struct bp_init_data *init, 104 enum dce_version dce_version) 105 { 106 struct bios_parser *bp = NULL; 107 108 bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL); 109 if (!bp) 110 return NULL; 111 112 if (bios_parser_construct(bp, init, dce_version)) 113 return &bp->base; 114 115 kfree(bp); 116 BREAK_TO_DEBUGGER(); 117 return NULL; 118 } 119 120 static void destruct(struct bios_parser *bp) 121 { 122 kfree(bp->base.bios_local_image); 123 kfree(bp->base.integrated_info); 124 } 125 126 static void bios_parser_destroy(struct dc_bios **dcb) 127 { 128 struct bios_parser *bp = BP_FROM_DCB(*dcb); 129 130 if (!bp) { 131 BREAK_TO_DEBUGGER(); 132 return; 133 } 134 135 destruct(bp); 136 137 kfree(bp); 138 *dcb = NULL; 139 } 140 141 static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset) 142 { 143 ATOM_OBJECT_TABLE *table; 144 145 uint32_t object_table_offset = bp->object_info_tbl_offset + offset; 146 147 table = GET_IMAGE(ATOM_OBJECT_TABLE, object_table_offset); 148 149 if (!table) 150 return 0; 151 else 152 return table->ucNumberOfObjects; 153 } 154 155 static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb) 156 { 157 struct bios_parser *bp = BP_FROM_DCB(dcb); 158 159 return get_number_of_objects(bp, 160 le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset)); 161 } 162 163 static struct graphics_object_id bios_parser_get_encoder_id( 164 struct dc_bios *dcb, 165 uint32_t i) 166 { 167 struct bios_parser *bp = BP_FROM_DCB(dcb); 168 struct graphics_object_id object_id = dal_graphics_object_id_init( 169 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN); 170 171 uint32_t encoder_table_offset = bp->object_info_tbl_offset 172 + le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset); 173 174 ATOM_OBJECT_TABLE *tbl = 175 GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset); 176 177 if (tbl && tbl->ucNumberOfObjects > i) { 178 const uint16_t id = le16_to_cpu(tbl->asObjects[i].usObjectID); 179 180 object_id = object_id_from_bios_object_id(id); 181 } 182 183 return object_id; 184 } 185 186 static struct graphics_object_id bios_parser_get_connector_id( 187 struct dc_bios *dcb, 188 uint8_t i) 189 { 190 struct bios_parser *bp = BP_FROM_DCB(dcb); 191 struct graphics_object_id object_id = dal_graphics_object_id_init( 192 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN); 193 uint16_t id; 194 195 uint32_t connector_table_offset = bp->object_info_tbl_offset 196 + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); 197 198 ATOM_OBJECT_TABLE *tbl = 199 GET_IMAGE(ATOM_OBJECT_TABLE, connector_table_offset); 200 201 if (!tbl) { 202 dm_error("Can't get connector table from atom bios.\n"); 203 return object_id; 204 } 205 206 if (tbl->ucNumberOfObjects <= i) { 207 dm_error("Can't find connector id %d in connector table of size %d.\n", 208 i, tbl->ucNumberOfObjects); 209 return object_id; 210 } 211 212 id = le16_to_cpu(tbl->asObjects[i].usObjectID); 213 object_id = object_id_from_bios_object_id(id); 214 return object_id; 215 } 216 217 static uint32_t bios_parser_get_dst_number(struct dc_bios *dcb, 218 struct graphics_object_id id) 219 { 220 struct bios_parser *bp = BP_FROM_DCB(dcb); 221 ATOM_OBJECT *object = get_bios_object(bp, id); 222 223 return get_dst_number_from_object(bp, object); 224 } 225 226 static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb, 227 struct graphics_object_id object_id, uint32_t index, 228 struct graphics_object_id *src_object_id) 229 { 230 uint32_t number; 231 uint16_t *id; 232 ATOM_OBJECT *object; 233 struct bios_parser *bp = BP_FROM_DCB(dcb); 234 235 if (!src_object_id) 236 return BP_RESULT_BADINPUT; 237 238 object = get_bios_object(bp, object_id); 239 240 if (!object) { 241 BREAK_TO_DEBUGGER(); /* Invalid object id */ 242 return BP_RESULT_BADINPUT; 243 } 244 245 number = get_src_obj_list(bp, object, &id); 246 247 if (number <= index) 248 return BP_RESULT_BADINPUT; 249 250 *src_object_id = object_id_from_bios_object_id(id[index]); 251 252 return BP_RESULT_OK; 253 } 254 255 static enum bp_result bios_parser_get_dst_obj(struct dc_bios *dcb, 256 struct graphics_object_id object_id, uint32_t index, 257 struct graphics_object_id *dest_object_id) 258 { 259 uint32_t number; 260 uint16_t *id = NULL; 261 ATOM_OBJECT *object; 262 struct bios_parser *bp = BP_FROM_DCB(dcb); 263 264 if (!dest_object_id) 265 return BP_RESULT_BADINPUT; 266 267 object = get_bios_object(bp, object_id); 268 269 number = get_dest_obj_list(bp, object, &id); 270 271 if (number <= index || !id) 272 return BP_RESULT_BADINPUT; 273 274 *dest_object_id = object_id_from_bios_object_id(id[index]); 275 276 return BP_RESULT_OK; 277 } 278 279 static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb, 280 struct graphics_object_id id, 281 struct graphics_object_i2c_info *info) 282 { 283 uint32_t offset; 284 ATOM_OBJECT *object; 285 ATOM_COMMON_RECORD_HEADER *header; 286 ATOM_I2C_RECORD *record; 287 struct bios_parser *bp = BP_FROM_DCB(dcb); 288 289 if (!info) 290 return BP_RESULT_BADINPUT; 291 292 object = get_bios_object(bp, id); 293 294 if (!object) 295 return BP_RESULT_BADINPUT; 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 if (LAST_RECORD_TYPE == header->ucRecordType || 307 !header->ucRecordSize) 308 break; 309 310 if (ATOM_I2C_RECORD_TYPE == header->ucRecordType 311 && sizeof(ATOM_I2C_RECORD) <= header->ucRecordSize) { 312 /* get the I2C info */ 313 record = (ATOM_I2C_RECORD *) header; 314 315 if (get_gpio_i2c_info(bp, record, info) == BP_RESULT_OK) 316 return BP_RESULT_OK; 317 } 318 319 offset += header->ucRecordSize; 320 } 321 322 return BP_RESULT_NORECORD; 323 } 324 325 static enum bp_result get_voltage_ddc_info_v1(uint8_t *i2c_line, 326 ATOM_COMMON_TABLE_HEADER *header, 327 uint8_t *address) 328 { 329 enum bp_result result = BP_RESULT_NORECORD; 330 ATOM_VOLTAGE_OBJECT_INFO *info = 331 (ATOM_VOLTAGE_OBJECT_INFO *) address; 332 333 uint8_t *voltage_current_object = (uint8_t *) &info->asVoltageObj[0]; 334 335 while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) { 336 ATOM_VOLTAGE_OBJECT *object = 337 (ATOM_VOLTAGE_OBJECT *) voltage_current_object; 338 339 if ((object->ucVoltageType == SET_VOLTAGE_INIT_MODE) && 340 (object->ucVoltageType & 341 VOLTAGE_CONTROLLED_BY_I2C_MASK)) { 342 343 *i2c_line = object->asControl.ucVoltageControlI2cLine 344 ^ 0x90; 345 result = BP_RESULT_OK; 346 break; 347 } 348 349 voltage_current_object += object->ucSize; 350 } 351 return result; 352 } 353 354 static enum bp_result get_voltage_ddc_info_v3(uint8_t *i2c_line, 355 uint32_t index, 356 ATOM_COMMON_TABLE_HEADER *header, 357 uint8_t *address) 358 { 359 enum bp_result result = BP_RESULT_NORECORD; 360 ATOM_VOLTAGE_OBJECT_INFO_V3_1 *info = 361 (ATOM_VOLTAGE_OBJECT_INFO_V3_1 *) address; 362 363 uint8_t *voltage_current_object = 364 (uint8_t *) (&(info->asVoltageObj[0])); 365 366 while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) { 367 ATOM_I2C_VOLTAGE_OBJECT_V3 *object = 368 (ATOM_I2C_VOLTAGE_OBJECT_V3 *) voltage_current_object; 369 370 if (object->sHeader.ucVoltageMode == 371 ATOM_INIT_VOLTAGE_REGULATOR) { 372 if (object->sHeader.ucVoltageType == index) { 373 *i2c_line = object->ucVoltageControlI2cLine 374 ^ 0x90; 375 result = BP_RESULT_OK; 376 break; 377 } 378 } 379 380 voltage_current_object += le16_to_cpu(object->sHeader.usSize); 381 } 382 return result; 383 } 384 385 static enum bp_result bios_parser_get_thermal_ddc_info( 386 struct dc_bios *dcb, 387 uint32_t i2c_channel_id, 388 struct graphics_object_i2c_info *info) 389 { 390 struct bios_parser *bp = BP_FROM_DCB(dcb); 391 ATOM_I2C_ID_CONFIG_ACCESS *config; 392 ATOM_I2C_RECORD record; 393 394 if (!info) 395 return BP_RESULT_BADINPUT; 396 397 config = (ATOM_I2C_ID_CONFIG_ACCESS *) &i2c_channel_id; 398 399 record.sucI2cId.bfHW_Capable = config->sbfAccess.bfHW_Capable; 400 record.sucI2cId.bfI2C_LineMux = config->sbfAccess.bfI2C_LineMux; 401 record.sucI2cId.bfHW_EngineID = config->sbfAccess.bfHW_EngineID; 402 403 return get_gpio_i2c_info(bp, &record, info); 404 } 405 406 static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb, 407 uint32_t index, 408 struct graphics_object_i2c_info *info) 409 { 410 uint8_t i2c_line = 0; 411 enum bp_result result = BP_RESULT_NORECORD; 412 uint8_t *voltage_info_address; 413 ATOM_COMMON_TABLE_HEADER *header; 414 struct atom_data_revision revision = {0}; 415 struct bios_parser *bp = BP_FROM_DCB(dcb); 416 417 if (!DATA_TABLES(VoltageObjectInfo)) 418 return result; 419 420 voltage_info_address = bios_get_image(&bp->base, DATA_TABLES(VoltageObjectInfo), sizeof(ATOM_COMMON_TABLE_HEADER)); 421 422 header = (ATOM_COMMON_TABLE_HEADER *) voltage_info_address; 423 424 get_atom_data_table_revision(header, &revision); 425 426 switch (revision.major) { 427 case 1: 428 case 2: 429 result = get_voltage_ddc_info_v1(&i2c_line, header, 430 voltage_info_address); 431 break; 432 case 3: 433 if (revision.minor != 1) 434 break; 435 result = get_voltage_ddc_info_v3(&i2c_line, index, header, 436 voltage_info_address); 437 break; 438 } 439 440 if (result == BP_RESULT_OK) 441 result = bios_parser_get_thermal_ddc_info(dcb, 442 i2c_line, info); 443 444 return result; 445 } 446 447 /* TODO: temporary commented out to suppress 'defined but not used' warning */ 448 #if 0 449 static enum bp_result bios_parser_get_ddc_info_for_i2c_line( 450 struct bios_parser *bp, 451 uint8_t i2c_line, struct graphics_object_i2c_info *info) 452 { 453 uint32_t offset; 454 ATOM_OBJECT *object; 455 ATOM_OBJECT_TABLE *table; 456 uint32_t i; 457 458 if (!info) 459 return BP_RESULT_BADINPUT; 460 461 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); 462 463 offset += bp->object_info_tbl_offset; 464 465 table = GET_IMAGE(ATOM_OBJECT_TABLE, offset); 466 467 if (!table) 468 return BP_RESULT_BADBIOSTABLE; 469 470 for (i = 0; i < table->ucNumberOfObjects; i++) { 471 object = &table->asObjects[i]; 472 473 if (!object) { 474 BREAK_TO_DEBUGGER(); /* Invalid object id */ 475 return BP_RESULT_BADINPUT; 476 } 477 478 offset = le16_to_cpu(object->usRecordOffset) 479 + bp->object_info_tbl_offset; 480 481 for (;;) { 482 ATOM_COMMON_RECORD_HEADER *header = 483 GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); 484 485 if (!header) 486 return BP_RESULT_BADBIOSTABLE; 487 488 offset += header->ucRecordSize; 489 490 if (LAST_RECORD_TYPE == header->ucRecordType || 491 !header->ucRecordSize) 492 break; 493 494 if (ATOM_I2C_RECORD_TYPE == header->ucRecordType 495 && sizeof(ATOM_I2C_RECORD) <= 496 header->ucRecordSize) { 497 ATOM_I2C_RECORD *record = 498 (ATOM_I2C_RECORD *) header; 499 500 if (i2c_line != record->sucI2cId.bfI2C_LineMux) 501 continue; 502 503 /* get the I2C info */ 504 if (get_gpio_i2c_info(bp, record, info) == 505 BP_RESULT_OK) 506 return BP_RESULT_OK; 507 } 508 } 509 } 510 511 return BP_RESULT_NORECORD; 512 } 513 #endif 514 515 static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb, 516 struct graphics_object_id id, 517 struct graphics_object_hpd_info *info) 518 { 519 struct bios_parser *bp = BP_FROM_DCB(dcb); 520 ATOM_OBJECT *object; 521 ATOM_HPD_INT_RECORD *record = NULL; 522 523 if (!info) 524 return BP_RESULT_BADINPUT; 525 526 object = get_bios_object(bp, id); 527 528 if (!object) 529 return BP_RESULT_BADINPUT; 530 531 record = get_hpd_record(bp, object); 532 533 if (record != NULL) { 534 info->hpd_int_gpio_uid = record->ucHPDIntGPIOID; 535 info->hpd_active = record->ucPlugged_PinState; 536 return BP_RESULT_OK; 537 } 538 539 return BP_RESULT_NORECORD; 540 } 541 542 static enum bp_result bios_parser_get_device_tag_record( 543 struct bios_parser *bp, 544 ATOM_OBJECT *object, 545 ATOM_CONNECTOR_DEVICE_TAG_RECORD **record) 546 { 547 ATOM_COMMON_RECORD_HEADER *header; 548 uint32_t offset; 549 550 offset = le16_to_cpu(object->usRecordOffset) 551 + bp->object_info_tbl_offset; 552 553 for (;;) { 554 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); 555 556 if (!header) 557 return BP_RESULT_BADBIOSTABLE; 558 559 offset += header->ucRecordSize; 560 561 if (LAST_RECORD_TYPE == header->ucRecordType || 562 !header->ucRecordSize) 563 break; 564 565 if (ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE != 566 header->ucRecordType) 567 continue; 568 569 if (sizeof(ATOM_CONNECTOR_DEVICE_TAG) > header->ucRecordSize) 570 continue; 571 572 *record = (ATOM_CONNECTOR_DEVICE_TAG_RECORD *) header; 573 return BP_RESULT_OK; 574 } 575 576 return BP_RESULT_NORECORD; 577 } 578 579 static enum bp_result bios_parser_get_device_tag( 580 struct dc_bios *dcb, 581 struct graphics_object_id connector_object_id, 582 uint32_t device_tag_index, 583 struct connector_device_tag_info *info) 584 { 585 struct bios_parser *bp = BP_FROM_DCB(dcb); 586 ATOM_OBJECT *object; 587 ATOM_CONNECTOR_DEVICE_TAG_RECORD *record = NULL; 588 ATOM_CONNECTOR_DEVICE_TAG *device_tag; 589 590 if (!info) 591 return BP_RESULT_BADINPUT; 592 593 /* getBiosObject will return MXM object */ 594 object = get_bios_object(bp, connector_object_id); 595 596 if (!object) { 597 BREAK_TO_DEBUGGER(); /* Invalid object id */ 598 return BP_RESULT_BADINPUT; 599 } 600 601 if (bios_parser_get_device_tag_record(bp, object, &record) 602 != BP_RESULT_OK) 603 return BP_RESULT_NORECORD; 604 605 if (device_tag_index >= record->ucNumberOfDevice) 606 return BP_RESULT_NORECORD; 607 608 device_tag = &record->asDeviceTag[device_tag_index]; 609 610 info->acpi_device = le32_to_cpu(device_tag->ulACPIDeviceEnum); 611 info->dev_id = 612 device_type_from_device_id(le16_to_cpu(device_tag->usDeviceID)); 613 614 return BP_RESULT_OK; 615 } 616 617 static enum bp_result get_firmware_info_v1_4( 618 struct bios_parser *bp, 619 struct dc_firmware_info *info); 620 static enum bp_result get_firmware_info_v2_1( 621 struct bios_parser *bp, 622 struct dc_firmware_info *info); 623 static enum bp_result get_firmware_info_v2_2( 624 struct bios_parser *bp, 625 struct dc_firmware_info *info); 626 627 static enum bp_result bios_parser_get_firmware_info( 628 struct dc_bios *dcb, 629 struct dc_firmware_info *info) 630 { 631 struct bios_parser *bp = BP_FROM_DCB(dcb); 632 enum bp_result result = BP_RESULT_BADBIOSTABLE; 633 ATOM_COMMON_TABLE_HEADER *header; 634 struct atom_data_revision revision; 635 636 if (info && DATA_TABLES(FirmwareInfo)) { 637 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, 638 DATA_TABLES(FirmwareInfo)); 639 get_atom_data_table_revision(header, &revision); 640 switch (revision.major) { 641 case 1: 642 switch (revision.minor) { 643 case 4: 644 result = get_firmware_info_v1_4(bp, info); 645 break; 646 default: 647 break; 648 } 649 break; 650 651 case 2: 652 switch (revision.minor) { 653 case 1: 654 result = get_firmware_info_v2_1(bp, info); 655 break; 656 case 2: 657 result = get_firmware_info_v2_2(bp, info); 658 break; 659 default: 660 break; 661 } 662 break; 663 default: 664 break; 665 } 666 } 667 668 return result; 669 } 670 671 static enum bp_result get_firmware_info_v1_4( 672 struct bios_parser *bp, 673 struct dc_firmware_info *info) 674 { 675 ATOM_FIRMWARE_INFO_V1_4 *firmware_info = 676 GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4, 677 DATA_TABLES(FirmwareInfo)); 678 679 if (!info) 680 return BP_RESULT_BADINPUT; 681 682 if (!firmware_info) 683 return BP_RESULT_BADBIOSTABLE; 684 685 memset(info, 0, sizeof(*info)); 686 687 /* Pixel clock pll information. We need to convert from 10KHz units into 688 * KHz units */ 689 info->pll_info.crystal_frequency = 690 le16_to_cpu(firmware_info->usReferenceClock) * 10; 691 info->pll_info.min_input_pxl_clk_pll_frequency = 692 le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10; 693 info->pll_info.max_input_pxl_clk_pll_frequency = 694 le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10; 695 info->pll_info.min_output_pxl_clk_pll_frequency = 696 le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10; 697 info->pll_info.max_output_pxl_clk_pll_frequency = 698 le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10; 699 700 if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support) 701 /* Since there is no information on the SS, report conservative 702 * value 3% for bandwidth calculation */ 703 /* unit of 0.01% */ 704 info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000; 705 706 if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support) 707 /* Since there is no information on the SS,report conservative 708 * value 3% for bandwidth calculation */ 709 /* unit of 0.01% */ 710 info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000; 711 712 return BP_RESULT_OK; 713 } 714 715 static enum bp_result get_ss_info_v3_1( 716 struct bios_parser *bp, 717 uint32_t id, 718 uint32_t index, 719 struct spread_spectrum_info *ss_info); 720 721 static enum bp_result get_firmware_info_v2_1( 722 struct bios_parser *bp, 723 struct dc_firmware_info *info) 724 { 725 ATOM_FIRMWARE_INFO_V2_1 *firmwareInfo = 726 GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1, DATA_TABLES(FirmwareInfo)); 727 struct spread_spectrum_info internalSS; 728 uint32_t index; 729 730 if (!info) 731 return BP_RESULT_BADINPUT; 732 733 if (!firmwareInfo) 734 return BP_RESULT_BADBIOSTABLE; 735 736 memset(info, 0, sizeof(*info)); 737 738 /* Pixel clock pll information. We need to convert from 10KHz units into 739 * KHz units */ 740 info->pll_info.crystal_frequency = 741 le16_to_cpu(firmwareInfo->usCoreReferenceClock) * 10; 742 info->pll_info.min_input_pxl_clk_pll_frequency = 743 le16_to_cpu(firmwareInfo->usMinPixelClockPLL_Input) * 10; 744 info->pll_info.max_input_pxl_clk_pll_frequency = 745 le16_to_cpu(firmwareInfo->usMaxPixelClockPLL_Input) * 10; 746 info->pll_info.min_output_pxl_clk_pll_frequency = 747 le32_to_cpu(firmwareInfo->ulMinPixelClockPLL_Output) * 10; 748 info->pll_info.max_output_pxl_clk_pll_frequency = 749 le32_to_cpu(firmwareInfo->ulMaxPixelClockPLL_Output) * 10; 750 info->default_display_engine_pll_frequency = 751 le32_to_cpu(firmwareInfo->ulDefaultDispEngineClkFreq) * 10; 752 info->external_clock_source_frequency_for_dp = 753 le16_to_cpu(firmwareInfo->usUniphyDPModeExtClkFreq) * 10; 754 info->min_allowed_bl_level = firmwareInfo->ucMinAllowedBL_Level; 755 756 /* There should be only one entry in the SS info table for Memory Clock 757 */ 758 index = 0; 759 if (firmwareInfo->usFirmwareCapability.sbfAccess.MemoryClockSS_Support) 760 /* Since there is no information for external SS, report 761 * conservative value 3% for bandwidth calculation */ 762 /* unit of 0.01% */ 763 info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000; 764 else if (get_ss_info_v3_1(bp, 765 ASIC_INTERNAL_MEMORY_SS, index, &internalSS) == BP_RESULT_OK) { 766 if (internalSS.spread_spectrum_percentage) { 767 info->feature.memory_clk_ss_percentage = 768 internalSS.spread_spectrum_percentage; 769 if (internalSS.type.CENTER_MODE) { 770 /* if it is centermode, the exact SS Percentage 771 * will be round up of half of the percentage 772 * reported in the SS table */ 773 ++info->feature.memory_clk_ss_percentage; 774 info->feature.memory_clk_ss_percentage /= 2; 775 } 776 } 777 } 778 779 /* There should be only one entry in the SS info table for Engine Clock 780 */ 781 index = 1; 782 if (firmwareInfo->usFirmwareCapability.sbfAccess.EngineClockSS_Support) 783 /* Since there is no information for external SS, report 784 * conservative value 3% for bandwidth calculation */ 785 /* unit of 0.01% */ 786 info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000; 787 else if (get_ss_info_v3_1(bp, 788 ASIC_INTERNAL_ENGINE_SS, index, &internalSS) == BP_RESULT_OK) { 789 if (internalSS.spread_spectrum_percentage) { 790 info->feature.engine_clk_ss_percentage = 791 internalSS.spread_spectrum_percentage; 792 if (internalSS.type.CENTER_MODE) { 793 /* if it is centermode, the exact SS Percentage 794 * will be round up of half of the percentage 795 * reported in the SS table */ 796 ++info->feature.engine_clk_ss_percentage; 797 info->feature.engine_clk_ss_percentage /= 2; 798 } 799 } 800 } 801 802 return BP_RESULT_OK; 803 } 804 805 static enum bp_result get_firmware_info_v2_2( 806 struct bios_parser *bp, 807 struct dc_firmware_info *info) 808 { 809 ATOM_FIRMWARE_INFO_V2_2 *firmware_info; 810 struct spread_spectrum_info internal_ss; 811 uint32_t index; 812 813 if (!info) 814 return BP_RESULT_BADINPUT; 815 816 firmware_info = GET_IMAGE(ATOM_FIRMWARE_INFO_V2_2, 817 DATA_TABLES(FirmwareInfo)); 818 819 if (!firmware_info) 820 return BP_RESULT_BADBIOSTABLE; 821 822 memset(info, 0, sizeof(*info)); 823 824 /* Pixel clock pll information. We need to convert from 10KHz units into 825 * KHz units */ 826 info->pll_info.crystal_frequency = 827 le16_to_cpu(firmware_info->usCoreReferenceClock) * 10; 828 info->pll_info.min_input_pxl_clk_pll_frequency = 829 le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10; 830 info->pll_info.max_input_pxl_clk_pll_frequency = 831 le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10; 832 info->pll_info.min_output_pxl_clk_pll_frequency = 833 le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10; 834 info->pll_info.max_output_pxl_clk_pll_frequency = 835 le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10; 836 info->default_display_engine_pll_frequency = 837 le32_to_cpu(firmware_info->ulDefaultDispEngineClkFreq) * 10; 838 info->external_clock_source_frequency_for_dp = 839 le16_to_cpu(firmware_info->usUniphyDPModeExtClkFreq) * 10; 840 841 /* There should be only one entry in the SS info table for Memory Clock 842 */ 843 index = 0; 844 if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support) 845 /* Since there is no information for external SS, report 846 * conservative value 3% for bandwidth calculation */ 847 /* unit of 0.01% */ 848 info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000; 849 else if (get_ss_info_v3_1(bp, 850 ASIC_INTERNAL_MEMORY_SS, index, &internal_ss) == BP_RESULT_OK) { 851 if (internal_ss.spread_spectrum_percentage) { 852 info->feature.memory_clk_ss_percentage = 853 internal_ss.spread_spectrum_percentage; 854 if (internal_ss.type.CENTER_MODE) { 855 /* if it is centermode, the exact SS Percentage 856 * will be round up of half of the percentage 857 * reported in the SS table */ 858 ++info->feature.memory_clk_ss_percentage; 859 info->feature.memory_clk_ss_percentage /= 2; 860 } 861 } 862 } 863 864 /* There should be only one entry in the SS info table for Engine Clock 865 */ 866 index = 1; 867 if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support) 868 /* Since there is no information for external SS, report 869 * conservative value 3% for bandwidth calculation */ 870 /* unit of 0.01% */ 871 info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000; 872 else if (get_ss_info_v3_1(bp, 873 ASIC_INTERNAL_ENGINE_SS, index, &internal_ss) == BP_RESULT_OK) { 874 if (internal_ss.spread_spectrum_percentage) { 875 info->feature.engine_clk_ss_percentage = 876 internal_ss.spread_spectrum_percentage; 877 if (internal_ss.type.CENTER_MODE) { 878 /* if it is centermode, the exact SS Percentage 879 * will be round up of half of the percentage 880 * reported in the SS table */ 881 ++info->feature.engine_clk_ss_percentage; 882 info->feature.engine_clk_ss_percentage /= 2; 883 } 884 } 885 } 886 887 /* Remote Display */ 888 info->remote_display_config = firmware_info->ucRemoteDisplayConfig; 889 890 /* Is allowed minimum BL level */ 891 info->min_allowed_bl_level = firmware_info->ucMinAllowedBL_Level; 892 /* Used starting from CI */ 893 info->smu_gpu_pll_output_freq = 894 (uint32_t) (le32_to_cpu(firmware_info->ulGPUPLL_OutputFreq) * 10); 895 896 return BP_RESULT_OK; 897 } 898 899 static enum bp_result get_ss_info_v3_1( 900 struct bios_parser *bp, 901 uint32_t id, 902 uint32_t index, 903 struct spread_spectrum_info *ss_info) 904 { 905 ATOM_ASIC_INTERNAL_SS_INFO_V3 *ss_table_header_include; 906 ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl; 907 uint32_t table_size; 908 uint32_t i; 909 uint32_t table_index = 0; 910 911 if (!ss_info) 912 return BP_RESULT_BADINPUT; 913 914 if (!DATA_TABLES(ASIC_InternalSS_Info)) 915 return BP_RESULT_UNSUPPORTED; 916 917 ss_table_header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3, 918 DATA_TABLES(ASIC_InternalSS_Info)); 919 table_size = 920 (le16_to_cpu(ss_table_header_include->sHeader.usStructureSize) 921 - sizeof(ATOM_COMMON_TABLE_HEADER)) 922 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3); 923 924 tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *) 925 &ss_table_header_include->asSpreadSpectrum[0]; 926 927 memset(ss_info, 0, sizeof(struct spread_spectrum_info)); 928 929 for (i = 0; i < table_size; i++) { 930 if (tbl[i].ucClockIndication != (uint8_t) id) 931 continue; 932 933 if (table_index != index) { 934 table_index++; 935 continue; 936 } 937 /* VBIOS introduced new defines for Version 3, same values as 938 * before, so now use these new ones for Version 3. 939 * Shouldn't affect field VBIOS's V3 as define values are still 940 * same. 941 * #define SS_MODE_V3_CENTRE_SPREAD_MASK 0x01 942 * #define SS_MODE_V3_EXTERNAL_SS_MASK 0x02 943 944 * Old VBIOS defines: 945 * #define ATOM_SS_CENTRE_SPREAD_MODE_MASK 0x00000001 946 * #define ATOM_EXTERNAL_SS_MASK 0x00000002 947 */ 948 949 if (SS_MODE_V3_EXTERNAL_SS_MASK & tbl[i].ucSpreadSpectrumMode) 950 ss_info->type.EXTERNAL = true; 951 952 if (SS_MODE_V3_CENTRE_SPREAD_MASK & tbl[i].ucSpreadSpectrumMode) 953 ss_info->type.CENTER_MODE = true; 954 955 /* Older VBIOS (in field) always provides SS percentage in 0.01% 956 * units set Divider to 100 */ 957 ss_info->spread_percentage_divider = 100; 958 959 /* #define SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 0x10 */ 960 if (SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 961 & tbl[i].ucSpreadSpectrumMode) 962 ss_info->spread_percentage_divider = 1000; 963 964 ss_info->type.STEP_AND_DELAY_INFO = false; 965 /* convert [10KHz] into [KHz] */ 966 ss_info->target_clock_range = 967 le32_to_cpu(tbl[i].ulTargetClockRange) * 10; 968 ss_info->spread_spectrum_percentage = 969 (uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage); 970 ss_info->spread_spectrum_range = 971 (uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10); 972 973 return BP_RESULT_OK; 974 } 975 return BP_RESULT_NORECORD; 976 } 977 978 static enum bp_result bios_parser_transmitter_control( 979 struct dc_bios *dcb, 980 struct bp_transmitter_control *cntl) 981 { 982 struct bios_parser *bp = BP_FROM_DCB(dcb); 983 984 if (!bp->cmd_tbl.transmitter_control) 985 return BP_RESULT_FAILURE; 986 987 return bp->cmd_tbl.transmitter_control(bp, cntl); 988 } 989 990 static enum bp_result bios_parser_encoder_control( 991 struct dc_bios *dcb, 992 struct bp_encoder_control *cntl) 993 { 994 struct bios_parser *bp = BP_FROM_DCB(dcb); 995 996 if (!bp->cmd_tbl.dig_encoder_control) 997 return BP_RESULT_FAILURE; 998 999 return bp->cmd_tbl.dig_encoder_control(bp, cntl); 1000 } 1001 1002 static enum bp_result bios_parser_adjust_pixel_clock( 1003 struct dc_bios *dcb, 1004 struct bp_adjust_pixel_clock_parameters *bp_params) 1005 { 1006 struct bios_parser *bp = BP_FROM_DCB(dcb); 1007 1008 if (!bp->cmd_tbl.adjust_display_pll) 1009 return BP_RESULT_FAILURE; 1010 1011 return bp->cmd_tbl.adjust_display_pll(bp, bp_params); 1012 } 1013 1014 static enum bp_result bios_parser_set_pixel_clock( 1015 struct dc_bios *dcb, 1016 struct bp_pixel_clock_parameters *bp_params) 1017 { 1018 struct bios_parser *bp = BP_FROM_DCB(dcb); 1019 1020 if (!bp->cmd_tbl.set_pixel_clock) 1021 return BP_RESULT_FAILURE; 1022 1023 return bp->cmd_tbl.set_pixel_clock(bp, bp_params); 1024 } 1025 1026 static enum bp_result bios_parser_set_dce_clock( 1027 struct dc_bios *dcb, 1028 struct bp_set_dce_clock_parameters *bp_params) 1029 { 1030 struct bios_parser *bp = BP_FROM_DCB(dcb); 1031 1032 if (!bp->cmd_tbl.set_dce_clock) 1033 return BP_RESULT_FAILURE; 1034 1035 return bp->cmd_tbl.set_dce_clock(bp, bp_params); 1036 } 1037 1038 static enum bp_result bios_parser_enable_spread_spectrum_on_ppll( 1039 struct dc_bios *dcb, 1040 struct bp_spread_spectrum_parameters *bp_params, 1041 bool enable) 1042 { 1043 struct bios_parser *bp = BP_FROM_DCB(dcb); 1044 1045 if (!bp->cmd_tbl.enable_spread_spectrum_on_ppll) 1046 return BP_RESULT_FAILURE; 1047 1048 return bp->cmd_tbl.enable_spread_spectrum_on_ppll( 1049 bp, bp_params, enable); 1050 1051 } 1052 1053 static enum bp_result bios_parser_program_crtc_timing( 1054 struct dc_bios *dcb, 1055 struct bp_hw_crtc_timing_parameters *bp_params) 1056 { 1057 struct bios_parser *bp = BP_FROM_DCB(dcb); 1058 1059 if (!bp->cmd_tbl.set_crtc_timing) 1060 return BP_RESULT_FAILURE; 1061 1062 return bp->cmd_tbl.set_crtc_timing(bp, bp_params); 1063 } 1064 1065 static enum bp_result bios_parser_program_display_engine_pll( 1066 struct dc_bios *dcb, 1067 struct bp_pixel_clock_parameters *bp_params) 1068 { 1069 struct bios_parser *bp = BP_FROM_DCB(dcb); 1070 1071 if (!bp->cmd_tbl.program_clock) 1072 return BP_RESULT_FAILURE; 1073 1074 return bp->cmd_tbl.program_clock(bp, bp_params); 1075 1076 } 1077 1078 1079 static enum bp_result bios_parser_enable_crtc( 1080 struct dc_bios *dcb, 1081 enum controller_id id, 1082 bool enable) 1083 { 1084 struct bios_parser *bp = BP_FROM_DCB(dcb); 1085 1086 if (!bp->cmd_tbl.enable_crtc) 1087 return BP_RESULT_FAILURE; 1088 1089 return bp->cmd_tbl.enable_crtc(bp, id, enable); 1090 } 1091 1092 static enum bp_result bios_parser_crtc_source_select( 1093 struct dc_bios *dcb, 1094 struct bp_crtc_source_select *bp_params) 1095 { 1096 struct bios_parser *bp = BP_FROM_DCB(dcb); 1097 1098 if (!bp->cmd_tbl.select_crtc_source) 1099 return BP_RESULT_FAILURE; 1100 1101 return bp->cmd_tbl.select_crtc_source(bp, bp_params); 1102 } 1103 1104 static enum bp_result bios_parser_enable_disp_power_gating( 1105 struct dc_bios *dcb, 1106 enum controller_id controller_id, 1107 enum bp_pipe_control_action action) 1108 { 1109 struct bios_parser *bp = BP_FROM_DCB(dcb); 1110 1111 if (!bp->cmd_tbl.enable_disp_power_gating) 1112 return BP_RESULT_FAILURE; 1113 1114 return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id, 1115 action); 1116 } 1117 1118 static bool bios_parser_is_device_id_supported( 1119 struct dc_bios *dcb, 1120 struct device_id id) 1121 { 1122 struct bios_parser *bp = BP_FROM_DCB(dcb); 1123 1124 uint32_t mask = get_support_mask_for_device_id(id); 1125 1126 return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0; 1127 } 1128 1129 static enum bp_result bios_parser_crt_control( 1130 struct dc_bios *dcb, 1131 enum engine_id engine_id, 1132 bool enable, 1133 uint32_t pixel_clock) 1134 { 1135 struct bios_parser *bp = BP_FROM_DCB(dcb); 1136 uint8_t standard; 1137 1138 if (!bp->cmd_tbl.dac1_encoder_control && 1139 engine_id == ENGINE_ID_DACA) 1140 return BP_RESULT_FAILURE; 1141 if (!bp->cmd_tbl.dac2_encoder_control && 1142 engine_id == ENGINE_ID_DACB) 1143 return BP_RESULT_FAILURE; 1144 /* validate params */ 1145 switch (engine_id) { 1146 case ENGINE_ID_DACA: 1147 case ENGINE_ID_DACB: 1148 break; 1149 default: 1150 /* unsupported engine */ 1151 return BP_RESULT_FAILURE; 1152 } 1153 1154 standard = ATOM_DAC1_PS2; /* == ATOM_DAC2_PS2 */ 1155 1156 if (enable) { 1157 if (engine_id == ENGINE_ID_DACA) { 1158 bp->cmd_tbl.dac1_encoder_control(bp, enable, 1159 pixel_clock, standard); 1160 if (bp->cmd_tbl.dac1_output_control != NULL) 1161 bp->cmd_tbl.dac1_output_control(bp, enable); 1162 } else { 1163 bp->cmd_tbl.dac2_encoder_control(bp, enable, 1164 pixel_clock, standard); 1165 if (bp->cmd_tbl.dac2_output_control != NULL) 1166 bp->cmd_tbl.dac2_output_control(bp, enable); 1167 } 1168 } else { 1169 if (engine_id == ENGINE_ID_DACA) { 1170 if (bp->cmd_tbl.dac1_output_control != NULL) 1171 bp->cmd_tbl.dac1_output_control(bp, enable); 1172 bp->cmd_tbl.dac1_encoder_control(bp, enable, 1173 pixel_clock, standard); 1174 } else { 1175 if (bp->cmd_tbl.dac2_output_control != NULL) 1176 bp->cmd_tbl.dac2_output_control(bp, enable); 1177 bp->cmd_tbl.dac2_encoder_control(bp, enable, 1178 pixel_clock, standard); 1179 } 1180 } 1181 1182 return BP_RESULT_OK; 1183 } 1184 1185 static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, 1186 ATOM_OBJECT *object) 1187 { 1188 ATOM_COMMON_RECORD_HEADER *header; 1189 uint32_t offset; 1190 1191 if (!object) { 1192 BREAK_TO_DEBUGGER(); /* Invalid object */ 1193 return NULL; 1194 } 1195 1196 offset = le16_to_cpu(object->usRecordOffset) 1197 + bp->object_info_tbl_offset; 1198 1199 for (;;) { 1200 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); 1201 1202 if (!header) 1203 return NULL; 1204 1205 if (LAST_RECORD_TYPE == header->ucRecordType || 1206 !header->ucRecordSize) 1207 break; 1208 1209 if (ATOM_HPD_INT_RECORD_TYPE == header->ucRecordType 1210 && sizeof(ATOM_HPD_INT_RECORD) <= header->ucRecordSize) 1211 return (ATOM_HPD_INT_RECORD *) header; 1212 1213 offset += header->ucRecordSize; 1214 } 1215 1216 return NULL; 1217 } 1218 1219 /** 1220 * Get I2C information of input object id 1221 * 1222 * search all records to find the ATOM_I2C_RECORD_TYPE record IR 1223 */ 1224 static ATOM_I2C_RECORD *get_i2c_record( 1225 struct bios_parser *bp, 1226 ATOM_OBJECT *object) 1227 { 1228 uint32_t offset; 1229 ATOM_COMMON_RECORD_HEADER *record_header; 1230 1231 if (!object) { 1232 BREAK_TO_DEBUGGER(); 1233 /* Invalid object */ 1234 return NULL; 1235 } 1236 1237 offset = le16_to_cpu(object->usRecordOffset) 1238 + bp->object_info_tbl_offset; 1239 1240 for (;;) { 1241 record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); 1242 1243 if (!record_header) 1244 return NULL; 1245 1246 if (LAST_RECORD_TYPE == record_header->ucRecordType || 1247 0 == record_header->ucRecordSize) 1248 break; 1249 1250 if (ATOM_I2C_RECORD_TYPE == record_header->ucRecordType && 1251 sizeof(ATOM_I2C_RECORD) <= 1252 record_header->ucRecordSize) { 1253 return (ATOM_I2C_RECORD *)record_header; 1254 } 1255 1256 offset += record_header->ucRecordSize; 1257 } 1258 1259 return NULL; 1260 } 1261 1262 static enum bp_result get_ss_info_from_ss_info_table( 1263 struct bios_parser *bp, 1264 uint32_t id, 1265 struct spread_spectrum_info *ss_info); 1266 static enum bp_result get_ss_info_from_tbl( 1267 struct bios_parser *bp, 1268 uint32_t id, 1269 struct spread_spectrum_info *ss_info); 1270 /** 1271 * bios_parser_get_spread_spectrum_info 1272 * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or 1273 * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info 1274 * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info ver 3.1, 1275 * there is only one entry for each signal /ss id. However, there is 1276 * no planning of supporting multiple spread Sprectum entry for EverGreen 1277 * @param [in] this 1278 * @param [in] signal, ASSignalType to be converted to info index 1279 * @param [in] index, number of entries that match the converted info index 1280 * @param [out] ss_info, sprectrum information structure, 1281 * @return Bios parser result code 1282 */ 1283 static enum bp_result bios_parser_get_spread_spectrum_info( 1284 struct dc_bios *dcb, 1285 enum as_signal_type signal, 1286 uint32_t index, 1287 struct spread_spectrum_info *ss_info) 1288 { 1289 struct bios_parser *bp = BP_FROM_DCB(dcb); 1290 enum bp_result result = BP_RESULT_UNSUPPORTED; 1291 uint32_t clk_id_ss = 0; 1292 ATOM_COMMON_TABLE_HEADER *header; 1293 struct atom_data_revision tbl_revision; 1294 1295 if (!ss_info) /* check for bad input */ 1296 return BP_RESULT_BADINPUT; 1297 /* signal translation */ 1298 clk_id_ss = signal_to_ss_id(signal); 1299 1300 if (!DATA_TABLES(ASIC_InternalSS_Info)) 1301 if (!index) 1302 return get_ss_info_from_ss_info_table(bp, clk_id_ss, 1303 ss_info); 1304 1305 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, 1306 DATA_TABLES(ASIC_InternalSS_Info)); 1307 get_atom_data_table_revision(header, &tbl_revision); 1308 1309 switch (tbl_revision.major) { 1310 case 2: 1311 switch (tbl_revision.minor) { 1312 case 1: 1313 /* there can not be more then one entry for Internal 1314 * SS Info table version 2.1 */ 1315 if (!index) 1316 return get_ss_info_from_tbl(bp, clk_id_ss, 1317 ss_info); 1318 break; 1319 default: 1320 break; 1321 } 1322 break; 1323 1324 case 3: 1325 switch (tbl_revision.minor) { 1326 case 1: 1327 return get_ss_info_v3_1(bp, clk_id_ss, index, ss_info); 1328 default: 1329 break; 1330 } 1331 break; 1332 default: 1333 break; 1334 } 1335 /* there can not be more then one entry for SS Info table */ 1336 return result; 1337 } 1338 1339 static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1( 1340 struct bios_parser *bp, 1341 uint32_t id, 1342 struct spread_spectrum_info *info); 1343 1344 /** 1345 * get_ss_info_from_table 1346 * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or 1347 * SS_Info table from the VBIOS 1348 * There can not be more than 1 entry for ASIC_InternalSS_Info Ver 2.1 or 1349 * SS_Info. 1350 * 1351 * @param this 1352 * @param id, spread sprectrum info index 1353 * @param pSSinfo, sprectrum information structure, 1354 * @return Bios parser result code 1355 */ 1356 static enum bp_result get_ss_info_from_tbl( 1357 struct bios_parser *bp, 1358 uint32_t id, 1359 struct spread_spectrum_info *ss_info) 1360 { 1361 if (!ss_info) /* check for bad input, if ss_info is not NULL */ 1362 return BP_RESULT_BADINPUT; 1363 /* for SS_Info table only support DP and LVDS */ 1364 if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS) 1365 return get_ss_info_from_ss_info_table(bp, id, ss_info); 1366 else 1367 return get_ss_info_from_internal_ss_info_tbl_V2_1(bp, id, 1368 ss_info); 1369 } 1370 1371 /** 1372 * get_ss_info_from_internal_ss_info_tbl_V2_1 1373 * Get spread sprectrum information from the ASIC_InternalSS_Info table Ver 2.1 1374 * from the VBIOS 1375 * There will not be multiple entry for Ver 2.1 1376 * 1377 * @param id, spread sprectrum info index 1378 * @param pSSinfo, sprectrum information structure, 1379 * @return Bios parser result code 1380 */ 1381 static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1( 1382 struct bios_parser *bp, 1383 uint32_t id, 1384 struct spread_spectrum_info *info) 1385 { 1386 enum bp_result result = BP_RESULT_UNSUPPORTED; 1387 ATOM_ASIC_INTERNAL_SS_INFO_V2 *header; 1388 ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl; 1389 uint32_t tbl_size, i; 1390 1391 if (!DATA_TABLES(ASIC_InternalSS_Info)) 1392 return result; 1393 1394 header = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2, 1395 DATA_TABLES(ASIC_InternalSS_Info)); 1396 1397 memset(info, 0, sizeof(struct spread_spectrum_info)); 1398 1399 tbl_size = (le16_to_cpu(header->sHeader.usStructureSize) 1400 - sizeof(ATOM_COMMON_TABLE_HEADER)) 1401 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2); 1402 1403 tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *) 1404 &(header->asSpreadSpectrum[0]); 1405 for (i = 0; i < tbl_size; i++) { 1406 result = BP_RESULT_NORECORD; 1407 1408 if (tbl[i].ucClockIndication != (uint8_t)id) 1409 continue; 1410 1411 if (ATOM_EXTERNAL_SS_MASK 1412 & tbl[i].ucSpreadSpectrumMode) { 1413 info->type.EXTERNAL = true; 1414 } 1415 if (ATOM_SS_CENTRE_SPREAD_MODE_MASK 1416 & tbl[i].ucSpreadSpectrumMode) { 1417 info->type.CENTER_MODE = true; 1418 } 1419 info->type.STEP_AND_DELAY_INFO = false; 1420 /* convert [10KHz] into [KHz] */ 1421 info->target_clock_range = 1422 le32_to_cpu(tbl[i].ulTargetClockRange) * 10; 1423 info->spread_spectrum_percentage = 1424 (uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage); 1425 info->spread_spectrum_range = 1426 (uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10); 1427 result = BP_RESULT_OK; 1428 break; 1429 } 1430 1431 return result; 1432 1433 } 1434 1435 /** 1436 * get_ss_info_from_ss_info_table 1437 * Get spread sprectrum information from the SS_Info table from the VBIOS 1438 * if the pointer to info is NULL, indicate the caller what to know the number 1439 * of entries that matches the id 1440 * for, the SS_Info table, there should not be more than 1 entry match. 1441 * 1442 * @param [in] id, spread sprectrum id 1443 * @param [out] pSSinfo, sprectrum information structure, 1444 * @return Bios parser result code 1445 */ 1446 static enum bp_result get_ss_info_from_ss_info_table( 1447 struct bios_parser *bp, 1448 uint32_t id, 1449 struct spread_spectrum_info *ss_info) 1450 { 1451 enum bp_result result = BP_RESULT_UNSUPPORTED; 1452 ATOM_SPREAD_SPECTRUM_INFO *tbl; 1453 ATOM_COMMON_TABLE_HEADER *header; 1454 uint32_t table_size; 1455 uint32_t i; 1456 uint32_t id_local = SS_ID_UNKNOWN; 1457 struct atom_data_revision revision; 1458 1459 /* exist of the SS_Info table */ 1460 /* check for bad input, pSSinfo can not be NULL */ 1461 if (!DATA_TABLES(SS_Info) || !ss_info) 1462 return result; 1463 1464 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(SS_Info)); 1465 get_atom_data_table_revision(header, &revision); 1466 1467 tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, DATA_TABLES(SS_Info)); 1468 1469 if (1 != revision.major || 2 > revision.minor) 1470 return result; 1471 1472 /* have to convert from Internal_SS format to SS_Info format */ 1473 switch (id) { 1474 case ASIC_INTERNAL_SS_ON_DP: 1475 id_local = SS_ID_DP1; 1476 break; 1477 case ASIC_INTERNAL_SS_ON_LVDS: 1478 { 1479 struct embedded_panel_info panel_info; 1480 1481 if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info) 1482 == BP_RESULT_OK) 1483 id_local = panel_info.ss_id; 1484 break; 1485 } 1486 default: 1487 break; 1488 } 1489 1490 if (id_local == SS_ID_UNKNOWN) 1491 return result; 1492 1493 table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) - 1494 sizeof(ATOM_COMMON_TABLE_HEADER)) / 1495 sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT); 1496 1497 for (i = 0; i < table_size; i++) { 1498 if (id_local != (uint32_t)tbl->asSS_Info[i].ucSS_Id) 1499 continue; 1500 1501 memset(ss_info, 0, sizeof(struct spread_spectrum_info)); 1502 1503 if (ATOM_EXTERNAL_SS_MASK & 1504 tbl->asSS_Info[i].ucSpreadSpectrumType) 1505 ss_info->type.EXTERNAL = true; 1506 1507 if (ATOM_SS_CENTRE_SPREAD_MODE_MASK & 1508 tbl->asSS_Info[i].ucSpreadSpectrumType) 1509 ss_info->type.CENTER_MODE = true; 1510 1511 ss_info->type.STEP_AND_DELAY_INFO = true; 1512 ss_info->spread_spectrum_percentage = 1513 (uint32_t)le16_to_cpu(tbl->asSS_Info[i].usSpreadSpectrumPercentage); 1514 ss_info->step_and_delay_info.step = tbl->asSS_Info[i].ucSS_Step; 1515 ss_info->step_and_delay_info.delay = 1516 tbl->asSS_Info[i].ucSS_Delay; 1517 ss_info->step_and_delay_info.recommended_ref_div = 1518 tbl->asSS_Info[i].ucRecommendedRef_Div; 1519 ss_info->spread_spectrum_range = 1520 (uint32_t)tbl->asSS_Info[i].ucSS_Range * 10000; 1521 1522 /* there will be only one entry for each display type in SS_info 1523 * table */ 1524 result = BP_RESULT_OK; 1525 break; 1526 } 1527 1528 return result; 1529 } 1530 static enum bp_result get_embedded_panel_info_v1_2( 1531 struct bios_parser *bp, 1532 struct embedded_panel_info *info); 1533 static enum bp_result get_embedded_panel_info_v1_3( 1534 struct bios_parser *bp, 1535 struct embedded_panel_info *info); 1536 1537 static enum bp_result bios_parser_get_embedded_panel_info( 1538 struct dc_bios *dcb, 1539 struct embedded_panel_info *info) 1540 { 1541 struct bios_parser *bp = BP_FROM_DCB(dcb); 1542 ATOM_COMMON_TABLE_HEADER *hdr; 1543 1544 if (!DATA_TABLES(LCD_Info)) 1545 return BP_RESULT_FAILURE; 1546 1547 hdr = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(LCD_Info)); 1548 1549 if (!hdr) 1550 return BP_RESULT_BADBIOSTABLE; 1551 1552 switch (hdr->ucTableFormatRevision) { 1553 case 1: 1554 switch (hdr->ucTableContentRevision) { 1555 case 0: 1556 case 1: 1557 case 2: 1558 return get_embedded_panel_info_v1_2(bp, info); 1559 case 3: 1560 return get_embedded_panel_info_v1_3(bp, info); 1561 default: 1562 break; 1563 } 1564 default: 1565 break; 1566 } 1567 1568 return BP_RESULT_FAILURE; 1569 } 1570 1571 static enum bp_result get_embedded_panel_info_v1_2( 1572 struct bios_parser *bp, 1573 struct embedded_panel_info *info) 1574 { 1575 ATOM_LVDS_INFO_V12 *lvds; 1576 1577 if (!info) 1578 return BP_RESULT_BADINPUT; 1579 1580 if (!DATA_TABLES(LVDS_Info)) 1581 return BP_RESULT_UNSUPPORTED; 1582 1583 lvds = 1584 GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info)); 1585 1586 if (!lvds) 1587 return BP_RESULT_BADBIOSTABLE; 1588 1589 if (1 != lvds->sHeader.ucTableFormatRevision 1590 || 2 > lvds->sHeader.ucTableContentRevision) 1591 return BP_RESULT_UNSUPPORTED; 1592 1593 memset(info, 0, sizeof(struct embedded_panel_info)); 1594 1595 /* We need to convert from 10KHz units into KHz units*/ 1596 info->lcd_timing.pixel_clk = 1597 le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10; 1598 /* usHActive does not include borders, according to VBIOS team*/ 1599 info->lcd_timing.horizontal_addressable = 1600 le16_to_cpu(lvds->sLCDTiming.usHActive); 1601 /* usHBlanking_Time includes borders, so we should really be subtracting 1602 * borders duing this translation, but LVDS generally*/ 1603 /* doesn't have borders, so we should be okay leaving this as is for 1604 * now. May need to revisit if we ever have LVDS with borders*/ 1605 info->lcd_timing.horizontal_blanking_time = 1606 le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time); 1607 /* usVActive does not include borders, according to VBIOS team*/ 1608 info->lcd_timing.vertical_addressable = 1609 le16_to_cpu(lvds->sLCDTiming.usVActive); 1610 /* usVBlanking_Time includes borders, so we should really be subtracting 1611 * borders duing this translation, but LVDS generally*/ 1612 /* doesn't have borders, so we should be okay leaving this as is for 1613 * now. May need to revisit if we ever have LVDS with borders*/ 1614 info->lcd_timing.vertical_blanking_time = 1615 le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time); 1616 info->lcd_timing.horizontal_sync_offset = 1617 le16_to_cpu(lvds->sLCDTiming.usHSyncOffset); 1618 info->lcd_timing.horizontal_sync_width = 1619 le16_to_cpu(lvds->sLCDTiming.usHSyncWidth); 1620 info->lcd_timing.vertical_sync_offset = 1621 le16_to_cpu(lvds->sLCDTiming.usVSyncOffset); 1622 info->lcd_timing.vertical_sync_width = 1623 le16_to_cpu(lvds->sLCDTiming.usVSyncWidth); 1624 info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder; 1625 info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder; 1626 info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 1627 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff; 1628 info->lcd_timing.misc_info.H_SYNC_POLARITY = 1629 ~(uint32_t) 1630 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity; 1631 info->lcd_timing.misc_info.V_SYNC_POLARITY = 1632 ~(uint32_t) 1633 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity; 1634 info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 1635 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff; 1636 info->lcd_timing.misc_info.H_REPLICATION_BY2 = 1637 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2; 1638 info->lcd_timing.misc_info.V_REPLICATION_BY2 = 1639 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2; 1640 info->lcd_timing.misc_info.COMPOSITE_SYNC = 1641 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync; 1642 info->lcd_timing.misc_info.INTERLACE = 1643 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace; 1644 info->lcd_timing.misc_info.DOUBLE_CLOCK = 1645 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock; 1646 info->ss_id = lvds->ucSS_Id; 1647 1648 { 1649 uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate); 1650 /* Get minimum supported refresh rate*/ 1651 if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr) 1652 info->supported_rr.REFRESH_RATE_30HZ = 1; 1653 else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr) 1654 info->supported_rr.REFRESH_RATE_40HZ = 1; 1655 else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr) 1656 info->supported_rr.REFRESH_RATE_48HZ = 1; 1657 else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr) 1658 info->supported_rr.REFRESH_RATE_50HZ = 1; 1659 else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr) 1660 info->supported_rr.REFRESH_RATE_60HZ = 1; 1661 } 1662 1663 /*Drr panel support can be reported by VBIOS*/ 1664 if (LCDPANEL_CAP_DRR_SUPPORTED 1665 & lvds->ucLCDPanel_SpecialHandlingCap) 1666 info->drr_enabled = 1; 1667 1668 if (ATOM_PANEL_MISC_DUAL & lvds->ucLVDS_Misc) 1669 info->lcd_timing.misc_info.DOUBLE_CLOCK = true; 1670 1671 if (ATOM_PANEL_MISC_888RGB & lvds->ucLVDS_Misc) 1672 info->lcd_timing.misc_info.RGB888 = true; 1673 1674 info->lcd_timing.misc_info.GREY_LEVEL = 1675 (uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL & 1676 lvds->ucLVDS_Misc) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT; 1677 1678 if (ATOM_PANEL_MISC_SPATIAL & lvds->ucLVDS_Misc) 1679 info->lcd_timing.misc_info.SPATIAL = true; 1680 1681 if (ATOM_PANEL_MISC_TEMPORAL & lvds->ucLVDS_Misc) 1682 info->lcd_timing.misc_info.TEMPORAL = true; 1683 1684 if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc) 1685 info->lcd_timing.misc_info.API_ENABLED = true; 1686 1687 return BP_RESULT_OK; 1688 } 1689 1690 static enum bp_result get_embedded_panel_info_v1_3( 1691 struct bios_parser *bp, 1692 struct embedded_panel_info *info) 1693 { 1694 ATOM_LCD_INFO_V13 *lvds; 1695 1696 if (!info) 1697 return BP_RESULT_BADINPUT; 1698 1699 if (!DATA_TABLES(LCD_Info)) 1700 return BP_RESULT_UNSUPPORTED; 1701 1702 lvds = GET_IMAGE(ATOM_LCD_INFO_V13, DATA_TABLES(LCD_Info)); 1703 1704 if (!lvds) 1705 return BP_RESULT_BADBIOSTABLE; 1706 1707 if (!((1 == lvds->sHeader.ucTableFormatRevision) 1708 && (3 <= lvds->sHeader.ucTableContentRevision))) 1709 return BP_RESULT_UNSUPPORTED; 1710 1711 memset(info, 0, sizeof(struct embedded_panel_info)); 1712 1713 /* We need to convert from 10KHz units into KHz units */ 1714 info->lcd_timing.pixel_clk = 1715 le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10; 1716 /* usHActive does not include borders, according to VBIOS team */ 1717 info->lcd_timing.horizontal_addressable = 1718 le16_to_cpu(lvds->sLCDTiming.usHActive); 1719 /* usHBlanking_Time includes borders, so we should really be subtracting 1720 * borders duing this translation, but LVDS generally*/ 1721 /* doesn't have borders, so we should be okay leaving this as is for 1722 * now. May need to revisit if we ever have LVDS with borders*/ 1723 info->lcd_timing.horizontal_blanking_time = 1724 le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time); 1725 /* usVActive does not include borders, according to VBIOS team*/ 1726 info->lcd_timing.vertical_addressable = 1727 le16_to_cpu(lvds->sLCDTiming.usVActive); 1728 /* usVBlanking_Time includes borders, so we should really be subtracting 1729 * borders duing this translation, but LVDS generally*/ 1730 /* doesn't have borders, so we should be okay leaving this as is for 1731 * now. May need to revisit if we ever have LVDS with borders*/ 1732 info->lcd_timing.vertical_blanking_time = 1733 le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time); 1734 info->lcd_timing.horizontal_sync_offset = 1735 le16_to_cpu(lvds->sLCDTiming.usHSyncOffset); 1736 info->lcd_timing.horizontal_sync_width = 1737 le16_to_cpu(lvds->sLCDTiming.usHSyncWidth); 1738 info->lcd_timing.vertical_sync_offset = 1739 le16_to_cpu(lvds->sLCDTiming.usVSyncOffset); 1740 info->lcd_timing.vertical_sync_width = 1741 le16_to_cpu(lvds->sLCDTiming.usVSyncWidth); 1742 info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder; 1743 info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder; 1744 info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 1745 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff; 1746 info->lcd_timing.misc_info.H_SYNC_POLARITY = 1747 ~(uint32_t) 1748 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity; 1749 info->lcd_timing.misc_info.V_SYNC_POLARITY = 1750 ~(uint32_t) 1751 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity; 1752 info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 1753 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff; 1754 info->lcd_timing.misc_info.H_REPLICATION_BY2 = 1755 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2; 1756 info->lcd_timing.misc_info.V_REPLICATION_BY2 = 1757 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2; 1758 info->lcd_timing.misc_info.COMPOSITE_SYNC = 1759 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync; 1760 info->lcd_timing.misc_info.INTERLACE = 1761 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace; 1762 info->lcd_timing.misc_info.DOUBLE_CLOCK = 1763 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock; 1764 info->ss_id = lvds->ucSS_Id; 1765 1766 /* Drr panel support can be reported by VBIOS*/ 1767 if (LCDPANEL_CAP_V13_DRR_SUPPORTED 1768 & lvds->ucLCDPanel_SpecialHandlingCap) 1769 info->drr_enabled = 1; 1770 1771 /* Get supported refresh rate*/ 1772 if (info->drr_enabled == 1) { 1773 uint8_t min_rr = 1774 lvds->sRefreshRateSupport.ucMinRefreshRateForDRR; 1775 uint8_t rr = lvds->sRefreshRateSupport.ucSupportedRefreshRate; 1776 1777 if (min_rr != 0) { 1778 if (SUPPORTED_LCD_REFRESHRATE_30Hz & min_rr) 1779 info->supported_rr.REFRESH_RATE_30HZ = 1; 1780 else if (SUPPORTED_LCD_REFRESHRATE_40Hz & min_rr) 1781 info->supported_rr.REFRESH_RATE_40HZ = 1; 1782 else if (SUPPORTED_LCD_REFRESHRATE_48Hz & min_rr) 1783 info->supported_rr.REFRESH_RATE_48HZ = 1; 1784 else if (SUPPORTED_LCD_REFRESHRATE_50Hz & min_rr) 1785 info->supported_rr.REFRESH_RATE_50HZ = 1; 1786 else if (SUPPORTED_LCD_REFRESHRATE_60Hz & min_rr) 1787 info->supported_rr.REFRESH_RATE_60HZ = 1; 1788 } else { 1789 if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr) 1790 info->supported_rr.REFRESH_RATE_30HZ = 1; 1791 else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr) 1792 info->supported_rr.REFRESH_RATE_40HZ = 1; 1793 else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr) 1794 info->supported_rr.REFRESH_RATE_48HZ = 1; 1795 else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr) 1796 info->supported_rr.REFRESH_RATE_50HZ = 1; 1797 else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr) 1798 info->supported_rr.REFRESH_RATE_60HZ = 1; 1799 } 1800 } 1801 1802 if (ATOM_PANEL_MISC_V13_DUAL & lvds->ucLCD_Misc) 1803 info->lcd_timing.misc_info.DOUBLE_CLOCK = true; 1804 1805 if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR & lvds->ucLCD_Misc) 1806 info->lcd_timing.misc_info.RGB888 = true; 1807 1808 info->lcd_timing.misc_info.GREY_LEVEL = 1809 (uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL & 1810 lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT; 1811 1812 return BP_RESULT_OK; 1813 } 1814 1815 /** 1816 * bios_parser_get_encoder_cap_info 1817 * 1818 * @brief 1819 * Get encoder capability information of input object id 1820 * 1821 * @param object_id, Object id 1822 * @param object_id, encoder cap information structure 1823 * 1824 * @return Bios parser result code 1825 * 1826 */ 1827 static enum bp_result bios_parser_get_encoder_cap_info( 1828 struct dc_bios *dcb, 1829 struct graphics_object_id object_id, 1830 struct bp_encoder_cap_info *info) 1831 { 1832 struct bios_parser *bp = BP_FROM_DCB(dcb); 1833 ATOM_OBJECT *object; 1834 ATOM_ENCODER_CAP_RECORD_V2 *record = NULL; 1835 1836 if (!info) 1837 return BP_RESULT_BADINPUT; 1838 1839 object = get_bios_object(bp, object_id); 1840 1841 if (!object) 1842 return BP_RESULT_BADINPUT; 1843 1844 record = get_encoder_cap_record(bp, object); 1845 if (!record) 1846 return BP_RESULT_NORECORD; 1847 1848 info->DP_HBR2_EN = record->usHBR2En; 1849 info->DP_HBR3_EN = record->usHBR3En; 1850 info->HDMI_6GB_EN = record->usHDMI6GEn; 1851 return BP_RESULT_OK; 1852 } 1853 1854 /** 1855 * get_encoder_cap_record 1856 * 1857 * @brief 1858 * Get encoder cap record for the object 1859 * 1860 * @param object, ATOM object 1861 * 1862 * @return atom encoder cap record 1863 * 1864 * @note 1865 * search all records to find the ATOM_ENCODER_CAP_RECORD_V2 record 1866 */ 1867 static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record( 1868 struct bios_parser *bp, 1869 ATOM_OBJECT *object) 1870 { 1871 ATOM_COMMON_RECORD_HEADER *header; 1872 uint32_t offset; 1873 1874 if (!object) { 1875 BREAK_TO_DEBUGGER(); /* Invalid object */ 1876 return NULL; 1877 } 1878 1879 offset = le16_to_cpu(object->usRecordOffset) 1880 + bp->object_info_tbl_offset; 1881 1882 for (;;) { 1883 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); 1884 1885 if (!header) 1886 return NULL; 1887 1888 offset += header->ucRecordSize; 1889 1890 if (LAST_RECORD_TYPE == header->ucRecordType || 1891 !header->ucRecordSize) 1892 break; 1893 1894 if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType) 1895 continue; 1896 1897 if (sizeof(ATOM_ENCODER_CAP_RECORD_V2) <= header->ucRecordSize) 1898 return (ATOM_ENCODER_CAP_RECORD_V2 *)header; 1899 } 1900 1901 return NULL; 1902 } 1903 1904 static uint32_t get_ss_entry_number( 1905 struct bios_parser *bp, 1906 uint32_t id); 1907 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1( 1908 struct bios_parser *bp, 1909 uint32_t id); 1910 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1( 1911 struct bios_parser *bp, 1912 uint32_t id); 1913 static uint32_t get_ss_entry_number_from_ss_info_tbl( 1914 struct bios_parser *bp, 1915 uint32_t id); 1916 1917 /** 1918 * BiosParserObject::GetNumberofSpreadSpectrumEntry 1919 * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from 1920 * the VBIOS that match the SSid (to be converted from signal) 1921 * 1922 * @param[in] signal, ASSignalType to be converted to SSid 1923 * @return number of SS Entry that match the signal 1924 */ 1925 static uint32_t bios_parser_get_ss_entry_number( 1926 struct dc_bios *dcb, 1927 enum as_signal_type signal) 1928 { 1929 struct bios_parser *bp = BP_FROM_DCB(dcb); 1930 uint32_t ss_id = 0; 1931 ATOM_COMMON_TABLE_HEADER *header; 1932 struct atom_data_revision revision; 1933 1934 ss_id = signal_to_ss_id(signal); 1935 1936 if (!DATA_TABLES(ASIC_InternalSS_Info)) 1937 return get_ss_entry_number_from_ss_info_tbl(bp, ss_id); 1938 1939 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, 1940 DATA_TABLES(ASIC_InternalSS_Info)); 1941 get_atom_data_table_revision(header, &revision); 1942 1943 switch (revision.major) { 1944 case 2: 1945 switch (revision.minor) { 1946 case 1: 1947 return get_ss_entry_number(bp, ss_id); 1948 default: 1949 break; 1950 } 1951 break; 1952 case 3: 1953 switch (revision.minor) { 1954 case 1: 1955 return 1956 get_ss_entry_number_from_internal_ss_info_tbl_V3_1( 1957 bp, ss_id); 1958 default: 1959 break; 1960 } 1961 break; 1962 default: 1963 break; 1964 } 1965 1966 return 0; 1967 } 1968 1969 /** 1970 * get_ss_entry_number_from_ss_info_tbl 1971 * Get Number of spread spectrum entry from the SS_Info table from the VBIOS. 1972 * 1973 * @note There can only be one entry for each id for SS_Info Table 1974 * 1975 * @param [in] id, spread spectrum id 1976 * @return number of SS Entry that match the id 1977 */ 1978 static uint32_t get_ss_entry_number_from_ss_info_tbl( 1979 struct bios_parser *bp, 1980 uint32_t id) 1981 { 1982 ATOM_SPREAD_SPECTRUM_INFO *tbl; 1983 ATOM_COMMON_TABLE_HEADER *header; 1984 uint32_t table_size; 1985 uint32_t i; 1986 uint32_t number = 0; 1987 uint32_t id_local = SS_ID_UNKNOWN; 1988 struct atom_data_revision revision; 1989 1990 /* SS_Info table exist */ 1991 if (!DATA_TABLES(SS_Info)) 1992 return number; 1993 1994 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, 1995 DATA_TABLES(SS_Info)); 1996 get_atom_data_table_revision(header, &revision); 1997 1998 tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, 1999 DATA_TABLES(SS_Info)); 2000 2001 if (1 != revision.major || 2 > revision.minor) 2002 return number; 2003 2004 /* have to convert from Internal_SS format to SS_Info format */ 2005 switch (id) { 2006 case ASIC_INTERNAL_SS_ON_DP: 2007 id_local = SS_ID_DP1; 2008 break; 2009 case ASIC_INTERNAL_SS_ON_LVDS: { 2010 struct embedded_panel_info panel_info; 2011 2012 if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info) 2013 == BP_RESULT_OK) 2014 id_local = panel_info.ss_id; 2015 break; 2016 } 2017 default: 2018 break; 2019 } 2020 2021 if (id_local == SS_ID_UNKNOWN) 2022 return number; 2023 2024 table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) - 2025 sizeof(ATOM_COMMON_TABLE_HEADER)) / 2026 sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT); 2027 2028 for (i = 0; i < table_size; i++) 2029 if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) { 2030 number = 1; 2031 break; 2032 } 2033 2034 return number; 2035 } 2036 2037 /** 2038 * get_ss_entry_number 2039 * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or 2040 * SS_Info table from the VBIOS 2041 * There can not be more than 1 entry for ASIC_InternalSS_Info Ver 2.1 or 2042 * SS_Info. 2043 * 2044 * @param id, spread sprectrum info index 2045 * @return Bios parser result code 2046 */ 2047 static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id) 2048 { 2049 if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS) 2050 return get_ss_entry_number_from_ss_info_tbl(bp, id); 2051 2052 return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id); 2053 } 2054 2055 /** 2056 * get_ss_entry_number_from_internal_ss_info_tbl_v2_1 2057 * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table 2058 * Ver 2.1 from the VBIOS 2059 * There will not be multiple entry for Ver 2.1 2060 * 2061 * @param id, spread sprectrum info index 2062 * @return number of SS Entry that match the id 2063 */ 2064 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1( 2065 struct bios_parser *bp, 2066 uint32_t id) 2067 { 2068 ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include; 2069 ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl; 2070 uint32_t size; 2071 uint32_t i; 2072 2073 if (!DATA_TABLES(ASIC_InternalSS_Info)) 2074 return 0; 2075 2076 header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2, 2077 DATA_TABLES(ASIC_InternalSS_Info)); 2078 2079 size = (le16_to_cpu(header_include->sHeader.usStructureSize) 2080 - sizeof(ATOM_COMMON_TABLE_HEADER)) 2081 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2); 2082 2083 tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *) 2084 &header_include->asSpreadSpectrum[0]; 2085 for (i = 0; i < size; i++) 2086 if (tbl[i].ucClockIndication == (uint8_t)id) 2087 return 1; 2088 2089 return 0; 2090 } 2091 /** 2092 * get_ss_entry_number_from_internal_ss_info_table_V3_1 2093 * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of 2094 * the VBIOS that matches id 2095 * 2096 * @param[in] id, spread sprectrum id 2097 * @return number of SS Entry that match the id 2098 */ 2099 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1( 2100 struct bios_parser *bp, 2101 uint32_t id) 2102 { 2103 uint32_t number = 0; 2104 ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include; 2105 ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl; 2106 uint32_t size; 2107 uint32_t i; 2108 2109 if (!DATA_TABLES(ASIC_InternalSS_Info)) 2110 return number; 2111 2112 header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3, 2113 DATA_TABLES(ASIC_InternalSS_Info)); 2114 size = (le16_to_cpu(header_include->sHeader.usStructureSize) - 2115 sizeof(ATOM_COMMON_TABLE_HEADER)) / 2116 sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3); 2117 2118 tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *) 2119 &header_include->asSpreadSpectrum[0]; 2120 2121 for (i = 0; i < size; i++) 2122 if (tbl[i].ucClockIndication == (uint8_t)id) 2123 number++; 2124 2125 return number; 2126 } 2127 2128 /** 2129 * bios_parser_get_gpio_pin_info 2130 * Get GpioPin information of input gpio id 2131 * 2132 * @param gpio_id, GPIO ID 2133 * @param info, GpioPin information structure 2134 * @return Bios parser result code 2135 * @note 2136 * to get the GPIO PIN INFO, we need: 2137 * 1. get the GPIO_ID from other object table, see GetHPDInfo() 2138 * 2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA 2139 * offset/mask 2140 */ 2141 static enum bp_result bios_parser_get_gpio_pin_info( 2142 struct dc_bios *dcb, 2143 uint32_t gpio_id, 2144 struct gpio_pin_info *info) 2145 { 2146 struct bios_parser *bp = BP_FROM_DCB(dcb); 2147 ATOM_GPIO_PIN_LUT *header; 2148 uint32_t count = 0; 2149 uint32_t i = 0; 2150 2151 if (!DATA_TABLES(GPIO_Pin_LUT)) 2152 return BP_RESULT_BADBIOSTABLE; 2153 2154 header = GET_IMAGE(ATOM_GPIO_PIN_LUT, DATA_TABLES(GPIO_Pin_LUT)); 2155 if (!header) 2156 return BP_RESULT_BADBIOSTABLE; 2157 2158 if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_PIN_LUT) 2159 > le16_to_cpu(header->sHeader.usStructureSize)) 2160 return BP_RESULT_BADBIOSTABLE; 2161 2162 if (1 != header->sHeader.ucTableContentRevision) 2163 return BP_RESULT_UNSUPPORTED; 2164 2165 count = (le16_to_cpu(header->sHeader.usStructureSize) 2166 - sizeof(ATOM_COMMON_TABLE_HEADER)) 2167 / sizeof(ATOM_GPIO_PIN_ASSIGNMENT); 2168 for (i = 0; i < count; ++i) { 2169 if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id) 2170 continue; 2171 2172 info->offset = 2173 (uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex); 2174 info->offset_y = info->offset + 2; 2175 info->offset_en = info->offset + 1; 2176 info->offset_mask = info->offset - 1; 2177 2178 info->mask = (uint32_t) (1 << 2179 header->asGPIO_Pin[i].ucGpioPinBitShift); 2180 info->mask_y = info->mask + 2; 2181 info->mask_en = info->mask + 1; 2182 info->mask_mask = info->mask - 1; 2183 2184 return BP_RESULT_OK; 2185 } 2186 2187 return BP_RESULT_NORECORD; 2188 } 2189 2190 static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, 2191 ATOM_I2C_RECORD *record, 2192 struct graphics_object_i2c_info *info) 2193 { 2194 ATOM_GPIO_I2C_INFO *header; 2195 uint32_t count = 0; 2196 2197 if (!info) 2198 return BP_RESULT_BADINPUT; 2199 2200 /* get the GPIO_I2C info */ 2201 if (!DATA_TABLES(GPIO_I2C_Info)) 2202 return BP_RESULT_BADBIOSTABLE; 2203 2204 header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info)); 2205 if (!header) 2206 return BP_RESULT_BADBIOSTABLE; 2207 2208 if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT) 2209 > le16_to_cpu(header->sHeader.usStructureSize)) 2210 return BP_RESULT_BADBIOSTABLE; 2211 2212 if (1 != header->sHeader.ucTableContentRevision) 2213 return BP_RESULT_UNSUPPORTED; 2214 2215 /* get data count */ 2216 count = (le16_to_cpu(header->sHeader.usStructureSize) 2217 - sizeof(ATOM_COMMON_TABLE_HEADER)) 2218 / sizeof(ATOM_GPIO_I2C_ASSIGMENT); 2219 if (count < record->sucI2cId.bfI2C_LineMux) 2220 return BP_RESULT_BADBIOSTABLE; 2221 2222 /* get the GPIO_I2C_INFO */ 2223 info->i2c_hw_assist = record->sucI2cId.bfHW_Capable; 2224 info->i2c_line = record->sucI2cId.bfI2C_LineMux; 2225 info->i2c_engine_id = record->sucI2cId.bfHW_EngineID; 2226 info->i2c_slave_address = record->ucI2CAddr; 2227 2228 info->gpio_info.clk_mask_register_index = 2229 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex); 2230 info->gpio_info.clk_en_register_index = 2231 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex); 2232 info->gpio_info.clk_y_register_index = 2233 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex); 2234 info->gpio_info.clk_a_register_index = 2235 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex); 2236 info->gpio_info.data_mask_register_index = 2237 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex); 2238 info->gpio_info.data_en_register_index = 2239 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex); 2240 info->gpio_info.data_y_register_index = 2241 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex); 2242 info->gpio_info.data_a_register_index = 2243 le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex); 2244 2245 info->gpio_info.clk_mask_shift = 2246 header->asGPIO_Info[info->i2c_line].ucClkMaskShift; 2247 info->gpio_info.clk_en_shift = 2248 header->asGPIO_Info[info->i2c_line].ucClkEnShift; 2249 info->gpio_info.clk_y_shift = 2250 header->asGPIO_Info[info->i2c_line].ucClkY_Shift; 2251 info->gpio_info.clk_a_shift = 2252 header->asGPIO_Info[info->i2c_line].ucClkA_Shift; 2253 info->gpio_info.data_mask_shift = 2254 header->asGPIO_Info[info->i2c_line].ucDataMaskShift; 2255 info->gpio_info.data_en_shift = 2256 header->asGPIO_Info[info->i2c_line].ucDataEnShift; 2257 info->gpio_info.data_y_shift = 2258 header->asGPIO_Info[info->i2c_line].ucDataY_Shift; 2259 info->gpio_info.data_a_shift = 2260 header->asGPIO_Info[info->i2c_line].ucDataA_Shift; 2261 2262 return BP_RESULT_OK; 2263 } 2264 2265 static bool dal_graphics_object_id_is_valid(struct graphics_object_id id) 2266 { 2267 bool rc = true; 2268 2269 switch (id.type) { 2270 case OBJECT_TYPE_UNKNOWN: 2271 rc = false; 2272 break; 2273 case OBJECT_TYPE_GPU: 2274 case OBJECT_TYPE_ENGINE: 2275 /* do NOT check for id.id == 0 */ 2276 if (id.enum_id == ENUM_ID_UNKNOWN) 2277 rc = false; 2278 break; 2279 default: 2280 if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN) 2281 rc = false; 2282 break; 2283 } 2284 2285 return rc; 2286 } 2287 2288 static bool dal_graphics_object_id_is_equal( 2289 struct graphics_object_id id1, 2290 struct graphics_object_id id2) 2291 { 2292 if (false == dal_graphics_object_id_is_valid(id1)) { 2293 dm_output_to_console( 2294 "%s: Warning: comparing invalid object 'id1'!\n", __func__); 2295 return false; 2296 } 2297 2298 if (false == dal_graphics_object_id_is_valid(id2)) { 2299 dm_output_to_console( 2300 "%s: Warning: comparing invalid object 'id2'!\n", __func__); 2301 return false; 2302 } 2303 2304 if (id1.id == id2.id && id1.enum_id == id2.enum_id 2305 && id1.type == id2.type) 2306 return true; 2307 2308 return false; 2309 } 2310 2311 static ATOM_OBJECT *get_bios_object(struct bios_parser *bp, 2312 struct graphics_object_id id) 2313 { 2314 uint32_t offset; 2315 ATOM_OBJECT_TABLE *tbl; 2316 uint32_t i; 2317 2318 switch (id.type) { 2319 case OBJECT_TYPE_ENCODER: 2320 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset); 2321 break; 2322 2323 case OBJECT_TYPE_CONNECTOR: 2324 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); 2325 break; 2326 2327 case OBJECT_TYPE_ROUTER: 2328 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset); 2329 break; 2330 2331 case OBJECT_TYPE_GENERIC: 2332 if (bp->object_info_tbl.revision.minor < 3) 2333 return NULL; 2334 offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset); 2335 break; 2336 2337 default: 2338 return NULL; 2339 } 2340 2341 offset += bp->object_info_tbl_offset; 2342 2343 tbl = GET_IMAGE(ATOM_OBJECT_TABLE, offset); 2344 if (!tbl) 2345 return NULL; 2346 2347 for (i = 0; i < tbl->ucNumberOfObjects; i++) 2348 if (dal_graphics_object_id_is_equal(id, 2349 object_id_from_bios_object_id( 2350 le16_to_cpu(tbl->asObjects[i].usObjectID)))) 2351 return &tbl->asObjects[i]; 2352 2353 return NULL; 2354 } 2355 2356 static uint32_t get_dest_obj_list(struct bios_parser *bp, 2357 ATOM_OBJECT *object, uint16_t **id_list) 2358 { 2359 uint32_t offset; 2360 uint8_t *number; 2361 2362 if (!object) { 2363 BREAK_TO_DEBUGGER(); /* Invalid object id */ 2364 return 0; 2365 } 2366 2367 offset = le16_to_cpu(object->usSrcDstTableOffset) 2368 + bp->object_info_tbl_offset; 2369 2370 number = GET_IMAGE(uint8_t, offset); 2371 if (!number) 2372 return 0; 2373 2374 offset += sizeof(uint8_t); 2375 offset += sizeof(uint16_t) * (*number); 2376 2377 number = GET_IMAGE(uint8_t, offset); 2378 if ((!number) || (!*number)) 2379 return 0; 2380 2381 offset += sizeof(uint8_t); 2382 *id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t)); 2383 2384 if (!*id_list) 2385 return 0; 2386 2387 return *number; 2388 } 2389 2390 static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object, 2391 uint16_t **id_list) 2392 { 2393 uint32_t offset; 2394 uint8_t *number; 2395 2396 if (!object) { 2397 BREAK_TO_DEBUGGER(); /* Invalid object id */ 2398 return 0; 2399 } 2400 2401 offset = le16_to_cpu(object->usSrcDstTableOffset) 2402 + bp->object_info_tbl_offset; 2403 2404 number = GET_IMAGE(uint8_t, offset); 2405 if (!number) 2406 return 0; 2407 2408 offset += sizeof(uint8_t); 2409 *id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t)); 2410 2411 if (!*id_list) 2412 return 0; 2413 2414 return *number; 2415 } 2416 2417 static uint32_t get_dst_number_from_object(struct bios_parser *bp, 2418 ATOM_OBJECT *object) 2419 { 2420 uint32_t offset; 2421 uint8_t *number; 2422 2423 if (!object) { 2424 BREAK_TO_DEBUGGER(); /* Invalid encoder object id*/ 2425 return 0; 2426 } 2427 2428 offset = le16_to_cpu(object->usSrcDstTableOffset) 2429 + bp->object_info_tbl_offset; 2430 2431 number = GET_IMAGE(uint8_t, offset); 2432 if (!number) 2433 return 0; 2434 2435 offset += sizeof(uint8_t); 2436 offset += sizeof(uint16_t) * (*number); 2437 2438 number = GET_IMAGE(uint8_t, offset); 2439 2440 if (!number) 2441 return 0; 2442 2443 return *number; 2444 } 2445 2446 static struct device_id device_type_from_device_id(uint16_t device_id) 2447 { 2448 2449 struct device_id result_device_id; 2450 2451 switch (device_id) { 2452 case ATOM_DEVICE_LCD1_SUPPORT: 2453 result_device_id.device_type = DEVICE_TYPE_LCD; 2454 result_device_id.enum_id = 1; 2455 break; 2456 2457 case ATOM_DEVICE_LCD2_SUPPORT: 2458 result_device_id.device_type = DEVICE_TYPE_LCD; 2459 result_device_id.enum_id = 2; 2460 break; 2461 2462 case ATOM_DEVICE_CRT1_SUPPORT: 2463 result_device_id.device_type = DEVICE_TYPE_CRT; 2464 result_device_id.enum_id = 1; 2465 break; 2466 2467 case ATOM_DEVICE_CRT2_SUPPORT: 2468 result_device_id.device_type = DEVICE_TYPE_CRT; 2469 result_device_id.enum_id = 2; 2470 break; 2471 2472 case ATOM_DEVICE_DFP1_SUPPORT: 2473 result_device_id.device_type = DEVICE_TYPE_DFP; 2474 result_device_id.enum_id = 1; 2475 break; 2476 2477 case ATOM_DEVICE_DFP2_SUPPORT: 2478 result_device_id.device_type = DEVICE_TYPE_DFP; 2479 result_device_id.enum_id = 2; 2480 break; 2481 2482 case ATOM_DEVICE_DFP3_SUPPORT: 2483 result_device_id.device_type = DEVICE_TYPE_DFP; 2484 result_device_id.enum_id = 3; 2485 break; 2486 2487 case ATOM_DEVICE_DFP4_SUPPORT: 2488 result_device_id.device_type = DEVICE_TYPE_DFP; 2489 result_device_id.enum_id = 4; 2490 break; 2491 2492 case ATOM_DEVICE_DFP5_SUPPORT: 2493 result_device_id.device_type = DEVICE_TYPE_DFP; 2494 result_device_id.enum_id = 5; 2495 break; 2496 2497 case ATOM_DEVICE_DFP6_SUPPORT: 2498 result_device_id.device_type = DEVICE_TYPE_DFP; 2499 result_device_id.enum_id = 6; 2500 break; 2501 2502 default: 2503 BREAK_TO_DEBUGGER(); /* Invalid device Id */ 2504 result_device_id.device_type = DEVICE_TYPE_UNKNOWN; 2505 result_device_id.enum_id = 0; 2506 } 2507 return result_device_id; 2508 } 2509 2510 static void get_atom_data_table_revision( 2511 ATOM_COMMON_TABLE_HEADER *atom_data_tbl, 2512 struct atom_data_revision *tbl_revision) 2513 { 2514 if (!tbl_revision) 2515 return; 2516 2517 /* initialize the revision to 0 which is invalid revision */ 2518 tbl_revision->major = 0; 2519 tbl_revision->minor = 0; 2520 2521 if (!atom_data_tbl) 2522 return; 2523 2524 tbl_revision->major = 2525 (uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl); 2526 tbl_revision->minor = 2527 (uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl); 2528 } 2529 2530 static uint32_t signal_to_ss_id(enum as_signal_type signal) 2531 { 2532 uint32_t clk_id_ss = 0; 2533 2534 switch (signal) { 2535 case AS_SIGNAL_TYPE_DVI: 2536 clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS; 2537 break; 2538 case AS_SIGNAL_TYPE_HDMI: 2539 clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI; 2540 break; 2541 case AS_SIGNAL_TYPE_LVDS: 2542 clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS; 2543 break; 2544 case AS_SIGNAL_TYPE_DISPLAY_PORT: 2545 clk_id_ss = ASIC_INTERNAL_SS_ON_DP; 2546 break; 2547 case AS_SIGNAL_TYPE_GPU_PLL: 2548 clk_id_ss = ASIC_INTERNAL_GPUPLL_SS; 2549 break; 2550 default: 2551 break; 2552 } 2553 return clk_id_ss; 2554 } 2555 2556 static uint32_t get_support_mask_for_device_id(struct device_id device_id) 2557 { 2558 enum dal_device_type device_type = device_id.device_type; 2559 uint32_t enum_id = device_id.enum_id; 2560 2561 switch (device_type) { 2562 case DEVICE_TYPE_LCD: 2563 switch (enum_id) { 2564 case 1: 2565 return ATOM_DEVICE_LCD1_SUPPORT; 2566 case 2: 2567 return ATOM_DEVICE_LCD2_SUPPORT; 2568 default: 2569 break; 2570 } 2571 break; 2572 case DEVICE_TYPE_CRT: 2573 switch (enum_id) { 2574 case 1: 2575 return ATOM_DEVICE_CRT1_SUPPORT; 2576 case 2: 2577 return ATOM_DEVICE_CRT2_SUPPORT; 2578 default: 2579 break; 2580 } 2581 break; 2582 case DEVICE_TYPE_DFP: 2583 switch (enum_id) { 2584 case 1: 2585 return ATOM_DEVICE_DFP1_SUPPORT; 2586 case 2: 2587 return ATOM_DEVICE_DFP2_SUPPORT; 2588 case 3: 2589 return ATOM_DEVICE_DFP3_SUPPORT; 2590 case 4: 2591 return ATOM_DEVICE_DFP4_SUPPORT; 2592 case 5: 2593 return ATOM_DEVICE_DFP5_SUPPORT; 2594 case 6: 2595 return ATOM_DEVICE_DFP6_SUPPORT; 2596 default: 2597 break; 2598 } 2599 break; 2600 case DEVICE_TYPE_CV: 2601 switch (enum_id) { 2602 case 1: 2603 return ATOM_DEVICE_CV_SUPPORT; 2604 default: 2605 break; 2606 } 2607 break; 2608 case DEVICE_TYPE_TV: 2609 switch (enum_id) { 2610 case 1: 2611 return ATOM_DEVICE_TV1_SUPPORT; 2612 default: 2613 break; 2614 } 2615 break; 2616 default: 2617 break; 2618 }; 2619 2620 /* Unidentified device ID, return empty support mask. */ 2621 return 0; 2622 } 2623 2624 /** 2625 * HwContext interface for writing MM registers 2626 */ 2627 2628 static bool i2c_read( 2629 struct bios_parser *bp, 2630 struct graphics_object_i2c_info *i2c_info, 2631 uint8_t *buffer, 2632 uint32_t length) 2633 { 2634 struct ddc *ddc; 2635 uint8_t offset[2] = { 0, 0 }; 2636 bool result = false; 2637 struct i2c_command cmd; 2638 struct gpio_ddc_hw_info hw_info = { 2639 i2c_info->i2c_hw_assist, 2640 i2c_info->i2c_line }; 2641 2642 ddc = dal_gpio_create_ddc(bp->base.ctx->gpio_service, 2643 i2c_info->gpio_info.clk_a_register_index, 2644 (1 << i2c_info->gpio_info.clk_a_shift), &hw_info); 2645 2646 if (!ddc) 2647 return result; 2648 2649 /*Using SW engine */ 2650 cmd.engine = I2C_COMMAND_ENGINE_SW; 2651 cmd.speed = ddc->ctx->dc->caps.i2c_speed_in_khz; 2652 2653 { 2654 struct i2c_payload payloads[] = { 2655 { 2656 .address = i2c_info->i2c_slave_address >> 1, 2657 .data = offset, 2658 .length = sizeof(offset), 2659 .write = true 2660 }, 2661 { 2662 .address = i2c_info->i2c_slave_address >> 1, 2663 .data = buffer, 2664 .length = length, 2665 .write = false 2666 } 2667 }; 2668 2669 cmd.payloads = payloads; 2670 cmd.number_of_payloads = ARRAY_SIZE(payloads); 2671 2672 /* TODO route this through drm i2c_adapter */ 2673 result = dal_i2caux_submit_i2c_command( 2674 ddc->ctx->i2caux, 2675 ddc, 2676 &cmd); 2677 } 2678 2679 dal_gpio_destroy_ddc(&ddc); 2680 2681 return result; 2682 } 2683 2684 /** 2685 * Read external display connection info table through i2c. 2686 * validate the GUID and checksum. 2687 * 2688 * @return enum bp_result whether all data was sucessfully read 2689 */ 2690 static enum bp_result get_ext_display_connection_info( 2691 struct bios_parser *bp, 2692 ATOM_OBJECT *opm_object, 2693 ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *ext_display_connection_info_tbl) 2694 { 2695 bool config_tbl_present = false; 2696 ATOM_I2C_RECORD *i2c_record = NULL; 2697 uint32_t i = 0; 2698 2699 if (opm_object == NULL) 2700 return BP_RESULT_BADINPUT; 2701 2702 i2c_record = get_i2c_record(bp, opm_object); 2703 2704 if (i2c_record != NULL) { 2705 ATOM_GPIO_I2C_INFO *gpio_i2c_header; 2706 struct graphics_object_i2c_info i2c_info; 2707 2708 gpio_i2c_header = GET_IMAGE(ATOM_GPIO_I2C_INFO, 2709 bp->master_data_tbl->ListOfDataTables.GPIO_I2C_Info); 2710 2711 if (NULL == gpio_i2c_header) 2712 return BP_RESULT_BADBIOSTABLE; 2713 2714 if (get_gpio_i2c_info(bp, i2c_record, &i2c_info) != 2715 BP_RESULT_OK) 2716 return BP_RESULT_BADBIOSTABLE; 2717 2718 if (i2c_read(bp, 2719 &i2c_info, 2720 (uint8_t *)ext_display_connection_info_tbl, 2721 sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO))) { 2722 config_tbl_present = true; 2723 } 2724 } 2725 2726 /* Validate GUID */ 2727 if (config_tbl_present) 2728 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; i++) { 2729 if (ext_display_connection_info_tbl->ucGuid[i] 2730 != ext_display_connection_guid[i]) { 2731 config_tbl_present = false; 2732 break; 2733 } 2734 } 2735 2736 /* Validate checksum */ 2737 if (config_tbl_present) { 2738 uint8_t check_sum = 0; 2739 uint8_t *buf = 2740 (uint8_t *)ext_display_connection_info_tbl; 2741 2742 for (i = 0; i < sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO); 2743 i++) { 2744 check_sum += buf[i]; 2745 } 2746 2747 if (check_sum != 0) 2748 config_tbl_present = false; 2749 } 2750 2751 if (config_tbl_present) 2752 return BP_RESULT_OK; 2753 else 2754 return BP_RESULT_FAILURE; 2755 } 2756 2757 /* 2758 * Gets the first device ID in the same group as the given ID for enumerating. 2759 * For instance, if any DFP device ID is passed, returns the device ID for DFP1. 2760 * 2761 * The first device ID in the same group as the passed device ID, or 0 if no 2762 * matching device group found. 2763 */ 2764 static uint32_t enum_first_device_id(uint32_t dev_id) 2765 { 2766 /* Return the first in the group that this ID belongs to. */ 2767 if (dev_id & ATOM_DEVICE_CRT_SUPPORT) 2768 return ATOM_DEVICE_CRT1_SUPPORT; 2769 else if (dev_id & ATOM_DEVICE_DFP_SUPPORT) 2770 return ATOM_DEVICE_DFP1_SUPPORT; 2771 else if (dev_id & ATOM_DEVICE_LCD_SUPPORT) 2772 return ATOM_DEVICE_LCD1_SUPPORT; 2773 else if (dev_id & ATOM_DEVICE_TV_SUPPORT) 2774 return ATOM_DEVICE_TV1_SUPPORT; 2775 else if (dev_id & ATOM_DEVICE_CV_SUPPORT) 2776 return ATOM_DEVICE_CV_SUPPORT; 2777 2778 /* No group found for this device ID. */ 2779 2780 dm_error("%s: incorrect input %d\n", __func__, dev_id); 2781 /* No matching support flag for given device ID */ 2782 return 0; 2783 } 2784 2785 /* 2786 * Gets the next device ID in the group for a given device ID. 2787 * 2788 * The current device ID being enumerated on. 2789 * 2790 * The next device ID in the group, or 0 if no device exists. 2791 */ 2792 static uint32_t enum_next_dev_id(uint32_t dev_id) 2793 { 2794 /* Get next device ID in the group. */ 2795 switch (dev_id) { 2796 case ATOM_DEVICE_CRT1_SUPPORT: 2797 return ATOM_DEVICE_CRT2_SUPPORT; 2798 case ATOM_DEVICE_LCD1_SUPPORT: 2799 return ATOM_DEVICE_LCD2_SUPPORT; 2800 case ATOM_DEVICE_DFP1_SUPPORT: 2801 return ATOM_DEVICE_DFP2_SUPPORT; 2802 case ATOM_DEVICE_DFP2_SUPPORT: 2803 return ATOM_DEVICE_DFP3_SUPPORT; 2804 case ATOM_DEVICE_DFP3_SUPPORT: 2805 return ATOM_DEVICE_DFP4_SUPPORT; 2806 case ATOM_DEVICE_DFP4_SUPPORT: 2807 return ATOM_DEVICE_DFP5_SUPPORT; 2808 case ATOM_DEVICE_DFP5_SUPPORT: 2809 return ATOM_DEVICE_DFP6_SUPPORT; 2810 } 2811 2812 /* Done enumerating through devices. */ 2813 return 0; 2814 } 2815 2816 /* 2817 * Returns the new device tag record for patched BIOS object. 2818 * 2819 * [IN] pExtDisplayPath - External display path to copy device tag from. 2820 * [IN] deviceSupport - Bit vector for device ID support flags. 2821 * [OUT] pDeviceTag - Device tag structure to fill with patched data. 2822 * 2823 * True if a compatible device ID was found, false otherwise. 2824 */ 2825 static bool get_patched_device_tag( 2826 struct bios_parser *bp, 2827 EXT_DISPLAY_PATH *ext_display_path, 2828 uint32_t device_support, 2829 ATOM_CONNECTOR_DEVICE_TAG *device_tag) 2830 { 2831 uint32_t dev_id; 2832 /* Use fallback behaviour if not supported. */ 2833 if (!bp->remap_device_tags) { 2834 device_tag->ulACPIDeviceEnum = 2835 cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum)); 2836 device_tag->usDeviceID = 2837 cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceTag)); 2838 return true; 2839 } 2840 2841 /* Find the first unused in the same group. */ 2842 dev_id = enum_first_device_id(le16_to_cpu(ext_display_path->usDeviceTag)); 2843 while (dev_id != 0) { 2844 /* Assign this device ID if supported. */ 2845 if ((device_support & dev_id) != 0) { 2846 device_tag->ulACPIDeviceEnum = 2847 cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum)); 2848 device_tag->usDeviceID = cpu_to_le16((USHORT) dev_id); 2849 return true; 2850 } 2851 2852 dev_id = enum_next_dev_id(dev_id); 2853 } 2854 2855 /* No compatible device ID found. */ 2856 return false; 2857 } 2858 2859 /* 2860 * Adds a device tag to a BIOS object's device tag record if there is 2861 * matching device ID supported. 2862 * 2863 * pObject - Pointer to the BIOS object to add the device tag to. 2864 * pExtDisplayPath - Display path to retrieve base device ID from. 2865 * pDeviceSupport - Pointer to bit vector for supported device IDs. 2866 */ 2867 static void add_device_tag_from_ext_display_path( 2868 struct bios_parser *bp, 2869 ATOM_OBJECT *object, 2870 EXT_DISPLAY_PATH *ext_display_path, 2871 uint32_t *device_support) 2872 { 2873 /* Get device tag record for object. */ 2874 ATOM_CONNECTOR_DEVICE_TAG *device_tag = NULL; 2875 ATOM_CONNECTOR_DEVICE_TAG_RECORD *device_tag_record = NULL; 2876 enum bp_result result = 2877 bios_parser_get_device_tag_record( 2878 bp, object, &device_tag_record); 2879 2880 if ((le16_to_cpu(ext_display_path->usDeviceTag) != CONNECTOR_OBJECT_ID_NONE) 2881 && (result == BP_RESULT_OK)) { 2882 uint8_t index; 2883 2884 if ((device_tag_record->ucNumberOfDevice == 1) && 2885 (le16_to_cpu(device_tag_record->asDeviceTag[0].usDeviceID) == 0)) { 2886 /*Workaround bug in current VBIOS releases where 2887 * ucNumberOfDevice = 1 but there is no actual device 2888 * tag data. This w/a is temporary until the updated 2889 * VBIOS is distributed. */ 2890 device_tag_record->ucNumberOfDevice = 2891 device_tag_record->ucNumberOfDevice - 1; 2892 } 2893 2894 /* Attempt to find a matching device ID. */ 2895 index = device_tag_record->ucNumberOfDevice; 2896 device_tag = &device_tag_record->asDeviceTag[index]; 2897 if (get_patched_device_tag( 2898 bp, 2899 ext_display_path, 2900 *device_support, 2901 device_tag)) { 2902 /* Update cached device support to remove assigned ID. 2903 */ 2904 *device_support &= ~le16_to_cpu(device_tag->usDeviceID); 2905 device_tag_record->ucNumberOfDevice++; 2906 } 2907 } 2908 } 2909 2910 /* 2911 * Read out a single EXT_DISPLAY_PATH from the external display connection info 2912 * table. The specific entry in the table is determined by the enum_id passed 2913 * in. 2914 * 2915 * EXT_DISPLAY_PATH describing a single Configuration table entry 2916 */ 2917 2918 #define INVALID_CONNECTOR 0xffff 2919 2920 static EXT_DISPLAY_PATH *get_ext_display_path_entry( 2921 ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *config_table, 2922 uint32_t bios_object_id) 2923 { 2924 EXT_DISPLAY_PATH *ext_display_path; 2925 uint32_t ext_display_path_index = 2926 ((bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT) - 1; 2927 2928 if (ext_display_path_index >= MAX_NUMBER_OF_EXT_DISPLAY_PATH) 2929 return NULL; 2930 2931 ext_display_path = &config_table->sPath[ext_display_path_index]; 2932 2933 if (le16_to_cpu(ext_display_path->usDeviceConnector) == INVALID_CONNECTOR) 2934 ext_display_path->usDeviceConnector = cpu_to_le16(0); 2935 2936 return ext_display_path; 2937 } 2938 2939 /* 2940 * Get AUX/DDC information of input object id 2941 * 2942 * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record 2943 * IR 2944 */ 2945 static ATOM_CONNECTOR_AUXDDC_LUT_RECORD *get_ext_connector_aux_ddc_lut_record( 2946 struct bios_parser *bp, 2947 ATOM_OBJECT *object) 2948 { 2949 uint32_t offset; 2950 ATOM_COMMON_RECORD_HEADER *header; 2951 2952 if (!object) { 2953 BREAK_TO_DEBUGGER(); 2954 /* Invalid object */ 2955 return NULL; 2956 } 2957 2958 offset = le16_to_cpu(object->usRecordOffset) 2959 + bp->object_info_tbl_offset; 2960 2961 for (;;) { 2962 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); 2963 2964 if (!header) 2965 return NULL; 2966 2967 if (LAST_RECORD_TYPE == header->ucRecordType || 2968 0 == header->ucRecordSize) 2969 break; 2970 2971 if (ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE == 2972 header->ucRecordType && 2973 sizeof(ATOM_CONNECTOR_AUXDDC_LUT_RECORD) <= 2974 header->ucRecordSize) 2975 return (ATOM_CONNECTOR_AUXDDC_LUT_RECORD *)(header); 2976 2977 offset += header->ucRecordSize; 2978 } 2979 2980 return NULL; 2981 } 2982 2983 /* 2984 * Get AUX/DDC information of input object id 2985 * 2986 * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record 2987 * IR 2988 */ 2989 static ATOM_CONNECTOR_HPDPIN_LUT_RECORD *get_ext_connector_hpd_pin_lut_record( 2990 struct bios_parser *bp, 2991 ATOM_OBJECT *object) 2992 { 2993 uint32_t offset; 2994 ATOM_COMMON_RECORD_HEADER *header; 2995 2996 if (!object) { 2997 BREAK_TO_DEBUGGER(); 2998 /* Invalid object */ 2999 return NULL; 3000 } 3001 3002 offset = le16_to_cpu(object->usRecordOffset) 3003 + bp->object_info_tbl_offset; 3004 3005 for (;;) { 3006 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); 3007 3008 if (!header) 3009 return NULL; 3010 3011 if (LAST_RECORD_TYPE == header->ucRecordType || 3012 0 == header->ucRecordSize) 3013 break; 3014 3015 if (ATOM_CONNECTOR_HPDPIN_LUT_RECORD_TYPE == 3016 header->ucRecordType && 3017 sizeof(ATOM_CONNECTOR_HPDPIN_LUT_RECORD) <= 3018 header->ucRecordSize) 3019 return (ATOM_CONNECTOR_HPDPIN_LUT_RECORD *)header; 3020 3021 offset += header->ucRecordSize; 3022 } 3023 3024 return NULL; 3025 } 3026 3027 /* 3028 * Check whether we need to patch the VBIOS connector info table with 3029 * data from an external display connection info table. This is 3030 * necessary to support MXM boards with an OPM (output personality 3031 * module). With these designs, the VBIOS connector info table 3032 * specifies an MXM_CONNECTOR with a unique ID. The driver retrieves 3033 * the external connection info table through i2c and then looks up the 3034 * connector ID to find the real connector type (e.g. DFP1). 3035 * 3036 */ 3037 static enum bp_result patch_bios_image_from_ext_display_connection_info( 3038 struct bios_parser *bp) 3039 { 3040 ATOM_OBJECT_TABLE *connector_tbl; 3041 uint32_t connector_tbl_offset; 3042 struct graphics_object_id object_id; 3043 ATOM_OBJECT *object; 3044 ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO ext_display_connection_info_tbl; 3045 EXT_DISPLAY_PATH *ext_display_path; 3046 ATOM_CONNECTOR_AUXDDC_LUT_RECORD *aux_ddc_lut_record = NULL; 3047 ATOM_I2C_RECORD *i2c_record = NULL; 3048 ATOM_CONNECTOR_HPDPIN_LUT_RECORD *hpd_pin_lut_record = NULL; 3049 ATOM_HPD_INT_RECORD *hpd_record = NULL; 3050 ATOM_OBJECT_TABLE *encoder_table; 3051 uint32_t encoder_table_offset; 3052 ATOM_OBJECT *opm_object = NULL; 3053 uint32_t i = 0; 3054 struct graphics_object_id opm_object_id = 3055 dal_graphics_object_id_init( 3056 GENERIC_ID_MXM_OPM, 3057 ENUM_ID_1, 3058 OBJECT_TYPE_GENERIC); 3059 ATOM_CONNECTOR_DEVICE_TAG_RECORD *dev_tag_record; 3060 uint32_t cached_device_support = 3061 le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport); 3062 3063 uint32_t dst_number; 3064 uint16_t *dst_object_id_list; 3065 3066 opm_object = get_bios_object(bp, opm_object_id); 3067 if (!opm_object) 3068 return BP_RESULT_UNSUPPORTED; 3069 3070 memset(&ext_display_connection_info_tbl, 0, 3071 sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO)); 3072 3073 connector_tbl_offset = bp->object_info_tbl_offset 3074 + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); 3075 connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset); 3076 3077 /* Read Connector info table from EEPROM through i2c */ 3078 if (get_ext_display_connection_info(bp, 3079 opm_object, 3080 &ext_display_connection_info_tbl) != BP_RESULT_OK) { 3081 3082 dm_logger_write(bp->base.ctx->logger, LOG_WARNING, 3083 "%s: Failed to read Connection Info Table", __func__); 3084 return BP_RESULT_UNSUPPORTED; 3085 } 3086 3087 /* Get pointer to AUX/DDC and HPD LUTs */ 3088 aux_ddc_lut_record = 3089 get_ext_connector_aux_ddc_lut_record(bp, opm_object); 3090 hpd_pin_lut_record = 3091 get_ext_connector_hpd_pin_lut_record(bp, opm_object); 3092 3093 if ((aux_ddc_lut_record == NULL) || (hpd_pin_lut_record == NULL)) 3094 return BP_RESULT_UNSUPPORTED; 3095 3096 /* Cache support bits for currently unmapped device types. */ 3097 if (bp->remap_device_tags) { 3098 for (i = 0; i < connector_tbl->ucNumberOfObjects; ++i) { 3099 uint32_t j; 3100 /* Remove support for all non-MXM connectors. */ 3101 object = &connector_tbl->asObjects[i]; 3102 object_id = object_id_from_bios_object_id( 3103 le16_to_cpu(object->usObjectID)); 3104 if ((OBJECT_TYPE_CONNECTOR != object_id.type) || 3105 (CONNECTOR_ID_MXM == object_id.id)) 3106 continue; 3107 3108 /* Remove support for all device tags. */ 3109 if (bios_parser_get_device_tag_record( 3110 bp, object, &dev_tag_record) != BP_RESULT_OK) 3111 continue; 3112 3113 for (j = 0; j < dev_tag_record->ucNumberOfDevice; ++j) { 3114 ATOM_CONNECTOR_DEVICE_TAG *device_tag = 3115 &dev_tag_record->asDeviceTag[j]; 3116 cached_device_support &= 3117 ~le16_to_cpu(device_tag->usDeviceID); 3118 } 3119 } 3120 } 3121 3122 /* Find all MXM connector objects and patch them with connector info 3123 * from the external display connection info table. */ 3124 for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) { 3125 uint32_t j; 3126 3127 object = &connector_tbl->asObjects[i]; 3128 object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID)); 3129 if ((OBJECT_TYPE_CONNECTOR != object_id.type) || 3130 (CONNECTOR_ID_MXM != object_id.id)) 3131 continue; 3132 3133 /* Get the correct connection info table entry based on the enum 3134 * id. */ 3135 ext_display_path = get_ext_display_path_entry( 3136 &ext_display_connection_info_tbl, 3137 le16_to_cpu(object->usObjectID)); 3138 if (!ext_display_path) 3139 return BP_RESULT_FAILURE; 3140 3141 /* Patch device connector ID */ 3142 object->usObjectID = 3143 cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceConnector)); 3144 3145 /* Patch device tag, ulACPIDeviceEnum. */ 3146 add_device_tag_from_ext_display_path( 3147 bp, 3148 object, 3149 ext_display_path, 3150 &cached_device_support); 3151 3152 /* Patch HPD info */ 3153 if (ext_display_path->ucExtHPDPINLutIndex < 3154 MAX_NUMBER_OF_EXT_HPDPIN_LUT_ENTRIES) { 3155 hpd_record = get_hpd_record(bp, object); 3156 if (hpd_record) { 3157 uint8_t index = 3158 ext_display_path->ucExtHPDPINLutIndex; 3159 hpd_record->ucHPDIntGPIOID = 3160 hpd_pin_lut_record->ucHPDPINMap[index]; 3161 } else { 3162 BREAK_TO_DEBUGGER(); 3163 /* Invalid hpd record */ 3164 return BP_RESULT_FAILURE; 3165 } 3166 } 3167 3168 /* Patch I2C/AUX info */ 3169 if (ext_display_path->ucExtHPDPINLutIndex < 3170 MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES) { 3171 i2c_record = get_i2c_record(bp, object); 3172 if (i2c_record) { 3173 uint8_t index = 3174 ext_display_path->ucExtAUXDDCLutIndex; 3175 i2c_record->sucI2cId = 3176 aux_ddc_lut_record->ucAUXDDCMap[index]; 3177 } else { 3178 BREAK_TO_DEBUGGER(); 3179 /* Invalid I2C record */ 3180 return BP_RESULT_FAILURE; 3181 } 3182 } 3183 3184 /* Merge with other MXM connectors that map to the same physical 3185 * connector. */ 3186 for (j = i + 1; 3187 j < connector_tbl->ucNumberOfObjects; j++) { 3188 ATOM_OBJECT *next_object; 3189 struct graphics_object_id next_object_id; 3190 EXT_DISPLAY_PATH *next_ext_display_path; 3191 3192 next_object = &connector_tbl->asObjects[j]; 3193 next_object_id = object_id_from_bios_object_id( 3194 le16_to_cpu(next_object->usObjectID)); 3195 3196 if ((OBJECT_TYPE_CONNECTOR != next_object_id.type) && 3197 (CONNECTOR_ID_MXM == next_object_id.id)) 3198 continue; 3199 3200 next_ext_display_path = get_ext_display_path_entry( 3201 &ext_display_connection_info_tbl, 3202 le16_to_cpu(next_object->usObjectID)); 3203 3204 if (next_ext_display_path == NULL) 3205 return BP_RESULT_FAILURE; 3206 3207 /* Merge if using same connector. */ 3208 if ((le16_to_cpu(next_ext_display_path->usDeviceConnector) == 3209 le16_to_cpu(ext_display_path->usDeviceConnector)) && 3210 (le16_to_cpu(ext_display_path->usDeviceConnector) != 0)) { 3211 /* Clear duplicate connector from table. */ 3212 next_object->usObjectID = cpu_to_le16(0); 3213 add_device_tag_from_ext_display_path( 3214 bp, 3215 object, 3216 ext_display_path, 3217 &cached_device_support); 3218 } 3219 } 3220 } 3221 3222 /* Find all encoders which have an MXM object as their destination. 3223 * Replace the MXM object with the real connector Id from the external 3224 * display connection info table */ 3225 3226 encoder_table_offset = bp->object_info_tbl_offset 3227 + le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset); 3228 encoder_table = GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset); 3229 3230 for (i = 0; i < encoder_table->ucNumberOfObjects; i++) { 3231 uint32_t j; 3232 3233 object = &encoder_table->asObjects[i]; 3234 3235 dst_number = get_dest_obj_list(bp, object, &dst_object_id_list); 3236 3237 for (j = 0; j < dst_number; j++) { 3238 object_id = object_id_from_bios_object_id( 3239 dst_object_id_list[j]); 3240 3241 if ((OBJECT_TYPE_CONNECTOR != object_id.type) || 3242 (CONNECTOR_ID_MXM != object_id.id)) 3243 continue; 3244 3245 /* Get the correct connection info table entry based on 3246 * the enum id. */ 3247 ext_display_path = 3248 get_ext_display_path_entry( 3249 &ext_display_connection_info_tbl, 3250 dst_object_id_list[j]); 3251 3252 if (ext_display_path == NULL) 3253 return BP_RESULT_FAILURE; 3254 3255 dst_object_id_list[j] = 3256 le16_to_cpu(ext_display_path->usDeviceConnector); 3257 } 3258 } 3259 3260 return BP_RESULT_OK; 3261 } 3262 3263 /* 3264 * Check whether we need to patch the VBIOS connector info table with 3265 * data from an external display connection info table. This is 3266 * necessary to support MXM boards with an OPM (output personality 3267 * module). With these designs, the VBIOS connector info table 3268 * specifies an MXM_CONNECTOR with a unique ID. The driver retrieves 3269 * the external connection info table through i2c and then looks up the 3270 * connector ID to find the real connector type (e.g. DFP1). 3271 * 3272 */ 3273 3274 static void process_ext_display_connection_info(struct bios_parser *bp) 3275 { 3276 ATOM_OBJECT_TABLE *connector_tbl; 3277 uint32_t connector_tbl_offset; 3278 struct graphics_object_id object_id; 3279 ATOM_OBJECT *object; 3280 bool mxm_connector_found = false; 3281 bool null_entry_found = false; 3282 uint32_t i = 0; 3283 3284 connector_tbl_offset = bp->object_info_tbl_offset + 3285 le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); 3286 connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset); 3287 3288 /* Look for MXM connectors to determine whether we need patch the VBIOS 3289 * connector info table. Look for null entries to determine whether we 3290 * need to compact connector table. */ 3291 for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) { 3292 object = &connector_tbl->asObjects[i]; 3293 object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID)); 3294 3295 if ((OBJECT_TYPE_CONNECTOR == object_id.type) && 3296 (CONNECTOR_ID_MXM == object_id.id)) { 3297 /* Once we found MXM connector - we can break */ 3298 mxm_connector_found = true; 3299 break; 3300 } else if (OBJECT_TYPE_CONNECTOR != object_id.type) { 3301 /* We need to continue looping - to check if MXM 3302 * connector present */ 3303 null_entry_found = true; 3304 } 3305 } 3306 3307 /* Patch BIOS image */ 3308 if (mxm_connector_found || null_entry_found) { 3309 uint32_t connectors_num = 0; 3310 uint8_t *original_bios; 3311 /* Step 1: Replace bios image with the new copy which will be 3312 * patched */ 3313 bp->base.bios_local_image = kzalloc(bp->base.bios_size, 3314 GFP_KERNEL); 3315 if (bp->base.bios_local_image == NULL) { 3316 BREAK_TO_DEBUGGER(); 3317 /* Failed to alloc bp->base.bios_local_image */ 3318 return; 3319 } 3320 3321 memmove(bp->base.bios_local_image, bp->base.bios, bp->base.bios_size); 3322 original_bios = bp->base.bios; 3323 bp->base.bios = bp->base.bios_local_image; 3324 connector_tbl = 3325 GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset); 3326 3327 /* Step 2: (only if MXM connector found) Patch BIOS image with 3328 * info from external module */ 3329 if (mxm_connector_found && 3330 patch_bios_image_from_ext_display_connection_info(bp) != 3331 BP_RESULT_OK) { 3332 /* Patching the bios image has failed. We will copy 3333 * again original image provided and afterwards 3334 * only remove null entries */ 3335 memmove( 3336 bp->base.bios_local_image, 3337 original_bios, 3338 bp->base.bios_size); 3339 } 3340 3341 /* Step 3: Compact connector table (remove null entries, valid 3342 * entries moved to beginning) */ 3343 for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) { 3344 object = &connector_tbl->asObjects[i]; 3345 object_id = object_id_from_bios_object_id( 3346 le16_to_cpu(object->usObjectID)); 3347 3348 if (OBJECT_TYPE_CONNECTOR != object_id.type) 3349 continue; 3350 3351 if (i != connectors_num) { 3352 memmove( 3353 &connector_tbl-> 3354 asObjects[connectors_num], 3355 object, 3356 sizeof(ATOM_OBJECT)); 3357 } 3358 ++connectors_num; 3359 } 3360 connector_tbl->ucNumberOfObjects = (uint8_t)connectors_num; 3361 } 3362 } 3363 3364 static void bios_parser_post_init(struct dc_bios *dcb) 3365 { 3366 struct bios_parser *bp = BP_FROM_DCB(dcb); 3367 3368 process_ext_display_connection_info(bp); 3369 } 3370 3371 /** 3372 * bios_parser_set_scratch_critical_state 3373 * 3374 * @brief 3375 * update critical state bit in VBIOS scratch register 3376 * 3377 * @param 3378 * bool - to set or reset state 3379 */ 3380 static void bios_parser_set_scratch_critical_state( 3381 struct dc_bios *dcb, 3382 bool state) 3383 { 3384 bios_set_scratch_critical_state(dcb, state); 3385 } 3386 3387 /* 3388 * get_integrated_info_v8 3389 * 3390 * @brief 3391 * Get V8 integrated BIOS information 3392 * 3393 * @param 3394 * bios_parser *bp - [in]BIOS parser handler to get master data table 3395 * integrated_info *info - [out] store and output integrated info 3396 * 3397 * @return 3398 * enum bp_result - BP_RESULT_OK if information is available, 3399 * BP_RESULT_BADBIOSTABLE otherwise. 3400 */ 3401 static enum bp_result get_integrated_info_v8( 3402 struct bios_parser *bp, 3403 struct integrated_info *info) 3404 { 3405 ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8; 3406 uint32_t i; 3407 3408 info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8, 3409 bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); 3410 3411 if (info_v8 == NULL) 3412 return BP_RESULT_BADBIOSTABLE; 3413 info->boot_up_engine_clock = le32_to_cpu(info_v8->ulBootUpEngineClock) * 10; 3414 info->dentist_vco_freq = le32_to_cpu(info_v8->ulDentistVCOFreq) * 10; 3415 info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10; 3416 3417 for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { 3418 /* Convert [10KHz] into [KHz] */ 3419 info->disp_clk_voltage[i].max_supported_clk = 3420 le32_to_cpu(info_v8->sDISPCLK_Voltage[i]. 3421 ulMaximumSupportedCLK) * 10; 3422 info->disp_clk_voltage[i].voltage_index = 3423 le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex); 3424 } 3425 3426 info->boot_up_req_display_vector = 3427 le32_to_cpu(info_v8->ulBootUpReqDisplayVector); 3428 info->gpu_cap_info = 3429 le32_to_cpu(info_v8->ulGPUCapInfo); 3430 3431 /* 3432 * system_config: Bit[0] = 0 : PCIE power gating disabled 3433 * = 1 : PCIE power gating enabled 3434 * Bit[1] = 0 : DDR-PLL shut down disabled 3435 * = 1 : DDR-PLL shut down enabled 3436 * Bit[2] = 0 : DDR-PLL power down disabled 3437 * = 1 : DDR-PLL power down enabled 3438 */ 3439 info->system_config = le32_to_cpu(info_v8->ulSystemConfig); 3440 info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo); 3441 info->boot_up_nb_voltage = 3442 le16_to_cpu(info_v8->usBootUpNBVoltage); 3443 info->ext_disp_conn_info_offset = 3444 le16_to_cpu(info_v8->usExtDispConnInfoOffset); 3445 info->memory_type = info_v8->ucMemoryType; 3446 info->ma_channel_number = info_v8->ucUMAChannelNumber; 3447 info->gmc_restore_reset_time = 3448 le32_to_cpu(info_v8->ulGMCRestoreResetTime); 3449 3450 info->minimum_n_clk = 3451 le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]); 3452 for (i = 1; i < 4; ++i) 3453 info->minimum_n_clk = 3454 info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ? 3455 info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]); 3456 3457 info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk); 3458 info->ddr_dll_power_up_time = 3459 le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime); 3460 info->ddr_pll_power_up_time = 3461 le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime); 3462 info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType); 3463 info->lvds_ss_percentage = 3464 le16_to_cpu(info_v8->usLvdsSSPercentage); 3465 info->lvds_sspread_rate_in_10hz = 3466 le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz); 3467 info->hdmi_ss_percentage = 3468 le16_to_cpu(info_v8->usHDMISSPercentage); 3469 info->hdmi_sspread_rate_in_10hz = 3470 le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz); 3471 info->dvi_ss_percentage = 3472 le16_to_cpu(info_v8->usDVISSPercentage); 3473 info->dvi_sspread_rate_in_10_hz = 3474 le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz); 3475 3476 info->max_lvds_pclk_freq_in_single_link = 3477 le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink); 3478 info->lvds_misc = info_v8->ucLvdsMisc; 3479 info->lvds_pwr_on_seq_dig_on_to_de_in_4ms = 3480 info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms; 3481 info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms = 3482 info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms; 3483 info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms = 3484 info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms; 3485 info->lvds_pwr_off_seq_vary_bl_to_de_in4ms = 3486 info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms; 3487 info->lvds_pwr_off_seq_de_to_dig_on_in4ms = 3488 info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms; 3489 info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms = 3490 info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; 3491 info->lvds_off_to_on_delay_in_4ms = 3492 info_v8->ucLVDSOffToOnDelay_in4Ms; 3493 info->lvds_bit_depth_control_val = 3494 le32_to_cpu(info_v8->ulLCDBitDepthControlVal); 3495 3496 for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) { 3497 /* Convert [10KHz] into [KHz] */ 3498 info->avail_s_clk[i].supported_s_clk = 3499 le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10; 3500 info->avail_s_clk[i].voltage_index = 3501 le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex); 3502 info->avail_s_clk[i].voltage_id = 3503 le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID); 3504 } 3505 3506 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) { 3507 info->ext_disp_conn_info.gu_id[i] = 3508 info_v8->sExtDispConnInfo.ucGuid[i]; 3509 } 3510 3511 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) { 3512 info->ext_disp_conn_info.path[i].device_connector_id = 3513 object_id_from_bios_object_id( 3514 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector)); 3515 3516 info->ext_disp_conn_info.path[i].ext_encoder_obj_id = 3517 object_id_from_bios_object_id( 3518 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId)); 3519 3520 info->ext_disp_conn_info.path[i].device_tag = 3521 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag); 3522 info->ext_disp_conn_info.path[i].device_acpi_enum = 3523 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum); 3524 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index = 3525 info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex; 3526 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index = 3527 info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex; 3528 info->ext_disp_conn_info.path[i].channel_mapping.raw = 3529 info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping; 3530 } 3531 info->ext_disp_conn_info.checksum = 3532 info_v8->sExtDispConnInfo.ucChecksum; 3533 3534 return BP_RESULT_OK; 3535 } 3536 3537 /* 3538 * get_integrated_info_v8 3539 * 3540 * @brief 3541 * Get V8 integrated BIOS information 3542 * 3543 * @param 3544 * bios_parser *bp - [in]BIOS parser handler to get master data table 3545 * integrated_info *info - [out] store and output integrated info 3546 * 3547 * @return 3548 * enum bp_result - BP_RESULT_OK if information is available, 3549 * BP_RESULT_BADBIOSTABLE otherwise. 3550 */ 3551 static enum bp_result get_integrated_info_v9( 3552 struct bios_parser *bp, 3553 struct integrated_info *info) 3554 { 3555 ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9; 3556 uint32_t i; 3557 3558 info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9, 3559 bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); 3560 3561 if (!info_v9) 3562 return BP_RESULT_BADBIOSTABLE; 3563 3564 info->boot_up_engine_clock = le32_to_cpu(info_v9->ulBootUpEngineClock) * 10; 3565 info->dentist_vco_freq = le32_to_cpu(info_v9->ulDentistVCOFreq) * 10; 3566 info->boot_up_uma_clock = le32_to_cpu(info_v9->ulBootUpUMAClock) * 10; 3567 3568 for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { 3569 /* Convert [10KHz] into [KHz] */ 3570 info->disp_clk_voltage[i].max_supported_clk = 3571 le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10; 3572 info->disp_clk_voltage[i].voltage_index = 3573 le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex); 3574 } 3575 3576 info->boot_up_req_display_vector = 3577 le32_to_cpu(info_v9->ulBootUpReqDisplayVector); 3578 info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo); 3579 3580 /* 3581 * system_config: Bit[0] = 0 : PCIE power gating disabled 3582 * = 1 : PCIE power gating enabled 3583 * Bit[1] = 0 : DDR-PLL shut down disabled 3584 * = 1 : DDR-PLL shut down enabled 3585 * Bit[2] = 0 : DDR-PLL power down disabled 3586 * = 1 : DDR-PLL power down enabled 3587 */ 3588 info->system_config = le32_to_cpu(info_v9->ulSystemConfig); 3589 info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo); 3590 info->boot_up_nb_voltage = le16_to_cpu(info_v9->usBootUpNBVoltage); 3591 info->ext_disp_conn_info_offset = le16_to_cpu(info_v9->usExtDispConnInfoOffset); 3592 info->memory_type = info_v9->ucMemoryType; 3593 info->ma_channel_number = info_v9->ucUMAChannelNumber; 3594 info->gmc_restore_reset_time = le32_to_cpu(info_v9->ulGMCRestoreResetTime); 3595 3596 info->minimum_n_clk = le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]); 3597 for (i = 1; i < 4; ++i) 3598 info->minimum_n_clk = 3599 info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ? 3600 info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]); 3601 3602 info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk); 3603 info->ddr_dll_power_up_time = le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime); 3604 info->ddr_pll_power_up_time = le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime); 3605 info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType); 3606 info->lvds_ss_percentage = le16_to_cpu(info_v9->usLvdsSSPercentage); 3607 info->lvds_sspread_rate_in_10hz = le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz); 3608 info->hdmi_ss_percentage = le16_to_cpu(info_v9->usHDMISSPercentage); 3609 info->hdmi_sspread_rate_in_10hz = le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz); 3610 info->dvi_ss_percentage = le16_to_cpu(info_v9->usDVISSPercentage); 3611 info->dvi_sspread_rate_in_10_hz = le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz); 3612 3613 info->max_lvds_pclk_freq_in_single_link = 3614 le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink); 3615 info->lvds_misc = info_v9->ucLvdsMisc; 3616 info->lvds_pwr_on_seq_dig_on_to_de_in_4ms = 3617 info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms; 3618 info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms = 3619 info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms; 3620 info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms = 3621 info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms; 3622 info->lvds_pwr_off_seq_vary_bl_to_de_in4ms = 3623 info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms; 3624 info->lvds_pwr_off_seq_de_to_dig_on_in4ms = 3625 info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms; 3626 info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms = 3627 info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms; 3628 info->lvds_off_to_on_delay_in_4ms = 3629 info_v9->ucLVDSOffToOnDelay_in4Ms; 3630 info->lvds_bit_depth_control_val = 3631 le32_to_cpu(info_v9->ulLCDBitDepthControlVal); 3632 3633 for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) { 3634 /* Convert [10KHz] into [KHz] */ 3635 info->avail_s_clk[i].supported_s_clk = 3636 le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10; 3637 info->avail_s_clk[i].voltage_index = 3638 le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex); 3639 info->avail_s_clk[i].voltage_id = 3640 le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID); 3641 } 3642 3643 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) { 3644 info->ext_disp_conn_info.gu_id[i] = 3645 info_v9->sExtDispConnInfo.ucGuid[i]; 3646 } 3647 3648 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) { 3649 info->ext_disp_conn_info.path[i].device_connector_id = 3650 object_id_from_bios_object_id( 3651 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector)); 3652 3653 info->ext_disp_conn_info.path[i].ext_encoder_obj_id = 3654 object_id_from_bios_object_id( 3655 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId)); 3656 3657 info->ext_disp_conn_info.path[i].device_tag = 3658 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag); 3659 info->ext_disp_conn_info.path[i].device_acpi_enum = 3660 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum); 3661 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index = 3662 info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex; 3663 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index = 3664 info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex; 3665 info->ext_disp_conn_info.path[i].channel_mapping.raw = 3666 info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping; 3667 } 3668 info->ext_disp_conn_info.checksum = 3669 info_v9->sExtDispConnInfo.ucChecksum; 3670 3671 return BP_RESULT_OK; 3672 } 3673 3674 /* 3675 * construct_integrated_info 3676 * 3677 * @brief 3678 * Get integrated BIOS information based on table revision 3679 * 3680 * @param 3681 * bios_parser *bp - [in]BIOS parser handler to get master data table 3682 * integrated_info *info - [out] store and output integrated info 3683 * 3684 * @return 3685 * enum bp_result - BP_RESULT_OK if information is available, 3686 * BP_RESULT_BADBIOSTABLE otherwise. 3687 */ 3688 static enum bp_result construct_integrated_info( 3689 struct bios_parser *bp, 3690 struct integrated_info *info) 3691 { 3692 enum bp_result result = BP_RESULT_BADBIOSTABLE; 3693 3694 ATOM_COMMON_TABLE_HEADER *header; 3695 struct atom_data_revision revision; 3696 3697 if (bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) { 3698 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, 3699 bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo); 3700 3701 get_atom_data_table_revision(header, &revision); 3702 3703 /* Don't need to check major revision as they are all 1 */ 3704 switch (revision.minor) { 3705 case 8: 3706 result = get_integrated_info_v8(bp, info); 3707 break; 3708 case 9: 3709 result = get_integrated_info_v9(bp, info); 3710 break; 3711 default: 3712 return result; 3713 3714 } 3715 } 3716 3717 /* Sort voltage table from low to high*/ 3718 if (result == BP_RESULT_OK) { 3719 struct clock_voltage_caps temp = {0, 0}; 3720 uint32_t i; 3721 uint32_t j; 3722 3723 for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) { 3724 for (j = i; j > 0; --j) { 3725 if ( 3726 info->disp_clk_voltage[j].max_supported_clk < 3727 info->disp_clk_voltage[j-1].max_supported_clk) { 3728 /* swap j and j - 1*/ 3729 temp = info->disp_clk_voltage[j-1]; 3730 info->disp_clk_voltage[j-1] = 3731 info->disp_clk_voltage[j]; 3732 info->disp_clk_voltage[j] = temp; 3733 } 3734 } 3735 } 3736 3737 } 3738 3739 return result; 3740 } 3741 3742 static struct integrated_info *bios_parser_create_integrated_info( 3743 struct dc_bios *dcb) 3744 { 3745 struct bios_parser *bp = BP_FROM_DCB(dcb); 3746 struct integrated_info *info = NULL; 3747 3748 info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL); 3749 3750 if (info == NULL) { 3751 ASSERT_CRITICAL(0); 3752 return NULL; 3753 } 3754 3755 if (construct_integrated_info(bp, info) == BP_RESULT_OK) 3756 return info; 3757 3758 kfree(info); 3759 3760 return NULL; 3761 } 3762 3763 /******************************************************************************/ 3764 3765 static const struct dc_vbios_funcs vbios_funcs = { 3766 .get_connectors_number = bios_parser_get_connectors_number, 3767 3768 .get_encoder_id = bios_parser_get_encoder_id, 3769 3770 .get_connector_id = bios_parser_get_connector_id, 3771 3772 .get_dst_number = bios_parser_get_dst_number, 3773 3774 .get_src_obj = bios_parser_get_src_obj, 3775 3776 .get_dst_obj = bios_parser_get_dst_obj, 3777 3778 .get_i2c_info = bios_parser_get_i2c_info, 3779 3780 .get_voltage_ddc_info = bios_parser_get_voltage_ddc_info, 3781 3782 .get_thermal_ddc_info = bios_parser_get_thermal_ddc_info, 3783 3784 .get_hpd_info = bios_parser_get_hpd_info, 3785 3786 .get_device_tag = bios_parser_get_device_tag, 3787 3788 .get_firmware_info = bios_parser_get_firmware_info, 3789 3790 .get_spread_spectrum_info = bios_parser_get_spread_spectrum_info, 3791 3792 .get_ss_entry_number = bios_parser_get_ss_entry_number, 3793 3794 .get_embedded_panel_info = bios_parser_get_embedded_panel_info, 3795 3796 .get_gpio_pin_info = bios_parser_get_gpio_pin_info, 3797 3798 .get_embedded_panel_info = bios_parser_get_embedded_panel_info, 3799 3800 .get_gpio_pin_info = bios_parser_get_gpio_pin_info, 3801 3802 .get_encoder_cap_info = bios_parser_get_encoder_cap_info, 3803 3804 /* bios scratch register communication */ 3805 .is_accelerated_mode = bios_is_accelerated_mode, 3806 3807 .set_scratch_critical_state = bios_parser_set_scratch_critical_state, 3808 3809 .is_device_id_supported = bios_parser_is_device_id_supported, 3810 3811 /* COMMANDS */ 3812 .encoder_control = bios_parser_encoder_control, 3813 3814 .transmitter_control = bios_parser_transmitter_control, 3815 3816 .crt_control = bios_parser_crt_control, /* not used in DAL3. keep for now in case we need to support VGA on Bonaire */ 3817 3818 .enable_crtc = bios_parser_enable_crtc, 3819 3820 .adjust_pixel_clock = bios_parser_adjust_pixel_clock, 3821 3822 .set_pixel_clock = bios_parser_set_pixel_clock, 3823 3824 .set_dce_clock = bios_parser_set_dce_clock, 3825 3826 .enable_spread_spectrum_on_ppll = bios_parser_enable_spread_spectrum_on_ppll, 3827 3828 .program_crtc_timing = bios_parser_program_crtc_timing, /* still use. should probably retire and program directly */ 3829 3830 .crtc_source_select = bios_parser_crtc_source_select, /* still use. should probably retire and program directly */ 3831 3832 .program_display_engine_pll = bios_parser_program_display_engine_pll, 3833 3834 .enable_disp_power_gating = bios_parser_enable_disp_power_gating, 3835 3836 /* SW init and patch */ 3837 .post_init = bios_parser_post_init, /* patch vbios table for mxm module by reading i2c */ 3838 3839 .bios_parser_destroy = bios_parser_destroy, 3840 }; 3841 3842 static bool bios_parser_construct( 3843 struct bios_parser *bp, 3844 struct bp_init_data *init, 3845 enum dce_version dce_version) 3846 { 3847 uint16_t *rom_header_offset = NULL; 3848 ATOM_ROM_HEADER *rom_header = NULL; 3849 ATOM_OBJECT_HEADER *object_info_tbl; 3850 struct atom_data_revision tbl_rev = {0}; 3851 3852 if (!init) 3853 return false; 3854 3855 if (!init->bios) 3856 return false; 3857 3858 bp->base.funcs = &vbios_funcs; 3859 bp->base.bios = init->bios; 3860 bp->base.bios_size = bp->base.bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT; 3861 3862 bp->base.ctx = init->ctx; 3863 bp->base.bios_local_image = NULL; 3864 3865 rom_header_offset = 3866 GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER); 3867 3868 if (!rom_header_offset) 3869 return false; 3870 3871 rom_header = GET_IMAGE(ATOM_ROM_HEADER, *rom_header_offset); 3872 3873 if (!rom_header) 3874 return false; 3875 3876 get_atom_data_table_revision(&rom_header->sHeader, &tbl_rev); 3877 if (tbl_rev.major >= 2 && tbl_rev.minor >= 2) 3878 return false; 3879 3880 bp->master_data_tbl = 3881 GET_IMAGE(ATOM_MASTER_DATA_TABLE, 3882 rom_header->usMasterDataTableOffset); 3883 3884 if (!bp->master_data_tbl) 3885 return false; 3886 3887 bp->object_info_tbl_offset = DATA_TABLES(Object_Header); 3888 3889 if (!bp->object_info_tbl_offset) 3890 return false; 3891 3892 object_info_tbl = 3893 GET_IMAGE(ATOM_OBJECT_HEADER, bp->object_info_tbl_offset); 3894 3895 if (!object_info_tbl) 3896 return false; 3897 3898 get_atom_data_table_revision(&object_info_tbl->sHeader, 3899 &bp->object_info_tbl.revision); 3900 3901 if (bp->object_info_tbl.revision.major == 1 3902 && bp->object_info_tbl.revision.minor >= 3) { 3903 ATOM_OBJECT_HEADER_V3 *tbl_v3; 3904 3905 tbl_v3 = GET_IMAGE(ATOM_OBJECT_HEADER_V3, 3906 bp->object_info_tbl_offset); 3907 if (!tbl_v3) 3908 return false; 3909 3910 bp->object_info_tbl.v1_3 = tbl_v3; 3911 } else if (bp->object_info_tbl.revision.major == 1 3912 && bp->object_info_tbl.revision.minor >= 1) 3913 bp->object_info_tbl.v1_1 = object_info_tbl; 3914 else 3915 return false; 3916 3917 dal_bios_parser_init_cmd_tbl(bp); 3918 dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version); 3919 3920 bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base); 3921 3922 return true; 3923 } 3924 3925 /******************************************************************************/ 3926