3796 lines · c
1/*2 * Copyright 2012-15 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26#include "dm_services.h"27#include "core_types.h"28 29#include "ObjectID.h"30#include "atomfirmware.h"31 32#include "dc_bios_types.h"33#include "include/grph_object_ctrl_defs.h"34#include "include/bios_parser_interface.h"35#include "include/logger_interface.h"36 37#include "command_table2.h"38 39#include "bios_parser_helper.h"40#include "command_table_helper2.h"41#include "bios_parser2.h"42#include "bios_parser_types_internal2.h"43#include "bios_parser_interface.h"44 45#include "bios_parser_common.h"46 47#define DC_LOGGER \48 bp->base.ctx->logger49 50#define LAST_RECORD_TYPE 0xff51#define SMU9_SYSPLL0_ID 052 53static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,54 struct atom_i2c_record *record,55 struct graphics_object_i2c_info *info);56 57static enum bp_result bios_parser_get_firmware_info(58 struct dc_bios *dcb,59 struct dc_firmware_info *info);60 61static enum bp_result bios_parser_get_encoder_cap_info(62 struct dc_bios *dcb,63 struct graphics_object_id object_id,64 struct bp_encoder_cap_info *info);65 66static enum bp_result get_firmware_info_v3_1(67 struct bios_parser *bp,68 struct dc_firmware_info *info);69 70static enum bp_result get_firmware_info_v3_2(71 struct bios_parser *bp,72 struct dc_firmware_info *info);73 74static enum bp_result get_firmware_info_v3_4(75 struct bios_parser *bp,76 struct dc_firmware_info *info);77 78static enum bp_result get_firmware_info_v3_5(79 struct bios_parser *bp,80 struct dc_firmware_info *info);81 82static struct atom_hpd_int_record *get_hpd_record(struct bios_parser *bp,83 struct atom_display_object_path_v2 *object);84 85static struct atom_encoder_caps_record *get_encoder_cap_record(86 struct bios_parser *bp,87 struct atom_display_object_path_v2 *object);88 89#define BIOS_IMAGE_SIZE_OFFSET 290#define BIOS_IMAGE_SIZE_UNIT 51291 92#define DATA_TABLES(table) (bp->master_data_tbl->listOfdatatables.table)93 94static void bios_parser2_destruct(struct bios_parser *bp)95{96 kfree(bp->base.bios_local_image);97 kfree(bp->base.integrated_info);98}99 100static void firmware_parser_destroy(struct dc_bios **dcb)101{102 struct bios_parser *bp = BP_FROM_DCB(*dcb);103 104 if (!bp) {105 BREAK_TO_DEBUGGER();106 return;107 }108 109 bios_parser2_destruct(bp);110 111 kfree(bp);112 *dcb = NULL;113}114 115static void get_atom_data_table_revision(116 struct atom_common_table_header *atom_data_tbl,117 struct atom_data_revision *tbl_revision)118{119 if (!tbl_revision)120 return;121 122 /* initialize the revision to 0 which is invalid revision */123 tbl_revision->major = 0;124 tbl_revision->minor = 0;125 126 if (!atom_data_tbl)127 return;128 129 tbl_revision->major =130 (uint32_t) atom_data_tbl->format_revision & 0x3f;131 tbl_revision->minor =132 (uint32_t) atom_data_tbl->content_revision & 0x3f;133}134 135/* BIOS oject table displaypath is per connector.136 * There is extra path not for connector. BIOS fill its encoderid as 0137 */138static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)139{140 struct bios_parser *bp = BP_FROM_DCB(dcb);141 unsigned int count = 0;142 unsigned int i;143 144 switch (bp->object_info_tbl.revision.minor) {145 default:146 case 4:147 for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++)148 if (bp->object_info_tbl.v1_4->display_path[i].encoderobjid != 0)149 count++;150 151 break;152 153 case 5:154 for (i = 0; i < bp->object_info_tbl.v1_5->number_of_path; i++)155 if (bp->object_info_tbl.v1_5->display_path[i].encoderobjid != 0)156 count++;157 158 break;159 }160 return count;161}162 163static struct graphics_object_id bios_parser_get_connector_id(164 struct dc_bios *dcb,165 uint8_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 struct object_info_table *tbl = &bp->object_info_tbl;171 struct display_object_info_table_v1_4 *v1_4 = tbl->v1_4;172 173 struct display_object_info_table_v1_5 *v1_5 = tbl->v1_5;174 175 switch (bp->object_info_tbl.revision.minor) {176 default:177 case 4:178 if (v1_4->number_of_path > i) {179 /* If display_objid is generic object id, the encoderObj180 * /extencoderobjId should be 0181 */182 if (v1_4->display_path[i].encoderobjid != 0 &&183 v1_4->display_path[i].display_objid != 0)184 object_id = object_id_from_bios_object_id(185 v1_4->display_path[i].display_objid);186 }187 break;188 189 case 5:190 if (v1_5->number_of_path > i) {191 /* If display_objid is generic object id, the encoderObjId192 * should be 0193 */194 if (v1_5->display_path[i].encoderobjid != 0 &&195 v1_5->display_path[i].display_objid != 0)196 object_id = object_id_from_bios_object_id(197 v1_5->display_path[i].display_objid);198 }199 break;200 }201 return object_id;202}203 204static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,205 struct graphics_object_id object_id, uint32_t index,206 struct graphics_object_id *src_object_id)207{208 struct bios_parser *bp = BP_FROM_DCB(dcb);209 unsigned int i;210 enum bp_result bp_result = BP_RESULT_BADINPUT;211 struct graphics_object_id obj_id = { 0 };212 struct object_info_table *tbl = &bp->object_info_tbl;213 214 if (!src_object_id)215 return bp_result;216 217 switch (object_id.type) {218 /* Encoder's Source is GPU. BIOS does not provide GPU, since all219 * displaypaths point to same GPU (0x1100). Hardcode GPU object type220 */221 case OBJECT_TYPE_ENCODER:222 /* TODO: since num of src must be less than 2.223 * If found in for loop, should break.224 * DAL2 implementation may be changed too225 */226 switch (bp->object_info_tbl.revision.minor) {227 default:228 case 4:229 for (i = 0; i < tbl->v1_4->number_of_path; i++) {230 obj_id = object_id_from_bios_object_id(231 tbl->v1_4->display_path[i].encoderobjid);232 if (object_id.type == obj_id.type &&233 object_id.id == obj_id.id &&234 object_id.enum_id == obj_id.enum_id) {235 *src_object_id =236 object_id_from_bios_object_id(237 0x1100);238 /* break; */239 }240 }241 bp_result = BP_RESULT_OK;242 break;243 244 case 5:245 for (i = 0; i < tbl->v1_5->number_of_path; i++) {246 obj_id = object_id_from_bios_object_id(247 tbl->v1_5->display_path[i].encoderobjid);248 if (object_id.type == obj_id.type &&249 object_id.id == obj_id.id &&250 object_id.enum_id == obj_id.enum_id) {251 *src_object_id =252 object_id_from_bios_object_id(253 0x1100);254 /* break; */255 }256 }257 bp_result = BP_RESULT_OK;258 break;259 }260 break;261 case OBJECT_TYPE_CONNECTOR:262 switch (bp->object_info_tbl.revision.minor) {263 default:264 case 4:265 for (i = 0; i < tbl->v1_4->number_of_path; i++) {266 obj_id = object_id_from_bios_object_id(267 tbl->v1_4->display_path[i]268 .display_objid);269 270 if (object_id.type == obj_id.type &&271 object_id.id == obj_id.id &&272 object_id.enum_id == obj_id.enum_id) {273 *src_object_id =274 object_id_from_bios_object_id(275 tbl->v1_4276 ->display_path[i]277 .encoderobjid);278 /* break; */279 }280 }281 bp_result = BP_RESULT_OK;282 break;283 }284 bp_result = BP_RESULT_OK;285 break;286 case 5:287 for (i = 0; i < tbl->v1_5->number_of_path; i++) {288 obj_id = object_id_from_bios_object_id(289 tbl->v1_5->display_path[i].display_objid);290 291 if (object_id.type == obj_id.type &&292 object_id.id == obj_id.id &&293 object_id.enum_id == obj_id.enum_id) {294 *src_object_id = object_id_from_bios_object_id(295 tbl->v1_5->display_path[i].encoderobjid);296 /* break; */297 }298 }299 bp_result = BP_RESULT_OK;300 break;301 302 default:303 bp_result = BP_RESULT_OK;304 break;305 }306 307 return bp_result;308}309 310/* from graphics_object_id, find display path which includes the object_id */311static struct atom_display_object_path_v2 *get_bios_object(312 struct bios_parser *bp,313 struct graphics_object_id id)314{315 unsigned int i;316 struct graphics_object_id obj_id = {0};317 318 switch (id.type) {319 case OBJECT_TYPE_ENCODER:320 for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) {321 obj_id = object_id_from_bios_object_id(322 bp->object_info_tbl.v1_4->display_path[i].encoderobjid);323 if (id.type == obj_id.type && id.id == obj_id.id324 && id.enum_id == obj_id.enum_id)325 return &bp->object_info_tbl.v1_4->display_path[i];326 }327 fallthrough;328 case OBJECT_TYPE_CONNECTOR:329 case OBJECT_TYPE_GENERIC:330 /* Both Generic and Connector Object ID331 * will be stored on display_objid332 */333 for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) {334 obj_id = object_id_from_bios_object_id(335 bp->object_info_tbl.v1_4->display_path[i].display_objid);336 if (id.type == obj_id.type && id.id == obj_id.id337 && id.enum_id == obj_id.enum_id)338 return &bp->object_info_tbl.v1_4->display_path[i];339 }340 fallthrough;341 default:342 return NULL;343 }344}345 346/* from graphics_object_id, find display path which includes the object_id */347static struct atom_display_object_path_v3 *get_bios_object_from_path_v3(struct bios_parser *bp,348 struct graphics_object_id id)349{350 unsigned int i;351 struct graphics_object_id obj_id = {0};352 353 switch (id.type) {354 case OBJECT_TYPE_ENCODER:355 for (i = 0; i < bp->object_info_tbl.v1_5->number_of_path; i++) {356 obj_id = object_id_from_bios_object_id(357 bp->object_info_tbl.v1_5->display_path[i].encoderobjid);358 if (id.type == obj_id.type && id.id == obj_id.id359 && id.enum_id == obj_id.enum_id)360 return &bp->object_info_tbl.v1_5->display_path[i];361 }362 break;363 364 case OBJECT_TYPE_CONNECTOR:365 case OBJECT_TYPE_GENERIC:366 /* Both Generic and Connector Object ID367 * will be stored on display_objid368 */369 for (i = 0; i < bp->object_info_tbl.v1_5->number_of_path; i++) {370 obj_id = object_id_from_bios_object_id(371 bp->object_info_tbl.v1_5->display_path[i].display_objid);372 if (id.type == obj_id.type && id.id == obj_id.id373 && id.enum_id == obj_id.enum_id)374 return &bp->object_info_tbl.v1_5->display_path[i];375 }376 break;377 378 default:379 return NULL;380 }381 382 return NULL;383}384 385static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,386 struct graphics_object_id id,387 struct graphics_object_i2c_info *info)388{389 uint32_t offset;390 struct atom_display_object_path_v2 *object;391 392 struct atom_display_object_path_v3 *object_path_v3;393 394 struct atom_common_record_header *header;395 struct atom_i2c_record *record;396 struct atom_i2c_record dummy_record = {0};397 struct bios_parser *bp = BP_FROM_DCB(dcb);398 399 if (!info)400 return BP_RESULT_BADINPUT;401 402 if (id.type == OBJECT_TYPE_GENERIC) {403 dummy_record.i2c_id = id.id;404 405 if (get_gpio_i2c_info(bp, &dummy_record, info) == BP_RESULT_OK)406 return BP_RESULT_OK;407 else408 return BP_RESULT_NORECORD;409 }410 411 switch (bp->object_info_tbl.revision.minor) {412 case 4:413 default:414 object = get_bios_object(bp, id);415 416 if (!object)417 return BP_RESULT_BADINPUT;418 419 offset = object->disp_recordoffset + bp->object_info_tbl_offset;420 break;421 case 5:422 object_path_v3 = get_bios_object_from_path_v3(bp, id);423 424 if (!object_path_v3)425 return BP_RESULT_BADINPUT;426 427 offset = object_path_v3->disp_recordoffset + bp->object_info_tbl_offset;428 break;429 }430 431 for (;;) {432 header = GET_IMAGE(struct atom_common_record_header, offset);433 434 if (!header)435 return BP_RESULT_BADBIOSTABLE;436 437 if (header->record_type == LAST_RECORD_TYPE ||438 !header->record_size)439 break;440 441 if (header->record_type == ATOM_I2C_RECORD_TYPE442 && sizeof(struct atom_i2c_record) <=443 header->record_size) {444 /* get the I2C info */445 record = (struct atom_i2c_record *) header;446 447 if (get_gpio_i2c_info(bp, record, info) ==448 BP_RESULT_OK)449 return BP_RESULT_OK;450 }451 452 offset += header->record_size;453 }454 455 return BP_RESULT_NORECORD;456}457 458static enum bp_result get_gpio_i2c_info(459 struct bios_parser *bp,460 struct atom_i2c_record *record,461 struct graphics_object_i2c_info *info)462{463 struct atom_gpio_pin_lut_v2_1 *header;464 uint32_t count = 0;465 unsigned int table_index = 0;466 bool find_valid = false;467 struct atom_gpio_pin_assignment *pin;468 469 if (!info)470 return BP_RESULT_BADINPUT;471 472 /* get the GPIO_I2C info */473 if (!DATA_TABLES(gpio_pin_lut))474 return BP_RESULT_BADBIOSTABLE;475 476 header = GET_IMAGE(struct atom_gpio_pin_lut_v2_1,477 DATA_TABLES(gpio_pin_lut));478 if (!header)479 return BP_RESULT_BADBIOSTABLE;480 481 if (sizeof(struct atom_common_table_header) +482 sizeof(struct atom_gpio_pin_assignment) >483 le16_to_cpu(header->table_header.structuresize))484 return BP_RESULT_BADBIOSTABLE;485 486 /* TODO: is version change? */487 if (header->table_header.content_revision != 1)488 return BP_RESULT_UNSUPPORTED;489 490 /* get data count */491 count = (le16_to_cpu(header->table_header.structuresize)492 - sizeof(struct atom_common_table_header))493 / sizeof(struct atom_gpio_pin_assignment);494 495 pin = (struct atom_gpio_pin_assignment *) header->gpio_pin;496 497 for (table_index = 0; table_index < count; table_index++) {498 if (((record->i2c_id & I2C_HW_CAP) == (pin->gpio_id & I2C_HW_CAP)) &&499 ((record->i2c_id & I2C_HW_ENGINE_ID_MASK) == (pin->gpio_id & I2C_HW_ENGINE_ID_MASK)) &&500 ((record->i2c_id & I2C_HW_LANE_MUX) == (pin->gpio_id & I2C_HW_LANE_MUX))) {501 /* still valid */502 find_valid = true;503 break;504 }505 pin = (struct atom_gpio_pin_assignment *)((uint8_t *)pin + sizeof(struct atom_gpio_pin_assignment));506 }507 508 /* If we don't find the entry that we are looking for then509 * we will return BP_Result_BadBiosTable.510 */511 if (find_valid == false)512 return BP_RESULT_BADBIOSTABLE;513 514 /* get the GPIO_I2C_INFO */515 info->i2c_hw_assist = (record->i2c_id & I2C_HW_CAP) ? true : false;516 info->i2c_line = record->i2c_id & I2C_HW_LANE_MUX;517 info->i2c_engine_id = (record->i2c_id & I2C_HW_ENGINE_ID_MASK) >> 4;518 info->i2c_slave_address = record->i2c_slave_addr;519 520 /* TODO: check how to get register offset for en, Y, etc. */521 info->gpio_info.clk_a_register_index = le16_to_cpu(pin->data_a_reg_index);522 info->gpio_info.clk_a_shift = pin->gpio_bitshift;523 524 return BP_RESULT_OK;525}526 527static struct atom_hpd_int_record *get_hpd_record_for_path_v3(struct bios_parser *bp,528 struct atom_display_object_path_v3 *object)529{530 struct atom_common_record_header *header;531 uint32_t offset;532 533 if (!object) {534 BREAK_TO_DEBUGGER(); /* Invalid object */535 return NULL;536 }537 538 offset = object->disp_recordoffset + bp->object_info_tbl_offset;539 540 for (;;) {541 header = GET_IMAGE(struct atom_common_record_header, offset);542 543 if (!header)544 return NULL;545 546 if (header->record_type == ATOM_RECORD_END_TYPE ||547 !header->record_size)548 break;549 550 if (header->record_type == ATOM_HPD_INT_RECORD_TYPE551 && sizeof(struct atom_hpd_int_record) <=552 header->record_size)553 return (struct atom_hpd_int_record *) header;554 555 offset += header->record_size;556 }557 558 return NULL;559}560 561static enum bp_result bios_parser_get_hpd_info(562 struct dc_bios *dcb,563 struct graphics_object_id id,564 struct graphics_object_hpd_info *info)565{566 struct bios_parser *bp = BP_FROM_DCB(dcb);567 struct atom_display_object_path_v2 *object;568 struct atom_display_object_path_v3 *object_path_v3;569 struct atom_hpd_int_record *record = NULL;570 571 if (!info)572 return BP_RESULT_BADINPUT;573 574 switch (bp->object_info_tbl.revision.minor) {575 case 4:576 default:577 object = get_bios_object(bp, id);578 579 if (!object)580 return BP_RESULT_BADINPUT;581 582 record = get_hpd_record(bp, object);583 break;584 case 5:585 object_path_v3 = get_bios_object_from_path_v3(bp, id);586 587 if (!object_path_v3)588 return BP_RESULT_BADINPUT;589 590 record = get_hpd_record_for_path_v3(bp, object_path_v3);591 break;592 }593 594 if (record != NULL) {595 info->hpd_int_gpio_uid = record->pin_id;596 info->hpd_active = record->plugin_pin_state;597 return BP_RESULT_OK;598 }599 600 return BP_RESULT_NORECORD;601}602 603static struct atom_hpd_int_record *get_hpd_record(604 struct bios_parser *bp,605 struct atom_display_object_path_v2 *object)606{607 struct atom_common_record_header *header;608 uint32_t offset;609 610 if (!object) {611 BREAK_TO_DEBUGGER(); /* Invalid object */612 return NULL;613 }614 615 offset = le16_to_cpu(object->disp_recordoffset)616 + bp->object_info_tbl_offset;617 618 for (;;) {619 header = GET_IMAGE(struct atom_common_record_header, offset);620 621 if (!header)622 return NULL;623 624 if (header->record_type == LAST_RECORD_TYPE ||625 !header->record_size)626 break;627 628 if (header->record_type == ATOM_HPD_INT_RECORD_TYPE629 && sizeof(struct atom_hpd_int_record) <=630 header->record_size)631 return (struct atom_hpd_int_record *) header;632 633 offset += header->record_size;634 }635 636 return NULL;637}638 639/**640 * bios_parser_get_gpio_pin_info641 * Get GpioPin information of input gpio id642 *643 * @dcb: pointer to the DC BIOS644 * @gpio_id: GPIO ID645 * @info: GpioPin information structure646 * return: Bios parser result code647 * note:648 * to get the GPIO PIN INFO, we need:649 * 1. get the GPIO_ID from other object table, see GetHPDInfo()650 * 2. in DATA_TABLE.GPIO_Pin_LUT, search all records,651 * to get the registerA offset/mask652 */653static enum bp_result bios_parser_get_gpio_pin_info(654 struct dc_bios *dcb,655 uint32_t gpio_id,656 struct gpio_pin_info *info)657{658 struct bios_parser *bp = BP_FROM_DCB(dcb);659 struct atom_gpio_pin_lut_v2_1 *header;660 uint32_t count = 0;661 uint32_t i = 0;662 663 if (!DATA_TABLES(gpio_pin_lut))664 return BP_RESULT_BADBIOSTABLE;665 666 header = GET_IMAGE(struct atom_gpio_pin_lut_v2_1,667 DATA_TABLES(gpio_pin_lut));668 if (!header)669 return BP_RESULT_BADBIOSTABLE;670 671 if (sizeof(struct atom_common_table_header) +672 sizeof(struct atom_gpio_pin_assignment)673 > le16_to_cpu(header->table_header.structuresize))674 return BP_RESULT_BADBIOSTABLE;675 676 if (header->table_header.content_revision != 1)677 return BP_RESULT_UNSUPPORTED;678 679 /* Temporary hard code gpio pin info */680 count = (le16_to_cpu(header->table_header.structuresize)681 - sizeof(struct atom_common_table_header))682 / sizeof(struct atom_gpio_pin_assignment);683 for (i = 0; i < count; ++i) {684 if (header->gpio_pin[i].gpio_id != gpio_id)685 continue;686 687 info->offset =688 (uint32_t) le16_to_cpu(689 header->gpio_pin[i].data_a_reg_index);690 info->offset_y = info->offset + 2;691 info->offset_en = info->offset + 1;692 info->offset_mask = info->offset - 1;693 694 info->mask = (uint32_t) (1 <<695 header->gpio_pin[i].gpio_bitshift);696 info->mask_y = info->mask + 2;697 info->mask_en = info->mask + 1;698 info->mask_mask = info->mask - 1;699 700 return BP_RESULT_OK;701 }702 703 return BP_RESULT_NORECORD;704}705 706static struct device_id device_type_from_device_id(uint16_t device_id)707{708 709 struct device_id result_device_id;710 711 result_device_id.raw_device_tag = device_id;712 713 switch (device_id) {714 case ATOM_DISPLAY_LCD1_SUPPORT:715 result_device_id.device_type = DEVICE_TYPE_LCD;716 result_device_id.enum_id = 1;717 break;718 719 case ATOM_DISPLAY_LCD2_SUPPORT:720 result_device_id.device_type = DEVICE_TYPE_LCD;721 result_device_id.enum_id = 2;722 break;723 724 case ATOM_DISPLAY_DFP1_SUPPORT:725 result_device_id.device_type = DEVICE_TYPE_DFP;726 result_device_id.enum_id = 1;727 break;728 729 case ATOM_DISPLAY_DFP2_SUPPORT:730 result_device_id.device_type = DEVICE_TYPE_DFP;731 result_device_id.enum_id = 2;732 break;733 734 case ATOM_DISPLAY_DFP3_SUPPORT:735 result_device_id.device_type = DEVICE_TYPE_DFP;736 result_device_id.enum_id = 3;737 break;738 739 case ATOM_DISPLAY_DFP4_SUPPORT:740 result_device_id.device_type = DEVICE_TYPE_DFP;741 result_device_id.enum_id = 4;742 break;743 744 case ATOM_DISPLAY_DFP5_SUPPORT:745 result_device_id.device_type = DEVICE_TYPE_DFP;746 result_device_id.enum_id = 5;747 break;748 749 case ATOM_DISPLAY_DFP6_SUPPORT:750 result_device_id.device_type = DEVICE_TYPE_DFP;751 result_device_id.enum_id = 6;752 break;753 754 default:755 BREAK_TO_DEBUGGER(); /* Invalid device Id */756 result_device_id.device_type = DEVICE_TYPE_UNKNOWN;757 result_device_id.enum_id = 0;758 }759 return result_device_id;760}761 762static enum bp_result bios_parser_get_device_tag(763 struct dc_bios *dcb,764 struct graphics_object_id connector_object_id,765 uint32_t device_tag_index,766 struct connector_device_tag_info *info)767{768 struct bios_parser *bp = BP_FROM_DCB(dcb);769 struct atom_display_object_path_v2 *object;770 771 struct atom_display_object_path_v3 *object_path_v3;772 773 774 if (!info)775 return BP_RESULT_BADINPUT;776 777 switch (bp->object_info_tbl.revision.minor) {778 case 4:779 default:780 /* getBiosObject will return MXM object */781 object = get_bios_object(bp, connector_object_id);782 783 if (!object) {784 BREAK_TO_DEBUGGER(); /* Invalid object id */785 return BP_RESULT_BADINPUT;786 }787 788 info->acpi_device = 0; /* BIOS no longer provides this */789 info->dev_id = device_type_from_device_id(object->device_tag);790 break;791 case 5:792 object_path_v3 = get_bios_object_from_path_v3(bp, connector_object_id);793 794 if (!object_path_v3) {795 BREAK_TO_DEBUGGER(); /* Invalid object id */796 return BP_RESULT_BADINPUT;797 }798 info->acpi_device = 0; /* BIOS no longer provides this */799 info->dev_id = device_type_from_device_id(object_path_v3->device_tag);800 break;801 }802 803 return BP_RESULT_OK;804}805 806static enum bp_result get_ss_info_v4_1(807 struct bios_parser *bp,808 uint32_t id,809 uint32_t index,810 struct spread_spectrum_info *ss_info)811{812 enum bp_result result = BP_RESULT_OK;813 struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL;814 struct atom_smu_info_v3_3 *smu_info = NULL;815 816 if (!ss_info)817 return BP_RESULT_BADINPUT;818 819 if (!DATA_TABLES(dce_info))820 return BP_RESULT_BADBIOSTABLE;821 822 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_1,823 DATA_TABLES(dce_info));824 if (!disp_cntl_tbl)825 return BP_RESULT_BADBIOSTABLE;826 827 828 ss_info->type.STEP_AND_DELAY_INFO = false;829 ss_info->spread_percentage_divider = 1000;830 /* BIOS no longer uses target clock. Always enable for now */831 ss_info->target_clock_range = 0xffffffff;832 833 switch (id) {834 case AS_SIGNAL_TYPE_DVI:835 ss_info->spread_spectrum_percentage =836 disp_cntl_tbl->dvi_ss_percentage;837 ss_info->spread_spectrum_range =838 disp_cntl_tbl->dvi_ss_rate_10hz * 10;839 if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)840 ss_info->type.CENTER_MODE = true;841 842 DC_LOG_BIOS("AS_SIGNAL_TYPE_DVI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);843 break;844 case AS_SIGNAL_TYPE_HDMI:845 ss_info->spread_spectrum_percentage =846 disp_cntl_tbl->hdmi_ss_percentage;847 ss_info->spread_spectrum_range =848 disp_cntl_tbl->hdmi_ss_rate_10hz * 10;849 if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)850 ss_info->type.CENTER_MODE = true;851 852 DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);853 break;854 /* TODO LVDS not support anymore? */855 case AS_SIGNAL_TYPE_DISPLAY_PORT:856 ss_info->spread_spectrum_percentage =857 disp_cntl_tbl->dp_ss_percentage;858 ss_info->spread_spectrum_range =859 disp_cntl_tbl->dp_ss_rate_10hz * 10;860 if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)861 ss_info->type.CENTER_MODE = true;862 863 DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage);864 break;865 case AS_SIGNAL_TYPE_GPU_PLL:866 /* atom_firmware: DAL only get data from dce_info table.867 * if data within smu_info is needed for DAL, VBIOS should868 * copy it into dce_info869 */870 result = BP_RESULT_UNSUPPORTED;871 break;872 case AS_SIGNAL_TYPE_XGMI:873 smu_info = GET_IMAGE(struct atom_smu_info_v3_3,874 DATA_TABLES(smu_info));875 if (!smu_info)876 return BP_RESULT_BADBIOSTABLE;877 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info->gpuclk_ss_percentage);878 ss_info->spread_spectrum_percentage =879 smu_info->waflclk_ss_percentage;880 ss_info->spread_spectrum_range =881 smu_info->gpuclk_ss_rate_10hz * 10;882 if (smu_info->waflclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)883 ss_info->type.CENTER_MODE = true;884 885 DC_LOG_BIOS("AS_SIGNAL_TYPE_XGMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);886 break;887 default:888 result = BP_RESULT_UNSUPPORTED;889 }890 891 return result;892}893 894static enum bp_result get_ss_info_v4_2(895 struct bios_parser *bp,896 uint32_t id,897 uint32_t index,898 struct spread_spectrum_info *ss_info)899{900 enum bp_result result = BP_RESULT_OK;901 struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL;902 struct atom_smu_info_v3_1 *smu_info = NULL;903 904 if (!ss_info)905 return BP_RESULT_BADINPUT;906 907 if (!DATA_TABLES(dce_info))908 return BP_RESULT_BADBIOSTABLE;909 910 if (!DATA_TABLES(smu_info))911 return BP_RESULT_BADBIOSTABLE;912 913 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_2,914 DATA_TABLES(dce_info));915 if (!disp_cntl_tbl)916 return BP_RESULT_BADBIOSTABLE;917 918 smu_info = GET_IMAGE(struct atom_smu_info_v3_1, DATA_TABLES(smu_info));919 if (!smu_info)920 return BP_RESULT_BADBIOSTABLE;921 922 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info->gpuclk_ss_percentage);923 ss_info->type.STEP_AND_DELAY_INFO = false;924 ss_info->spread_percentage_divider = 1000;925 /* BIOS no longer uses target clock. Always enable for now */926 ss_info->target_clock_range = 0xffffffff;927 928 switch (id) {929 case AS_SIGNAL_TYPE_DVI:930 ss_info->spread_spectrum_percentage =931 disp_cntl_tbl->dvi_ss_percentage;932 ss_info->spread_spectrum_range =933 disp_cntl_tbl->dvi_ss_rate_10hz * 10;934 if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)935 ss_info->type.CENTER_MODE = true;936 937 DC_LOG_BIOS("AS_SIGNAL_TYPE_DVI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);938 break;939 case AS_SIGNAL_TYPE_HDMI:940 ss_info->spread_spectrum_percentage =941 disp_cntl_tbl->hdmi_ss_percentage;942 ss_info->spread_spectrum_range =943 disp_cntl_tbl->hdmi_ss_rate_10hz * 10;944 if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)945 ss_info->type.CENTER_MODE = true;946 947 DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);948 break;949 /* TODO LVDS not support anymore? */950 case AS_SIGNAL_TYPE_DISPLAY_PORT:951 ss_info->spread_spectrum_percentage =952 smu_info->gpuclk_ss_percentage;953 ss_info->spread_spectrum_range =954 smu_info->gpuclk_ss_rate_10hz * 10;955 if (smu_info->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)956 ss_info->type.CENTER_MODE = true;957 958 DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage);959 break;960 case AS_SIGNAL_TYPE_GPU_PLL:961 /* atom_firmware: DAL only get data from dce_info table.962 * if data within smu_info is needed for DAL, VBIOS should963 * copy it into dce_info964 */965 result = BP_RESULT_UNSUPPORTED;966 break;967 default:968 result = BP_RESULT_UNSUPPORTED;969 }970 971 return result;972}973 974static enum bp_result get_ss_info_v4_5(975 struct bios_parser *bp,976 uint32_t id,977 uint32_t index,978 struct spread_spectrum_info *ss_info)979{980 enum bp_result result = BP_RESULT_OK;981 struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;982 983 if (!ss_info)984 return BP_RESULT_BADINPUT;985 986 if (!DATA_TABLES(dce_info))987 return BP_RESULT_BADBIOSTABLE;988 989 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_5,990 DATA_TABLES(dce_info));991 if (!disp_cntl_tbl)992 return BP_RESULT_BADBIOSTABLE;993 994 ss_info->type.STEP_AND_DELAY_INFO = false;995 ss_info->spread_percentage_divider = 1000;996 /* BIOS no longer uses target clock. Always enable for now */997 ss_info->target_clock_range = 0xffffffff;998 999 switch (id) {1000 case AS_SIGNAL_TYPE_DVI:1001 ss_info->spread_spectrum_percentage =1002 disp_cntl_tbl->dvi_ss_percentage;1003 ss_info->spread_spectrum_range =1004 disp_cntl_tbl->dvi_ss_rate_10hz * 10;1005 if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)1006 ss_info->type.CENTER_MODE = true;1007 1008 DC_LOG_BIOS("AS_SIGNAL_TYPE_DVI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);1009 break;1010 case AS_SIGNAL_TYPE_HDMI:1011 ss_info->spread_spectrum_percentage =1012 disp_cntl_tbl->hdmi_ss_percentage;1013 ss_info->spread_spectrum_range =1014 disp_cntl_tbl->hdmi_ss_rate_10hz * 10;1015 if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)1016 ss_info->type.CENTER_MODE = true;1017 1018 DC_LOG_BIOS("AS_SIGNAL_TYPE_HDMI ss_percentage: %d\n", ss_info->spread_spectrum_percentage);1019 break;1020 case AS_SIGNAL_TYPE_DISPLAY_PORT:1021 if (bp->base.integrated_info) {1022 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", bp->base.integrated_info->gpuclk_ss_percentage);1023 ss_info->spread_spectrum_percentage =1024 bp->base.integrated_info->gpuclk_ss_percentage;1025 ss_info->type.CENTER_MODE =1026 bp->base.integrated_info->gpuclk_ss_type;1027 } else {1028 ss_info->spread_spectrum_percentage =1029 disp_cntl_tbl->dp_ss_percentage;1030 ss_info->spread_spectrum_range =1031 disp_cntl_tbl->dp_ss_rate_10hz * 10;1032 if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)1033 ss_info->type.CENTER_MODE = true;1034 }1035 DC_LOG_BIOS("AS_SIGNAL_TYPE_DISPLAY_PORT ss_percentage: %d\n", ss_info->spread_spectrum_percentage);1036 break;1037 case AS_SIGNAL_TYPE_GPU_PLL:1038 /* atom_smu_info_v4_0 does not have fields for SS for SMU Display PLL anymore.1039 * SMU Display PLL supposed to be without spread.1040 * Better place for it would be in atom_display_controller_info_v4_5 table.1041 */1042 result = BP_RESULT_UNSUPPORTED;1043 break;1044 default:1045 result = BP_RESULT_UNSUPPORTED;1046 break;1047 }1048 1049 return result;1050}1051 1052/**1053 * bios_parser_get_spread_spectrum_info1054 * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or1055 * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info1056 * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info1057 * ver 3.1,1058 * there is only one entry for each signal /ss id. However, there is1059 * no planning of supporting multiple spread Sprectum entry for EverGreen1060 * @dcb: pointer to the DC BIOS1061 * @signal: ASSignalType to be converted to info index1062 * @index: number of entries that match the converted info index1063 * @ss_info: sprectrum information structure,1064 * return: Bios parser result code1065 */1066static enum bp_result bios_parser_get_spread_spectrum_info(1067 struct dc_bios *dcb,1068 enum as_signal_type signal,1069 uint32_t index,1070 struct spread_spectrum_info *ss_info)1071{1072 struct bios_parser *bp = BP_FROM_DCB(dcb);1073 enum bp_result result = BP_RESULT_UNSUPPORTED;1074 struct atom_common_table_header *header;1075 struct atom_data_revision tbl_revision;1076 1077 if (!ss_info) /* check for bad input */1078 return BP_RESULT_BADINPUT;1079 1080 if (!DATA_TABLES(dce_info))1081 return BP_RESULT_UNSUPPORTED;1082 1083 header = GET_IMAGE(struct atom_common_table_header,1084 DATA_TABLES(dce_info));1085 get_atom_data_table_revision(header, &tbl_revision);1086 1087 switch (tbl_revision.major) {1088 case 4:1089 switch (tbl_revision.minor) {1090 case 1:1091 return get_ss_info_v4_1(bp, signal, index, ss_info);1092 case 2:1093 case 3:1094 case 4:1095 return get_ss_info_v4_2(bp, signal, index, ss_info);1096 case 5:1097 return get_ss_info_v4_5(bp, signal, index, ss_info);1098 1099 default:1100 ASSERT(0);1101 break;1102 }1103 break;1104 default:1105 break;1106 }1107 /* there can not be more then one entry for SS Info table */1108 return result;1109}1110 1111static enum bp_result get_soc_bb_info_v4_4(1112 struct bios_parser *bp,1113 struct bp_soc_bb_info *soc_bb_info)1114{1115 enum bp_result result = BP_RESULT_OK;1116 struct atom_display_controller_info_v4_4 *disp_cntl_tbl = NULL;1117 1118 if (!soc_bb_info)1119 return BP_RESULT_BADINPUT;1120 1121 if (!DATA_TABLES(dce_info))1122 return BP_RESULT_BADBIOSTABLE;1123 1124 if (!DATA_TABLES(smu_info))1125 return BP_RESULT_BADBIOSTABLE;1126 1127 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_4,1128 DATA_TABLES(dce_info));1129 if (!disp_cntl_tbl)1130 return BP_RESULT_BADBIOSTABLE;1131 1132 soc_bb_info->dram_clock_change_latency_100ns = disp_cntl_tbl->max_mclk_chg_lat;1133 soc_bb_info->dram_sr_enter_exit_latency_100ns = disp_cntl_tbl->max_sr_enter_exit_lat;1134 soc_bb_info->dram_sr_exit_latency_100ns = disp_cntl_tbl->max_sr_exit_lat;1135 1136 return result;1137}1138 1139static enum bp_result get_soc_bb_info_v4_5(1140 struct bios_parser *bp,1141 struct bp_soc_bb_info *soc_bb_info)1142{1143 enum bp_result result = BP_RESULT_OK;1144 struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;1145 1146 if (!soc_bb_info)1147 return BP_RESULT_BADINPUT;1148 1149 if (!DATA_TABLES(dce_info))1150 return BP_RESULT_BADBIOSTABLE;1151 1152 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_5,1153 DATA_TABLES(dce_info));1154 if (!disp_cntl_tbl)1155 return BP_RESULT_BADBIOSTABLE;1156 1157 soc_bb_info->dram_clock_change_latency_100ns = disp_cntl_tbl->max_mclk_chg_lat;1158 soc_bb_info->dram_sr_enter_exit_latency_100ns = disp_cntl_tbl->max_sr_enter_exit_lat;1159 soc_bb_info->dram_sr_exit_latency_100ns = disp_cntl_tbl->max_sr_exit_lat;1160 1161 return result;1162}1163 1164static enum bp_result bios_parser_get_soc_bb_info(1165 struct dc_bios *dcb,1166 struct bp_soc_bb_info *soc_bb_info)1167{1168 struct bios_parser *bp = BP_FROM_DCB(dcb);1169 enum bp_result result = BP_RESULT_UNSUPPORTED;1170 struct atom_common_table_header *header;1171 struct atom_data_revision tbl_revision;1172 1173 if (!soc_bb_info) /* check for bad input */1174 return BP_RESULT_BADINPUT;1175 1176 if (!DATA_TABLES(dce_info))1177 return BP_RESULT_UNSUPPORTED;1178 1179 header = GET_IMAGE(struct atom_common_table_header,1180 DATA_TABLES(dce_info));1181 get_atom_data_table_revision(header, &tbl_revision);1182 1183 switch (tbl_revision.major) {1184 case 4:1185 switch (tbl_revision.minor) {1186 case 1:1187 case 2:1188 case 3:1189 break;1190 case 4:1191 result = get_soc_bb_info_v4_4(bp, soc_bb_info);1192 break;1193 case 5:1194 result = get_soc_bb_info_v4_5(bp, soc_bb_info);1195 break;1196 default:1197 break;1198 }1199 break;1200 default:1201 break;1202 }1203 1204 return result;1205}1206 1207static enum bp_result get_disp_caps_v4_1(1208 struct bios_parser *bp,1209 uint8_t *dce_caps)1210{1211 enum bp_result result = BP_RESULT_OK;1212 struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL;1213 1214 if (!dce_caps)1215 return BP_RESULT_BADINPUT;1216 1217 if (!DATA_TABLES(dce_info))1218 return BP_RESULT_BADBIOSTABLE;1219 1220 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_1,1221 DATA_TABLES(dce_info));1222 1223 if (!disp_cntl_tbl)1224 return BP_RESULT_BADBIOSTABLE;1225 1226 *dce_caps = disp_cntl_tbl->display_caps;1227 1228 return result;1229}1230 1231static enum bp_result get_disp_caps_v4_2(1232 struct bios_parser *bp,1233 uint8_t *dce_caps)1234{1235 enum bp_result result = BP_RESULT_OK;1236 struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL;1237 1238 if (!dce_caps)1239 return BP_RESULT_BADINPUT;1240 1241 if (!DATA_TABLES(dce_info))1242 return BP_RESULT_BADBIOSTABLE;1243 1244 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_2,1245 DATA_TABLES(dce_info));1246 1247 if (!disp_cntl_tbl)1248 return BP_RESULT_BADBIOSTABLE;1249 1250 *dce_caps = disp_cntl_tbl->display_caps;1251 1252 return result;1253}1254 1255static enum bp_result get_disp_caps_v4_3(1256 struct bios_parser *bp,1257 uint8_t *dce_caps)1258{1259 enum bp_result result = BP_RESULT_OK;1260 struct atom_display_controller_info_v4_3 *disp_cntl_tbl = NULL;1261 1262 if (!dce_caps)1263 return BP_RESULT_BADINPUT;1264 1265 if (!DATA_TABLES(dce_info))1266 return BP_RESULT_BADBIOSTABLE;1267 1268 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_3,1269 DATA_TABLES(dce_info));1270 1271 if (!disp_cntl_tbl)1272 return BP_RESULT_BADBIOSTABLE;1273 1274 *dce_caps = disp_cntl_tbl->display_caps;1275 1276 return result;1277}1278 1279static enum bp_result get_disp_caps_v4_4(1280 struct bios_parser *bp,1281 uint8_t *dce_caps)1282{1283 enum bp_result result = BP_RESULT_OK;1284 struct atom_display_controller_info_v4_4 *disp_cntl_tbl = NULL;1285 1286 if (!dce_caps)1287 return BP_RESULT_BADINPUT;1288 1289 if (!DATA_TABLES(dce_info))1290 return BP_RESULT_BADBIOSTABLE;1291 1292 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_4,1293 DATA_TABLES(dce_info));1294 1295 if (!disp_cntl_tbl)1296 return BP_RESULT_BADBIOSTABLE;1297 1298 *dce_caps = disp_cntl_tbl->display_caps;1299 1300 return result;1301}1302 1303static enum bp_result get_disp_caps_v4_5(1304 struct bios_parser *bp,1305 uint8_t *dce_caps)1306{1307 enum bp_result result = BP_RESULT_OK;1308 struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;1309 1310 if (!dce_caps)1311 return BP_RESULT_BADINPUT;1312 1313 if (!DATA_TABLES(dce_info))1314 return BP_RESULT_BADBIOSTABLE;1315 1316 disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_5,1317 DATA_TABLES(dce_info));1318 1319 if (!disp_cntl_tbl)1320 return BP_RESULT_BADBIOSTABLE;1321 1322 *dce_caps = disp_cntl_tbl->display_caps;1323 1324 return result;1325}1326 1327static enum bp_result bios_parser_get_lttpr_interop(1328 struct dc_bios *dcb,1329 uint8_t *dce_caps)1330{1331 struct bios_parser *bp = BP_FROM_DCB(dcb);1332 enum bp_result result = BP_RESULT_UNSUPPORTED;1333 struct atom_common_table_header *header;1334 struct atom_data_revision tbl_revision;1335 1336 if (!DATA_TABLES(dce_info))1337 return BP_RESULT_UNSUPPORTED;1338 1339 header = GET_IMAGE(struct atom_common_table_header,1340 DATA_TABLES(dce_info));1341 get_atom_data_table_revision(header, &tbl_revision);1342 switch (tbl_revision.major) {1343 case 4:1344 switch (tbl_revision.minor) {1345 case 1:1346 result = get_disp_caps_v4_1(bp, dce_caps);1347 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);1348 break;1349 case 2:1350 result = get_disp_caps_v4_2(bp, dce_caps);1351 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);1352 break;1353 case 3:1354 result = get_disp_caps_v4_3(bp, dce_caps);1355 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);1356 break;1357 case 4:1358 result = get_disp_caps_v4_4(bp, dce_caps);1359 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);1360 break;1361 case 5:1362 result = get_disp_caps_v4_5(bp, dce_caps);1363 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE);1364 break;1365 1366 default:1367 break;1368 }1369 break;1370 default:1371 break;1372 }1373 DC_LOG_BIOS("DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE: %d tbl_revision.major = %d tbl_revision.minor = %d\n", *dce_caps, tbl_revision.major, tbl_revision.minor);1374 return result;1375}1376 1377static enum bp_result bios_parser_get_lttpr_caps(1378 struct dc_bios *dcb,1379 uint8_t *dce_caps)1380{1381 struct bios_parser *bp = BP_FROM_DCB(dcb);1382 enum bp_result result = BP_RESULT_UNSUPPORTED;1383 struct atom_common_table_header *header;1384 struct atom_data_revision tbl_revision;1385 1386 if (!DATA_TABLES(dce_info))1387 return BP_RESULT_UNSUPPORTED;1388 1389 *dce_caps = 0;1390 header = GET_IMAGE(struct atom_common_table_header,1391 DATA_TABLES(dce_info));1392 get_atom_data_table_revision(header, &tbl_revision);1393 switch (tbl_revision.major) {1394 case 4:1395 switch (tbl_revision.minor) {1396 case 1:1397 result = get_disp_caps_v4_1(bp, dce_caps);1398 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);1399 break;1400 case 2:1401 result = get_disp_caps_v4_2(bp, dce_caps);1402 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);1403 break;1404 case 3:1405 result = get_disp_caps_v4_3(bp, dce_caps);1406 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);1407 break;1408 case 4:1409 result = get_disp_caps_v4_4(bp, dce_caps);1410 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);1411 break;1412 case 5:1413 result = get_disp_caps_v4_5(bp, dce_caps);1414 *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE);1415 break;1416 default:1417 break;1418 }1419 break;1420 default:1421 break;1422 }1423 DC_LOG_BIOS("DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE: %d tbl_revision.major = %d tbl_revision.minor = %d\n", *dce_caps, tbl_revision.major, tbl_revision.minor);1424 if (dcb->ctx->dc->config.force_bios_enable_lttpr && *dce_caps == 0) {1425 *dce_caps = 1;1426 DC_LOG_BIOS("DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE: forced enabled");1427 }1428 return result;1429}1430 1431static enum bp_result get_embedded_panel_info_v2_1(1432 struct bios_parser *bp,1433 struct embedded_panel_info *info)1434{1435 struct lcd_info_v2_1 *lvds;1436 1437 if (!info)1438 return BP_RESULT_BADINPUT;1439 1440 if (!DATA_TABLES(lcd_info))1441 return BP_RESULT_UNSUPPORTED;1442 1443 lvds = GET_IMAGE(struct lcd_info_v2_1, DATA_TABLES(lcd_info));1444 1445 if (!lvds)1446 return BP_RESULT_BADBIOSTABLE;1447 1448 /* TODO: previous vv1_3, should v2_1 */1449 if (!((lvds->table_header.format_revision == 2)1450 && (lvds->table_header.content_revision >= 1)))1451 return BP_RESULT_UNSUPPORTED;1452 1453 memset(info, 0, sizeof(struct embedded_panel_info));1454 1455 /* We need to convert from 10KHz units into KHz units */1456 info->lcd_timing.pixel_clk = le16_to_cpu(lvds->lcd_timing.pixclk) * 10;1457 /* usHActive does not include borders, according to VBIOS team */1458 info->lcd_timing.horizontal_addressable = le16_to_cpu(lvds->lcd_timing.h_active);1459 /* usHBlanking_Time includes borders, so we should really be1460 * subtractingborders duing this translation, but LVDS generally1461 * doesn't have borders, so we should be okay leaving this as is for1462 * now. May need to revisit if we ever have LVDS with borders1463 */1464 info->lcd_timing.horizontal_blanking_time = le16_to_cpu(lvds->lcd_timing.h_blanking_time);1465 /* usVActive does not include borders, according to VBIOS team*/1466 info->lcd_timing.vertical_addressable = le16_to_cpu(lvds->lcd_timing.v_active);1467 /* usVBlanking_Time includes borders, so we should really be1468 * subtracting borders duing this translation, but LVDS generally1469 * doesn't have borders, so we should be okay leaving this as is for1470 * now. May need to revisit if we ever have LVDS with borders1471 */1472 info->lcd_timing.vertical_blanking_time = le16_to_cpu(lvds->lcd_timing.v_blanking_time);1473 info->lcd_timing.horizontal_sync_offset = le16_to_cpu(lvds->lcd_timing.h_sync_offset);1474 info->lcd_timing.horizontal_sync_width = le16_to_cpu(lvds->lcd_timing.h_sync_width);1475 info->lcd_timing.vertical_sync_offset = le16_to_cpu(lvds->lcd_timing.v_sync_offset);1476 info->lcd_timing.vertical_sync_width = le16_to_cpu(lvds->lcd_timing.v_syncwidth);1477 info->lcd_timing.horizontal_border = lvds->lcd_timing.h_border;1478 info->lcd_timing.vertical_border = lvds->lcd_timing.v_border;1479 1480 /* not provided by VBIOS */1481 info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 0;1482 1483 info->lcd_timing.misc_info.H_SYNC_POLARITY = ~(uint32_t) (lvds->lcd_timing.miscinfo1484 & ATOM_HSYNC_POLARITY);1485 info->lcd_timing.misc_info.V_SYNC_POLARITY = ~(uint32_t) (lvds->lcd_timing.miscinfo1486 & ATOM_VSYNC_POLARITY);1487 1488 /* not provided by VBIOS */1489 info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0;1490 1491 info->lcd_timing.misc_info.H_REPLICATION_BY2 = !!(lvds->lcd_timing.miscinfo1492 & ATOM_H_REPLICATIONBY2);1493 info->lcd_timing.misc_info.V_REPLICATION_BY2 = !!(lvds->lcd_timing.miscinfo1494 & ATOM_V_REPLICATIONBY2);1495 info->lcd_timing.misc_info.COMPOSITE_SYNC = !!(lvds->lcd_timing.miscinfo1496 & ATOM_COMPOSITESYNC);1497 info->lcd_timing.misc_info.INTERLACE = !!(lvds->lcd_timing.miscinfo & ATOM_INTERLACE);1498 1499 /* not provided by VBIOS*/1500 info->lcd_timing.misc_info.DOUBLE_CLOCK = 0;1501 /* not provided by VBIOS*/1502 info->ss_id = 0;1503 1504 info->realtek_eDPToLVDS = !!(lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID);1505 1506 return BP_RESULT_OK;1507}1508 1509static enum bp_result bios_parser_get_embedded_panel_info(1510 struct dc_bios *dcb,1511 struct embedded_panel_info *info)1512{1513 struct bios_parser1514 *bp = BP_FROM_DCB(dcb);1515 struct atom_common_table_header *header;1516 struct atom_data_revision tbl_revision;1517 1518 if (!DATA_TABLES(lcd_info))1519 return BP_RESULT_FAILURE;1520 1521 header = GET_IMAGE(struct atom_common_table_header, DATA_TABLES(lcd_info));1522 1523 if (!header)1524 return BP_RESULT_BADBIOSTABLE;1525 1526 get_atom_data_table_revision(header, &tbl_revision);1527 1528 switch (tbl_revision.major) {1529 case 2:1530 switch (tbl_revision.minor) {1531 case 1:1532 return get_embedded_panel_info_v2_1(bp, info);1533 default:1534 break;1535 }1536 break;1537 default:1538 break;1539 }1540 1541 return BP_RESULT_FAILURE;1542}1543 1544static uint32_t get_support_mask_for_device_id(struct device_id device_id)1545{1546 enum dal_device_type device_type = device_id.device_type;1547 uint32_t enum_id = device_id.enum_id;1548 1549 switch (device_type) {1550 case DEVICE_TYPE_LCD:1551 switch (enum_id) {1552 case 1:1553 return ATOM_DISPLAY_LCD1_SUPPORT;1554 default:1555 break;1556 }1557 break;1558 case DEVICE_TYPE_DFP:1559 switch (enum_id) {1560 case 1:1561 return ATOM_DISPLAY_DFP1_SUPPORT;1562 case 2:1563 return ATOM_DISPLAY_DFP2_SUPPORT;1564 case 3:1565 return ATOM_DISPLAY_DFP3_SUPPORT;1566 case 4:1567 return ATOM_DISPLAY_DFP4_SUPPORT;1568 case 5:1569 return ATOM_DISPLAY_DFP5_SUPPORT;1570 case 6:1571 return ATOM_DISPLAY_DFP6_SUPPORT;1572 default:1573 break;1574 }1575 break;1576 default:1577 break;1578 }1579 1580 /* Unidentified device ID, return empty support mask. */1581 return 0;1582}1583 1584static bool bios_parser_is_device_id_supported(1585 struct dc_bios *dcb,1586 struct device_id id)1587{1588 struct bios_parser *bp = BP_FROM_DCB(dcb);1589 1590 uint32_t mask = get_support_mask_for_device_id(id);1591 1592 switch (bp->object_info_tbl.revision.minor) {1593 case 4:1594 default:1595 return (le16_to_cpu(bp->object_info_tbl.v1_4->supporteddevices) & mask) != 0;1596 break;1597 case 5:1598 return (le16_to_cpu(bp->object_info_tbl.v1_5->supporteddevices) & mask) != 0;1599 break;1600 }1601}1602 1603static uint32_t bios_parser_get_ss_entry_number(1604 struct dc_bios *dcb,1605 enum as_signal_type signal)1606{1607 /* TODO: DAL2 atomfirmware implementation does not need this.1608 * why DAL3 need this?1609 */1610 return 1;1611}1612 1613static enum bp_result bios_parser_transmitter_control(1614 struct dc_bios *dcb,1615 struct bp_transmitter_control *cntl)1616{1617 struct bios_parser *bp = BP_FROM_DCB(dcb);1618 1619 if (!bp->cmd_tbl.transmitter_control)1620 return BP_RESULT_FAILURE;1621 1622 return bp->cmd_tbl.transmitter_control(bp, cntl);1623}1624 1625static enum bp_result bios_parser_encoder_control(1626 struct dc_bios *dcb,1627 struct bp_encoder_control *cntl)1628{1629 struct bios_parser *bp = BP_FROM_DCB(dcb);1630 1631 if (!bp->cmd_tbl.dig_encoder_control)1632 return BP_RESULT_FAILURE;1633 1634 return bp->cmd_tbl.dig_encoder_control(bp, cntl);1635}1636 1637static enum bp_result bios_parser_set_pixel_clock(1638 struct dc_bios *dcb,1639 struct bp_pixel_clock_parameters *bp_params)1640{1641 struct bios_parser *bp = BP_FROM_DCB(dcb);1642 1643 if (!bp->cmd_tbl.set_pixel_clock)1644 return BP_RESULT_FAILURE;1645 1646 return bp->cmd_tbl.set_pixel_clock(bp, bp_params);1647}1648 1649static enum bp_result bios_parser_set_dce_clock(1650 struct dc_bios *dcb,1651 struct bp_set_dce_clock_parameters *bp_params)1652{1653 struct bios_parser *bp = BP_FROM_DCB(dcb);1654 1655 if (!bp->cmd_tbl.set_dce_clock)1656 return BP_RESULT_FAILURE;1657 1658 return bp->cmd_tbl.set_dce_clock(bp, bp_params);1659}1660 1661static enum bp_result bios_parser_program_crtc_timing(1662 struct dc_bios *dcb,1663 struct bp_hw_crtc_timing_parameters *bp_params)1664{1665 struct bios_parser *bp = BP_FROM_DCB(dcb);1666 1667 if (!bp->cmd_tbl.set_crtc_timing)1668 return BP_RESULT_FAILURE;1669 1670 return bp->cmd_tbl.set_crtc_timing(bp, bp_params);1671}1672 1673static enum bp_result bios_parser_enable_crtc(1674 struct dc_bios *dcb,1675 enum controller_id id,1676 bool enable)1677{1678 struct bios_parser *bp = BP_FROM_DCB(dcb);1679 1680 if (!bp->cmd_tbl.enable_crtc)1681 return BP_RESULT_FAILURE;1682 1683 return bp->cmd_tbl.enable_crtc(bp, id, enable);1684}1685 1686static enum bp_result bios_parser_enable_disp_power_gating(1687 struct dc_bios *dcb,1688 enum controller_id controller_id,1689 enum bp_pipe_control_action action)1690{1691 struct bios_parser *bp = BP_FROM_DCB(dcb);1692 1693 if (!bp->cmd_tbl.enable_disp_power_gating)1694 return BP_RESULT_FAILURE;1695 1696 return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id,1697 action);1698}1699 1700static enum bp_result bios_parser_enable_lvtma_control(1701 struct dc_bios *dcb,1702 uint8_t uc_pwr_on,1703 uint8_t pwrseq_instance,1704 uint8_t bypass_panel_control_wait)1705{1706 struct bios_parser *bp = BP_FROM_DCB(dcb);1707 1708 if (!bp->cmd_tbl.enable_lvtma_control)1709 return BP_RESULT_FAILURE;1710 1711 return bp->cmd_tbl.enable_lvtma_control(bp, uc_pwr_on, pwrseq_instance, bypass_panel_control_wait);1712}1713 1714static bool bios_parser_is_accelerated_mode(1715 struct dc_bios *dcb)1716{1717 return bios_is_accelerated_mode(dcb);1718}1719 1720/**1721 * bios_parser_set_scratch_critical_state - update critical state bit1722 * in VBIOS scratch register1723 *1724 * @dcb: pointer to the DC BIO1725 * @state: set or reset state1726 */1727static void bios_parser_set_scratch_critical_state(1728 struct dc_bios *dcb,1729 bool state)1730{1731 bios_set_scratch_critical_state(dcb, state);1732}1733 1734static enum bp_result bios_parser_get_firmware_info(1735 struct dc_bios *dcb,1736 struct dc_firmware_info *info)1737{1738 struct bios_parser *bp = BP_FROM_DCB(dcb);1739 static enum bp_result result = BP_RESULT_BADBIOSTABLE;1740 struct atom_common_table_header *header;1741 1742 struct atom_data_revision revision;1743 1744 if (info && DATA_TABLES(firmwareinfo)) {1745 header = GET_IMAGE(struct atom_common_table_header,1746 DATA_TABLES(firmwareinfo));1747 get_atom_data_table_revision(header, &revision);1748 switch (revision.major) {1749 case 3:1750 switch (revision.minor) {1751 case 1:1752 result = get_firmware_info_v3_1(bp, info);1753 break;1754 case 2:1755 case 3:1756 result = get_firmware_info_v3_2(bp, info);1757 break;1758 case 4:1759 result = get_firmware_info_v3_4(bp, info);1760 break;1761 case 5:1762 result = get_firmware_info_v3_5(bp, info);1763 break;1764 default:1765 break;1766 }1767 break;1768 default:1769 break;1770 }1771 }1772 1773 return result;1774}1775 1776static enum bp_result get_firmware_info_v3_1(1777 struct bios_parser *bp,1778 struct dc_firmware_info *info)1779{1780 struct atom_firmware_info_v3_1 *firmware_info;1781 struct atom_display_controller_info_v4_1 *dce_info = NULL;1782 1783 if (!info)1784 return BP_RESULT_BADINPUT;1785 1786 firmware_info = GET_IMAGE(struct atom_firmware_info_v3_1,1787 DATA_TABLES(firmwareinfo));1788 1789 dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1,1790 DATA_TABLES(dce_info));1791 1792 if (!firmware_info || !dce_info)1793 return BP_RESULT_BADBIOSTABLE;1794 1795 memset(info, 0, sizeof(*info));1796 1797 /* Pixel clock pll information. */1798 /* We need to convert from 10KHz units into KHz units */1799 info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;1800 info->default_engine_clk = firmware_info->bootup_sclk_in10khz * 10;1801 1802 /* 27MHz for Vega10: */1803 info->pll_info.crystal_frequency = dce_info->dce_refclk_10khz * 10;1804 1805 /* Hardcode frequency if BIOS gives no DCE Ref Clk */1806 if (info->pll_info.crystal_frequency == 0)1807 info->pll_info.crystal_frequency = 27000;1808 /*dp_phy_ref_clk is not correct for atom_display_controller_info_v4_2, but we don't use it*/1809 info->dp_phy_ref_clk = dce_info->dpphy_refclk_10khz * 10;1810 info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10;1811 1812 /* Get GPU PLL VCO Clock */1813 1814 if (bp->cmd_tbl.get_smu_clock_info != NULL) {1815 /* VBIOS gives in 10KHz */1816 info->smu_gpu_pll_output_freq =1817 bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;1818 }1819 1820 info->oem_i2c_present = false;1821 1822 return BP_RESULT_OK;1823}1824 1825static enum bp_result get_firmware_info_v3_2(1826 struct bios_parser *bp,1827 struct dc_firmware_info *info)1828{1829 struct atom_firmware_info_v3_2 *firmware_info;1830 struct atom_display_controller_info_v4_1 *dce_info = NULL;1831 struct atom_common_table_header *header;1832 struct atom_data_revision revision;1833 struct atom_smu_info_v3_2 *smu_info_v3_2 = NULL;1834 struct atom_smu_info_v3_3 *smu_info_v3_3 = NULL;1835 1836 if (!info)1837 return BP_RESULT_BADINPUT;1838 1839 firmware_info = GET_IMAGE(struct atom_firmware_info_v3_2,1840 DATA_TABLES(firmwareinfo));1841 1842 dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1,1843 DATA_TABLES(dce_info));1844 1845 if (!firmware_info || !dce_info)1846 return BP_RESULT_BADBIOSTABLE;1847 1848 memset(info, 0, sizeof(*info));1849 1850 header = GET_IMAGE(struct atom_common_table_header,1851 DATA_TABLES(smu_info));1852 get_atom_data_table_revision(header, &revision);1853 1854 if (revision.minor == 2) {1855 /* Vega12 */1856 smu_info_v3_2 = GET_IMAGE(struct atom_smu_info_v3_2,1857 DATA_TABLES(smu_info));1858 if (!smu_info_v3_2)1859 return BP_RESULT_BADBIOSTABLE;1860 1861 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_2->gpuclk_ss_percentage);1862 1863 info->default_engine_clk = smu_info_v3_2->bootup_dcefclk_10khz * 10;1864 } else if (revision.minor == 3) {1865 /* Vega20 */1866 smu_info_v3_3 = GET_IMAGE(struct atom_smu_info_v3_3,1867 DATA_TABLES(smu_info));1868 if (!smu_info_v3_3)1869 return BP_RESULT_BADBIOSTABLE;1870 1871 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_3->gpuclk_ss_percentage);1872 1873 info->default_engine_clk = smu_info_v3_3->bootup_dcefclk_10khz * 10;1874 }1875 1876 // We need to convert from 10KHz units into KHz units.1877 info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;1878 1879 /* 27MHz for Vega10 & Vega12; 100MHz for Vega20 */1880 info->pll_info.crystal_frequency = dce_info->dce_refclk_10khz * 10;1881 /* Hardcode frequency if BIOS gives no DCE Ref Clk */1882 if (info->pll_info.crystal_frequency == 0) {1883 if (revision.minor == 2)1884 info->pll_info.crystal_frequency = 27000;1885 else if (revision.minor == 3)1886 info->pll_info.crystal_frequency = 100000;1887 }1888 /*dp_phy_ref_clk is not correct for atom_display_controller_info_v4_2, but we don't use it*/1889 info->dp_phy_ref_clk = dce_info->dpphy_refclk_10khz * 10;1890 info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10;1891 1892 /* Get GPU PLL VCO Clock */1893 if (bp->cmd_tbl.get_smu_clock_info != NULL) {1894 if (revision.minor == 2)1895 info->smu_gpu_pll_output_freq =1896 bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;1897 else if (revision.minor == 3)1898 info->smu_gpu_pll_output_freq =1899 bp->cmd_tbl.get_smu_clock_info(bp, SMU11_SYSPLL3_0_ID) * 10;1900 }1901 1902 if (firmware_info->board_i2c_feature_id == 0x2) {1903 info->oem_i2c_present = true;1904 info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;1905 } else {1906 info->oem_i2c_present = false;1907 }1908 1909 return BP_RESULT_OK;1910}1911 1912static enum bp_result get_firmware_info_v3_4(1913 struct bios_parser *bp,1914 struct dc_firmware_info *info)1915{1916 struct atom_firmware_info_v3_4 *firmware_info;1917 struct atom_common_table_header *header;1918 struct atom_data_revision revision;1919 struct atom_display_controller_info_v4_1 *dce_info_v4_1 = NULL;1920 struct atom_display_controller_info_v4_4 *dce_info_v4_4 = NULL;1921 1922 struct atom_smu_info_v3_5 *smu_info_v3_5 = NULL;1923 struct atom_display_controller_info_v4_5 *dce_info_v4_5 = NULL;1924 struct atom_smu_info_v4_0 *smu_info_v4_0 = NULL;1925 1926 if (!info)1927 return BP_RESULT_BADINPUT;1928 1929 firmware_info = GET_IMAGE(struct atom_firmware_info_v3_4,1930 DATA_TABLES(firmwareinfo));1931 1932 if (!firmware_info)1933 return BP_RESULT_BADBIOSTABLE;1934 1935 memset(info, 0, sizeof(*info));1936 1937 header = GET_IMAGE(struct atom_common_table_header,1938 DATA_TABLES(dce_info));1939 1940 get_atom_data_table_revision(header, &revision);1941 1942 switch (revision.major) {1943 case 4:1944 switch (revision.minor) {1945 case 5:1946 dce_info_v4_5 = GET_IMAGE(struct atom_display_controller_info_v4_5,1947 DATA_TABLES(dce_info));1948 1949 if (!dce_info_v4_5)1950 return BP_RESULT_BADBIOSTABLE;1951 1952 /* 100MHz expected */1953 info->pll_info.crystal_frequency = dce_info_v4_5->dce_refclk_10khz * 10;1954 info->dp_phy_ref_clk = dce_info_v4_5->dpphy_refclk_10khz * 10;1955 /* 50MHz expected */1956 info->i2c_engine_ref_clk = dce_info_v4_5->i2c_engine_refclk_10khz * 10;1957 1958 /* For DCN32/321 Display PLL VCO Frequency from dce_info_v4_5 may not be reliable */1959 break;1960 1961 case 4:1962 dce_info_v4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,1963 DATA_TABLES(dce_info));1964 1965 if (!dce_info_v4_4)1966 return BP_RESULT_BADBIOSTABLE;1967 1968 /* 100MHz expected */1969 info->pll_info.crystal_frequency = dce_info_v4_4->dce_refclk_10khz * 10;1970 info->dp_phy_ref_clk = dce_info_v4_4->dpphy_refclk_10khz * 10;1971 /* 50MHz expected */1972 info->i2c_engine_ref_clk = dce_info_v4_4->i2c_engine_refclk_10khz * 10;1973 1974 /* Get SMU Display PLL VCO Frequency in KHz*/1975 info->smu_gpu_pll_output_freq = dce_info_v4_4->dispclk_pll_vco_freq * 10;1976 break;1977 1978 default:1979 /* should not come here, keep as backup, as was before */1980 dce_info_v4_1 = GET_IMAGE(struct atom_display_controller_info_v4_1,1981 DATA_TABLES(dce_info));1982 1983 if (!dce_info_v4_1)1984 return BP_RESULT_BADBIOSTABLE;1985 1986 info->pll_info.crystal_frequency = dce_info_v4_1->dce_refclk_10khz * 10;1987 info->dp_phy_ref_clk = dce_info_v4_1->dpphy_refclk_10khz * 10;1988 info->i2c_engine_ref_clk = dce_info_v4_1->i2c_engine_refclk_10khz * 10;1989 break;1990 }1991 break;1992 1993 default:1994 ASSERT(0);1995 break;1996 }1997 1998 header = GET_IMAGE(struct atom_common_table_header,1999 DATA_TABLES(smu_info));2000 get_atom_data_table_revision(header, &revision);2001 2002 switch (revision.major) {2003 case 3:2004 switch (revision.minor) {2005 case 5:2006 smu_info_v3_5 = GET_IMAGE(struct atom_smu_info_v3_5,2007 DATA_TABLES(smu_info));2008 2009 if (!smu_info_v3_5)2010 return BP_RESULT_BADBIOSTABLE;2011 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_5->gpuclk_ss_percentage);2012 info->default_engine_clk = smu_info_v3_5->bootup_dcefclk_10khz * 10;2013 break;2014 2015 default:2016 break;2017 }2018 break;2019 2020 case 4:2021 switch (revision.minor) {2022 case 0:2023 smu_info_v4_0 = GET_IMAGE(struct atom_smu_info_v4_0,2024 DATA_TABLES(smu_info));2025 2026 if (!smu_info_v4_0)2027 return BP_RESULT_BADBIOSTABLE;2028 2029 /* For DCN32/321 bootup DCFCLK from smu_info_v4_0 may not be reliable */2030 break;2031 2032 default:2033 break;2034 }2035 break;2036 2037 default:2038 break;2039 }2040 2041 // We need to convert from 10KHz units into KHz units.2042 info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;2043 2044 if (firmware_info->board_i2c_feature_id == 0x2) {2045 info->oem_i2c_present = true;2046 info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;2047 } else {2048 info->oem_i2c_present = false;2049 }2050 2051 return BP_RESULT_OK;2052}2053 2054static enum bp_result get_firmware_info_v3_5(2055 struct bios_parser *bp,2056 struct dc_firmware_info *info)2057{2058 struct atom_firmware_info_v3_5 *firmware_info;2059 struct atom_common_table_header *header;2060 struct atom_data_revision revision;2061 struct atom_display_controller_info_v4_5 *dce_info_v4_5 = NULL;2062 2063 if (!info)2064 return BP_RESULT_BADINPUT;2065 2066 firmware_info = GET_IMAGE(struct atom_firmware_info_v3_5,2067 DATA_TABLES(firmwareinfo));2068 2069 if (!firmware_info)2070 return BP_RESULT_BADBIOSTABLE;2071 2072 memset(info, 0, sizeof(*info));2073 2074 if (firmware_info->board_i2c_feature_id == 0x2) {2075 info->oem_i2c_present = true;2076 info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id;2077 } else {2078 info->oem_i2c_present = false;2079 }2080 2081 header = GET_IMAGE(struct atom_common_table_header,2082 DATA_TABLES(dce_info));2083 2084 get_atom_data_table_revision(header, &revision);2085 2086 switch (revision.major) {2087 case 4:2088 switch (revision.minor) {2089 case 5:2090 dce_info_v4_5 = GET_IMAGE(struct atom_display_controller_info_v4_5,2091 DATA_TABLES(dce_info));2092 2093 if (!dce_info_v4_5)2094 return BP_RESULT_BADBIOSTABLE;2095 2096 /* 100MHz expected */2097 info->pll_info.crystal_frequency = dce_info_v4_5->dce_refclk_10khz * 10;2098 break;2099 default:2100 break;2101 }2102 break;2103 default:2104 break;2105 }2106 2107 2108 return BP_RESULT_OK;2109}2110 2111static enum bp_result bios_parser_get_encoder_cap_info(2112 struct dc_bios *dcb,2113 struct graphics_object_id object_id,2114 struct bp_encoder_cap_info *info)2115{2116 struct bios_parser *bp = BP_FROM_DCB(dcb);2117 struct atom_display_object_path_v2 *object;2118 struct atom_encoder_caps_record *record = NULL;2119 2120 if (!info)2121 return BP_RESULT_BADINPUT;2122 2123#if defined(CONFIG_DRM_AMD_DC_FP)2124 /* encoder cap record not available in v1_5 */2125 if (bp->object_info_tbl.revision.minor == 5)2126 return BP_RESULT_NORECORD;2127#endif2128 2129 object = get_bios_object(bp, object_id);2130 2131 if (!object)2132 return BP_RESULT_BADINPUT;2133 2134 record = get_encoder_cap_record(bp, object);2135 if (!record)2136 return BP_RESULT_NORECORD;2137 DC_LOG_BIOS("record->encodercaps 0x%x for object_id 0x%x", record->encodercaps, object_id.id);2138 2139 info->DP_HBR2_CAP = (record->encodercaps &2140 ATOM_ENCODER_CAP_RECORD_HBR2) ? 1 : 0;2141 info->DP_HBR2_EN = (record->encodercaps &2142 ATOM_ENCODER_CAP_RECORD_HBR2_EN) ? 1 : 0;2143 info->DP_HBR3_EN = (record->encodercaps &2144 ATOM_ENCODER_CAP_RECORD_HBR3_EN) ? 1 : 0;2145 info->HDMI_6GB_EN = (record->encodercaps &2146 ATOM_ENCODER_CAP_RECORD_HDMI6Gbps_EN) ? 1 : 0;2147 info->IS_DP2_CAPABLE = (record->encodercaps &2148 ATOM_ENCODER_CAP_RECORD_DP2) ? 1 : 0;2149 info->DP_UHBR10_EN = (record->encodercaps &2150 ATOM_ENCODER_CAP_RECORD_UHBR10_EN) ? 1 : 0;2151 info->DP_UHBR13_5_EN = (record->encodercaps &2152 ATOM_ENCODER_CAP_RECORD_UHBR13_5_EN) ? 1 : 0;2153 info->DP_UHBR20_EN = (record->encodercaps &2154 ATOM_ENCODER_CAP_RECORD_UHBR20_EN) ? 1 : 0;2155 info->DP_IS_USB_C = (record->encodercaps &2156 ATOM_ENCODER_CAP_RECORD_USB_C_TYPE) ? 1 : 0;2157 DC_LOG_BIOS("\t info->DP_IS_USB_C %d", info->DP_IS_USB_C);2158 2159 return BP_RESULT_OK;2160}2161 2162 2163static struct atom_encoder_caps_record *get_encoder_cap_record(2164 struct bios_parser *bp,2165 struct atom_display_object_path_v2 *object)2166{2167 struct atom_common_record_header *header;2168 uint32_t offset;2169 2170 if (!object) {2171 BREAK_TO_DEBUGGER(); /* Invalid object */2172 return NULL;2173 }2174 2175 offset = object->encoder_recordoffset + bp->object_info_tbl_offset;2176 2177 for (;;) {2178 header = GET_IMAGE(struct atom_common_record_header, offset);2179 2180 if (!header)2181 return NULL;2182 2183 offset += header->record_size;2184 2185 if (header->record_type == LAST_RECORD_TYPE ||2186 !header->record_size)2187 break;2188 2189 if (header->record_type != ATOM_ENCODER_CAP_RECORD_TYPE)2190 continue;2191 2192 if (sizeof(struct atom_encoder_caps_record) <=2193 header->record_size)2194 return (struct atom_encoder_caps_record *)header;2195 }2196 2197 return NULL;2198}2199 2200static struct atom_disp_connector_caps_record *get_disp_connector_caps_record(2201 struct bios_parser *bp,2202 struct atom_display_object_path_v2 *object)2203{2204 struct atom_common_record_header *header;2205 uint32_t offset;2206 2207 if (!object) {2208 BREAK_TO_DEBUGGER(); /* Invalid object */2209 return NULL;2210 }2211 2212 offset = object->disp_recordoffset + bp->object_info_tbl_offset;2213 2214 for (;;) {2215 header = GET_IMAGE(struct atom_common_record_header, offset);2216 2217 if (!header)2218 return NULL;2219 2220 offset += header->record_size;2221 2222 if (header->record_type == LAST_RECORD_TYPE ||2223 !header->record_size)2224 break;2225 2226 if (header->record_type != ATOM_DISP_CONNECTOR_CAPS_RECORD_TYPE)2227 continue;2228 2229 if (sizeof(struct atom_disp_connector_caps_record) <=2230 header->record_size)2231 return (struct atom_disp_connector_caps_record *)header;2232 }2233 2234 return NULL;2235}2236 2237static struct atom_connector_caps_record *get_connector_caps_record(struct bios_parser *bp,2238 struct atom_display_object_path_v3 *object)2239{2240 struct atom_common_record_header *header;2241 uint32_t offset;2242 2243 if (!object) {2244 BREAK_TO_DEBUGGER(); /* Invalid object */2245 return NULL;2246 }2247 2248 offset = object->disp_recordoffset + bp->object_info_tbl_offset;2249 2250 for (;;) {2251 header = GET_IMAGE(struct atom_common_record_header, offset);2252 2253 if (!header)2254 return NULL;2255 2256 offset += header->record_size;2257 2258 if (header->record_type == ATOM_RECORD_END_TYPE ||2259 !header->record_size)2260 break;2261 2262 if (header->record_type != ATOM_CONNECTOR_CAP_RECORD_TYPE)2263 continue;2264 2265 if (sizeof(struct atom_connector_caps_record) <= header->record_size)2266 return (struct atom_connector_caps_record *)header;2267 }2268 2269 return NULL;2270}2271 2272static enum bp_result bios_parser_get_disp_connector_caps_info(2273 struct dc_bios *dcb,2274 struct graphics_object_id object_id,2275 struct bp_disp_connector_caps_info *info)2276{2277 struct bios_parser *bp = BP_FROM_DCB(dcb);2278 struct atom_display_object_path_v2 *object;2279 struct atom_display_object_path_v3 *object_path_v3;2280 struct atom_connector_caps_record *record_path_v3;2281 struct atom_disp_connector_caps_record *record = NULL;2282 2283 if (!info)2284 return BP_RESULT_BADINPUT;2285 2286 switch (bp->object_info_tbl.revision.minor) {2287 case 4:2288 default:2289 object = get_bios_object(bp, object_id);2290 2291 if (!object)2292 return BP_RESULT_BADINPUT;2293 2294 record = get_disp_connector_caps_record(bp, object);2295 if (!record)2296 return BP_RESULT_NORECORD;2297 2298 info->INTERNAL_DISPLAY =2299 (record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY) ? 1 : 0;2300 info->INTERNAL_DISPLAY_BL =2301 (record->connectcaps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL) ? 1 : 0;2302 break;2303 case 5:2304 object_path_v3 = get_bios_object_from_path_v3(bp, object_id);2305 2306 if (!object_path_v3)2307 return BP_RESULT_BADINPUT;2308 2309 record_path_v3 = get_connector_caps_record(bp, object_path_v3);2310 if (!record_path_v3)2311 return BP_RESULT_NORECORD;2312 2313 info->INTERNAL_DISPLAY = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY)2314 ? 1 : 0;2315 info->INTERNAL_DISPLAY_BL = (record_path_v3->connector_caps & ATOM_CONNECTOR_CAP_INTERNAL_DISPLAY_BL)2316 ? 1 : 0;2317 break;2318 }2319 2320 return BP_RESULT_OK;2321}2322 2323static struct atom_connector_speed_record *get_connector_speed_cap_record(struct bios_parser *bp,2324 struct atom_display_object_path_v3 *object)2325{2326 struct atom_common_record_header *header;2327 uint32_t offset;2328 2329 if (!object) {2330 BREAK_TO_DEBUGGER(); /* Invalid object */2331 return NULL;2332 }2333 2334 offset = object->disp_recordoffset + bp->object_info_tbl_offset;2335 2336 for (;;) {2337 header = GET_IMAGE(struct atom_common_record_header, offset);2338 2339 if (!header)2340 return NULL;2341 2342 offset += header->record_size;2343 2344 if (header->record_type == ATOM_RECORD_END_TYPE ||2345 !header->record_size)2346 break;2347 2348 if (header->record_type != ATOM_CONNECTOR_SPEED_UPTO)2349 continue;2350 2351 if (sizeof(struct atom_connector_speed_record) <= header->record_size)2352 return (struct atom_connector_speed_record *)header;2353 }2354 2355 return NULL;2356}2357 2358static enum bp_result bios_parser_get_connector_speed_cap_info(2359 struct dc_bios *dcb,2360 struct graphics_object_id object_id,2361 struct bp_connector_speed_cap_info *info)2362{2363 struct bios_parser *bp = BP_FROM_DCB(dcb);2364 struct atom_display_object_path_v3 *object_path_v3;2365 //struct atom_connector_speed_record *record = NULL;2366 struct atom_connector_speed_record *record;2367 2368 if (!info)2369 return BP_RESULT_BADINPUT;2370 2371 object_path_v3 = get_bios_object_from_path_v3(bp, object_id);2372 2373 if (!object_path_v3)2374 return BP_RESULT_BADINPUT;2375 2376 record = get_connector_speed_cap_record(bp, object_path_v3);2377 if (!record)2378 return BP_RESULT_NORECORD;2379 2380 info->DP_HBR2_EN = (record->connector_max_speed >= 5400) ? 1 : 0;2381 info->DP_HBR3_EN = (record->connector_max_speed >= 8100) ? 1 : 0;2382 info->HDMI_6GB_EN = (record->connector_max_speed >= 5940) ? 1 : 0;2383 info->DP_UHBR10_EN = (record->connector_max_speed >= 10000) ? 1 : 0;2384 info->DP_UHBR13_5_EN = (record->connector_max_speed >= 13500) ? 1 : 0;2385 info->DP_UHBR20_EN = (record->connector_max_speed >= 20000) ? 1 : 0;2386 return BP_RESULT_OK;2387}2388 2389static enum bp_result get_vram_info_v23(2390 struct bios_parser *bp,2391 struct dc_vram_info *info)2392{2393 struct atom_vram_info_header_v2_3 *info_v23;2394 static enum bp_result result = BP_RESULT_OK;2395 2396 info_v23 = GET_IMAGE(struct atom_vram_info_header_v2_3,2397 DATA_TABLES(vram_info));2398 2399 if (info_v23 == NULL)2400 return BP_RESULT_BADBIOSTABLE;2401 2402 info->num_chans = info_v23->vram_module[0].channel_num;2403 info->dram_channel_width_bytes = (1 << info_v23->vram_module[0].channel_width) / 8;2404 2405 return result;2406}2407 2408static enum bp_result get_vram_info_v24(2409 struct bios_parser *bp,2410 struct dc_vram_info *info)2411{2412 struct atom_vram_info_header_v2_4 *info_v24;2413 static enum bp_result result = BP_RESULT_OK;2414 2415 info_v24 = GET_IMAGE(struct atom_vram_info_header_v2_4,2416 DATA_TABLES(vram_info));2417 2418 if (info_v24 == NULL)2419 return BP_RESULT_BADBIOSTABLE;2420 2421 info->num_chans = info_v24->vram_module[0].channel_num;2422 info->dram_channel_width_bytes = (1 << info_v24->vram_module[0].channel_width) / 8;2423 2424 return result;2425}2426 2427static enum bp_result get_vram_info_v25(2428 struct bios_parser *bp,2429 struct dc_vram_info *info)2430{2431 struct atom_vram_info_header_v2_5 *info_v25;2432 static enum bp_result result = BP_RESULT_OK;2433 2434 info_v25 = GET_IMAGE(struct atom_vram_info_header_v2_5,2435 DATA_TABLES(vram_info));2436 2437 if (info_v25 == NULL)2438 return BP_RESULT_BADBIOSTABLE;2439 2440 info->num_chans = info_v25->vram_module[0].channel_num;2441 info->dram_channel_width_bytes = (1 << info_v25->vram_module[0].channel_width) / 8;2442 2443 return result;2444}2445 2446static enum bp_result get_vram_info_v30(2447 struct bios_parser *bp,2448 struct dc_vram_info *info)2449{2450 struct atom_vram_info_header_v3_0 *info_v30;2451 enum bp_result result = BP_RESULT_OK;2452 2453 info_v30 = GET_IMAGE(struct atom_vram_info_header_v3_0,2454 DATA_TABLES(vram_info));2455 2456 if (info_v30 == NULL)2457 return BP_RESULT_BADBIOSTABLE;2458 2459 info->num_chans = info_v30->channel_num;2460 info->dram_channel_width_bytes = (1 << info_v30->channel_width) / 8;2461 2462 return result;2463}2464 2465static enum bp_result get_vram_info_from_umc_info_v40(2466 struct bios_parser *bp,2467 struct dc_vram_info *info)2468{2469 struct atom_umc_info_v4_0 *info_v40;2470 enum bp_result result = BP_RESULT_OK;2471 2472 info_v40 = GET_IMAGE(struct atom_umc_info_v4_0,2473 DATA_TABLES(umc_info));2474 2475 if (info_v40 == NULL)2476 return BP_RESULT_BADBIOSTABLE;2477 2478 info->num_chans = info_v40->channel_num;2479 info->dram_channel_width_bytes = (1 << info_v40->channel_width) / 8;2480 2481 return result;2482}2483 2484/*2485 * get_integrated_info_v112486 *2487 * @brief2488 * Get V8 integrated BIOS information2489 *2490 * @param2491 * bios_parser *bp - [in]BIOS parser handler to get master data table2492 * integrated_info *info - [out] store and output integrated info2493 *2494 * @return2495 * static enum bp_result - BP_RESULT_OK if information is available,2496 * BP_RESULT_BADBIOSTABLE otherwise.2497 */2498static enum bp_result get_integrated_info_v11(2499 struct bios_parser *bp,2500 struct integrated_info *info)2501{2502 struct atom_integrated_system_info_v1_11 *info_v11;2503 uint32_t i;2504 2505 info_v11 = GET_IMAGE(struct atom_integrated_system_info_v1_11,2506 DATA_TABLES(integratedsysteminfo));2507 2508 if (info_v11 == NULL)2509 return BP_RESULT_BADBIOSTABLE;2510 2511 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v11->gpuclk_ss_percentage);2512 2513 info->gpu_cap_info =2514 le32_to_cpu(info_v11->gpucapinfo);2515 /*2516 * system_config: Bit[0] = 0 : PCIE power gating disabled2517 * = 1 : PCIE power gating enabled2518 * Bit[1] = 0 : DDR-PLL shut down disabled2519 * = 1 : DDR-PLL shut down enabled2520 * Bit[2] = 0 : DDR-PLL power down disabled2521 * = 1 : DDR-PLL power down enabled2522 */2523 info->system_config = le32_to_cpu(info_v11->system_config);2524 info->cpu_cap_info = le32_to_cpu(info_v11->cpucapinfo);2525 info->memory_type = info_v11->memorytype;2526 info->ma_channel_number = info_v11->umachannelnumber;2527 info->lvds_ss_percentage =2528 le16_to_cpu(info_v11->lvds_ss_percentage);2529 info->dp_ss_control =2530 le16_to_cpu(info_v11->reserved1);2531 info->lvds_sspread_rate_in_10hz =2532 le16_to_cpu(info_v11->lvds_ss_rate_10hz);2533 info->hdmi_ss_percentage =2534 le16_to_cpu(info_v11->hdmi_ss_percentage);2535 info->hdmi_sspread_rate_in_10hz =2536 le16_to_cpu(info_v11->hdmi_ss_rate_10hz);2537 info->dvi_ss_percentage =2538 le16_to_cpu(info_v11->dvi_ss_percentage);2539 info->dvi_sspread_rate_in_10_hz =2540 le16_to_cpu(info_v11->dvi_ss_rate_10hz);2541 info->lvds_misc = info_v11->lvds_misc;2542 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {2543 info->ext_disp_conn_info.gu_id[i] =2544 info_v11->extdispconninfo.guid[i];2545 }2546 2547 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {2548 info->ext_disp_conn_info.path[i].device_connector_id =2549 object_id_from_bios_object_id(2550 le16_to_cpu(info_v11->extdispconninfo.path[i].connectorobjid));2551 2552 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =2553 object_id_from_bios_object_id(2554 le16_to_cpu(2555 info_v11->extdispconninfo.path[i].ext_encoder_objid));2556 2557 info->ext_disp_conn_info.path[i].device_tag =2558 le16_to_cpu(2559 info_v11->extdispconninfo.path[i].device_tag);2560 info->ext_disp_conn_info.path[i].device_acpi_enum =2561 le16_to_cpu(2562 info_v11->extdispconninfo.path[i].device_acpi_enum);2563 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =2564 info_v11->extdispconninfo.path[i].auxddclut_index;2565 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =2566 info_v11->extdispconninfo.path[i].hpdlut_index;2567 info->ext_disp_conn_info.path[i].channel_mapping.raw =2568 info_v11->extdispconninfo.path[i].channelmapping;2569 info->ext_disp_conn_info.path[i].caps =2570 le16_to_cpu(info_v11->extdispconninfo.path[i].caps);2571 }2572 info->ext_disp_conn_info.checksum =2573 info_v11->extdispconninfo.checksum;2574 2575 info->dp0_ext_hdmi_slv_addr = info_v11->dp0_retimer_set.HdmiSlvAddr;2576 info->dp0_ext_hdmi_reg_num = info_v11->dp0_retimer_set.HdmiRegNum;2577 for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {2578 info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =2579 info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;2580 info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =2581 info_v11->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;2582 }2583 info->dp0_ext_hdmi_6g_reg_num = info_v11->dp0_retimer_set.Hdmi6GRegNum;2584 for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {2585 info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =2586 info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;2587 info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val =2588 info_v11->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;2589 }2590 2591 info->dp1_ext_hdmi_slv_addr = info_v11->dp1_retimer_set.HdmiSlvAddr;2592 info->dp1_ext_hdmi_reg_num = info_v11->dp1_retimer_set.HdmiRegNum;2593 for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {2594 info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =2595 info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;2596 info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =2597 info_v11->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;2598 }2599 info->dp1_ext_hdmi_6g_reg_num = info_v11->dp1_retimer_set.Hdmi6GRegNum;2600 for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {2601 info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =2602 info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;2603 info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val =2604 info_v11->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;2605 }2606 2607 info->dp2_ext_hdmi_slv_addr = info_v11->dp2_retimer_set.HdmiSlvAddr;2608 info->dp2_ext_hdmi_reg_num = info_v11->dp2_retimer_set.HdmiRegNum;2609 for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {2610 info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =2611 info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;2612 info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =2613 info_v11->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;2614 }2615 info->dp2_ext_hdmi_6g_reg_num = info_v11->dp2_retimer_set.Hdmi6GRegNum;2616 for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {2617 info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =2618 info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;2619 info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val =2620 info_v11->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;2621 }2622 2623 info->dp3_ext_hdmi_slv_addr = info_v11->dp3_retimer_set.HdmiSlvAddr;2624 info->dp3_ext_hdmi_reg_num = info_v11->dp3_retimer_set.HdmiRegNum;2625 for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {2626 info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =2627 info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;2628 info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =2629 info_v11->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;2630 }2631 info->dp3_ext_hdmi_6g_reg_num = info_v11->dp3_retimer_set.Hdmi6GRegNum;2632 for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {2633 info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =2634 info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;2635 info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val =2636 info_v11->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;2637 }2638 2639 2640 /** TODO - review **/2641 #if 02642 info->boot_up_engine_clock = le32_to_cpu(info_v11->ulBootUpEngineClock)2643 * 10;2644 info->dentist_vco_freq = le32_to_cpu(info_v11->ulDentistVCOFreq) * 10;2645 info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;2646 2647 for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {2648 /* Convert [10KHz] into [KHz] */2649 info->disp_clk_voltage[i].max_supported_clk =2650 le32_to_cpu(info_v11->sDISPCLK_Voltage[i].2651 ulMaximumSupportedCLK) * 10;2652 info->disp_clk_voltage[i].voltage_index =2653 le32_to_cpu(info_v11->sDISPCLK_Voltage[i].ulVoltageIndex);2654 }2655 2656 info->boot_up_req_display_vector =2657 le32_to_cpu(info_v11->ulBootUpReqDisplayVector);2658 info->boot_up_nb_voltage =2659 le16_to_cpu(info_v11->usBootUpNBVoltage);2660 info->ext_disp_conn_info_offset =2661 le16_to_cpu(info_v11->usExtDispConnInfoOffset);2662 info->gmc_restore_reset_time =2663 le32_to_cpu(info_v11->ulGMCRestoreResetTime);2664 info->minimum_n_clk =2665 le32_to_cpu(info_v11->ulNbpStateNClkFreq[0]);2666 for (i = 1; i < 4; ++i)2667 info->minimum_n_clk =2668 info->minimum_n_clk <2669 le32_to_cpu(info_v11->ulNbpStateNClkFreq[i]) ?2670 info->minimum_n_clk : le32_to_cpu(2671 info_v11->ulNbpStateNClkFreq[i]);2672 2673 info->idle_n_clk = le32_to_cpu(info_v11->ulIdleNClk);2674 info->ddr_dll_power_up_time =2675 le32_to_cpu(info_v11->ulDDR_DLL_PowerUpTime);2676 info->ddr_pll_power_up_time =2677 le32_to_cpu(info_v11->ulDDR_PLL_PowerUpTime);2678 info->pcie_clk_ss_type = le16_to_cpu(info_v11->usPCIEClkSSType);2679 info->max_lvds_pclk_freq_in_single_link =2680 le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink);2681 info->max_lvds_pclk_freq_in_single_link =2682 le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink);2683 info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =2684 info_v11->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;2685 info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =2686 info_v11->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;2687 info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =2688 info_v11->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;2689 info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =2690 info_v11->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;2691 info->lvds_pwr_off_seq_de_to_dig_on_in4ms =2692 info_v11->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;2693 info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =2694 info_v11->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;2695 info->lvds_off_to_on_delay_in_4ms =2696 info_v11->ucLVDSOffToOnDelay_in4Ms;2697 info->lvds_bit_depth_control_val =2698 le32_to_cpu(info_v11->ulLCDBitDepthControlVal);2699 2700 for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {2701 /* Convert [10KHz] into [KHz] */2702 info->avail_s_clk[i].supported_s_clk =2703 le32_to_cpu(info_v11->sAvail_SCLK[i].ulSupportedSCLK)2704 * 10;2705 info->avail_s_clk[i].voltage_index =2706 le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageIndex);2707 info->avail_s_clk[i].voltage_id =2708 le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageID);2709 }2710 #endif /* TODO*/2711 2712 return BP_RESULT_OK;2713}2714 2715static enum bp_result get_integrated_info_v2_1(2716 struct bios_parser *bp,2717 struct integrated_info *info)2718{2719 struct atom_integrated_system_info_v2_1 *info_v2_1;2720 uint32_t i;2721 2722 info_v2_1 = GET_IMAGE(struct atom_integrated_system_info_v2_1,2723 DATA_TABLES(integratedsysteminfo));2724 2725 if (info_v2_1 == NULL)2726 return BP_RESULT_BADBIOSTABLE;2727 2728 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_1->gpuclk_ss_percentage);2729 2730 info->gpu_cap_info =2731 le32_to_cpu(info_v2_1->gpucapinfo);2732 /*2733 * system_config: Bit[0] = 0 : PCIE power gating disabled2734 * = 1 : PCIE power gating enabled2735 * Bit[1] = 0 : DDR-PLL shut down disabled2736 * = 1 : DDR-PLL shut down enabled2737 * Bit[2] = 0 : DDR-PLL power down disabled2738 * = 1 : DDR-PLL power down enabled2739 */2740 info->system_config = le32_to_cpu(info_v2_1->system_config);2741 info->cpu_cap_info = le32_to_cpu(info_v2_1->cpucapinfo);2742 info->memory_type = info_v2_1->memorytype;2743 info->ma_channel_number = info_v2_1->umachannelnumber;2744 info->dp_ss_control =2745 le16_to_cpu(info_v2_1->reserved1);2746 2747 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {2748 info->ext_disp_conn_info.gu_id[i] =2749 info_v2_1->extdispconninfo.guid[i];2750 }2751 2752 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {2753 info->ext_disp_conn_info.path[i].device_connector_id =2754 object_id_from_bios_object_id(2755 le16_to_cpu(info_v2_1->extdispconninfo.path[i].connectorobjid));2756 2757 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =2758 object_id_from_bios_object_id(2759 le16_to_cpu(2760 info_v2_1->extdispconninfo.path[i].ext_encoder_objid));2761 2762 info->ext_disp_conn_info.path[i].device_tag =2763 le16_to_cpu(2764 info_v2_1->extdispconninfo.path[i].device_tag);2765 info->ext_disp_conn_info.path[i].device_acpi_enum =2766 le16_to_cpu(2767 info_v2_1->extdispconninfo.path[i].device_acpi_enum);2768 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =2769 info_v2_1->extdispconninfo.path[i].auxddclut_index;2770 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =2771 info_v2_1->extdispconninfo.path[i].hpdlut_index;2772 info->ext_disp_conn_info.path[i].channel_mapping.raw =2773 info_v2_1->extdispconninfo.path[i].channelmapping;2774 info->ext_disp_conn_info.path[i].caps =2775 le16_to_cpu(info_v2_1->extdispconninfo.path[i].caps);2776 }2777 2778 info->ext_disp_conn_info.checksum =2779 info_v2_1->extdispconninfo.checksum;2780 info->dp0_ext_hdmi_slv_addr = info_v2_1->dp0_retimer_set.HdmiSlvAddr;2781 info->dp0_ext_hdmi_reg_num = info_v2_1->dp0_retimer_set.HdmiRegNum;2782 for (i = 0; i < info->dp0_ext_hdmi_reg_num; i++) {2783 info->dp0_ext_hdmi_reg_settings[i].i2c_reg_index =2784 info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;2785 info->dp0_ext_hdmi_reg_settings[i].i2c_reg_val =2786 info_v2_1->dp0_retimer_set.HdmiRegSetting[i].ucI2cRegVal;2787 }2788 info->dp0_ext_hdmi_6g_reg_num = info_v2_1->dp0_retimer_set.Hdmi6GRegNum;2789 for (i = 0; i < info->dp0_ext_hdmi_6g_reg_num; i++) {2790 info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_index =2791 info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;2792 info->dp0_ext_hdmi_6g_reg_settings[i].i2c_reg_val =2793 info_v2_1->dp0_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;2794 }2795 info->dp1_ext_hdmi_slv_addr = info_v2_1->dp1_retimer_set.HdmiSlvAddr;2796 info->dp1_ext_hdmi_reg_num = info_v2_1->dp1_retimer_set.HdmiRegNum;2797 for (i = 0; i < info->dp1_ext_hdmi_reg_num; i++) {2798 info->dp1_ext_hdmi_reg_settings[i].i2c_reg_index =2799 info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;2800 info->dp1_ext_hdmi_reg_settings[i].i2c_reg_val =2801 info_v2_1->dp1_retimer_set.HdmiRegSetting[i].ucI2cRegVal;2802 }2803 info->dp1_ext_hdmi_6g_reg_num = info_v2_1->dp1_retimer_set.Hdmi6GRegNum;2804 for (i = 0; i < info->dp1_ext_hdmi_6g_reg_num; i++) {2805 info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_index =2806 info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;2807 info->dp1_ext_hdmi_6g_reg_settings[i].i2c_reg_val =2808 info_v2_1->dp1_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;2809 }2810 info->dp2_ext_hdmi_slv_addr = info_v2_1->dp2_retimer_set.HdmiSlvAddr;2811 info->dp2_ext_hdmi_reg_num = info_v2_1->dp2_retimer_set.HdmiRegNum;2812 for (i = 0; i < info->dp2_ext_hdmi_reg_num; i++) {2813 info->dp2_ext_hdmi_reg_settings[i].i2c_reg_index =2814 info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;2815 info->dp2_ext_hdmi_reg_settings[i].i2c_reg_val =2816 info_v2_1->dp2_retimer_set.HdmiRegSetting[i].ucI2cRegVal;2817 }2818 info->dp2_ext_hdmi_6g_reg_num = info_v2_1->dp2_retimer_set.Hdmi6GRegNum;2819 for (i = 0; i < info->dp2_ext_hdmi_6g_reg_num; i++) {2820 info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_index =2821 info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;2822 info->dp2_ext_hdmi_6g_reg_settings[i].i2c_reg_val =2823 info_v2_1->dp2_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;2824 }2825 info->dp3_ext_hdmi_slv_addr = info_v2_1->dp3_retimer_set.HdmiSlvAddr;2826 info->dp3_ext_hdmi_reg_num = info_v2_1->dp3_retimer_set.HdmiRegNum;2827 for (i = 0; i < info->dp3_ext_hdmi_reg_num; i++) {2828 info->dp3_ext_hdmi_reg_settings[i].i2c_reg_index =2829 info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegIndex;2830 info->dp3_ext_hdmi_reg_settings[i].i2c_reg_val =2831 info_v2_1->dp3_retimer_set.HdmiRegSetting[i].ucI2cRegVal;2832 }2833 info->dp3_ext_hdmi_6g_reg_num = info_v2_1->dp3_retimer_set.Hdmi6GRegNum;2834 for (i = 0; i < info->dp3_ext_hdmi_6g_reg_num; i++) {2835 info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_index =2836 info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegIndex;2837 info->dp3_ext_hdmi_6g_reg_settings[i].i2c_reg_val =2838 info_v2_1->dp3_retimer_set.Hdmi6GhzRegSetting[i].ucI2cRegVal;2839 }2840 2841 info->edp1_info.edp_backlight_pwm_hz =2842 le16_to_cpu(info_v2_1->edp1_info.edp_backlight_pwm_hz);2843 info->edp1_info.edp_ss_percentage =2844 le16_to_cpu(info_v2_1->edp1_info.edp_ss_percentage);2845 info->edp1_info.edp_ss_rate_10hz =2846 le16_to_cpu(info_v2_1->edp1_info.edp_ss_rate_10hz);2847 info->edp1_info.edp_pwr_on_off_delay =2848 info_v2_1->edp1_info.edp_pwr_on_off_delay;2849 info->edp1_info.edp_pwr_on_vary_bl_to_blon =2850 info_v2_1->edp1_info.edp_pwr_on_vary_bl_to_blon;2851 info->edp1_info.edp_pwr_down_bloff_to_vary_bloff =2852 info_v2_1->edp1_info.edp_pwr_down_bloff_to_vary_bloff;2853 info->edp1_info.edp_panel_bpc =2854 info_v2_1->edp1_info.edp_panel_bpc;2855 info->edp1_info.edp_bootup_bl_level = info_v2_1->edp1_info.edp_bootup_bl_level;2856 2857 info->edp2_info.edp_backlight_pwm_hz =2858 le16_to_cpu(info_v2_1->edp2_info.edp_backlight_pwm_hz);2859 info->edp2_info.edp_ss_percentage =2860 le16_to_cpu(info_v2_1->edp2_info.edp_ss_percentage);2861 info->edp2_info.edp_ss_rate_10hz =2862 le16_to_cpu(info_v2_1->edp2_info.edp_ss_rate_10hz);2863 info->edp2_info.edp_pwr_on_off_delay =2864 info_v2_1->edp2_info.edp_pwr_on_off_delay;2865 info->edp2_info.edp_pwr_on_vary_bl_to_blon =2866 info_v2_1->edp2_info.edp_pwr_on_vary_bl_to_blon;2867 info->edp2_info.edp_pwr_down_bloff_to_vary_bloff =2868 info_v2_1->edp2_info.edp_pwr_down_bloff_to_vary_bloff;2869 info->edp2_info.edp_panel_bpc =2870 info_v2_1->edp2_info.edp_panel_bpc;2871 info->edp2_info.edp_bootup_bl_level =2872 info_v2_1->edp2_info.edp_bootup_bl_level;2873 2874 return BP_RESULT_OK;2875}2876 2877static enum bp_result get_integrated_info_v2_2(2878 struct bios_parser *bp,2879 struct integrated_info *info)2880{2881 struct atom_integrated_system_info_v2_2 *info_v2_2;2882 uint32_t i;2883 2884 info_v2_2 = GET_IMAGE(struct atom_integrated_system_info_v2_2,2885 DATA_TABLES(integratedsysteminfo));2886 2887 if (info_v2_2 == NULL)2888 return BP_RESULT_BADBIOSTABLE;2889 2890 DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_2->gpuclk_ss_percentage);2891 2892 info->gpu_cap_info =2893 le32_to_cpu(info_v2_2->gpucapinfo);2894 /*2895 * system_config: Bit[0] = 0 : PCIE power gating disabled2896 * = 1 : PCIE power gating enabled2897 * Bit[1] = 0 : DDR-PLL shut down disabled2898 * = 1 : DDR-PLL shut down enabled2899 * Bit[2] = 0 : DDR-PLL power down disabled2900 * = 1 : DDR-PLL power down enabled2901 */2902 info->system_config = le32_to_cpu(info_v2_2->system_config);2903 info->cpu_cap_info = le32_to_cpu(info_v2_2->cpucapinfo);2904 info->memory_type = info_v2_2->memorytype;2905 info->ma_channel_number = info_v2_2->umachannelnumber;2906 info->dp_ss_control =2907 le16_to_cpu(info_v2_2->reserved1);2908 info->gpuclk_ss_percentage = info_v2_2->gpuclk_ss_percentage;2909 info->gpuclk_ss_type = info_v2_2->gpuclk_ss_type;2910 2911 for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {2912 info->ext_disp_conn_info.gu_id[i] =2913 info_v2_2->extdispconninfo.guid[i];2914 }2915 2916 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {2917 info->ext_disp_conn_info.path[i].device_connector_id =2918 object_id_from_bios_object_id(2919 le16_to_cpu(info_v2_2->extdispconninfo.path[i].connectorobjid));2920 2921 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =2922 object_id_from_bios_object_id(2923 le16_to_cpu(2924 info_v2_2->extdispconninfo.path[i].ext_encoder_objid));2925 2926 info->ext_disp_conn_info.path[i].device_tag =2927 le16_to_cpu(2928 info_v2_2->extdispconninfo.path[i].device_tag);2929 info->ext_disp_conn_info.path[i].device_acpi_enum =2930 le16_to_cpu(2931 info_v2_2->extdispconninfo.path[i].device_acpi_enum);2932 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =2933 info_v2_2->extdispconninfo.path[i].auxddclut_index;2934 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =2935 info_v2_2->extdispconninfo.path[i].hpdlut_index;2936 info->ext_disp_conn_info.path[i].channel_mapping.raw =2937 info_v2_2->extdispconninfo.path[i].channelmapping;2938 info->ext_disp_conn_info.path[i].caps =2939 le16_to_cpu(info_v2_2->extdispconninfo.path[i].caps);2940 }2941 2942 info->ext_disp_conn_info.checksum =2943 info_v2_2->extdispconninfo.checksum;2944 info->ext_disp_conn_info.fixdpvoltageswing =2945 info_v2_2->extdispconninfo.fixdpvoltageswing;2946 2947 info->edp1_info.edp_backlight_pwm_hz =2948 le16_to_cpu(info_v2_2->edp1_info.edp_backlight_pwm_hz);2949 info->edp1_info.edp_ss_percentage =2950 le16_to_cpu(info_v2_2->edp1_info.edp_ss_percentage);2951 info->edp1_info.edp_ss_rate_10hz =2952 le16_to_cpu(info_v2_2->edp1_info.edp_ss_rate_10hz);2953 info->edp1_info.edp_pwr_on_off_delay =2954 info_v2_2->edp1_info.edp_pwr_on_off_delay;2955 info->edp1_info.edp_pwr_on_vary_bl_to_blon =2956 info_v2_2->edp1_info.edp_pwr_on_vary_bl_to_blon;2957 info->edp1_info.edp_pwr_down_bloff_to_vary_bloff =2958 info_v2_2->edp1_info.edp_pwr_down_bloff_to_vary_bloff;2959 info->edp1_info.edp_panel_bpc =2960 info_v2_2->edp1_info.edp_panel_bpc;2961 info->edp1_info.edp_bootup_bl_level =2962 2963 info->edp2_info.edp_backlight_pwm_hz =2964 le16_to_cpu(info_v2_2->edp2_info.edp_backlight_pwm_hz);2965 info->edp2_info.edp_ss_percentage =2966 le16_to_cpu(info_v2_2->edp2_info.edp_ss_percentage);2967 info->edp2_info.edp_ss_rate_10hz =2968 le16_to_cpu(info_v2_2->edp2_info.edp_ss_rate_10hz);2969 info->edp2_info.edp_pwr_on_off_delay =2970 info_v2_2->edp2_info.edp_pwr_on_off_delay;2971 info->edp2_info.edp_pwr_on_vary_bl_to_blon =2972 info_v2_2->edp2_info.edp_pwr_on_vary_bl_to_blon;2973 info->edp2_info.edp_pwr_down_bloff_to_vary_bloff =2974 info_v2_2->edp2_info.edp_pwr_down_bloff_to_vary_bloff;2975 info->edp2_info.edp_panel_bpc =2976 info_v2_2->edp2_info.edp_panel_bpc;2977 info->edp2_info.edp_bootup_bl_level =2978 info_v2_2->edp2_info.edp_bootup_bl_level;2979 2980 return BP_RESULT_OK;2981}2982 2983/*2984 * construct_integrated_info2985 *2986 * @brief2987 * Get integrated BIOS information based on table revision2988 *2989 * @param2990 * bios_parser *bp - [in]BIOS parser handler to get master data table2991 * integrated_info *info - [out] store and output integrated info2992 *2993 * @return2994 * static enum bp_result - BP_RESULT_OK if information is available,2995 * BP_RESULT_BADBIOSTABLE otherwise.2996 */2997static enum bp_result construct_integrated_info(2998 struct bios_parser *bp,2999 struct integrated_info *info)3000{3001 static enum bp_result result = BP_RESULT_BADBIOSTABLE;3002 3003 struct atom_common_table_header *header;3004 struct atom_data_revision revision;3005 3006 int32_t i;3007 int32_t j;3008 3009 if (!info)3010 return result;3011 3012 if (info && DATA_TABLES(integratedsysteminfo)) {3013 header = GET_IMAGE(struct atom_common_table_header,3014 DATA_TABLES(integratedsysteminfo));3015 3016 get_atom_data_table_revision(header, &revision);3017 3018 switch (revision.major) {3019 case 1:3020 switch (revision.minor) {3021 case 11:3022 case 12:3023 result = get_integrated_info_v11(bp, info);3024 break;3025 default:3026 return result;3027 }3028 break;3029 case 2:3030 switch (revision.minor) {3031 case 1:3032 result = get_integrated_info_v2_1(bp, info);3033 break;3034 case 2:3035 case 3:3036 result = get_integrated_info_v2_2(bp, info);3037 break;3038 default:3039 return result;3040 }3041 break;3042 default:3043 return result;3044 }3045 if (result == BP_RESULT_OK) {3046 3047 DC_LOG_BIOS("edp1:\n"3048 "\tedp_pwr_on_off_delay = %d\n"3049 "\tedp_pwr_on_vary_bl_to_blon = %d\n"3050 "\tedp_pwr_down_bloff_to_vary_bloff = %d\n"3051 "\tedp_bootup_bl_level = %d\n",3052 info->edp1_info.edp_pwr_on_off_delay,3053 info->edp1_info.edp_pwr_on_vary_bl_to_blon,3054 info->edp1_info.edp_pwr_down_bloff_to_vary_bloff,3055 info->edp1_info.edp_bootup_bl_level);3056 DC_LOG_BIOS("edp2:\n"3057 "\tedp_pwr_on_off_delayv = %d\n"3058 "\tedp_pwr_on_vary_bl_to_blon = %d\n"3059 "\tedp_pwr_down_bloff_to_vary_bloff = %d\n"3060 "\tedp_bootup_bl_level = %d\n",3061 info->edp2_info.edp_pwr_on_off_delay,3062 info->edp2_info.edp_pwr_on_vary_bl_to_blon,3063 info->edp2_info.edp_pwr_down_bloff_to_vary_bloff,3064 info->edp2_info.edp_bootup_bl_level);3065 }3066 }3067 3068 if (result != BP_RESULT_OK)3069 return result;3070 else {3071 // Log each external path3072 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) {3073 if (info->ext_disp_conn_info.path[i].device_tag != 0)3074 DC_LOG_BIOS("integrated_info:For EXTERNAL DISPLAY PATH %d --------------\n"3075 "DEVICE_TAG: 0x%x\n"3076 "DEVICE_ACPI_ENUM: 0x%x\n"3077 "DEVICE_CONNECTOR_ID: 0x%x\n"3078 "EXT_AUX_DDC_LUT_INDEX: %d\n"3079 "EXT_HPD_PIN_LUT_INDEX: %d\n"3080 "EXT_ENCODER_OBJ_ID: 0x%x\n"3081 "Encoder CAPS: 0x%x\n",3082 i,3083 info->ext_disp_conn_info.path[i].device_tag,3084 info->ext_disp_conn_info.path[i].device_acpi_enum,3085 info->ext_disp_conn_info.path[i].device_connector_id.id,3086 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index,3087 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index,3088 info->ext_disp_conn_info.path[i].ext_encoder_obj_id.id,3089 info->ext_disp_conn_info.path[i].caps3090 );3091 if (info->ext_disp_conn_info.path[i].caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN)3092 DC_LOG_BIOS("BIOS EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);3093 else if (bp->base.ctx->dc->config.force_bios_fixed_vs) {3094 info->ext_disp_conn_info.path[i].caps |= EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN;3095 DC_LOG_BIOS("driver forced EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN on path %d\n", i);3096 }3097 }3098 // Log the Checksum and Voltage Swing3099 DC_LOG_BIOS("Integrated info table CHECKSUM: %d\n"3100 "Integrated info table FIX_DP_VOLTAGE_SWING: %d\n",3101 info->ext_disp_conn_info.checksum,3102 info->ext_disp_conn_info.fixdpvoltageswing);3103 if (bp->base.ctx->dc->config.force_bios_fixed_vs && info->ext_disp_conn_info.fixdpvoltageswing == 0) {3104 info->ext_disp_conn_info.fixdpvoltageswing = bp->base.ctx->dc->config.force_bios_fixed_vs & 0xF;3105 DC_LOG_BIOS("driver forced fixdpvoltageswing = %d\n", info->ext_disp_conn_info.fixdpvoltageswing);3106 }3107 }3108 /* Sort voltage table from low to high*/3109 for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {3110 for (j = i; j > 0; --j) {3111 if (info->disp_clk_voltage[j].max_supported_clk <3112 info->disp_clk_voltage[j-1].max_supported_clk)3113 swap(info->disp_clk_voltage[j-1], info->disp_clk_voltage[j]);3114 }3115 }3116 3117 return result;3118}3119 3120static enum bp_result bios_parser_get_vram_info(3121 struct dc_bios *dcb,3122 struct dc_vram_info *info)3123{3124 struct bios_parser *bp = BP_FROM_DCB(dcb);3125 enum bp_result result = BP_RESULT_BADBIOSTABLE;3126 struct atom_common_table_header *header;3127 struct atom_data_revision revision;3128 3129 // vram info moved to umc_info for DCN4x3130 if (info && DATA_TABLES(umc_info)) {3131 header = GET_IMAGE(struct atom_common_table_header,3132 DATA_TABLES(umc_info));3133 3134 get_atom_data_table_revision(header, &revision);3135 3136 switch (revision.major) {3137 case 4:3138 switch (revision.minor) {3139 case 0:3140 result = get_vram_info_from_umc_info_v40(bp, info);3141 break;3142 default:3143 break;3144 }3145 break;3146 default:3147 break;3148 }3149 }3150 3151 if (result != BP_RESULT_OK && info && DATA_TABLES(vram_info)) {3152 header = GET_IMAGE(struct atom_common_table_header,3153 DATA_TABLES(vram_info));3154 3155 get_atom_data_table_revision(header, &revision);3156 3157 switch (revision.major) {3158 case 2:3159 switch (revision.minor) {3160 case 3:3161 result = get_vram_info_v23(bp, info);3162 break;3163 case 4:3164 result = get_vram_info_v24(bp, info);3165 break;3166 case 5:3167 result = get_vram_info_v25(bp, info);3168 break;3169 default:3170 break;3171 }3172 break;3173 3174 case 3:3175 switch (revision.minor) {3176 case 0:3177 result = get_vram_info_v30(bp, info);3178 break;3179 default:3180 break;3181 }3182 break;3183 3184 default:3185 return result;3186 }3187 3188 }3189 return result;3190}3191 3192static struct integrated_info *bios_parser_create_integrated_info(3193 struct dc_bios *dcb)3194{3195 struct bios_parser *bp = BP_FROM_DCB(dcb);3196 struct integrated_info *info;3197 3198 info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL);3199 3200 if (info == NULL) {3201 ASSERT_CRITICAL(0);3202 return NULL;3203 }3204 3205 if (construct_integrated_info(bp, info) == BP_RESULT_OK)3206 return info;3207 3208 kfree(info);3209 3210 return NULL;3211}3212 3213static enum bp_result update_slot_layout_info(3214 struct dc_bios *dcb,3215 unsigned int i,3216 struct slot_layout_info *slot_layout_info)3217{3218 unsigned int record_offset;3219 unsigned int j;3220 struct atom_display_object_path_v2 *object;3221 struct atom_bracket_layout_record *record;3222 struct atom_common_record_header *record_header;3223 static enum bp_result result;3224 struct bios_parser *bp;3225 struct object_info_table *tbl;3226 struct display_object_info_table_v1_4 *v1_4;3227 3228 record = NULL;3229 record_header = NULL;3230 result = BP_RESULT_NORECORD;3231 3232 bp = BP_FROM_DCB(dcb);3233 tbl = &bp->object_info_tbl;3234 v1_4 = tbl->v1_4;3235 3236 object = &v1_4->display_path[i];3237 record_offset = (unsigned int)3238 (object->disp_recordoffset) +3239 (unsigned int)(bp->object_info_tbl_offset);3240 3241 for (;;) {3242 3243 record_header = (struct atom_common_record_header *)3244 GET_IMAGE(struct atom_common_record_header,3245 record_offset);3246 if (record_header == NULL) {3247 result = BP_RESULT_BADBIOSTABLE;3248 break;3249 }3250 3251 /* the end of the list */3252 if (record_header->record_type == 0xff ||3253 record_header->record_size == 0) {3254 break;3255 }3256 3257 if (record_header->record_type ==3258 ATOM_BRACKET_LAYOUT_RECORD_TYPE &&3259 sizeof(struct atom_bracket_layout_record)3260 <= record_header->record_size) {3261 record = (struct atom_bracket_layout_record *)3262 (record_header);3263 result = BP_RESULT_OK;3264 break;3265 }3266 3267 record_offset += record_header->record_size;3268 }3269 3270 /* return if the record not found */3271 if (result != BP_RESULT_OK)3272 return result;3273 3274 /* get slot sizes */3275 slot_layout_info->length = record->bracketlen;3276 slot_layout_info->width = record->bracketwidth;3277 3278 /* get info for each connector in the slot */3279 slot_layout_info->num_of_connectors = record->conn_num;3280 for (j = 0; j < slot_layout_info->num_of_connectors; ++j) {3281 slot_layout_info->connectors[j].connector_type =3282 (enum connector_layout_type)3283 (record->conn_info[j].connector_type);3284 switch (record->conn_info[j].connector_type) {3285 case CONNECTOR_TYPE_DVI_D:3286 slot_layout_info->connectors[j].connector_type =3287 CONNECTOR_LAYOUT_TYPE_DVI_D;3288 slot_layout_info->connectors[j].length =3289 CONNECTOR_SIZE_DVI;3290 break;3291 3292 case CONNECTOR_TYPE_HDMI:3293 slot_layout_info->connectors[j].connector_type =3294 CONNECTOR_LAYOUT_TYPE_HDMI;3295 slot_layout_info->connectors[j].length =3296 CONNECTOR_SIZE_HDMI;3297 break;3298 3299 case CONNECTOR_TYPE_DISPLAY_PORT:3300 slot_layout_info->connectors[j].connector_type =3301 CONNECTOR_LAYOUT_TYPE_DP;3302 slot_layout_info->connectors[j].length =3303 CONNECTOR_SIZE_DP;3304 break;3305 3306 case CONNECTOR_TYPE_MINI_DISPLAY_PORT:3307 slot_layout_info->connectors[j].connector_type =3308 CONNECTOR_LAYOUT_TYPE_MINI_DP;3309 slot_layout_info->connectors[j].length =3310 CONNECTOR_SIZE_MINI_DP;3311 break;3312 3313 default:3314 slot_layout_info->connectors[j].connector_type =3315 CONNECTOR_LAYOUT_TYPE_UNKNOWN;3316 slot_layout_info->connectors[j].length =3317 CONNECTOR_SIZE_UNKNOWN;3318 }3319 3320 slot_layout_info->connectors[j].position =3321 record->conn_info[j].position;3322 slot_layout_info->connectors[j].connector_id =3323 object_id_from_bios_object_id(3324 record->conn_info[j].connectorobjid);3325 }3326 return result;3327}3328 3329static enum bp_result update_slot_layout_info_v2(3330 struct dc_bios *dcb,3331 unsigned int i,3332 struct slot_layout_info *slot_layout_info)3333{3334 unsigned int record_offset;3335 struct atom_display_object_path_v3 *object;3336 struct atom_bracket_layout_record_v2 *record;3337 struct atom_common_record_header *record_header;3338 static enum bp_result result;3339 struct bios_parser *bp;3340 struct object_info_table *tbl;3341 struct display_object_info_table_v1_5 *v1_5;3342 struct graphics_object_id connector_id;3343 3344 record = NULL;3345 record_header = NULL;3346 result = BP_RESULT_NORECORD;3347 3348 bp = BP_FROM_DCB(dcb);3349 tbl = &bp->object_info_tbl;3350 v1_5 = tbl->v1_5;3351 3352 object = &v1_5->display_path[i];3353 record_offset = (unsigned int)3354 (object->disp_recordoffset) +3355 (unsigned int)(bp->object_info_tbl_offset);3356 3357 for (;;) {3358 3359 record_header = (struct atom_common_record_header *)3360 GET_IMAGE(struct atom_common_record_header,3361 record_offset);3362 if (record_header == NULL) {3363 result = BP_RESULT_BADBIOSTABLE;3364 break;3365 }3366 3367 /* the end of the list */3368 if (record_header->record_type == ATOM_RECORD_END_TYPE ||3369 record_header->record_size == 0) {3370 break;3371 }3372 3373 if (record_header->record_type ==3374 ATOM_BRACKET_LAYOUT_V2_RECORD_TYPE &&3375 sizeof(struct atom_bracket_layout_record_v2)3376 <= record_header->record_size) {3377 record = (struct atom_bracket_layout_record_v2 *)3378 (record_header);3379 result = BP_RESULT_OK;3380 break;3381 }3382 3383 record_offset += record_header->record_size;3384 }3385 3386 /* return if the record not found */3387 if (result != BP_RESULT_OK)3388 return result;3389 3390 /* get slot sizes */3391 connector_id = object_id_from_bios_object_id(object->display_objid);3392 3393 slot_layout_info->length = record->bracketlen;3394 slot_layout_info->width = record->bracketwidth;3395 slot_layout_info->num_of_connectors = v1_5->number_of_path;3396 slot_layout_info->connectors[i].position = record->conn_num;3397 slot_layout_info->connectors[i].connector_id = connector_id;3398 3399 switch (connector_id.id) {3400 case CONNECTOR_ID_SINGLE_LINK_DVID:3401 case CONNECTOR_ID_DUAL_LINK_DVID:3402 slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_DVI_D;3403 slot_layout_info->connectors[i].length = CONNECTOR_SIZE_DVI;3404 break;3405 3406 case CONNECTOR_ID_HDMI_TYPE_A:3407 slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_HDMI;3408 slot_layout_info->connectors[i].length = CONNECTOR_SIZE_HDMI;3409 break;3410 3411 case CONNECTOR_ID_DISPLAY_PORT:3412 case CONNECTOR_ID_USBC:3413 if (record->mini_type == MINI_TYPE_NORMAL) {3414 slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_DP;3415 slot_layout_info->connectors[i].length = CONNECTOR_SIZE_DP;3416 } else {3417 slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_MINI_DP;3418 slot_layout_info->connectors[i].length = CONNECTOR_SIZE_MINI_DP;3419 }3420 break;3421 3422 default:3423 slot_layout_info->connectors[i].connector_type = CONNECTOR_LAYOUT_TYPE_UNKNOWN;3424 slot_layout_info->connectors[i].length = CONNECTOR_SIZE_UNKNOWN;3425 }3426 return result;3427}3428 3429static enum bp_result get_bracket_layout_record(3430 struct dc_bios *dcb,3431 unsigned int bracket_layout_id,3432 struct slot_layout_info *slot_layout_info)3433{3434 unsigned int i;3435 struct bios_parser *bp = BP_FROM_DCB(dcb);3436 static enum bp_result result;3437 struct object_info_table *tbl;3438 struct display_object_info_table_v1_4 *v1_4;3439 struct display_object_info_table_v1_5 *v1_5;3440 3441 if (slot_layout_info == NULL) {3442 DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");3443 return BP_RESULT_BADINPUT;3444 }3445 3446 tbl = &bp->object_info_tbl;3447 v1_4 = tbl->v1_4;3448 v1_5 = tbl->v1_5;3449 3450 result = BP_RESULT_NORECORD;3451 switch (bp->object_info_tbl.revision.minor) {3452 case 4:3453 default:3454 for (i = 0; i < v1_4->number_of_path; ++i) {3455 if (bracket_layout_id == v1_4->display_path[i].display_objid) {3456 result = update_slot_layout_info(dcb, i, slot_layout_info);3457 break;3458 }3459 }3460 break;3461 case 5:3462 for (i = 0; i < v1_5->number_of_path; ++i)3463 result = update_slot_layout_info_v2(dcb, i, slot_layout_info);3464 break;3465 }3466 3467 return result;3468}3469 3470static enum bp_result bios_get_board_layout_info(3471 struct dc_bios *dcb,3472 struct board_layout_info *board_layout_info)3473{3474 unsigned int i;3475 struct bios_parser *bp;3476 static enum bp_result record_result;3477 unsigned int max_slots;3478 3479 const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {3480 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1,3481 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2,3482 0, 03483 };3484 3485 bp = BP_FROM_DCB(dcb);3486 3487 if (board_layout_info == NULL) {3488 DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");3489 return BP_RESULT_BADINPUT;3490 }3491 3492 board_layout_info->num_of_slots = 0;3493 max_slots = MAX_BOARD_SLOTS;3494 3495 // Assume single slot on v1_53496 if (bp->object_info_tbl.revision.minor == 5) {3497 max_slots = 1;3498 }3499 3500 for (i = 0; i < max_slots; ++i) {3501 record_result = get_bracket_layout_record(dcb,3502 slot_index_to_vbios_id[i],3503 &board_layout_info->slots[i]);3504 3505 if (record_result == BP_RESULT_NORECORD && i > 0)3506 break; /* no more slots present in bios */3507 else if (record_result != BP_RESULT_OK)3508 return record_result; /* fail */3509 3510 ++board_layout_info->num_of_slots;3511 }3512 3513 /* all data is valid */3514 board_layout_info->is_number_of_slots_valid = 1;3515 board_layout_info->is_slots_size_valid = 1;3516 board_layout_info->is_connector_offsets_valid = 1;3517 board_layout_info->is_connector_lengths_valid = 1;3518 3519 return BP_RESULT_OK;3520}3521 3522 3523static uint16_t bios_parser_pack_data_tables(3524 struct dc_bios *dcb,3525 void *dst)3526{3527 // TODO: There is data bytes alignment issue, disable it for now.3528 return 0;3529}3530 3531static struct atom_dc_golden_table_v1 *bios_get_golden_table(3532 struct bios_parser *bp,3533 uint32_t rev_major,3534 uint32_t rev_minor,3535 uint16_t *dc_golden_table_ver)3536{3537 struct atom_display_controller_info_v4_4 *disp_cntl_tbl_4_4 = NULL;3538 uint32_t dc_golden_offset = 0;3539 *dc_golden_table_ver = 0;3540 3541 if (!DATA_TABLES(dce_info))3542 return NULL;3543 3544 /* ver.4.4 or higher */3545 switch (rev_major) {3546 case 4:3547 switch (rev_minor) {3548 case 4:3549 disp_cntl_tbl_4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4,3550 DATA_TABLES(dce_info));3551 if (!disp_cntl_tbl_4_4)3552 return NULL;3553 dc_golden_offset = DATA_TABLES(dce_info) + disp_cntl_tbl_4_4->dc_golden_table_offset;3554 *dc_golden_table_ver = disp_cntl_tbl_4_4->dc_golden_table_ver;3555 break;3556 case 5:3557 default:3558 /* For atom_display_controller_info_v4_5 there is no need to get golden table from3559 * dc_golden_table_offset as all these fields previously in golden table used for AUX3560 * pre-charge settings are now available directly in atom_display_controller_info_v4_5.3561 */3562 break;3563 }3564 break;3565 }3566 3567 if (!dc_golden_offset)3568 return NULL;3569 3570 if (*dc_golden_table_ver != 1)3571 return NULL;3572 3573 return GET_IMAGE(struct atom_dc_golden_table_v1,3574 dc_golden_offset);3575}3576 3577static enum bp_result bios_get_atom_dc_golden_table(3578 struct dc_bios *dcb)3579{3580 struct bios_parser *bp = BP_FROM_DCB(dcb);3581 enum bp_result result = BP_RESULT_OK;3582 struct atom_dc_golden_table_v1 *atom_dc_golden_table = NULL;3583 struct atom_common_table_header *header;3584 struct atom_data_revision tbl_revision;3585 uint16_t dc_golden_table_ver = 0;3586 3587 header = GET_IMAGE(struct atom_common_table_header,3588 DATA_TABLES(dce_info));3589 if (!header)3590 return BP_RESULT_UNSUPPORTED;3591 3592 get_atom_data_table_revision(header, &tbl_revision);3593 3594 atom_dc_golden_table = bios_get_golden_table(bp,3595 tbl_revision.major,3596 tbl_revision.minor,3597 &dc_golden_table_ver);3598 3599 if (!atom_dc_golden_table)3600 return BP_RESULT_UNSUPPORTED;3601 3602 dcb->golden_table.dc_golden_table_ver = dc_golden_table_ver;3603 dcb->golden_table.aux_dphy_rx_control0_val = atom_dc_golden_table->aux_dphy_rx_control0_val;3604 dcb->golden_table.aux_dphy_rx_control1_val = atom_dc_golden_table->aux_dphy_rx_control1_val;3605 dcb->golden_table.aux_dphy_tx_control_val = atom_dc_golden_table->aux_dphy_tx_control_val;3606 dcb->golden_table.dc_gpio_aux_ctrl_0_val = atom_dc_golden_table->dc_gpio_aux_ctrl_0_val;3607 dcb->golden_table.dc_gpio_aux_ctrl_1_val = atom_dc_golden_table->dc_gpio_aux_ctrl_1_val;3608 dcb->golden_table.dc_gpio_aux_ctrl_2_val = atom_dc_golden_table->dc_gpio_aux_ctrl_2_val;3609 dcb->golden_table.dc_gpio_aux_ctrl_3_val = atom_dc_golden_table->dc_gpio_aux_ctrl_3_val;3610 dcb->golden_table.dc_gpio_aux_ctrl_4_val = atom_dc_golden_table->dc_gpio_aux_ctrl_4_val;3611 dcb->golden_table.dc_gpio_aux_ctrl_5_val = atom_dc_golden_table->dc_gpio_aux_ctrl_5_val;3612 3613 return result;3614}3615 3616 3617static const struct dc_vbios_funcs vbios_funcs = {3618 .get_connectors_number = bios_parser_get_connectors_number,3619 3620 .get_connector_id = bios_parser_get_connector_id,3621 3622 .get_src_obj = bios_parser_get_src_obj,3623 3624 .get_i2c_info = bios_parser_get_i2c_info,3625 3626 .get_hpd_info = bios_parser_get_hpd_info,3627 3628 .get_device_tag = bios_parser_get_device_tag,3629 3630 .get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,3631 3632 .get_ss_entry_number = bios_parser_get_ss_entry_number,3633 3634 .get_embedded_panel_info = bios_parser_get_embedded_panel_info,3635 3636 .get_gpio_pin_info = bios_parser_get_gpio_pin_info,3637 3638 .get_encoder_cap_info = bios_parser_get_encoder_cap_info,3639 3640 .is_device_id_supported = bios_parser_is_device_id_supported,3641 3642 .is_accelerated_mode = bios_parser_is_accelerated_mode,3643 3644 .set_scratch_critical_state = bios_parser_set_scratch_critical_state,3645 3646 3647/* COMMANDS */3648 .encoder_control = bios_parser_encoder_control,3649 3650 .transmitter_control = bios_parser_transmitter_control,3651 3652 .enable_crtc = bios_parser_enable_crtc,3653 3654 .set_pixel_clock = bios_parser_set_pixel_clock,3655 3656 .set_dce_clock = bios_parser_set_dce_clock,3657 3658 .program_crtc_timing = bios_parser_program_crtc_timing,3659 3660 .enable_disp_power_gating = bios_parser_enable_disp_power_gating,3661 3662 .bios_parser_destroy = firmware_parser_destroy,3663 3664 .get_board_layout_info = bios_get_board_layout_info,3665 .pack_data_tables = bios_parser_pack_data_tables,3666 3667 .get_atom_dc_golden_table = bios_get_atom_dc_golden_table,3668 3669 .enable_lvtma_control = bios_parser_enable_lvtma_control,3670 3671 .get_soc_bb_info = bios_parser_get_soc_bb_info,3672 3673 .get_disp_connector_caps_info = bios_parser_get_disp_connector_caps_info,3674 3675 .get_lttpr_caps = bios_parser_get_lttpr_caps,3676 3677 .get_lttpr_interop = bios_parser_get_lttpr_interop,3678 3679 .get_connector_speed_cap_info = bios_parser_get_connector_speed_cap_info,3680};3681 3682static bool bios_parser2_construct(3683 struct bios_parser *bp,3684 struct bp_init_data *init,3685 enum dce_version dce_version)3686{3687 uint16_t *rom_header_offset = NULL;3688 struct atom_rom_header_v2_2 *rom_header = NULL;3689 struct display_object_info_table_v1_4 *object_info_tbl;3690 struct atom_data_revision tbl_rev = {0};3691 3692 if (!init)3693 return false;3694 3695 if (!init->bios)3696 return false;3697 3698 bp->base.funcs = &vbios_funcs;3699 bp->base.bios = init->bios;3700 bp->base.bios_size = bp->base.bios[OFFSET_TO_ATOM_ROM_IMAGE_SIZE] * BIOS_IMAGE_SIZE_UNIT;3701 3702 bp->base.ctx = init->ctx;3703 3704 bp->base.bios_local_image = NULL;3705 3706 rom_header_offset =3707 GET_IMAGE(uint16_t, OFFSET_TO_ATOM_ROM_HEADER_POINTER);3708 3709 if (!rom_header_offset)3710 return false;3711 3712 rom_header = GET_IMAGE(struct atom_rom_header_v2_2, *rom_header_offset);3713 3714 if (!rom_header)3715 return false;3716 3717 get_atom_data_table_revision(&rom_header->table_header, &tbl_rev);3718 if (!(tbl_rev.major >= 2 && tbl_rev.minor >= 2))3719 return false;3720 3721 bp->master_data_tbl =3722 GET_IMAGE(struct atom_master_data_table_v2_1,3723 rom_header->masterdatatable_offset);3724 3725 if (!bp->master_data_tbl)3726 return false;3727 3728 bp->object_info_tbl_offset = DATA_TABLES(displayobjectinfo);3729 3730 if (!bp->object_info_tbl_offset)3731 return false;3732 3733 object_info_tbl =3734 GET_IMAGE(struct display_object_info_table_v1_4,3735 bp->object_info_tbl_offset);3736 3737 if (!object_info_tbl)3738 return false;3739 3740 get_atom_data_table_revision(&object_info_tbl->table_header,3741 &bp->object_info_tbl.revision);3742 3743 if (bp->object_info_tbl.revision.major == 13744 && bp->object_info_tbl.revision.minor == 4) {3745 struct display_object_info_table_v1_4 *tbl_v1_4;3746 3747 tbl_v1_4 = GET_IMAGE(struct display_object_info_table_v1_4,3748 bp->object_info_tbl_offset);3749 if (!tbl_v1_4)3750 return false;3751 3752 bp->object_info_tbl.v1_4 = tbl_v1_4;3753 } else if (bp->object_info_tbl.revision.major == 13754 && bp->object_info_tbl.revision.minor == 5) {3755 struct display_object_info_table_v1_5 *tbl_v1_5;3756 3757 tbl_v1_5 = GET_IMAGE(struct display_object_info_table_v1_5,3758 bp->object_info_tbl_offset);3759 if (!tbl_v1_5)3760 return false;3761 3762 bp->object_info_tbl.v1_5 = tbl_v1_5;3763 } else {3764 ASSERT(0);3765 return false;3766 }3767 3768 dal_firmware_parser_init_cmd_tbl(bp);3769 dal_bios_parser_init_cmd_tbl_helper2(&bp->cmd_helper, dce_version);3770 3771 bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);3772 bp->base.fw_info_valid = bios_parser_get_firmware_info(&bp->base, &bp->base.fw_info) == BP_RESULT_OK;3773 bios_parser_get_vram_info(&bp->base, &bp->base.vram_info);3774 bios_parser_get_soc_bb_info(&bp->base, &bp->base.bb_info);3775 return true;3776}3777 3778struct dc_bios *firmware_parser_create(3779 struct bp_init_data *init,3780 enum dce_version dce_version)3781{3782 struct bios_parser *bp;3783 3784 bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL);3785 if (!bp)3786 return NULL;3787 3788 if (bios_parser2_construct(bp, init, dce_version))3789 return &bp->base;3790 3791 kfree(bp);3792 return NULL;3793}3794 3795 3796