1 /* 2 * Copyright 2023 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: AMD 23 * 24 */ 25 26 /* FILE POLICY AND INTENDED USAGE: 27 * This file owns the creation/destruction of link structure. 28 */ 29 #include "link_factory.h" 30 #include "protocols/link_ddc.h" 31 #include "protocols/link_edp_panel_control.h" 32 #include "protocols/link_hpd.h" 33 #include "gpio_service_interface.h" 34 #include "atomfirmware.h" 35 36 #define DC_LOGGER_INIT(logger) 37 38 #define LINK_INFO(...) \ 39 DC_LOG_HW_HOTPLUG( \ 40 __VA_ARGS__) 41 42 static enum transmitter translate_encoder_to_transmitter(struct graphics_object_id encoder) 43 { 44 switch (encoder.id) { 45 case ENCODER_ID_INTERNAL_UNIPHY: 46 switch (encoder.enum_id) { 47 case ENUM_ID_1: 48 return TRANSMITTER_UNIPHY_A; 49 case ENUM_ID_2: 50 return TRANSMITTER_UNIPHY_B; 51 default: 52 return TRANSMITTER_UNKNOWN; 53 } 54 break; 55 case ENCODER_ID_INTERNAL_UNIPHY1: 56 switch (encoder.enum_id) { 57 case ENUM_ID_1: 58 return TRANSMITTER_UNIPHY_C; 59 case ENUM_ID_2: 60 return TRANSMITTER_UNIPHY_D; 61 default: 62 return TRANSMITTER_UNKNOWN; 63 } 64 break; 65 case ENCODER_ID_INTERNAL_UNIPHY2: 66 switch (encoder.enum_id) { 67 case ENUM_ID_1: 68 return TRANSMITTER_UNIPHY_E; 69 case ENUM_ID_2: 70 return TRANSMITTER_UNIPHY_F; 71 default: 72 return TRANSMITTER_UNKNOWN; 73 } 74 break; 75 case ENCODER_ID_INTERNAL_UNIPHY3: 76 switch (encoder.enum_id) { 77 case ENUM_ID_1: 78 return TRANSMITTER_UNIPHY_G; 79 default: 80 return TRANSMITTER_UNKNOWN; 81 } 82 break; 83 case ENCODER_ID_EXTERNAL_NUTMEG: 84 switch (encoder.enum_id) { 85 case ENUM_ID_1: 86 return TRANSMITTER_NUTMEG_CRT; 87 default: 88 return TRANSMITTER_UNKNOWN; 89 } 90 break; 91 case ENCODER_ID_EXTERNAL_TRAVIS: 92 switch (encoder.enum_id) { 93 case ENUM_ID_1: 94 return TRANSMITTER_TRAVIS_CRT; 95 case ENUM_ID_2: 96 return TRANSMITTER_TRAVIS_LCD; 97 default: 98 return TRANSMITTER_UNKNOWN; 99 } 100 break; 101 default: 102 return TRANSMITTER_UNKNOWN; 103 } 104 } 105 106 static void link_destruct(struct dc_link *link) 107 { 108 int i; 109 110 if (link->hpd_gpio) { 111 dal_gpio_destroy_irq(&link->hpd_gpio); 112 link->hpd_gpio = NULL; 113 } 114 115 if (link->ddc) 116 link_destroy_ddc_service(&link->ddc); 117 118 if (link->panel_cntl) 119 link->panel_cntl->funcs->destroy(&link->panel_cntl); 120 121 if (link->link_enc) { 122 /* Update link encoder resource tracking variables. These are used for 123 * the dynamic assignment of link encoders to streams. Virtual links 124 * are not assigned encoder resources on creation. 125 */ 126 if (link->link_id.id != CONNECTOR_ID_VIRTUAL) { 127 link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = NULL; 128 link->dc->res_pool->dig_link_enc_count--; 129 } 130 link->link_enc->funcs->destroy(&link->link_enc); 131 } 132 133 if (link->local_sink) 134 dc_sink_release(link->local_sink); 135 136 for (i = 0; i < link->sink_count; ++i) 137 dc_sink_release(link->remote_sinks[i]); 138 } 139 140 static enum channel_id get_ddc_line(struct dc_link *link) 141 { 142 struct ddc *ddc; 143 enum channel_id channel; 144 145 channel = CHANNEL_ID_UNKNOWN; 146 147 ddc = get_ddc_pin(link->ddc); 148 149 if (ddc) { 150 switch (dal_ddc_get_line(ddc)) { 151 case GPIO_DDC_LINE_DDC1: 152 channel = CHANNEL_ID_DDC1; 153 break; 154 case GPIO_DDC_LINE_DDC2: 155 channel = CHANNEL_ID_DDC2; 156 break; 157 case GPIO_DDC_LINE_DDC3: 158 channel = CHANNEL_ID_DDC3; 159 break; 160 case GPIO_DDC_LINE_DDC4: 161 channel = CHANNEL_ID_DDC4; 162 break; 163 case GPIO_DDC_LINE_DDC5: 164 channel = CHANNEL_ID_DDC5; 165 break; 166 case GPIO_DDC_LINE_DDC6: 167 channel = CHANNEL_ID_DDC6; 168 break; 169 case GPIO_DDC_LINE_DDC_VGA: 170 channel = CHANNEL_ID_DDC_VGA; 171 break; 172 case GPIO_DDC_LINE_I2C_PAD: 173 channel = CHANNEL_ID_I2C_PAD; 174 break; 175 default: 176 BREAK_TO_DEBUGGER(); 177 break; 178 } 179 } 180 181 return channel; 182 } 183 184 static bool dc_link_construct_phy(struct dc_link *link, 185 const struct link_init_data *init_params) 186 { 187 uint8_t i; 188 struct ddc_service_init_data ddc_service_init_data = { 0 }; 189 struct dc_context *dc_ctx = init_params->ctx; 190 struct encoder_init_data enc_init_data = { 0 }; 191 struct panel_cntl_init_data panel_cntl_init_data = { 0 }; 192 struct integrated_info info = { 0 }; 193 struct dc_bios *bios = init_params->dc->ctx->dc_bios; 194 const struct dc_vbios_funcs *bp_funcs = bios->funcs; 195 struct bp_disp_connector_caps_info disp_connect_caps_info = { 0 }; 196 197 DC_LOGGER_INIT(dc_ctx->logger); 198 199 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; 200 link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID; 201 link->link_status.dpcd_caps = &link->dpcd_caps; 202 203 link->dc = init_params->dc; 204 link->ctx = dc_ctx; 205 link->link_index = init_params->link_index; 206 207 memset(&link->preferred_training_settings, 0, 208 sizeof(struct dc_link_training_overrides)); 209 memset(&link->preferred_link_setting, 0, 210 sizeof(struct dc_link_settings)); 211 212 link->link_id = 213 bios->funcs->get_connector_id(bios, init_params->connector_index); 214 215 link->ep_type = DISPLAY_ENDPOINT_PHY; 216 217 DC_LOG_DC("BIOS object table - link_id: %d", link->link_id.id); 218 219 if (bios->funcs->get_disp_connector_caps_info) { 220 bios->funcs->get_disp_connector_caps_info(bios, link->link_id, &disp_connect_caps_info); 221 link->is_internal_display = disp_connect_caps_info.INTERNAL_DISPLAY; 222 DC_LOG_DC("BIOS object table - is_internal_display: %d", link->is_internal_display); 223 } 224 225 if (link->link_id.type != OBJECT_TYPE_CONNECTOR) { 226 dm_output_to_console("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n", 227 __func__, init_params->connector_index, 228 link->link_id.type, OBJECT_TYPE_CONNECTOR); 229 goto create_fail; 230 } 231 232 if (link->dc->res_pool->funcs->link_init) 233 link->dc->res_pool->funcs->link_init(link); 234 235 link->hpd_gpio = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id, 236 link->ctx->gpio_service); 237 238 if (link->hpd_gpio) { 239 dal_gpio_open(link->hpd_gpio, GPIO_MODE_INTERRUPT); 240 dal_gpio_unlock_pin(link->hpd_gpio); 241 link->irq_source_hpd = dal_irq_get_source(link->hpd_gpio); 242 243 DC_LOG_DC("BIOS object table - hpd_gpio id: %d", link->hpd_gpio->id); 244 DC_LOG_DC("BIOS object table - hpd_gpio en: %d", link->hpd_gpio->en); 245 } 246 247 switch (link->link_id.id) { 248 case CONNECTOR_ID_HDMI_TYPE_A: 249 link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A; 250 251 break; 252 case CONNECTOR_ID_SINGLE_LINK_DVID: 253 case CONNECTOR_ID_SINGLE_LINK_DVII: 254 link->connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; 255 break; 256 case CONNECTOR_ID_DUAL_LINK_DVID: 257 case CONNECTOR_ID_DUAL_LINK_DVII: 258 link->connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK; 259 break; 260 case CONNECTOR_ID_DISPLAY_PORT: 261 case CONNECTOR_ID_USBC: 262 link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; 263 264 if (link->hpd_gpio) 265 link->irq_source_hpd_rx = 266 dal_irq_get_rx_source(link->hpd_gpio); 267 268 break; 269 case CONNECTOR_ID_EDP: 270 link->connector_signal = SIGNAL_TYPE_EDP; 271 272 if (link->hpd_gpio) { 273 if (!link->dc->config.allow_edp_hotplug_detection) 274 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; 275 276 switch (link->dc->config.allow_edp_hotplug_detection) { 277 case 1: // only the 1st eDP handles hotplug 278 if (link->link_index == 0) 279 link->irq_source_hpd_rx = 280 dal_irq_get_rx_source(link->hpd_gpio); 281 else 282 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; 283 break; 284 case 2: // only the 2nd eDP handles hotplug 285 if (link->link_index == 1) 286 link->irq_source_hpd_rx = 287 dal_irq_get_rx_source(link->hpd_gpio); 288 else 289 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; 290 break; 291 default: 292 break; 293 } 294 } 295 296 break; 297 case CONNECTOR_ID_LVDS: 298 link->connector_signal = SIGNAL_TYPE_LVDS; 299 break; 300 default: 301 DC_LOG_WARNING("Unsupported Connector type:%d!\n", 302 link->link_id.id); 303 goto create_fail; 304 } 305 306 /* TODO: #DAL3 Implement id to str function.*/ 307 LINK_INFO("Connector[%d] description:" 308 "signal %d\n", 309 init_params->connector_index, 310 link->connector_signal); 311 312 ddc_service_init_data.ctx = link->ctx; 313 ddc_service_init_data.id = link->link_id; 314 ddc_service_init_data.link = link; 315 link->ddc = link_create_ddc_service(&ddc_service_init_data); 316 317 if (!link->ddc) { 318 DC_ERROR("Failed to create ddc_service!\n"); 319 goto ddc_create_fail; 320 } 321 322 if (!link->ddc->ddc_pin) { 323 DC_ERROR("Failed to get I2C info for connector!\n"); 324 goto ddc_create_fail; 325 } 326 327 link->ddc_hw_inst = 328 dal_ddc_get_line(get_ddc_pin(link->ddc)); 329 330 331 if (link->dc->res_pool->funcs->panel_cntl_create && 332 (link->link_id.id == CONNECTOR_ID_EDP || 333 link->link_id.id == CONNECTOR_ID_LVDS)) { 334 panel_cntl_init_data.ctx = dc_ctx; 335 panel_cntl_init_data.inst = 336 panel_cntl_init_data.ctx->dc_edp_id_count; 337 link->panel_cntl = 338 link->dc->res_pool->funcs->panel_cntl_create( 339 &panel_cntl_init_data); 340 panel_cntl_init_data.ctx->dc_edp_id_count++; 341 342 if (link->panel_cntl == NULL) { 343 DC_ERROR("Failed to create link panel_cntl!\n"); 344 goto panel_cntl_create_fail; 345 } 346 } 347 348 enc_init_data.ctx = dc_ctx; 349 bp_funcs->get_src_obj(dc_ctx->dc_bios, link->link_id, 0, 350 &enc_init_data.encoder); 351 enc_init_data.connector = link->link_id; 352 enc_init_data.channel = get_ddc_line(link); 353 enc_init_data.hpd_source = get_hpd_line(link); 354 355 link->hpd_src = enc_init_data.hpd_source; 356 357 enc_init_data.transmitter = 358 translate_encoder_to_transmitter(enc_init_data.encoder); 359 link->link_enc = 360 link->dc->res_pool->funcs->link_enc_create(dc_ctx, &enc_init_data); 361 362 DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C); 363 DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE); 364 365 if (!link->link_enc) { 366 DC_ERROR("Failed to create link encoder!\n"); 367 goto link_enc_create_fail; 368 } 369 370 /* Update link encoder tracking variables. These are used for the dynamic 371 * assignment of link encoders to streams. 372 */ 373 link->eng_id = link->link_enc->preferred_engine; 374 link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = link->link_enc; 375 link->dc->res_pool->dig_link_enc_count++; 376 377 link->link_enc_hw_inst = link->link_enc->transmitter; 378 for (i = 0; i < 4; i++) { 379 if (bp_funcs->get_device_tag(dc_ctx->dc_bios, 380 link->link_id, i, 381 &link->device_tag) != BP_RESULT_OK) { 382 DC_ERROR("Failed to find device tag!\n"); 383 goto device_tag_fail; 384 } 385 386 /* Look for device tag that matches connector signal, 387 * CRT for rgb, LCD for other supported signal tyes 388 */ 389 if (!bp_funcs->is_device_id_supported(dc_ctx->dc_bios, 390 link->device_tag.dev_id)) 391 continue; 392 if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT && 393 link->connector_signal != SIGNAL_TYPE_RGB) 394 continue; 395 if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD && 396 link->connector_signal == SIGNAL_TYPE_RGB) 397 continue; 398 399 DC_LOG_DC("BIOS object table - device_tag.acpi_device: %d", link->device_tag.acpi_device); 400 DC_LOG_DC("BIOS object table - device_tag.dev_id.device_type: %d", link->device_tag.dev_id.device_type); 401 DC_LOG_DC("BIOS object table - device_tag.dev_id.enum_id: %d", link->device_tag.dev_id.enum_id); 402 break; 403 } 404 405 if (bios->integrated_info) 406 info = *bios->integrated_info; 407 408 /* Look for channel mapping corresponding to connector and device tag */ 409 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) { 410 struct external_display_path *path = 411 &info.ext_disp_conn_info.path[i]; 412 413 if (path->device_connector_id.enum_id == link->link_id.enum_id && 414 path->device_connector_id.id == link->link_id.id && 415 path->device_connector_id.type == link->link_id.type) { 416 if (link->device_tag.acpi_device != 0 && 417 path->device_acpi_enum == link->device_tag.acpi_device) { 418 link->ddi_channel_mapping = path->channel_mapping; 419 link->chip_caps = path->caps; 420 DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X", link->ddi_channel_mapping.raw); 421 DC_LOG_DC("BIOS object table - chip_caps: %d", link->chip_caps); 422 } else if (path->device_tag == 423 link->device_tag.dev_id.raw_device_tag) { 424 link->ddi_channel_mapping = path->channel_mapping; 425 link->chip_caps = path->caps; 426 DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X", link->ddi_channel_mapping.raw); 427 DC_LOG_DC("BIOS object table - chip_caps: %d", link->chip_caps); 428 } 429 430 if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) { 431 link->bios_forced_drive_settings.VOLTAGE_SWING = 432 (info.ext_disp_conn_info.fixdpvoltageswing & 0x3); 433 link->bios_forced_drive_settings.PRE_EMPHASIS = 434 ((info.ext_disp_conn_info.fixdpvoltageswing >> 2) & 0x3); 435 } 436 437 break; 438 } 439 } 440 441 if (bios->funcs->get_atom_dc_golden_table) 442 bios->funcs->get_atom_dc_golden_table(bios); 443 444 /* 445 * TODO check if GPIO programmed correctly 446 * 447 * If GPIO isn't programmed correctly HPD might not rise or drain 448 * fast enough, leading to bounces. 449 */ 450 program_hpd_filter(link); 451 452 link->psr_settings.psr_vtotal_control_support = false; 453 link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; 454 455 DC_LOG_DC("BIOS object table - %s finished successfully.\n", __func__); 456 return true; 457 device_tag_fail: 458 link->link_enc->funcs->destroy(&link->link_enc); 459 link_enc_create_fail: 460 if (link->panel_cntl != NULL) 461 link->panel_cntl->funcs->destroy(&link->panel_cntl); 462 panel_cntl_create_fail: 463 link_destroy_ddc_service(&link->ddc); 464 ddc_create_fail: 465 create_fail: 466 467 if (link->hpd_gpio) { 468 dal_gpio_destroy_irq(&link->hpd_gpio); 469 link->hpd_gpio = NULL; 470 } 471 472 DC_LOG_DC("BIOS object table - %s failed.\n", __func__); 473 return false; 474 } 475 476 static bool dc_link_construct_dpia(struct dc_link *link, 477 const struct link_init_data *init_params) 478 { 479 struct ddc_service_init_data ddc_service_init_data = { 0 }; 480 struct dc_context *dc_ctx = init_params->ctx; 481 482 DC_LOGGER_INIT(dc_ctx->logger); 483 484 /* Initialized irq source for hpd and hpd rx */ 485 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; 486 link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID; 487 link->link_status.dpcd_caps = &link->dpcd_caps; 488 489 link->dc = init_params->dc; 490 link->ctx = dc_ctx; 491 link->link_index = init_params->link_index; 492 493 memset(&link->preferred_training_settings, 0, 494 sizeof(struct dc_link_training_overrides)); 495 memset(&link->preferred_link_setting, 0, 496 sizeof(struct dc_link_settings)); 497 498 /* Dummy Init for linkid */ 499 link->link_id.type = OBJECT_TYPE_CONNECTOR; 500 link->link_id.id = CONNECTOR_ID_DISPLAY_PORT; 501 link->link_id.enum_id = ENUM_ID_1 + init_params->connector_index; 502 link->is_internal_display = false; 503 link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; 504 LINK_INFO("Connector[%d] description:signal %d\n", 505 init_params->connector_index, 506 link->connector_signal); 507 508 link->ep_type = DISPLAY_ENDPOINT_USB4_DPIA; 509 link->is_dig_mapping_flexible = true; 510 511 /* TODO: Initialize link : funcs->link_init */ 512 513 ddc_service_init_data.ctx = link->ctx; 514 ddc_service_init_data.id = link->link_id; 515 ddc_service_init_data.link = link; 516 /* Set indicator for dpia link so that ddc wont be created */ 517 ddc_service_init_data.is_dpia_link = true; 518 519 link->ddc = link_create_ddc_service(&ddc_service_init_data); 520 if (!link->ddc) { 521 DC_ERROR("Failed to create ddc_service!\n"); 522 goto ddc_create_fail; 523 } 524 525 /* Set dpia port index : 0 to number of dpia ports */ 526 link->ddc_hw_inst = init_params->connector_index; 527 528 /* TODO: Create link encoder */ 529 530 link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; 531 532 /* Some docks seem to NAK I2C writes to segment pointer with mot=0. */ 533 link->wa_flags.dp_mot_reset_segment = true; 534 535 return true; 536 537 ddc_create_fail: 538 return false; 539 } 540 541 static bool link_construct(struct dc_link *link, 542 const struct link_init_data *init_params) 543 { 544 /* Handle dpia case */ 545 if (init_params->is_dpia_link == true) 546 return dc_link_construct_dpia(link, init_params); 547 else 548 return dc_link_construct_phy(link, init_params); 549 } 550 551 struct dc_link *link_create(const struct link_init_data *init_params) 552 { 553 struct dc_link *link = 554 kzalloc(sizeof(*link), GFP_KERNEL); 555 556 if (NULL == link) 557 goto alloc_fail; 558 559 if (false == link_construct(link, init_params)) 560 goto construct_fail; 561 562 return link; 563 564 construct_fail: 565 kfree(link); 566 567 alloc_fail: 568 return NULL; 569 } 570 571 void link_destroy(struct dc_link **link) 572 { 573 link_destruct(*link); 574 kfree(*link); 575 *link = NULL; 576 } 577 578