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