| .. | .. |
|---|
| 23 | 23 | * |
|---|
| 24 | 24 | */ |
|---|
| 25 | 25 | |
|---|
| 26 | +#include <linux/slab.h> |
|---|
| 27 | + |
|---|
| 26 | 28 | #include "dm_services.h" |
|---|
| 27 | 29 | |
|---|
| 28 | 30 | #include "atom.h" |
|---|
| .. | .. |
|---|
| 42 | 44 | #include "bios_parser_interface.h" |
|---|
| 43 | 45 | |
|---|
| 44 | 46 | #include "bios_parser_common.h" |
|---|
| 45 | | -/* TODO remove - only needed for default i2c speed */ |
|---|
| 47 | + |
|---|
| 46 | 48 | #include "dc.h" |
|---|
| 47 | 49 | |
|---|
| 48 | 50 | #define THREE_PERCENT_OF_10000 300 |
|---|
| .. | .. |
|---|
| 52 | 54 | #define DC_LOGGER \ |
|---|
| 53 | 55 | bp->base.ctx->logger |
|---|
| 54 | 56 | |
|---|
| 55 | | -/* GUID to validate external display connection info table (aka OPM module) */ |
|---|
| 56 | | -static const uint8_t ext_display_connection_guid[NUMBER_OF_UCHAR_FOR_GUID] = { |
|---|
| 57 | | - 0x91, 0x6E, 0x57, 0x09, |
|---|
| 58 | | - 0x3F, 0x6D, 0xD2, 0x11, |
|---|
| 59 | | - 0x39, 0x8E, 0x00, 0xA0, |
|---|
| 60 | | - 0xC9, 0x69, 0x72, 0x3B}; |
|---|
| 61 | | - |
|---|
| 62 | 57 | #define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table) |
|---|
| 63 | 58 | |
|---|
| 64 | 59 | static void get_atom_data_table_revision( |
|---|
| 65 | 60 | ATOM_COMMON_TABLE_HEADER *atom_data_tbl, |
|---|
| 66 | 61 | struct atom_data_revision *tbl_revision); |
|---|
| 67 | | -static uint32_t get_dst_number_from_object(struct bios_parser *bp, |
|---|
| 68 | | - ATOM_OBJECT *object); |
|---|
| 69 | 62 | static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object, |
|---|
| 70 | 63 | uint16_t **id_list); |
|---|
| 71 | | -static uint32_t get_dest_obj_list(struct bios_parser *bp, |
|---|
| 72 | | - ATOM_OBJECT *object, uint16_t **id_list); |
|---|
| 73 | 64 | static ATOM_OBJECT *get_bios_object(struct bios_parser *bp, |
|---|
| 74 | 65 | struct graphics_object_id id); |
|---|
| 75 | 66 | static enum bp_result get_gpio_i2c_info(struct bios_parser *bp, |
|---|
| .. | .. |
|---|
| 120 | 111 | return NULL; |
|---|
| 121 | 112 | } |
|---|
| 122 | 113 | |
|---|
| 123 | | -static void destruct(struct bios_parser *bp) |
|---|
| 114 | +static void bios_parser_destruct(struct bios_parser *bp) |
|---|
| 124 | 115 | { |
|---|
| 125 | 116 | kfree(bp->base.bios_local_image); |
|---|
| 126 | 117 | kfree(bp->base.integrated_info); |
|---|
| .. | .. |
|---|
| 135 | 126 | return; |
|---|
| 136 | 127 | } |
|---|
| 137 | 128 | |
|---|
| 138 | | - destruct(bp); |
|---|
| 129 | + bios_parser_destruct(bp); |
|---|
| 139 | 130 | |
|---|
| 140 | 131 | kfree(bp); |
|---|
| 141 | 132 | *dcb = NULL; |
|---|
| .. | .. |
|---|
| 161 | 152 | |
|---|
| 162 | 153 | return get_number_of_objects(bp, |
|---|
| 163 | 154 | le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset)); |
|---|
| 164 | | -} |
|---|
| 165 | | - |
|---|
| 166 | | -static struct graphics_object_id bios_parser_get_encoder_id( |
|---|
| 167 | | - struct dc_bios *dcb, |
|---|
| 168 | | - uint32_t i) |
|---|
| 169 | | -{ |
|---|
| 170 | | - struct bios_parser *bp = BP_FROM_DCB(dcb); |
|---|
| 171 | | - struct graphics_object_id object_id = dal_graphics_object_id_init( |
|---|
| 172 | | - 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN); |
|---|
| 173 | | - |
|---|
| 174 | | - uint32_t encoder_table_offset = bp->object_info_tbl_offset |
|---|
| 175 | | - + le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset); |
|---|
| 176 | | - |
|---|
| 177 | | - ATOM_OBJECT_TABLE *tbl = |
|---|
| 178 | | - GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset); |
|---|
| 179 | | - |
|---|
| 180 | | - if (tbl && tbl->ucNumberOfObjects > i) { |
|---|
| 181 | | - const uint16_t id = le16_to_cpu(tbl->asObjects[i].usObjectID); |
|---|
| 182 | | - |
|---|
| 183 | | - object_id = object_id_from_bios_object_id(id); |
|---|
| 184 | | - } |
|---|
| 185 | | - |
|---|
| 186 | | - return object_id; |
|---|
| 187 | 155 | } |
|---|
| 188 | 156 | |
|---|
| 189 | 157 | static struct graphics_object_id bios_parser_get_connector_id( |
|---|
| .. | .. |
|---|
| 217 | 185 | return object_id; |
|---|
| 218 | 186 | } |
|---|
| 219 | 187 | |
|---|
| 220 | | -static uint32_t bios_parser_get_dst_number(struct dc_bios *dcb, |
|---|
| 221 | | - struct graphics_object_id id) |
|---|
| 222 | | -{ |
|---|
| 223 | | - struct bios_parser *bp = BP_FROM_DCB(dcb); |
|---|
| 224 | | - ATOM_OBJECT *object = get_bios_object(bp, id); |
|---|
| 225 | | - |
|---|
| 226 | | - return get_dst_number_from_object(bp, object); |
|---|
| 227 | | -} |
|---|
| 228 | | - |
|---|
| 229 | 188 | static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb, |
|---|
| 230 | 189 | struct graphics_object_id object_id, uint32_t index, |
|---|
| 231 | 190 | struct graphics_object_id *src_object_id) |
|---|
| .. | .. |
|---|
| 251 | 210 | return BP_RESULT_BADINPUT; |
|---|
| 252 | 211 | |
|---|
| 253 | 212 | *src_object_id = object_id_from_bios_object_id(id[index]); |
|---|
| 254 | | - |
|---|
| 255 | | - return BP_RESULT_OK; |
|---|
| 256 | | -} |
|---|
| 257 | | - |
|---|
| 258 | | -static enum bp_result bios_parser_get_dst_obj(struct dc_bios *dcb, |
|---|
| 259 | | - struct graphics_object_id object_id, uint32_t index, |
|---|
| 260 | | - struct graphics_object_id *dest_object_id) |
|---|
| 261 | | -{ |
|---|
| 262 | | - uint32_t number; |
|---|
| 263 | | - uint16_t *id = NULL; |
|---|
| 264 | | - ATOM_OBJECT *object; |
|---|
| 265 | | - struct bios_parser *bp = BP_FROM_DCB(dcb); |
|---|
| 266 | | - |
|---|
| 267 | | - if (!dest_object_id) |
|---|
| 268 | | - return BP_RESULT_BADINPUT; |
|---|
| 269 | | - |
|---|
| 270 | | - object = get_bios_object(bp, object_id); |
|---|
| 271 | | - |
|---|
| 272 | | - number = get_dest_obj_list(bp, object, &id); |
|---|
| 273 | | - |
|---|
| 274 | | - if (number <= index || !id) |
|---|
| 275 | | - return BP_RESULT_BADINPUT; |
|---|
| 276 | | - |
|---|
| 277 | | - *dest_object_id = object_id_from_bios_object_id(id[index]); |
|---|
| 278 | 213 | |
|---|
| 279 | 214 | return BP_RESULT_OK; |
|---|
| 280 | 215 | } |
|---|
| .. | .. |
|---|
| 324 | 259 | |
|---|
| 325 | 260 | return BP_RESULT_NORECORD; |
|---|
| 326 | 261 | } |
|---|
| 327 | | - |
|---|
| 328 | | -static enum bp_result get_voltage_ddc_info_v1(uint8_t *i2c_line, |
|---|
| 329 | | - ATOM_COMMON_TABLE_HEADER *header, |
|---|
| 330 | | - uint8_t *address) |
|---|
| 331 | | -{ |
|---|
| 332 | | - enum bp_result result = BP_RESULT_NORECORD; |
|---|
| 333 | | - ATOM_VOLTAGE_OBJECT_INFO *info = |
|---|
| 334 | | - (ATOM_VOLTAGE_OBJECT_INFO *) address; |
|---|
| 335 | | - |
|---|
| 336 | | - uint8_t *voltage_current_object = (uint8_t *) &info->asVoltageObj[0]; |
|---|
| 337 | | - |
|---|
| 338 | | - while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) { |
|---|
| 339 | | - ATOM_VOLTAGE_OBJECT *object = |
|---|
| 340 | | - (ATOM_VOLTAGE_OBJECT *) voltage_current_object; |
|---|
| 341 | | - |
|---|
| 342 | | - if ((object->ucVoltageType == SET_VOLTAGE_INIT_MODE) && |
|---|
| 343 | | - (object->ucVoltageType & |
|---|
| 344 | | - VOLTAGE_CONTROLLED_BY_I2C_MASK)) { |
|---|
| 345 | | - |
|---|
| 346 | | - *i2c_line = object->asControl.ucVoltageControlI2cLine |
|---|
| 347 | | - ^ 0x90; |
|---|
| 348 | | - result = BP_RESULT_OK; |
|---|
| 349 | | - break; |
|---|
| 350 | | - } |
|---|
| 351 | | - |
|---|
| 352 | | - voltage_current_object += object->ucSize; |
|---|
| 353 | | - } |
|---|
| 354 | | - return result; |
|---|
| 355 | | -} |
|---|
| 356 | | - |
|---|
| 357 | | -static enum bp_result get_voltage_ddc_info_v3(uint8_t *i2c_line, |
|---|
| 358 | | - uint32_t index, |
|---|
| 359 | | - ATOM_COMMON_TABLE_HEADER *header, |
|---|
| 360 | | - uint8_t *address) |
|---|
| 361 | | -{ |
|---|
| 362 | | - enum bp_result result = BP_RESULT_NORECORD; |
|---|
| 363 | | - ATOM_VOLTAGE_OBJECT_INFO_V3_1 *info = |
|---|
| 364 | | - (ATOM_VOLTAGE_OBJECT_INFO_V3_1 *) address; |
|---|
| 365 | | - |
|---|
| 366 | | - uint8_t *voltage_current_object = |
|---|
| 367 | | - (uint8_t *) (&(info->asVoltageObj[0])); |
|---|
| 368 | | - |
|---|
| 369 | | - while ((address + le16_to_cpu(header->usStructureSize)) > voltage_current_object) { |
|---|
| 370 | | - ATOM_I2C_VOLTAGE_OBJECT_V3 *object = |
|---|
| 371 | | - (ATOM_I2C_VOLTAGE_OBJECT_V3 *) voltage_current_object; |
|---|
| 372 | | - |
|---|
| 373 | | - if (object->sHeader.ucVoltageMode == |
|---|
| 374 | | - ATOM_INIT_VOLTAGE_REGULATOR) { |
|---|
| 375 | | - if (object->sHeader.ucVoltageType == index) { |
|---|
| 376 | | - *i2c_line = object->ucVoltageControlI2cLine |
|---|
| 377 | | - ^ 0x90; |
|---|
| 378 | | - result = BP_RESULT_OK; |
|---|
| 379 | | - break; |
|---|
| 380 | | - } |
|---|
| 381 | | - } |
|---|
| 382 | | - |
|---|
| 383 | | - voltage_current_object += le16_to_cpu(object->sHeader.usSize); |
|---|
| 384 | | - } |
|---|
| 385 | | - return result; |
|---|
| 386 | | -} |
|---|
| 387 | | - |
|---|
| 388 | | -static enum bp_result bios_parser_get_thermal_ddc_info( |
|---|
| 389 | | - struct dc_bios *dcb, |
|---|
| 390 | | - uint32_t i2c_channel_id, |
|---|
| 391 | | - struct graphics_object_i2c_info *info) |
|---|
| 392 | | -{ |
|---|
| 393 | | - struct bios_parser *bp = BP_FROM_DCB(dcb); |
|---|
| 394 | | - ATOM_I2C_ID_CONFIG_ACCESS *config; |
|---|
| 395 | | - ATOM_I2C_RECORD record; |
|---|
| 396 | | - |
|---|
| 397 | | - if (!info) |
|---|
| 398 | | - return BP_RESULT_BADINPUT; |
|---|
| 399 | | - |
|---|
| 400 | | - config = (ATOM_I2C_ID_CONFIG_ACCESS *) &i2c_channel_id; |
|---|
| 401 | | - |
|---|
| 402 | | - record.sucI2cId.bfHW_Capable = config->sbfAccess.bfHW_Capable; |
|---|
| 403 | | - record.sucI2cId.bfI2C_LineMux = config->sbfAccess.bfI2C_LineMux; |
|---|
| 404 | | - record.sucI2cId.bfHW_EngineID = config->sbfAccess.bfHW_EngineID; |
|---|
| 405 | | - |
|---|
| 406 | | - return get_gpio_i2c_info(bp, &record, info); |
|---|
| 407 | | -} |
|---|
| 408 | | - |
|---|
| 409 | | -static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb, |
|---|
| 410 | | - uint32_t index, |
|---|
| 411 | | - struct graphics_object_i2c_info *info) |
|---|
| 412 | | -{ |
|---|
| 413 | | - uint8_t i2c_line = 0; |
|---|
| 414 | | - enum bp_result result = BP_RESULT_NORECORD; |
|---|
| 415 | | - uint8_t *voltage_info_address; |
|---|
| 416 | | - ATOM_COMMON_TABLE_HEADER *header; |
|---|
| 417 | | - struct atom_data_revision revision = {0}; |
|---|
| 418 | | - struct bios_parser *bp = BP_FROM_DCB(dcb); |
|---|
| 419 | | - |
|---|
| 420 | | - if (!DATA_TABLES(VoltageObjectInfo)) |
|---|
| 421 | | - return result; |
|---|
| 422 | | - |
|---|
| 423 | | - voltage_info_address = bios_get_image(&bp->base, DATA_TABLES(VoltageObjectInfo), sizeof(ATOM_COMMON_TABLE_HEADER)); |
|---|
| 424 | | - |
|---|
| 425 | | - header = (ATOM_COMMON_TABLE_HEADER *) voltage_info_address; |
|---|
| 426 | | - |
|---|
| 427 | | - get_atom_data_table_revision(header, &revision); |
|---|
| 428 | | - |
|---|
| 429 | | - switch (revision.major) { |
|---|
| 430 | | - case 1: |
|---|
| 431 | | - case 2: |
|---|
| 432 | | - result = get_voltage_ddc_info_v1(&i2c_line, header, |
|---|
| 433 | | - voltage_info_address); |
|---|
| 434 | | - break; |
|---|
| 435 | | - case 3: |
|---|
| 436 | | - if (revision.minor != 1) |
|---|
| 437 | | - break; |
|---|
| 438 | | - result = get_voltage_ddc_info_v3(&i2c_line, index, header, |
|---|
| 439 | | - voltage_info_address); |
|---|
| 440 | | - break; |
|---|
| 441 | | - } |
|---|
| 442 | | - |
|---|
| 443 | | - if (result == BP_RESULT_OK) |
|---|
| 444 | | - result = bios_parser_get_thermal_ddc_info(dcb, |
|---|
| 445 | | - i2c_line, info); |
|---|
| 446 | | - |
|---|
| 447 | | - return result; |
|---|
| 448 | | -} |
|---|
| 449 | | - |
|---|
| 450 | | -/* TODO: temporary commented out to suppress 'defined but not used' warning */ |
|---|
| 451 | | -#if 0 |
|---|
| 452 | | -static enum bp_result bios_parser_get_ddc_info_for_i2c_line( |
|---|
| 453 | | - struct bios_parser *bp, |
|---|
| 454 | | - uint8_t i2c_line, struct graphics_object_i2c_info *info) |
|---|
| 455 | | -{ |
|---|
| 456 | | - uint32_t offset; |
|---|
| 457 | | - ATOM_OBJECT *object; |
|---|
| 458 | | - ATOM_OBJECT_TABLE *table; |
|---|
| 459 | | - uint32_t i; |
|---|
| 460 | | - |
|---|
| 461 | | - if (!info) |
|---|
| 462 | | - return BP_RESULT_BADINPUT; |
|---|
| 463 | | - |
|---|
| 464 | | - offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); |
|---|
| 465 | | - |
|---|
| 466 | | - offset += bp->object_info_tbl_offset; |
|---|
| 467 | | - |
|---|
| 468 | | - table = GET_IMAGE(ATOM_OBJECT_TABLE, offset); |
|---|
| 469 | | - |
|---|
| 470 | | - if (!table) |
|---|
| 471 | | - return BP_RESULT_BADBIOSTABLE; |
|---|
| 472 | | - |
|---|
| 473 | | - for (i = 0; i < table->ucNumberOfObjects; i++) { |
|---|
| 474 | | - object = &table->asObjects[i]; |
|---|
| 475 | | - |
|---|
| 476 | | - if (!object) { |
|---|
| 477 | | - BREAK_TO_DEBUGGER(); /* Invalid object id */ |
|---|
| 478 | | - return BP_RESULT_BADINPUT; |
|---|
| 479 | | - } |
|---|
| 480 | | - |
|---|
| 481 | | - offset = le16_to_cpu(object->usRecordOffset) |
|---|
| 482 | | - + bp->object_info_tbl_offset; |
|---|
| 483 | | - |
|---|
| 484 | | - for (;;) { |
|---|
| 485 | | - ATOM_COMMON_RECORD_HEADER *header = |
|---|
| 486 | | - GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); |
|---|
| 487 | | - |
|---|
| 488 | | - if (!header) |
|---|
| 489 | | - return BP_RESULT_BADBIOSTABLE; |
|---|
| 490 | | - |
|---|
| 491 | | - offset += header->ucRecordSize; |
|---|
| 492 | | - |
|---|
| 493 | | - if (LAST_RECORD_TYPE == header->ucRecordType || |
|---|
| 494 | | - !header->ucRecordSize) |
|---|
| 495 | | - break; |
|---|
| 496 | | - |
|---|
| 497 | | - if (ATOM_I2C_RECORD_TYPE == header->ucRecordType |
|---|
| 498 | | - && sizeof(ATOM_I2C_RECORD) <= |
|---|
| 499 | | - header->ucRecordSize) { |
|---|
| 500 | | - ATOM_I2C_RECORD *record = |
|---|
| 501 | | - (ATOM_I2C_RECORD *) header; |
|---|
| 502 | | - |
|---|
| 503 | | - if (i2c_line != record->sucI2cId.bfI2C_LineMux) |
|---|
| 504 | | - continue; |
|---|
| 505 | | - |
|---|
| 506 | | - /* get the I2C info */ |
|---|
| 507 | | - if (get_gpio_i2c_info(bp, record, info) == |
|---|
| 508 | | - BP_RESULT_OK) |
|---|
| 509 | | - return BP_RESULT_OK; |
|---|
| 510 | | - } |
|---|
| 511 | | - } |
|---|
| 512 | | - } |
|---|
| 513 | | - |
|---|
| 514 | | - return BP_RESULT_NORECORD; |
|---|
| 515 | | -} |
|---|
| 516 | | -#endif |
|---|
| 517 | 262 | |
|---|
| 518 | 263 | static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb, |
|---|
| 519 | 264 | struct graphics_object_id id, |
|---|
| .. | .. |
|---|
| 1092 | 837 | return bp->cmd_tbl.enable_crtc(bp, id, enable); |
|---|
| 1093 | 838 | } |
|---|
| 1094 | 839 | |
|---|
| 1095 | | -static enum bp_result bios_parser_crtc_source_select( |
|---|
| 1096 | | - struct dc_bios *dcb, |
|---|
| 1097 | | - struct bp_crtc_source_select *bp_params) |
|---|
| 1098 | | -{ |
|---|
| 1099 | | - struct bios_parser *bp = BP_FROM_DCB(dcb); |
|---|
| 1100 | | - |
|---|
| 1101 | | - if (!bp->cmd_tbl.select_crtc_source) |
|---|
| 1102 | | - return BP_RESULT_FAILURE; |
|---|
| 1103 | | - |
|---|
| 1104 | | - return bp->cmd_tbl.select_crtc_source(bp, bp_params); |
|---|
| 1105 | | -} |
|---|
| 1106 | | - |
|---|
| 1107 | 840 | static enum bp_result bios_parser_enable_disp_power_gating( |
|---|
| 1108 | 841 | struct dc_bios *dcb, |
|---|
| 1109 | 842 | enum controller_id controller_id, |
|---|
| .. | .. |
|---|
| 1127 | 860 | uint32_t mask = get_support_mask_for_device_id(id); |
|---|
| 1128 | 861 | |
|---|
| 1129 | 862 | return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0; |
|---|
| 1130 | | -} |
|---|
| 1131 | | - |
|---|
| 1132 | | -static enum bp_result bios_parser_crt_control( |
|---|
| 1133 | | - struct dc_bios *dcb, |
|---|
| 1134 | | - enum engine_id engine_id, |
|---|
| 1135 | | - bool enable, |
|---|
| 1136 | | - uint32_t pixel_clock) |
|---|
| 1137 | | -{ |
|---|
| 1138 | | - struct bios_parser *bp = BP_FROM_DCB(dcb); |
|---|
| 1139 | | - uint8_t standard; |
|---|
| 1140 | | - |
|---|
| 1141 | | - if (!bp->cmd_tbl.dac1_encoder_control && |
|---|
| 1142 | | - engine_id == ENGINE_ID_DACA) |
|---|
| 1143 | | - return BP_RESULT_FAILURE; |
|---|
| 1144 | | - if (!bp->cmd_tbl.dac2_encoder_control && |
|---|
| 1145 | | - engine_id == ENGINE_ID_DACB) |
|---|
| 1146 | | - return BP_RESULT_FAILURE; |
|---|
| 1147 | | - /* validate params */ |
|---|
| 1148 | | - switch (engine_id) { |
|---|
| 1149 | | - case ENGINE_ID_DACA: |
|---|
| 1150 | | - case ENGINE_ID_DACB: |
|---|
| 1151 | | - break; |
|---|
| 1152 | | - default: |
|---|
| 1153 | | - /* unsupported engine */ |
|---|
| 1154 | | - return BP_RESULT_FAILURE; |
|---|
| 1155 | | - } |
|---|
| 1156 | | - |
|---|
| 1157 | | - standard = ATOM_DAC1_PS2; /* == ATOM_DAC2_PS2 */ |
|---|
| 1158 | | - |
|---|
| 1159 | | - if (enable) { |
|---|
| 1160 | | - if (engine_id == ENGINE_ID_DACA) { |
|---|
| 1161 | | - bp->cmd_tbl.dac1_encoder_control(bp, enable, |
|---|
| 1162 | | - pixel_clock, standard); |
|---|
| 1163 | | - if (bp->cmd_tbl.dac1_output_control != NULL) |
|---|
| 1164 | | - bp->cmd_tbl.dac1_output_control(bp, enable); |
|---|
| 1165 | | - } else { |
|---|
| 1166 | | - bp->cmd_tbl.dac2_encoder_control(bp, enable, |
|---|
| 1167 | | - pixel_clock, standard); |
|---|
| 1168 | | - if (bp->cmd_tbl.dac2_output_control != NULL) |
|---|
| 1169 | | - bp->cmd_tbl.dac2_output_control(bp, enable); |
|---|
| 1170 | | - } |
|---|
| 1171 | | - } else { |
|---|
| 1172 | | - if (engine_id == ENGINE_ID_DACA) { |
|---|
| 1173 | | - if (bp->cmd_tbl.dac1_output_control != NULL) |
|---|
| 1174 | | - bp->cmd_tbl.dac1_output_control(bp, enable); |
|---|
| 1175 | | - bp->cmd_tbl.dac1_encoder_control(bp, enable, |
|---|
| 1176 | | - pixel_clock, standard); |
|---|
| 1177 | | - } else { |
|---|
| 1178 | | - if (bp->cmd_tbl.dac2_output_control != NULL) |
|---|
| 1179 | | - bp->cmd_tbl.dac2_output_control(bp, enable); |
|---|
| 1180 | | - bp->cmd_tbl.dac2_encoder_control(bp, enable, |
|---|
| 1181 | | - pixel_clock, standard); |
|---|
| 1182 | | - } |
|---|
| 1183 | | - } |
|---|
| 1184 | | - |
|---|
| 1185 | | - return BP_RESULT_OK; |
|---|
| 1186 | 863 | } |
|---|
| 1187 | 864 | |
|---|
| 1188 | 865 | static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp, |
|---|
| .. | .. |
|---|
| 1214 | 891 | return (ATOM_HPD_INT_RECORD *) header; |
|---|
| 1215 | 892 | |
|---|
| 1216 | 893 | offset += header->ucRecordSize; |
|---|
| 1217 | | - } |
|---|
| 1218 | | - |
|---|
| 1219 | | - return NULL; |
|---|
| 1220 | | -} |
|---|
| 1221 | | - |
|---|
| 1222 | | -/** |
|---|
| 1223 | | - * Get I2C information of input object id |
|---|
| 1224 | | - * |
|---|
| 1225 | | - * search all records to find the ATOM_I2C_RECORD_TYPE record IR |
|---|
| 1226 | | - */ |
|---|
| 1227 | | -static ATOM_I2C_RECORD *get_i2c_record( |
|---|
| 1228 | | - struct bios_parser *bp, |
|---|
| 1229 | | - ATOM_OBJECT *object) |
|---|
| 1230 | | -{ |
|---|
| 1231 | | - uint32_t offset; |
|---|
| 1232 | | - ATOM_COMMON_RECORD_HEADER *record_header; |
|---|
| 1233 | | - |
|---|
| 1234 | | - if (!object) { |
|---|
| 1235 | | - BREAK_TO_DEBUGGER(); |
|---|
| 1236 | | - /* Invalid object */ |
|---|
| 1237 | | - return NULL; |
|---|
| 1238 | | - } |
|---|
| 1239 | | - |
|---|
| 1240 | | - offset = le16_to_cpu(object->usRecordOffset) |
|---|
| 1241 | | - + bp->object_info_tbl_offset; |
|---|
| 1242 | | - |
|---|
| 1243 | | - for (;;) { |
|---|
| 1244 | | - record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); |
|---|
| 1245 | | - |
|---|
| 1246 | | - if (!record_header) |
|---|
| 1247 | | - return NULL; |
|---|
| 1248 | | - |
|---|
| 1249 | | - if (LAST_RECORD_TYPE == record_header->ucRecordType || |
|---|
| 1250 | | - 0 == record_header->ucRecordSize) |
|---|
| 1251 | | - break; |
|---|
| 1252 | | - |
|---|
| 1253 | | - if (ATOM_I2C_RECORD_TYPE == record_header->ucRecordType && |
|---|
| 1254 | | - sizeof(ATOM_I2C_RECORD) <= |
|---|
| 1255 | | - record_header->ucRecordSize) { |
|---|
| 1256 | | - return (ATOM_I2C_RECORD *)record_header; |
|---|
| 1257 | | - } |
|---|
| 1258 | | - |
|---|
| 1259 | | - offset += record_header->ucRecordSize; |
|---|
| 1260 | 894 | } |
|---|
| 1261 | 895 | |
|---|
| 1262 | 896 | return NULL; |
|---|
| .. | .. |
|---|
| 2356 | 1990 | return NULL; |
|---|
| 2357 | 1991 | } |
|---|
| 2358 | 1992 | |
|---|
| 2359 | | -static uint32_t get_dest_obj_list(struct bios_parser *bp, |
|---|
| 2360 | | - ATOM_OBJECT *object, uint16_t **id_list) |
|---|
| 2361 | | -{ |
|---|
| 2362 | | - uint32_t offset; |
|---|
| 2363 | | - uint8_t *number; |
|---|
| 2364 | | - |
|---|
| 2365 | | - if (!object) { |
|---|
| 2366 | | - BREAK_TO_DEBUGGER(); /* Invalid object id */ |
|---|
| 2367 | | - return 0; |
|---|
| 2368 | | - } |
|---|
| 2369 | | - |
|---|
| 2370 | | - offset = le16_to_cpu(object->usSrcDstTableOffset) |
|---|
| 2371 | | - + bp->object_info_tbl_offset; |
|---|
| 2372 | | - |
|---|
| 2373 | | - number = GET_IMAGE(uint8_t, offset); |
|---|
| 2374 | | - if (!number) |
|---|
| 2375 | | - return 0; |
|---|
| 2376 | | - |
|---|
| 2377 | | - offset += sizeof(uint8_t); |
|---|
| 2378 | | - offset += sizeof(uint16_t) * (*number); |
|---|
| 2379 | | - |
|---|
| 2380 | | - number = GET_IMAGE(uint8_t, offset); |
|---|
| 2381 | | - if ((!number) || (!*number)) |
|---|
| 2382 | | - return 0; |
|---|
| 2383 | | - |
|---|
| 2384 | | - offset += sizeof(uint8_t); |
|---|
| 2385 | | - *id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t)); |
|---|
| 2386 | | - |
|---|
| 2387 | | - if (!*id_list) |
|---|
| 2388 | | - return 0; |
|---|
| 2389 | | - |
|---|
| 2390 | | - return *number; |
|---|
| 2391 | | -} |
|---|
| 2392 | | - |
|---|
| 2393 | 1993 | static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object, |
|---|
| 2394 | 1994 | uint16_t **id_list) |
|---|
| 2395 | 1995 | { |
|---|
| .. | .. |
|---|
| 2417 | 2017 | return *number; |
|---|
| 2418 | 2018 | } |
|---|
| 2419 | 2019 | |
|---|
| 2420 | | -static uint32_t get_dst_number_from_object(struct bios_parser *bp, |
|---|
| 2421 | | - ATOM_OBJECT *object) |
|---|
| 2422 | | -{ |
|---|
| 2423 | | - uint32_t offset; |
|---|
| 2424 | | - uint8_t *number; |
|---|
| 2425 | | - |
|---|
| 2426 | | - if (!object) { |
|---|
| 2427 | | - BREAK_TO_DEBUGGER(); /* Invalid encoder object id*/ |
|---|
| 2428 | | - return 0; |
|---|
| 2429 | | - } |
|---|
| 2430 | | - |
|---|
| 2431 | | - offset = le16_to_cpu(object->usSrcDstTableOffset) |
|---|
| 2432 | | - + bp->object_info_tbl_offset; |
|---|
| 2433 | | - |
|---|
| 2434 | | - number = GET_IMAGE(uint8_t, offset); |
|---|
| 2435 | | - if (!number) |
|---|
| 2436 | | - return 0; |
|---|
| 2437 | | - |
|---|
| 2438 | | - offset += sizeof(uint8_t); |
|---|
| 2439 | | - offset += sizeof(uint16_t) * (*number); |
|---|
| 2440 | | - |
|---|
| 2441 | | - number = GET_IMAGE(uint8_t, offset); |
|---|
| 2442 | | - |
|---|
| 2443 | | - if (!number) |
|---|
| 2444 | | - return 0; |
|---|
| 2445 | | - |
|---|
| 2446 | | - return *number; |
|---|
| 2447 | | -} |
|---|
| 2448 | | - |
|---|
| 2449 | 2020 | static struct device_id device_type_from_device_id(uint16_t device_id) |
|---|
| 2450 | 2021 | { |
|---|
| 2451 | 2022 | |
|---|
| 2452 | | - struct device_id result_device_id; |
|---|
| 2023 | + struct device_id result_device_id = {0}; |
|---|
| 2453 | 2024 | |
|---|
| 2454 | 2025 | switch (device_id) { |
|---|
| 2455 | 2026 | case ATOM_DEVICE_LCD1_SUPPORT: |
|---|
| .. | .. |
|---|
| 2618 | 2189 | break; |
|---|
| 2619 | 2190 | default: |
|---|
| 2620 | 2191 | break; |
|---|
| 2621 | | - }; |
|---|
| 2192 | + } |
|---|
| 2622 | 2193 | |
|---|
| 2623 | 2194 | /* Unidentified device ID, return empty support mask. */ |
|---|
| 2624 | 2195 | return 0; |
|---|
| 2625 | | -} |
|---|
| 2626 | | - |
|---|
| 2627 | | -/** |
|---|
| 2628 | | - * HwContext interface for writing MM registers |
|---|
| 2629 | | - */ |
|---|
| 2630 | | - |
|---|
| 2631 | | -static bool i2c_read( |
|---|
| 2632 | | - struct bios_parser *bp, |
|---|
| 2633 | | - struct graphics_object_i2c_info *i2c_info, |
|---|
| 2634 | | - uint8_t *buffer, |
|---|
| 2635 | | - uint32_t length) |
|---|
| 2636 | | -{ |
|---|
| 2637 | | - struct ddc *ddc; |
|---|
| 2638 | | - uint8_t offset[2] = { 0, 0 }; |
|---|
| 2639 | | - bool result = false; |
|---|
| 2640 | | - struct i2c_command cmd; |
|---|
| 2641 | | - struct gpio_ddc_hw_info hw_info = { |
|---|
| 2642 | | - i2c_info->i2c_hw_assist, |
|---|
| 2643 | | - i2c_info->i2c_line }; |
|---|
| 2644 | | - |
|---|
| 2645 | | - ddc = dal_gpio_create_ddc(bp->base.ctx->gpio_service, |
|---|
| 2646 | | - i2c_info->gpio_info.clk_a_register_index, |
|---|
| 2647 | | - (1 << i2c_info->gpio_info.clk_a_shift), &hw_info); |
|---|
| 2648 | | - |
|---|
| 2649 | | - if (!ddc) |
|---|
| 2650 | | - return result; |
|---|
| 2651 | | - |
|---|
| 2652 | | - /*Using SW engine */ |
|---|
| 2653 | | - cmd.engine = I2C_COMMAND_ENGINE_SW; |
|---|
| 2654 | | - cmd.speed = ddc->ctx->dc->caps.i2c_speed_in_khz; |
|---|
| 2655 | | - |
|---|
| 2656 | | - { |
|---|
| 2657 | | - struct i2c_payload payloads[] = { |
|---|
| 2658 | | - { |
|---|
| 2659 | | - .address = i2c_info->i2c_slave_address >> 1, |
|---|
| 2660 | | - .data = offset, |
|---|
| 2661 | | - .length = sizeof(offset), |
|---|
| 2662 | | - .write = true |
|---|
| 2663 | | - }, |
|---|
| 2664 | | - { |
|---|
| 2665 | | - .address = i2c_info->i2c_slave_address >> 1, |
|---|
| 2666 | | - .data = buffer, |
|---|
| 2667 | | - .length = length, |
|---|
| 2668 | | - .write = false |
|---|
| 2669 | | - } |
|---|
| 2670 | | - }; |
|---|
| 2671 | | - |
|---|
| 2672 | | - cmd.payloads = payloads; |
|---|
| 2673 | | - cmd.number_of_payloads = ARRAY_SIZE(payloads); |
|---|
| 2674 | | - |
|---|
| 2675 | | - /* TODO route this through drm i2c_adapter */ |
|---|
| 2676 | | - result = dal_i2caux_submit_i2c_command( |
|---|
| 2677 | | - ddc->ctx->i2caux, |
|---|
| 2678 | | - ddc, |
|---|
| 2679 | | - &cmd); |
|---|
| 2680 | | - } |
|---|
| 2681 | | - |
|---|
| 2682 | | - dal_gpio_destroy_ddc(&ddc); |
|---|
| 2683 | | - |
|---|
| 2684 | | - return result; |
|---|
| 2685 | | -} |
|---|
| 2686 | | - |
|---|
| 2687 | | -/** |
|---|
| 2688 | | - * Read external display connection info table through i2c. |
|---|
| 2689 | | - * validate the GUID and checksum. |
|---|
| 2690 | | - * |
|---|
| 2691 | | - * @return enum bp_result whether all data was sucessfully read |
|---|
| 2692 | | - */ |
|---|
| 2693 | | -static enum bp_result get_ext_display_connection_info( |
|---|
| 2694 | | - struct bios_parser *bp, |
|---|
| 2695 | | - ATOM_OBJECT *opm_object, |
|---|
| 2696 | | - ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *ext_display_connection_info_tbl) |
|---|
| 2697 | | -{ |
|---|
| 2698 | | - bool config_tbl_present = false; |
|---|
| 2699 | | - ATOM_I2C_RECORD *i2c_record = NULL; |
|---|
| 2700 | | - uint32_t i = 0; |
|---|
| 2701 | | - |
|---|
| 2702 | | - if (opm_object == NULL) |
|---|
| 2703 | | - return BP_RESULT_BADINPUT; |
|---|
| 2704 | | - |
|---|
| 2705 | | - i2c_record = get_i2c_record(bp, opm_object); |
|---|
| 2706 | | - |
|---|
| 2707 | | - if (i2c_record != NULL) { |
|---|
| 2708 | | - ATOM_GPIO_I2C_INFO *gpio_i2c_header; |
|---|
| 2709 | | - struct graphics_object_i2c_info i2c_info; |
|---|
| 2710 | | - |
|---|
| 2711 | | - gpio_i2c_header = GET_IMAGE(ATOM_GPIO_I2C_INFO, |
|---|
| 2712 | | - bp->master_data_tbl->ListOfDataTables.GPIO_I2C_Info); |
|---|
| 2713 | | - |
|---|
| 2714 | | - if (NULL == gpio_i2c_header) |
|---|
| 2715 | | - return BP_RESULT_BADBIOSTABLE; |
|---|
| 2716 | | - |
|---|
| 2717 | | - if (get_gpio_i2c_info(bp, i2c_record, &i2c_info) != |
|---|
| 2718 | | - BP_RESULT_OK) |
|---|
| 2719 | | - return BP_RESULT_BADBIOSTABLE; |
|---|
| 2720 | | - |
|---|
| 2721 | | - if (i2c_read(bp, |
|---|
| 2722 | | - &i2c_info, |
|---|
| 2723 | | - (uint8_t *)ext_display_connection_info_tbl, |
|---|
| 2724 | | - sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO))) { |
|---|
| 2725 | | - config_tbl_present = true; |
|---|
| 2726 | | - } |
|---|
| 2727 | | - } |
|---|
| 2728 | | - |
|---|
| 2729 | | - /* Validate GUID */ |
|---|
| 2730 | | - if (config_tbl_present) |
|---|
| 2731 | | - for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; i++) { |
|---|
| 2732 | | - if (ext_display_connection_info_tbl->ucGuid[i] |
|---|
| 2733 | | - != ext_display_connection_guid[i]) { |
|---|
| 2734 | | - config_tbl_present = false; |
|---|
| 2735 | | - break; |
|---|
| 2736 | | - } |
|---|
| 2737 | | - } |
|---|
| 2738 | | - |
|---|
| 2739 | | - /* Validate checksum */ |
|---|
| 2740 | | - if (config_tbl_present) { |
|---|
| 2741 | | - uint8_t check_sum = 0; |
|---|
| 2742 | | - uint8_t *buf = |
|---|
| 2743 | | - (uint8_t *)ext_display_connection_info_tbl; |
|---|
| 2744 | | - |
|---|
| 2745 | | - for (i = 0; i < sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO); |
|---|
| 2746 | | - i++) { |
|---|
| 2747 | | - check_sum += buf[i]; |
|---|
| 2748 | | - } |
|---|
| 2749 | | - |
|---|
| 2750 | | - if (check_sum != 0) |
|---|
| 2751 | | - config_tbl_present = false; |
|---|
| 2752 | | - } |
|---|
| 2753 | | - |
|---|
| 2754 | | - if (config_tbl_present) |
|---|
| 2755 | | - return BP_RESULT_OK; |
|---|
| 2756 | | - else |
|---|
| 2757 | | - return BP_RESULT_FAILURE; |
|---|
| 2758 | | -} |
|---|
| 2759 | | - |
|---|
| 2760 | | -/* |
|---|
| 2761 | | - * Gets the first device ID in the same group as the given ID for enumerating. |
|---|
| 2762 | | - * For instance, if any DFP device ID is passed, returns the device ID for DFP1. |
|---|
| 2763 | | - * |
|---|
| 2764 | | - * The first device ID in the same group as the passed device ID, or 0 if no |
|---|
| 2765 | | - * matching device group found. |
|---|
| 2766 | | - */ |
|---|
| 2767 | | -static uint32_t enum_first_device_id(uint32_t dev_id) |
|---|
| 2768 | | -{ |
|---|
| 2769 | | - /* Return the first in the group that this ID belongs to. */ |
|---|
| 2770 | | - if (dev_id & ATOM_DEVICE_CRT_SUPPORT) |
|---|
| 2771 | | - return ATOM_DEVICE_CRT1_SUPPORT; |
|---|
| 2772 | | - else if (dev_id & ATOM_DEVICE_DFP_SUPPORT) |
|---|
| 2773 | | - return ATOM_DEVICE_DFP1_SUPPORT; |
|---|
| 2774 | | - else if (dev_id & ATOM_DEVICE_LCD_SUPPORT) |
|---|
| 2775 | | - return ATOM_DEVICE_LCD1_SUPPORT; |
|---|
| 2776 | | - else if (dev_id & ATOM_DEVICE_TV_SUPPORT) |
|---|
| 2777 | | - return ATOM_DEVICE_TV1_SUPPORT; |
|---|
| 2778 | | - else if (dev_id & ATOM_DEVICE_CV_SUPPORT) |
|---|
| 2779 | | - return ATOM_DEVICE_CV_SUPPORT; |
|---|
| 2780 | | - |
|---|
| 2781 | | - /* No group found for this device ID. */ |
|---|
| 2782 | | - |
|---|
| 2783 | | - dm_error("%s: incorrect input %d\n", __func__, dev_id); |
|---|
| 2784 | | - /* No matching support flag for given device ID */ |
|---|
| 2785 | | - return 0; |
|---|
| 2786 | | -} |
|---|
| 2787 | | - |
|---|
| 2788 | | -/* |
|---|
| 2789 | | - * Gets the next device ID in the group for a given device ID. |
|---|
| 2790 | | - * |
|---|
| 2791 | | - * The current device ID being enumerated on. |
|---|
| 2792 | | - * |
|---|
| 2793 | | - * The next device ID in the group, or 0 if no device exists. |
|---|
| 2794 | | - */ |
|---|
| 2795 | | -static uint32_t enum_next_dev_id(uint32_t dev_id) |
|---|
| 2796 | | -{ |
|---|
| 2797 | | - /* Get next device ID in the group. */ |
|---|
| 2798 | | - switch (dev_id) { |
|---|
| 2799 | | - case ATOM_DEVICE_CRT1_SUPPORT: |
|---|
| 2800 | | - return ATOM_DEVICE_CRT2_SUPPORT; |
|---|
| 2801 | | - case ATOM_DEVICE_LCD1_SUPPORT: |
|---|
| 2802 | | - return ATOM_DEVICE_LCD2_SUPPORT; |
|---|
| 2803 | | - case ATOM_DEVICE_DFP1_SUPPORT: |
|---|
| 2804 | | - return ATOM_DEVICE_DFP2_SUPPORT; |
|---|
| 2805 | | - case ATOM_DEVICE_DFP2_SUPPORT: |
|---|
| 2806 | | - return ATOM_DEVICE_DFP3_SUPPORT; |
|---|
| 2807 | | - case ATOM_DEVICE_DFP3_SUPPORT: |
|---|
| 2808 | | - return ATOM_DEVICE_DFP4_SUPPORT; |
|---|
| 2809 | | - case ATOM_DEVICE_DFP4_SUPPORT: |
|---|
| 2810 | | - return ATOM_DEVICE_DFP5_SUPPORT; |
|---|
| 2811 | | - case ATOM_DEVICE_DFP5_SUPPORT: |
|---|
| 2812 | | - return ATOM_DEVICE_DFP6_SUPPORT; |
|---|
| 2813 | | - } |
|---|
| 2814 | | - |
|---|
| 2815 | | - /* Done enumerating through devices. */ |
|---|
| 2816 | | - return 0; |
|---|
| 2817 | | -} |
|---|
| 2818 | | - |
|---|
| 2819 | | -/* |
|---|
| 2820 | | - * Returns the new device tag record for patched BIOS object. |
|---|
| 2821 | | - * |
|---|
| 2822 | | - * [IN] pExtDisplayPath - External display path to copy device tag from. |
|---|
| 2823 | | - * [IN] deviceSupport - Bit vector for device ID support flags. |
|---|
| 2824 | | - * [OUT] pDeviceTag - Device tag structure to fill with patched data. |
|---|
| 2825 | | - * |
|---|
| 2826 | | - * True if a compatible device ID was found, false otherwise. |
|---|
| 2827 | | - */ |
|---|
| 2828 | | -static bool get_patched_device_tag( |
|---|
| 2829 | | - struct bios_parser *bp, |
|---|
| 2830 | | - EXT_DISPLAY_PATH *ext_display_path, |
|---|
| 2831 | | - uint32_t device_support, |
|---|
| 2832 | | - ATOM_CONNECTOR_DEVICE_TAG *device_tag) |
|---|
| 2833 | | -{ |
|---|
| 2834 | | - uint32_t dev_id; |
|---|
| 2835 | | - /* Use fallback behaviour if not supported. */ |
|---|
| 2836 | | - if (!bp->remap_device_tags) { |
|---|
| 2837 | | - device_tag->ulACPIDeviceEnum = |
|---|
| 2838 | | - cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum)); |
|---|
| 2839 | | - device_tag->usDeviceID = |
|---|
| 2840 | | - cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceTag)); |
|---|
| 2841 | | - return true; |
|---|
| 2842 | | - } |
|---|
| 2843 | | - |
|---|
| 2844 | | - /* Find the first unused in the same group. */ |
|---|
| 2845 | | - dev_id = enum_first_device_id(le16_to_cpu(ext_display_path->usDeviceTag)); |
|---|
| 2846 | | - while (dev_id != 0) { |
|---|
| 2847 | | - /* Assign this device ID if supported. */ |
|---|
| 2848 | | - if ((device_support & dev_id) != 0) { |
|---|
| 2849 | | - device_tag->ulACPIDeviceEnum = |
|---|
| 2850 | | - cpu_to_le32((uint32_t) le16_to_cpu(ext_display_path->usDeviceACPIEnum)); |
|---|
| 2851 | | - device_tag->usDeviceID = cpu_to_le16((USHORT) dev_id); |
|---|
| 2852 | | - return true; |
|---|
| 2853 | | - } |
|---|
| 2854 | | - |
|---|
| 2855 | | - dev_id = enum_next_dev_id(dev_id); |
|---|
| 2856 | | - } |
|---|
| 2857 | | - |
|---|
| 2858 | | - /* No compatible device ID found. */ |
|---|
| 2859 | | - return false; |
|---|
| 2860 | | -} |
|---|
| 2861 | | - |
|---|
| 2862 | | -/* |
|---|
| 2863 | | - * Adds a device tag to a BIOS object's device tag record if there is |
|---|
| 2864 | | - * matching device ID supported. |
|---|
| 2865 | | - * |
|---|
| 2866 | | - * pObject - Pointer to the BIOS object to add the device tag to. |
|---|
| 2867 | | - * pExtDisplayPath - Display path to retrieve base device ID from. |
|---|
| 2868 | | - * pDeviceSupport - Pointer to bit vector for supported device IDs. |
|---|
| 2869 | | - */ |
|---|
| 2870 | | -static void add_device_tag_from_ext_display_path( |
|---|
| 2871 | | - struct bios_parser *bp, |
|---|
| 2872 | | - ATOM_OBJECT *object, |
|---|
| 2873 | | - EXT_DISPLAY_PATH *ext_display_path, |
|---|
| 2874 | | - uint32_t *device_support) |
|---|
| 2875 | | -{ |
|---|
| 2876 | | - /* Get device tag record for object. */ |
|---|
| 2877 | | - ATOM_CONNECTOR_DEVICE_TAG *device_tag = NULL; |
|---|
| 2878 | | - ATOM_CONNECTOR_DEVICE_TAG_RECORD *device_tag_record = NULL; |
|---|
| 2879 | | - enum bp_result result = |
|---|
| 2880 | | - bios_parser_get_device_tag_record( |
|---|
| 2881 | | - bp, object, &device_tag_record); |
|---|
| 2882 | | - |
|---|
| 2883 | | - if ((le16_to_cpu(ext_display_path->usDeviceTag) != CONNECTOR_OBJECT_ID_NONE) |
|---|
| 2884 | | - && (result == BP_RESULT_OK)) { |
|---|
| 2885 | | - uint8_t index; |
|---|
| 2886 | | - |
|---|
| 2887 | | - if ((device_tag_record->ucNumberOfDevice == 1) && |
|---|
| 2888 | | - (le16_to_cpu(device_tag_record->asDeviceTag[0].usDeviceID) == 0)) { |
|---|
| 2889 | | - /*Workaround bug in current VBIOS releases where |
|---|
| 2890 | | - * ucNumberOfDevice = 1 but there is no actual device |
|---|
| 2891 | | - * tag data. This w/a is temporary until the updated |
|---|
| 2892 | | - * VBIOS is distributed. */ |
|---|
| 2893 | | - device_tag_record->ucNumberOfDevice = |
|---|
| 2894 | | - device_tag_record->ucNumberOfDevice - 1; |
|---|
| 2895 | | - } |
|---|
| 2896 | | - |
|---|
| 2897 | | - /* Attempt to find a matching device ID. */ |
|---|
| 2898 | | - index = device_tag_record->ucNumberOfDevice; |
|---|
| 2899 | | - device_tag = &device_tag_record->asDeviceTag[index]; |
|---|
| 2900 | | - if (get_patched_device_tag( |
|---|
| 2901 | | - bp, |
|---|
| 2902 | | - ext_display_path, |
|---|
| 2903 | | - *device_support, |
|---|
| 2904 | | - device_tag)) { |
|---|
| 2905 | | - /* Update cached device support to remove assigned ID. |
|---|
| 2906 | | - */ |
|---|
| 2907 | | - *device_support &= ~le16_to_cpu(device_tag->usDeviceID); |
|---|
| 2908 | | - device_tag_record->ucNumberOfDevice++; |
|---|
| 2909 | | - } |
|---|
| 2910 | | - } |
|---|
| 2911 | | -} |
|---|
| 2912 | | - |
|---|
| 2913 | | -/* |
|---|
| 2914 | | - * Read out a single EXT_DISPLAY_PATH from the external display connection info |
|---|
| 2915 | | - * table. The specific entry in the table is determined by the enum_id passed |
|---|
| 2916 | | - * in. |
|---|
| 2917 | | - * |
|---|
| 2918 | | - * EXT_DISPLAY_PATH describing a single Configuration table entry |
|---|
| 2919 | | - */ |
|---|
| 2920 | | - |
|---|
| 2921 | | -#define INVALID_CONNECTOR 0xffff |
|---|
| 2922 | | - |
|---|
| 2923 | | -static EXT_DISPLAY_PATH *get_ext_display_path_entry( |
|---|
| 2924 | | - ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO *config_table, |
|---|
| 2925 | | - uint32_t bios_object_id) |
|---|
| 2926 | | -{ |
|---|
| 2927 | | - EXT_DISPLAY_PATH *ext_display_path; |
|---|
| 2928 | | - uint32_t ext_display_path_index = |
|---|
| 2929 | | - ((bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT) - 1; |
|---|
| 2930 | | - |
|---|
| 2931 | | - if (ext_display_path_index >= MAX_NUMBER_OF_EXT_DISPLAY_PATH) |
|---|
| 2932 | | - return NULL; |
|---|
| 2933 | | - |
|---|
| 2934 | | - ext_display_path = &config_table->sPath[ext_display_path_index]; |
|---|
| 2935 | | - |
|---|
| 2936 | | - if (le16_to_cpu(ext_display_path->usDeviceConnector) == INVALID_CONNECTOR) |
|---|
| 2937 | | - ext_display_path->usDeviceConnector = cpu_to_le16(0); |
|---|
| 2938 | | - |
|---|
| 2939 | | - return ext_display_path; |
|---|
| 2940 | | -} |
|---|
| 2941 | | - |
|---|
| 2942 | | -/* |
|---|
| 2943 | | - * Get AUX/DDC information of input object id |
|---|
| 2944 | | - * |
|---|
| 2945 | | - * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record |
|---|
| 2946 | | - * IR |
|---|
| 2947 | | - */ |
|---|
| 2948 | | -static ATOM_CONNECTOR_AUXDDC_LUT_RECORD *get_ext_connector_aux_ddc_lut_record( |
|---|
| 2949 | | - struct bios_parser *bp, |
|---|
| 2950 | | - ATOM_OBJECT *object) |
|---|
| 2951 | | -{ |
|---|
| 2952 | | - uint32_t offset; |
|---|
| 2953 | | - ATOM_COMMON_RECORD_HEADER *header; |
|---|
| 2954 | | - |
|---|
| 2955 | | - if (!object) { |
|---|
| 2956 | | - BREAK_TO_DEBUGGER(); |
|---|
| 2957 | | - /* Invalid object */ |
|---|
| 2958 | | - return NULL; |
|---|
| 2959 | | - } |
|---|
| 2960 | | - |
|---|
| 2961 | | - offset = le16_to_cpu(object->usRecordOffset) |
|---|
| 2962 | | - + bp->object_info_tbl_offset; |
|---|
| 2963 | | - |
|---|
| 2964 | | - for (;;) { |
|---|
| 2965 | | - header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); |
|---|
| 2966 | | - |
|---|
| 2967 | | - if (!header) |
|---|
| 2968 | | - return NULL; |
|---|
| 2969 | | - |
|---|
| 2970 | | - if (LAST_RECORD_TYPE == header->ucRecordType || |
|---|
| 2971 | | - 0 == header->ucRecordSize) |
|---|
| 2972 | | - break; |
|---|
| 2973 | | - |
|---|
| 2974 | | - if (ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE == |
|---|
| 2975 | | - header->ucRecordType && |
|---|
| 2976 | | - sizeof(ATOM_CONNECTOR_AUXDDC_LUT_RECORD) <= |
|---|
| 2977 | | - header->ucRecordSize) |
|---|
| 2978 | | - return (ATOM_CONNECTOR_AUXDDC_LUT_RECORD *)(header); |
|---|
| 2979 | | - |
|---|
| 2980 | | - offset += header->ucRecordSize; |
|---|
| 2981 | | - } |
|---|
| 2982 | | - |
|---|
| 2983 | | - return NULL; |
|---|
| 2984 | | -} |
|---|
| 2985 | | - |
|---|
| 2986 | | -/* |
|---|
| 2987 | | - * Get AUX/DDC information of input object id |
|---|
| 2988 | | - * |
|---|
| 2989 | | - * search all records to find the ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE record |
|---|
| 2990 | | - * IR |
|---|
| 2991 | | - */ |
|---|
| 2992 | | -static ATOM_CONNECTOR_HPDPIN_LUT_RECORD *get_ext_connector_hpd_pin_lut_record( |
|---|
| 2993 | | - struct bios_parser *bp, |
|---|
| 2994 | | - ATOM_OBJECT *object) |
|---|
| 2995 | | -{ |
|---|
| 2996 | | - uint32_t offset; |
|---|
| 2997 | | - ATOM_COMMON_RECORD_HEADER *header; |
|---|
| 2998 | | - |
|---|
| 2999 | | - if (!object) { |
|---|
| 3000 | | - BREAK_TO_DEBUGGER(); |
|---|
| 3001 | | - /* Invalid object */ |
|---|
| 3002 | | - return NULL; |
|---|
| 3003 | | - } |
|---|
| 3004 | | - |
|---|
| 3005 | | - offset = le16_to_cpu(object->usRecordOffset) |
|---|
| 3006 | | - + bp->object_info_tbl_offset; |
|---|
| 3007 | | - |
|---|
| 3008 | | - for (;;) { |
|---|
| 3009 | | - header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset); |
|---|
| 3010 | | - |
|---|
| 3011 | | - if (!header) |
|---|
| 3012 | | - return NULL; |
|---|
| 3013 | | - |
|---|
| 3014 | | - if (LAST_RECORD_TYPE == header->ucRecordType || |
|---|
| 3015 | | - 0 == header->ucRecordSize) |
|---|
| 3016 | | - break; |
|---|
| 3017 | | - |
|---|
| 3018 | | - if (ATOM_CONNECTOR_HPDPIN_LUT_RECORD_TYPE == |
|---|
| 3019 | | - header->ucRecordType && |
|---|
| 3020 | | - sizeof(ATOM_CONNECTOR_HPDPIN_LUT_RECORD) <= |
|---|
| 3021 | | - header->ucRecordSize) |
|---|
| 3022 | | - return (ATOM_CONNECTOR_HPDPIN_LUT_RECORD *)header; |
|---|
| 3023 | | - |
|---|
| 3024 | | - offset += header->ucRecordSize; |
|---|
| 3025 | | - } |
|---|
| 3026 | | - |
|---|
| 3027 | | - return NULL; |
|---|
| 3028 | | -} |
|---|
| 3029 | | - |
|---|
| 3030 | | -/* |
|---|
| 3031 | | - * Check whether we need to patch the VBIOS connector info table with |
|---|
| 3032 | | - * data from an external display connection info table. This is |
|---|
| 3033 | | - * necessary to support MXM boards with an OPM (output personality |
|---|
| 3034 | | - * module). With these designs, the VBIOS connector info table |
|---|
| 3035 | | - * specifies an MXM_CONNECTOR with a unique ID. The driver retrieves |
|---|
| 3036 | | - * the external connection info table through i2c and then looks up the |
|---|
| 3037 | | - * connector ID to find the real connector type (e.g. DFP1). |
|---|
| 3038 | | - * |
|---|
| 3039 | | - */ |
|---|
| 3040 | | -static enum bp_result patch_bios_image_from_ext_display_connection_info( |
|---|
| 3041 | | - struct bios_parser *bp) |
|---|
| 3042 | | -{ |
|---|
| 3043 | | - ATOM_OBJECT_TABLE *connector_tbl; |
|---|
| 3044 | | - uint32_t connector_tbl_offset; |
|---|
| 3045 | | - struct graphics_object_id object_id; |
|---|
| 3046 | | - ATOM_OBJECT *object; |
|---|
| 3047 | | - ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO ext_display_connection_info_tbl; |
|---|
| 3048 | | - EXT_DISPLAY_PATH *ext_display_path; |
|---|
| 3049 | | - ATOM_CONNECTOR_AUXDDC_LUT_RECORD *aux_ddc_lut_record = NULL; |
|---|
| 3050 | | - ATOM_I2C_RECORD *i2c_record = NULL; |
|---|
| 3051 | | - ATOM_CONNECTOR_HPDPIN_LUT_RECORD *hpd_pin_lut_record = NULL; |
|---|
| 3052 | | - ATOM_HPD_INT_RECORD *hpd_record = NULL; |
|---|
| 3053 | | - ATOM_OBJECT_TABLE *encoder_table; |
|---|
| 3054 | | - uint32_t encoder_table_offset; |
|---|
| 3055 | | - ATOM_OBJECT *opm_object = NULL; |
|---|
| 3056 | | - uint32_t i = 0; |
|---|
| 3057 | | - struct graphics_object_id opm_object_id = |
|---|
| 3058 | | - dal_graphics_object_id_init( |
|---|
| 3059 | | - GENERIC_ID_MXM_OPM, |
|---|
| 3060 | | - ENUM_ID_1, |
|---|
| 3061 | | - OBJECT_TYPE_GENERIC); |
|---|
| 3062 | | - ATOM_CONNECTOR_DEVICE_TAG_RECORD *dev_tag_record; |
|---|
| 3063 | | - uint32_t cached_device_support = |
|---|
| 3064 | | - le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport); |
|---|
| 3065 | | - |
|---|
| 3066 | | - uint32_t dst_number; |
|---|
| 3067 | | - uint16_t *dst_object_id_list; |
|---|
| 3068 | | - |
|---|
| 3069 | | - opm_object = get_bios_object(bp, opm_object_id); |
|---|
| 3070 | | - if (!opm_object) |
|---|
| 3071 | | - return BP_RESULT_UNSUPPORTED; |
|---|
| 3072 | | - |
|---|
| 3073 | | - memset(&ext_display_connection_info_tbl, 0, |
|---|
| 3074 | | - sizeof(ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO)); |
|---|
| 3075 | | - |
|---|
| 3076 | | - connector_tbl_offset = bp->object_info_tbl_offset |
|---|
| 3077 | | - + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); |
|---|
| 3078 | | - connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset); |
|---|
| 3079 | | - |
|---|
| 3080 | | - /* Read Connector info table from EEPROM through i2c */ |
|---|
| 3081 | | - if (get_ext_display_connection_info(bp, |
|---|
| 3082 | | - opm_object, |
|---|
| 3083 | | - &ext_display_connection_info_tbl) != BP_RESULT_OK) { |
|---|
| 3084 | | - |
|---|
| 3085 | | - DC_LOG_WARNING("%s: Failed to read Connection Info Table", __func__); |
|---|
| 3086 | | - return BP_RESULT_UNSUPPORTED; |
|---|
| 3087 | | - } |
|---|
| 3088 | | - |
|---|
| 3089 | | - /* Get pointer to AUX/DDC and HPD LUTs */ |
|---|
| 3090 | | - aux_ddc_lut_record = |
|---|
| 3091 | | - get_ext_connector_aux_ddc_lut_record(bp, opm_object); |
|---|
| 3092 | | - hpd_pin_lut_record = |
|---|
| 3093 | | - get_ext_connector_hpd_pin_lut_record(bp, opm_object); |
|---|
| 3094 | | - |
|---|
| 3095 | | - if ((aux_ddc_lut_record == NULL) || (hpd_pin_lut_record == NULL)) |
|---|
| 3096 | | - return BP_RESULT_UNSUPPORTED; |
|---|
| 3097 | | - |
|---|
| 3098 | | - /* Cache support bits for currently unmapped device types. */ |
|---|
| 3099 | | - if (bp->remap_device_tags) { |
|---|
| 3100 | | - for (i = 0; i < connector_tbl->ucNumberOfObjects; ++i) { |
|---|
| 3101 | | - uint32_t j; |
|---|
| 3102 | | - /* Remove support for all non-MXM connectors. */ |
|---|
| 3103 | | - object = &connector_tbl->asObjects[i]; |
|---|
| 3104 | | - object_id = object_id_from_bios_object_id( |
|---|
| 3105 | | - le16_to_cpu(object->usObjectID)); |
|---|
| 3106 | | - if ((OBJECT_TYPE_CONNECTOR != object_id.type) || |
|---|
| 3107 | | - (CONNECTOR_ID_MXM == object_id.id)) |
|---|
| 3108 | | - continue; |
|---|
| 3109 | | - |
|---|
| 3110 | | - /* Remove support for all device tags. */ |
|---|
| 3111 | | - if (bios_parser_get_device_tag_record( |
|---|
| 3112 | | - bp, object, &dev_tag_record) != BP_RESULT_OK) |
|---|
| 3113 | | - continue; |
|---|
| 3114 | | - |
|---|
| 3115 | | - for (j = 0; j < dev_tag_record->ucNumberOfDevice; ++j) { |
|---|
| 3116 | | - ATOM_CONNECTOR_DEVICE_TAG *device_tag = |
|---|
| 3117 | | - &dev_tag_record->asDeviceTag[j]; |
|---|
| 3118 | | - cached_device_support &= |
|---|
| 3119 | | - ~le16_to_cpu(device_tag->usDeviceID); |
|---|
| 3120 | | - } |
|---|
| 3121 | | - } |
|---|
| 3122 | | - } |
|---|
| 3123 | | - |
|---|
| 3124 | | - /* Find all MXM connector objects and patch them with connector info |
|---|
| 3125 | | - * from the external display connection info table. */ |
|---|
| 3126 | | - for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) { |
|---|
| 3127 | | - uint32_t j; |
|---|
| 3128 | | - |
|---|
| 3129 | | - object = &connector_tbl->asObjects[i]; |
|---|
| 3130 | | - object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID)); |
|---|
| 3131 | | - if ((OBJECT_TYPE_CONNECTOR != object_id.type) || |
|---|
| 3132 | | - (CONNECTOR_ID_MXM != object_id.id)) |
|---|
| 3133 | | - continue; |
|---|
| 3134 | | - |
|---|
| 3135 | | - /* Get the correct connection info table entry based on the enum |
|---|
| 3136 | | - * id. */ |
|---|
| 3137 | | - ext_display_path = get_ext_display_path_entry( |
|---|
| 3138 | | - &ext_display_connection_info_tbl, |
|---|
| 3139 | | - le16_to_cpu(object->usObjectID)); |
|---|
| 3140 | | - if (!ext_display_path) |
|---|
| 3141 | | - return BP_RESULT_FAILURE; |
|---|
| 3142 | | - |
|---|
| 3143 | | - /* Patch device connector ID */ |
|---|
| 3144 | | - object->usObjectID = |
|---|
| 3145 | | - cpu_to_le16(le16_to_cpu(ext_display_path->usDeviceConnector)); |
|---|
| 3146 | | - |
|---|
| 3147 | | - /* Patch device tag, ulACPIDeviceEnum. */ |
|---|
| 3148 | | - add_device_tag_from_ext_display_path( |
|---|
| 3149 | | - bp, |
|---|
| 3150 | | - object, |
|---|
| 3151 | | - ext_display_path, |
|---|
| 3152 | | - &cached_device_support); |
|---|
| 3153 | | - |
|---|
| 3154 | | - /* Patch HPD info */ |
|---|
| 3155 | | - if (ext_display_path->ucExtHPDPINLutIndex < |
|---|
| 3156 | | - MAX_NUMBER_OF_EXT_HPDPIN_LUT_ENTRIES) { |
|---|
| 3157 | | - hpd_record = get_hpd_record(bp, object); |
|---|
| 3158 | | - if (hpd_record) { |
|---|
| 3159 | | - uint8_t index = |
|---|
| 3160 | | - ext_display_path->ucExtHPDPINLutIndex; |
|---|
| 3161 | | - hpd_record->ucHPDIntGPIOID = |
|---|
| 3162 | | - hpd_pin_lut_record->ucHPDPINMap[index]; |
|---|
| 3163 | | - } else { |
|---|
| 3164 | | - BREAK_TO_DEBUGGER(); |
|---|
| 3165 | | - /* Invalid hpd record */ |
|---|
| 3166 | | - return BP_RESULT_FAILURE; |
|---|
| 3167 | | - } |
|---|
| 3168 | | - } |
|---|
| 3169 | | - |
|---|
| 3170 | | - /* Patch I2C/AUX info */ |
|---|
| 3171 | | - if (ext_display_path->ucExtHPDPINLutIndex < |
|---|
| 3172 | | - MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES) { |
|---|
| 3173 | | - i2c_record = get_i2c_record(bp, object); |
|---|
| 3174 | | - if (i2c_record) { |
|---|
| 3175 | | - uint8_t index = |
|---|
| 3176 | | - ext_display_path->ucExtAUXDDCLutIndex; |
|---|
| 3177 | | - i2c_record->sucI2cId = |
|---|
| 3178 | | - aux_ddc_lut_record->ucAUXDDCMap[index]; |
|---|
| 3179 | | - } else { |
|---|
| 3180 | | - BREAK_TO_DEBUGGER(); |
|---|
| 3181 | | - /* Invalid I2C record */ |
|---|
| 3182 | | - return BP_RESULT_FAILURE; |
|---|
| 3183 | | - } |
|---|
| 3184 | | - } |
|---|
| 3185 | | - |
|---|
| 3186 | | - /* Merge with other MXM connectors that map to the same physical |
|---|
| 3187 | | - * connector. */ |
|---|
| 3188 | | - for (j = i + 1; |
|---|
| 3189 | | - j < connector_tbl->ucNumberOfObjects; j++) { |
|---|
| 3190 | | - ATOM_OBJECT *next_object; |
|---|
| 3191 | | - struct graphics_object_id next_object_id; |
|---|
| 3192 | | - EXT_DISPLAY_PATH *next_ext_display_path; |
|---|
| 3193 | | - |
|---|
| 3194 | | - next_object = &connector_tbl->asObjects[j]; |
|---|
| 3195 | | - next_object_id = object_id_from_bios_object_id( |
|---|
| 3196 | | - le16_to_cpu(next_object->usObjectID)); |
|---|
| 3197 | | - |
|---|
| 3198 | | - if ((OBJECT_TYPE_CONNECTOR != next_object_id.type) && |
|---|
| 3199 | | - (CONNECTOR_ID_MXM == next_object_id.id)) |
|---|
| 3200 | | - continue; |
|---|
| 3201 | | - |
|---|
| 3202 | | - next_ext_display_path = get_ext_display_path_entry( |
|---|
| 3203 | | - &ext_display_connection_info_tbl, |
|---|
| 3204 | | - le16_to_cpu(next_object->usObjectID)); |
|---|
| 3205 | | - |
|---|
| 3206 | | - if (next_ext_display_path == NULL) |
|---|
| 3207 | | - return BP_RESULT_FAILURE; |
|---|
| 3208 | | - |
|---|
| 3209 | | - /* Merge if using same connector. */ |
|---|
| 3210 | | - if ((le16_to_cpu(next_ext_display_path->usDeviceConnector) == |
|---|
| 3211 | | - le16_to_cpu(ext_display_path->usDeviceConnector)) && |
|---|
| 3212 | | - (le16_to_cpu(ext_display_path->usDeviceConnector) != 0)) { |
|---|
| 3213 | | - /* Clear duplicate connector from table. */ |
|---|
| 3214 | | - next_object->usObjectID = cpu_to_le16(0); |
|---|
| 3215 | | - add_device_tag_from_ext_display_path( |
|---|
| 3216 | | - bp, |
|---|
| 3217 | | - object, |
|---|
| 3218 | | - ext_display_path, |
|---|
| 3219 | | - &cached_device_support); |
|---|
| 3220 | | - } |
|---|
| 3221 | | - } |
|---|
| 3222 | | - } |
|---|
| 3223 | | - |
|---|
| 3224 | | - /* Find all encoders which have an MXM object as their destination. |
|---|
| 3225 | | - * Replace the MXM object with the real connector Id from the external |
|---|
| 3226 | | - * display connection info table */ |
|---|
| 3227 | | - |
|---|
| 3228 | | - encoder_table_offset = bp->object_info_tbl_offset |
|---|
| 3229 | | - + le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset); |
|---|
| 3230 | | - encoder_table = GET_IMAGE(ATOM_OBJECT_TABLE, encoder_table_offset); |
|---|
| 3231 | | - |
|---|
| 3232 | | - for (i = 0; i < encoder_table->ucNumberOfObjects; i++) { |
|---|
| 3233 | | - uint32_t j; |
|---|
| 3234 | | - |
|---|
| 3235 | | - object = &encoder_table->asObjects[i]; |
|---|
| 3236 | | - |
|---|
| 3237 | | - dst_number = get_dest_obj_list(bp, object, &dst_object_id_list); |
|---|
| 3238 | | - |
|---|
| 3239 | | - for (j = 0; j < dst_number; j++) { |
|---|
| 3240 | | - object_id = object_id_from_bios_object_id( |
|---|
| 3241 | | - dst_object_id_list[j]); |
|---|
| 3242 | | - |
|---|
| 3243 | | - if ((OBJECT_TYPE_CONNECTOR != object_id.type) || |
|---|
| 3244 | | - (CONNECTOR_ID_MXM != object_id.id)) |
|---|
| 3245 | | - continue; |
|---|
| 3246 | | - |
|---|
| 3247 | | - /* Get the correct connection info table entry based on |
|---|
| 3248 | | - * the enum id. */ |
|---|
| 3249 | | - ext_display_path = |
|---|
| 3250 | | - get_ext_display_path_entry( |
|---|
| 3251 | | - &ext_display_connection_info_tbl, |
|---|
| 3252 | | - dst_object_id_list[j]); |
|---|
| 3253 | | - |
|---|
| 3254 | | - if (ext_display_path == NULL) |
|---|
| 3255 | | - return BP_RESULT_FAILURE; |
|---|
| 3256 | | - |
|---|
| 3257 | | - dst_object_id_list[j] = |
|---|
| 3258 | | - le16_to_cpu(ext_display_path->usDeviceConnector); |
|---|
| 3259 | | - } |
|---|
| 3260 | | - } |
|---|
| 3261 | | - |
|---|
| 3262 | | - return BP_RESULT_OK; |
|---|
| 3263 | | -} |
|---|
| 3264 | | - |
|---|
| 3265 | | -/* |
|---|
| 3266 | | - * Check whether we need to patch the VBIOS connector info table with |
|---|
| 3267 | | - * data from an external display connection info table. This is |
|---|
| 3268 | | - * necessary to support MXM boards with an OPM (output personality |
|---|
| 3269 | | - * module). With these designs, the VBIOS connector info table |
|---|
| 3270 | | - * specifies an MXM_CONNECTOR with a unique ID. The driver retrieves |
|---|
| 3271 | | - * the external connection info table through i2c and then looks up the |
|---|
| 3272 | | - * connector ID to find the real connector type (e.g. DFP1). |
|---|
| 3273 | | - * |
|---|
| 3274 | | - */ |
|---|
| 3275 | | - |
|---|
| 3276 | | -static void process_ext_display_connection_info(struct bios_parser *bp) |
|---|
| 3277 | | -{ |
|---|
| 3278 | | - ATOM_OBJECT_TABLE *connector_tbl; |
|---|
| 3279 | | - uint32_t connector_tbl_offset; |
|---|
| 3280 | | - struct graphics_object_id object_id; |
|---|
| 3281 | | - ATOM_OBJECT *object; |
|---|
| 3282 | | - bool mxm_connector_found = false; |
|---|
| 3283 | | - bool null_entry_found = false; |
|---|
| 3284 | | - uint32_t i = 0; |
|---|
| 3285 | | - |
|---|
| 3286 | | - connector_tbl_offset = bp->object_info_tbl_offset + |
|---|
| 3287 | | - le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset); |
|---|
| 3288 | | - connector_tbl = GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset); |
|---|
| 3289 | | - |
|---|
| 3290 | | - /* Look for MXM connectors to determine whether we need patch the VBIOS |
|---|
| 3291 | | - * connector info table. Look for null entries to determine whether we |
|---|
| 3292 | | - * need to compact connector table. */ |
|---|
| 3293 | | - for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) { |
|---|
| 3294 | | - object = &connector_tbl->asObjects[i]; |
|---|
| 3295 | | - object_id = object_id_from_bios_object_id(le16_to_cpu(object->usObjectID)); |
|---|
| 3296 | | - |
|---|
| 3297 | | - if ((OBJECT_TYPE_CONNECTOR == object_id.type) && |
|---|
| 3298 | | - (CONNECTOR_ID_MXM == object_id.id)) { |
|---|
| 3299 | | - /* Once we found MXM connector - we can break */ |
|---|
| 3300 | | - mxm_connector_found = true; |
|---|
| 3301 | | - break; |
|---|
| 3302 | | - } else if (OBJECT_TYPE_CONNECTOR != object_id.type) { |
|---|
| 3303 | | - /* We need to continue looping - to check if MXM |
|---|
| 3304 | | - * connector present */ |
|---|
| 3305 | | - null_entry_found = true; |
|---|
| 3306 | | - } |
|---|
| 3307 | | - } |
|---|
| 3308 | | - |
|---|
| 3309 | | - /* Patch BIOS image */ |
|---|
| 3310 | | - if (mxm_connector_found || null_entry_found) { |
|---|
| 3311 | | - uint32_t connectors_num = 0; |
|---|
| 3312 | | - uint8_t *original_bios; |
|---|
| 3313 | | - /* Step 1: Replace bios image with the new copy which will be |
|---|
| 3314 | | - * patched */ |
|---|
| 3315 | | - bp->base.bios_local_image = kzalloc(bp->base.bios_size, |
|---|
| 3316 | | - GFP_KERNEL); |
|---|
| 3317 | | - if (bp->base.bios_local_image == NULL) { |
|---|
| 3318 | | - BREAK_TO_DEBUGGER(); |
|---|
| 3319 | | - /* Failed to alloc bp->base.bios_local_image */ |
|---|
| 3320 | | - return; |
|---|
| 3321 | | - } |
|---|
| 3322 | | - |
|---|
| 3323 | | - memmove(bp->base.bios_local_image, bp->base.bios, bp->base.bios_size); |
|---|
| 3324 | | - original_bios = bp->base.bios; |
|---|
| 3325 | | - bp->base.bios = bp->base.bios_local_image; |
|---|
| 3326 | | - connector_tbl = |
|---|
| 3327 | | - GET_IMAGE(ATOM_OBJECT_TABLE, connector_tbl_offset); |
|---|
| 3328 | | - |
|---|
| 3329 | | - /* Step 2: (only if MXM connector found) Patch BIOS image with |
|---|
| 3330 | | - * info from external module */ |
|---|
| 3331 | | - if (mxm_connector_found && |
|---|
| 3332 | | - patch_bios_image_from_ext_display_connection_info(bp) != |
|---|
| 3333 | | - BP_RESULT_OK) { |
|---|
| 3334 | | - /* Patching the bios image has failed. We will copy |
|---|
| 3335 | | - * again original image provided and afterwards |
|---|
| 3336 | | - * only remove null entries */ |
|---|
| 3337 | | - memmove( |
|---|
| 3338 | | - bp->base.bios_local_image, |
|---|
| 3339 | | - original_bios, |
|---|
| 3340 | | - bp->base.bios_size); |
|---|
| 3341 | | - } |
|---|
| 3342 | | - |
|---|
| 3343 | | - /* Step 3: Compact connector table (remove null entries, valid |
|---|
| 3344 | | - * entries moved to beginning) */ |
|---|
| 3345 | | - for (i = 0; i < connector_tbl->ucNumberOfObjects; i++) { |
|---|
| 3346 | | - object = &connector_tbl->asObjects[i]; |
|---|
| 3347 | | - object_id = object_id_from_bios_object_id( |
|---|
| 3348 | | - le16_to_cpu(object->usObjectID)); |
|---|
| 3349 | | - |
|---|
| 3350 | | - if (OBJECT_TYPE_CONNECTOR != object_id.type) |
|---|
| 3351 | | - continue; |
|---|
| 3352 | | - |
|---|
| 3353 | | - if (i != connectors_num) { |
|---|
| 3354 | | - memmove( |
|---|
| 3355 | | - &connector_tbl-> |
|---|
| 3356 | | - asObjects[connectors_num], |
|---|
| 3357 | | - object, |
|---|
| 3358 | | - sizeof(ATOM_OBJECT)); |
|---|
| 3359 | | - } |
|---|
| 3360 | | - ++connectors_num; |
|---|
| 3361 | | - } |
|---|
| 3362 | | - connector_tbl->ucNumberOfObjects = (uint8_t)connectors_num; |
|---|
| 3363 | | - } |
|---|
| 3364 | | -} |
|---|
| 3365 | | - |
|---|
| 3366 | | -static void bios_parser_post_init(struct dc_bios *dcb) |
|---|
| 3367 | | -{ |
|---|
| 3368 | | - struct bios_parser *bp = BP_FROM_DCB(dcb); |
|---|
| 3369 | | - |
|---|
| 3370 | | - process_ext_display_connection_info(bp); |
|---|
| 3371 | 2196 | } |
|---|
| 3372 | 2197 | |
|---|
| 3373 | 2198 | /** |
|---|
| .. | .. |
|---|
| 3718 | 2543 | |
|---|
| 3719 | 2544 | /* Sort voltage table from low to high*/ |
|---|
| 3720 | 2545 | if (result == BP_RESULT_OK) { |
|---|
| 3721 | | - struct clock_voltage_caps temp = {0, 0}; |
|---|
| 3722 | 2546 | uint32_t i; |
|---|
| 3723 | 2547 | uint32_t j; |
|---|
| 3724 | 2548 | |
|---|
| .. | .. |
|---|
| 3728 | 2552 | info->disp_clk_voltage[j].max_supported_clk < |
|---|
| 3729 | 2553 | info->disp_clk_voltage[j-1].max_supported_clk) { |
|---|
| 3730 | 2554 | /* swap j and j - 1*/ |
|---|
| 3731 | | - temp = info->disp_clk_voltage[j-1]; |
|---|
| 3732 | | - info->disp_clk_voltage[j-1] = |
|---|
| 3733 | | - info->disp_clk_voltage[j]; |
|---|
| 3734 | | - info->disp_clk_voltage[j] = temp; |
|---|
| 2555 | + swap(info->disp_clk_voltage[j - 1], |
|---|
| 2556 | + info->disp_clk_voltage[j]); |
|---|
| 3735 | 2557 | } |
|---|
| 3736 | 2558 | } |
|---|
| 3737 | 2559 | } |
|---|
| .. | .. |
|---|
| 3917 | 2739 | struct board_layout_info *board_layout_info) |
|---|
| 3918 | 2740 | { |
|---|
| 3919 | 2741 | unsigned int i; |
|---|
| 3920 | | - struct bios_parser *bp; |
|---|
| 3921 | 2742 | enum bp_result record_result; |
|---|
| 3922 | 2743 | |
|---|
| 3923 | 2744 | const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = { |
|---|
| .. | .. |
|---|
| 3926 | 2747 | 0, 0 |
|---|
| 3927 | 2748 | }; |
|---|
| 3928 | 2749 | |
|---|
| 3929 | | - bp = BP_FROM_DCB(dcb); |
|---|
| 3930 | 2750 | if (board_layout_info == NULL) { |
|---|
| 3931 | 2751 | DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n"); |
|---|
| 3932 | 2752 | return BP_RESULT_BADINPUT; |
|---|
| .. | .. |
|---|
| 3961 | 2781 | static const struct dc_vbios_funcs vbios_funcs = { |
|---|
| 3962 | 2782 | .get_connectors_number = bios_parser_get_connectors_number, |
|---|
| 3963 | 2783 | |
|---|
| 3964 | | - .get_encoder_id = bios_parser_get_encoder_id, |
|---|
| 3965 | | - |
|---|
| 3966 | 2784 | .get_connector_id = bios_parser_get_connector_id, |
|---|
| 3967 | | - |
|---|
| 3968 | | - .get_dst_number = bios_parser_get_dst_number, |
|---|
| 3969 | 2785 | |
|---|
| 3970 | 2786 | .get_src_obj = bios_parser_get_src_obj, |
|---|
| 3971 | 2787 | |
|---|
| 3972 | | - .get_dst_obj = bios_parser_get_dst_obj, |
|---|
| 3973 | | - |
|---|
| 3974 | 2788 | .get_i2c_info = bios_parser_get_i2c_info, |
|---|
| 3975 | | - |
|---|
| 3976 | | - .get_voltage_ddc_info = bios_parser_get_voltage_ddc_info, |
|---|
| 3977 | | - |
|---|
| 3978 | | - .get_thermal_ddc_info = bios_parser_get_thermal_ddc_info, |
|---|
| 3979 | 2789 | |
|---|
| 3980 | 2790 | .get_hpd_info = bios_parser_get_hpd_info, |
|---|
| 3981 | 2791 | |
|---|
| 3982 | 2792 | .get_device_tag = bios_parser_get_device_tag, |
|---|
| 3983 | | - |
|---|
| 3984 | | - .get_firmware_info = bios_parser_get_firmware_info, |
|---|
| 3985 | 2793 | |
|---|
| 3986 | 2794 | .get_spread_spectrum_info = bios_parser_get_spread_spectrum_info, |
|---|
| 3987 | 2795 | |
|---|
| .. | .. |
|---|
| 3995 | 2803 | |
|---|
| 3996 | 2804 | /* bios scratch register communication */ |
|---|
| 3997 | 2805 | .is_accelerated_mode = bios_is_accelerated_mode, |
|---|
| 3998 | | - .get_vga_enabled_displays = bios_get_vga_enabled_displays, |
|---|
| 3999 | 2806 | |
|---|
| 4000 | 2807 | .set_scratch_critical_state = bios_parser_set_scratch_critical_state, |
|---|
| 4001 | 2808 | |
|---|
| .. | .. |
|---|
| 4005 | 2812 | .encoder_control = bios_parser_encoder_control, |
|---|
| 4006 | 2813 | |
|---|
| 4007 | 2814 | .transmitter_control = bios_parser_transmitter_control, |
|---|
| 4008 | | - |
|---|
| 4009 | | - .crt_control = bios_parser_crt_control, /* not used in DAL3. keep for now in case we need to support VGA on Bonaire */ |
|---|
| 4010 | 2815 | |
|---|
| 4011 | 2816 | .enable_crtc = bios_parser_enable_crtc, |
|---|
| 4012 | 2817 | |
|---|
| .. | .. |
|---|
| 4020 | 2825 | |
|---|
| 4021 | 2826 | .program_crtc_timing = bios_parser_program_crtc_timing, /* still use. should probably retire and program directly */ |
|---|
| 4022 | 2827 | |
|---|
| 4023 | | - .crtc_source_select = bios_parser_crtc_source_select, /* still use. should probably retire and program directly */ |
|---|
| 4024 | | - |
|---|
| 4025 | 2828 | .program_display_engine_pll = bios_parser_program_display_engine_pll, |
|---|
| 4026 | 2829 | |
|---|
| 4027 | 2830 | .enable_disp_power_gating = bios_parser_enable_disp_power_gating, |
|---|
| 4028 | 2831 | |
|---|
| 4029 | 2832 | /* SW init and patch */ |
|---|
| 4030 | | - .post_init = bios_parser_post_init, /* patch vbios table for mxm module by reading i2c */ |
|---|
| 4031 | 2833 | |
|---|
| 4032 | 2834 | .bios_parser_destroy = bios_parser_destroy, |
|---|
| 4033 | 2835 | |
|---|
| 4034 | 2836 | .get_board_layout_info = bios_get_board_layout_info, |
|---|
| 2837 | + |
|---|
| 2838 | + .get_atom_dc_golden_table = NULL |
|---|
| 4035 | 2839 | }; |
|---|
| 4036 | 2840 | |
|---|
| 4037 | 2841 | static bool bios_parser_construct( |
|---|
| .. | .. |
|---|
| 4113 | 2917 | dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version); |
|---|
| 4114 | 2918 | |
|---|
| 4115 | 2919 | bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base); |
|---|
| 2920 | + bp->base.fw_info_valid = bios_parser_get_firmware_info(&bp->base, &bp->base.fw_info) == BP_RESULT_OK; |
|---|
| 4116 | 2921 | |
|---|
| 4117 | 2922 | return true; |
|---|
| 4118 | 2923 | } |
|---|