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