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 "link_detection.h" 31 #include "link_resource.h" 32 #include "link_validation.h" 33 #include "link_dpms.h" 34 #include "accessories/link_dp_cts.h" 35 #include "accessories/link_dp_trace.h" 36 #include "protocols/link_ddc.h" 37 #include "protocols/link_dp_capability.h" 38 #include "protocols/link_dp_dpia_bw.h" 39 #include "protocols/link_dp_dpia.h" 40 #include "protocols/link_dp_irq_handler.h" 41 #include "protocols/link_dp_phy.h" 42 #include "protocols/link_dp_training.h" 43 #include "protocols/link_edp_panel_control.h" 44 #include "protocols/link_dp_panel_replay.h" 45 #include "protocols/link_hdmi_frl.h" 46 #include "protocols/link_hpd.h" 47 #include "gpio_service_interface.h" 48 #include "atomfirmware.h" 49 50 #define DC_LOGGER \ 51 dc_ctx->logger 52 #define DC_LOGGER_INIT(logger) 53 54 #define LINK_INFO(...) \ 55 DC_LOG_HW_HOTPLUG( \ 56 __VA_ARGS__) 57 58 /* link factory owns the creation/destruction of link structures. */ 59 static void construct_link_service_factory(struct link_service *link_srv) 60 { 61 62 link_srv->create_link = link_create; 63 link_srv->destroy_link = link_destroy; 64 } 65 66 /* link_detection manages link detection states and receiver states by using 67 * various link protocols. It also provides helper functions to interpret 68 * certain capabilities or status based on the states it manages or retrieve 69 * them directly from connected receivers. 70 */ 71 static void construct_link_service_detection(struct link_service *link_srv) 72 { 73 link_srv->detect_link = link_detect; 74 link_srv->detect_connection_type = link_detect_connection_type; 75 link_srv->add_remote_sink = link_add_remote_sink; 76 link_srv->remove_remote_sink = link_remove_remote_sink; 77 link_srv->get_hpd_state = link_get_hpd_state; 78 link_srv->enable_hpd = link_enable_hpd; 79 link_srv->disable_hpd = link_disable_hpd; 80 link_srv->enable_hpd_filter = link_enable_hpd_filter; 81 link_srv->reset_cur_dp_mst_topology = link_reset_cur_dp_mst_topology; 82 link_srv->get_status = link_get_status; 83 link_srv->is_hdcp1x_supported = link_is_hdcp14; 84 link_srv->is_hdcp2x_supported = link_is_hdcp22; 85 link_srv->clear_dprx_states = link_clear_dprx_states; 86 } 87 88 /* link resource implements accessors to link resource. */ 89 static void construct_link_service_resource(struct link_service *link_srv) 90 { 91 link_srv->get_cur_res_map = link_get_cur_res_map; 92 link_srv->restore_res_map = link_restore_res_map; 93 link_srv->get_cur_link_res = link_get_cur_link_res; 94 } 95 96 /* link validation owns timing validation against various link limitations. (ex. 97 * link bandwidth, receiver capability or our hardware capability) It also 98 * provides helper functions exposing bandwidth formulas used in validation. 99 */ 100 static void construct_link_service_validation(struct link_service *link_srv) 101 { 102 link_srv->validate_mode_timing = link_validate_mode_timing; 103 link_srv->dp_link_bandwidth_kbps = dp_link_bandwidth_kbps; 104 link_srv->validate_dp_tunnel_bandwidth = link_validate_dp_tunnel_bandwidth; 105 link_srv->frl_link_bandwidth_kbps = frl_link_bandwidth_kbps; 106 link_srv->frl_margin_check_uncompressed_video = frl_capacity_computations_uncompressed_video; 107 link_srv->dp_required_hblank_size_bytes = dp_required_hblank_size_bytes; 108 } 109 110 /* link dpms owns the programming sequence of stream's dpms state associated 111 * with the link and link's enable/disable sequences as result of the stream's 112 * dpms state change. 113 */ 114 static void construct_link_service_dpms(struct link_service *link_srv) 115 { 116 link_srv->set_dpms_on = link_set_dpms_on; 117 link_srv->set_dpms_off = link_set_dpms_off; 118 link_srv->resume = link_resume; 119 link_srv->blank_all_dp_displays = link_blank_all_dp_displays; 120 link_srv->blank_all_edp_displays = link_blank_all_edp_displays; 121 link_srv->blank_dp_stream = link_blank_dp_stream; 122 link_srv->increase_mst_payload = link_increase_mst_payload; 123 link_srv->reduce_mst_payload = link_reduce_mst_payload; 124 link_srv->set_dsc_on_stream = link_set_dsc_on_stream; 125 link_srv->set_dsc_enable = link_set_dsc_enable; 126 link_srv->update_dsc_config = link_update_dsc_config; 127 link_srv->wait_for_unlocked = link_wait_for_unlocked; 128 } 129 130 /* link ddc implements generic display communication protocols such as i2c, aux 131 * and scdc. It should not contain any specific applications of these 132 * protocols such as display capability query, detection, or handshaking such as 133 * link training. 134 */ 135 static void construct_link_service_ddc(struct link_service *link_srv) 136 { 137 link_srv->create_ddc_service = link_create_ddc_service; 138 link_srv->destroy_ddc_service = link_destroy_ddc_service; 139 link_srv->query_ddc_data = link_query_ddc_data; 140 link_srv->aux_transfer_raw = link_aux_transfer_raw; 141 link_srv->configure_fixed_vs_pe_retimer = link_configure_fixed_vs_pe_retimer; 142 link_srv->aux_transfer_with_retries_no_mutex = 143 link_aux_transfer_with_retries_no_mutex; 144 link_srv->is_in_aux_transaction_mode = link_is_in_aux_transaction_mode; 145 link_srv->get_aux_defer_delay = link_get_aux_defer_delay; 146 } 147 148 /* link dp capability implements dp specific link capability retrieval sequence. 149 * It is responsible for retrieving, parsing, overriding, deciding capability 150 * obtained from dp link. Link capability consists of encoders, DPRXs, cables, 151 * retimers, usb and all other possible backend capabilities. 152 */ 153 static void construct_link_service_dp_capability(struct link_service *link_srv) 154 { 155 link_srv->dp_is_sink_present = dp_is_sink_present; 156 link_srv->dp_is_fec_supported = dp_is_fec_supported; 157 link_srv->dp_is_128b_132b_signal = dp_is_128b_132b_signal; 158 link_srv->dp_get_max_link_enc_cap = dp_get_max_link_enc_cap; 159 link_srv->dp_get_verified_link_cap = dp_get_verified_link_cap; 160 link_srv->dp_get_encoding_format = link_dp_get_encoding_format; 161 link_srv->dp_should_enable_fec = dp_should_enable_fec; 162 link_srv->dp_decide_link_settings = link_decide_link_settings; 163 link_srv->dp_decide_tunnel_settings = link_decide_dp_tunnel_settings; 164 link_srv->mst_decide_link_encoding_format = 165 mst_decide_link_encoding_format; 166 link_srv->edp_decide_link_settings = edp_decide_link_settings; 167 link_srv->bw_kbps_from_raw_frl_link_rate_data = 168 link_bw_kbps_from_raw_frl_link_rate_data; 169 link_srv->dp_overwrite_extended_receiver_cap = 170 dp_overwrite_extended_receiver_cap; 171 link_srv->dp_decide_lttpr_mode = dp_decide_lttpr_mode; 172 link_srv->dp_get_lttpr_count = dp_get_lttpr_count; 173 link_srv->edp_get_alpm_support = edp_get_alpm_support; 174 } 175 176 /* link dp phy/dpia implements basic dp phy/dpia functionality such as 177 * enable/disable output and set lane/drive settings. It is responsible for 178 * maintaining and update software state representing current phy/dpia status 179 * such as current link settings. 180 */ 181 static void construct_link_service_dp_phy_or_dpia(struct link_service *link_srv) 182 { 183 link_srv->dpia_handle_usb4_bandwidth_allocation_for_link = 184 dpia_handle_usb4_bandwidth_allocation_for_link; 185 link_srv->dp_set_drive_settings = dp_set_drive_settings; 186 link_srv->dpcd_write_rx_power_ctrl = dpcd_write_rx_power_ctrl; 187 } 188 189 /* link dp irq handler implements DP HPD short pulse handling sequence according 190 * to DP specifications 191 */ 192 static void construct_link_service_dp_irq_handler(struct link_service *link_srv) 193 { 194 link_srv->dp_parse_link_loss_status = dp_parse_link_loss_status; 195 link_srv->dp_should_allow_hpd_rx_irq = dp_should_allow_hpd_rx_irq; 196 link_srv->dp_handle_link_loss = dp_handle_link_loss; 197 link_srv->dp_read_hpd_rx_irq_data = dp_read_hpd_rx_irq_data; 198 link_srv->dp_handle_hpd_rx_irq = dp_handle_hpd_rx_irq; 199 } 200 201 /* link edp panel control implements retrieval and configuration of eDP panel 202 * features such as PSR and ABM and it also manages specs defined eDP panel 203 * power sequences. 204 */ 205 static void construct_link_service_edp_panel_control(struct link_service *link_srv) 206 { 207 link_srv->edp_panel_backlight_power_on = edp_panel_backlight_power_on; 208 link_srv->edp_get_backlight_level = edp_get_backlight_level; 209 link_srv->edp_get_backlight_level_nits = edp_get_backlight_level_nits; 210 link_srv->edp_set_backlight_level = edp_set_backlight_level; 211 link_srv->edp_set_backlight_level_nits = edp_set_backlight_level_nits; 212 link_srv->edp_get_target_backlight_pwm = edp_get_target_backlight_pwm; 213 link_srv->edp_get_psr_state = edp_get_psr_state; 214 link_srv->edp_set_psr_allow_active = edp_set_psr_allow_active; 215 link_srv->edp_setup_psr = edp_setup_psr; 216 link_srv->edp_set_sink_vtotal_in_psr_active = 217 edp_set_sink_vtotal_in_psr_active; 218 link_srv->edp_get_psr_residency = edp_get_psr_residency; 219 220 link_srv->edp_get_replay_state = edp_get_replay_state; 221 link_srv->edp_set_replay_allow_active = edp_set_replay_allow_active; 222 link_srv->edp_send_replay_cmd = edp_send_replay_cmd; 223 link_srv->edp_set_coasting_vtotal = edp_set_coasting_vtotal; 224 link_srv->edp_replay_residency = edp_replay_residency; 225 link_srv->edp_set_replay_power_opt_and_coasting_vtotal = edp_set_replay_power_opt_and_coasting_vtotal; 226 227 link_srv->edp_wait_for_t12 = edp_wait_for_t12; 228 link_srv->edp_is_ilr_optimization_required = 229 edp_is_ilr_optimization_required; 230 link_srv->edp_backlight_enable_aux = edp_backlight_enable_aux; 231 link_srv->edp_add_delay_for_T9 = edp_add_delay_for_T9; 232 link_srv->edp_receiver_ready_T9 = edp_receiver_ready_T9; 233 link_srv->edp_receiver_ready_T7 = edp_receiver_ready_T7; 234 link_srv->edp_power_alpm_dpcd_enable = edp_power_alpm_dpcd_enable; 235 link_srv->edp_set_panel_power = edp_set_panel_power; 236 } 237 238 /* link dp panel replay implements DP panel replay functionality. 239 */ 240 static void construct_link_service_dp_panel_replay(struct link_service *link_srv) 241 { 242 link_srv->dp_setup_replay = dp_setup_replay; 243 link_srv->dp_pr_get_panel_inst = dp_pr_get_panel_inst; 244 link_srv->dp_pr_enable = dp_pr_enable; 245 link_srv->dp_pr_update_state = dp_pr_update_state; 246 link_srv->dp_pr_set_general_cmd = dp_pr_set_general_cmd; 247 link_srv->dp_pr_get_state = dp_pr_get_state; 248 } 249 250 /* link hdmi frl implements FRL link capability and link training related 251 * functions. FRL link is established by order of retrieve_link, verify_link, 252 * and poll_status. Other helper functions exist to obtain information required 253 * to maintain the correct sequence according to HDMI specification. Each 254 * sequence and state inside link training functions are timing sensitive and order sensitive. 255 * It is mandatory that these functions are debugged with FRL_LTP output message 256 * configurable in DSAT. Any changes in the LT sequence should follow the HDMI 257 * specification as much as possible and tested through HDMI electrical and 258 * link layer compliance. 259 */ 260 static void construct_link_service_hdmi_frl(struct link_service *link_srv) 261 { 262 link_srv->hdmi_frl_poll_status_flag = hdmi_frl_poll_status_flag; 263 link_srv->hdmi_frl_get_verified_link_cap = 264 hdmi_frl_get_verified_link_cap; 265 link_srv->hdmi_frl_set_preferred_link_settings = 266 hdmi_frl_set_preferred_link_settings; 267 } 268 269 /* link dp cts implements dp compliance test automation protocols and manual 270 * testing interfaces for debugging and certification purpose. 271 */ 272 static void construct_link_service_dp_cts(struct link_service *link_srv) 273 { 274 link_srv->dp_handle_automated_test = dp_handle_automated_test; 275 link_srv->dp_set_test_pattern = dp_set_test_pattern; 276 link_srv->dp_set_preferred_link_settings = 277 dp_set_preferred_link_settings; 278 link_srv->dp_set_preferred_training_settings = 279 dp_set_preferred_training_settings; 280 } 281 282 /* link dp trace implements tracing interfaces for tracking major dp sequences 283 * including execution status and timestamps 284 */ 285 static void construct_link_service_dp_trace(struct link_service *link_srv) 286 { 287 link_srv->dp_trace_is_initialized = dp_trace_is_initialized; 288 link_srv->dp_trace_set_is_logged_flag = dp_trace_set_is_logged_flag; 289 link_srv->dp_trace_is_logged = dp_trace_is_logged; 290 link_srv->dp_trace_get_lt_end_timestamp = dp_trace_get_lt_end_timestamp; 291 link_srv->dp_trace_get_lt_counts = dp_trace_get_lt_counts; 292 link_srv->dp_trace_get_link_loss_count = dp_trace_get_link_loss_count; 293 link_srv->dp_trace_set_edp_power_timestamp = 294 dp_trace_set_edp_power_timestamp; 295 link_srv->dp_trace_get_edp_poweron_timestamp = 296 dp_trace_get_edp_poweron_timestamp; 297 link_srv->dp_trace_get_edp_poweroff_timestamp = 298 dp_trace_get_edp_poweroff_timestamp; 299 link_srv->dp_trace_source_sequence = dp_trace_source_sequence; 300 } 301 302 static void construct_link_service(struct link_service *link_srv) 303 { 304 /* All link service functions should fall under some sub categories. 305 * If a new function doesn't perfectly fall under an existing sub 306 * category, it must be that you are either adding a whole new aspect of 307 * responsibility to link service or something doesn't belong to link 308 * service. In that case please contact the arch owner to arrange a 309 * design review meeting. 310 */ 311 construct_link_service_factory(link_srv); 312 construct_link_service_detection(link_srv); 313 construct_link_service_resource(link_srv); 314 construct_link_service_validation(link_srv); 315 construct_link_service_dpms(link_srv); 316 construct_link_service_ddc(link_srv); 317 construct_link_service_dp_capability(link_srv); 318 construct_link_service_dp_phy_or_dpia(link_srv); 319 construct_link_service_dp_irq_handler(link_srv); 320 construct_link_service_edp_panel_control(link_srv); 321 construct_link_service_dp_panel_replay(link_srv); 322 construct_link_service_hdmi_frl(link_srv); 323 construct_link_service_dp_cts(link_srv); 324 construct_link_service_dp_trace(link_srv); 325 } 326 327 struct link_service *link_create_link_service(void) 328 { 329 struct link_service *link_srv = kzalloc_obj(*link_srv); 330 331 if (link_srv == NULL) 332 goto fail; 333 334 construct_link_service(link_srv); 335 336 return link_srv; 337 fail: 338 return NULL; 339 } 340 341 void link_destroy_link_service(struct link_service **link_srv) 342 { 343 kfree(*link_srv); 344 *link_srv = NULL; 345 } 346 347 static enum transmitter translate_encoder_to_transmitter( 348 struct graphics_object_id encoder) 349 { 350 switch (encoder.id) { 351 case ENCODER_ID_INTERNAL_UNIPHY: 352 switch (encoder.enum_id) { 353 case ENUM_ID_1: 354 return TRANSMITTER_UNIPHY_A; 355 case ENUM_ID_2: 356 return TRANSMITTER_UNIPHY_B; 357 default: 358 return TRANSMITTER_UNKNOWN; 359 } 360 break; 361 case ENCODER_ID_INTERNAL_UNIPHY1: 362 switch (encoder.enum_id) { 363 case ENUM_ID_1: 364 return TRANSMITTER_UNIPHY_C; 365 case ENUM_ID_2: 366 return TRANSMITTER_UNIPHY_D; 367 default: 368 return TRANSMITTER_UNKNOWN; 369 } 370 break; 371 case ENCODER_ID_INTERNAL_UNIPHY2: 372 switch (encoder.enum_id) { 373 case ENUM_ID_1: 374 return TRANSMITTER_UNIPHY_E; 375 case ENUM_ID_2: 376 return TRANSMITTER_UNIPHY_F; 377 default: 378 return TRANSMITTER_UNKNOWN; 379 } 380 break; 381 case ENCODER_ID_INTERNAL_UNIPHY3: 382 switch (encoder.enum_id) { 383 case ENUM_ID_1: 384 return TRANSMITTER_UNIPHY_G; 385 default: 386 return TRANSMITTER_UNKNOWN; 387 } 388 break; 389 default: 390 return TRANSMITTER_UNKNOWN; 391 } 392 } 393 394 static bool encoder_is_external_dp( 395 struct graphics_object_id encoder) 396 { 397 switch (encoder.id) { 398 case ENCODER_ID_EXTERNAL_NUTMEG: 399 case ENCODER_ID_EXTERNAL_TRAVIS: 400 return true; 401 default: 402 return false; 403 } 404 } 405 406 static void link_destruct(struct dc_link *link) 407 { 408 unsigned int i; 409 410 if (link->ddc) 411 link_destroy_ddc_service(&link->ddc); 412 413 if (link->panel_cntl) 414 link->panel_cntl->funcs->destroy(&link->panel_cntl); 415 416 if (link->link_enc && !link->is_dig_mapping_flexible) { 417 /* Update link encoder resource tracking variables. These are used for 418 * the dynamic assignment of link encoders to streams. Virtual links 419 * are not assigned encoder resources on creation. 420 */ 421 if (link->link_id.id != CONNECTOR_ID_VIRTUAL && link->eng_id != ENGINE_ID_UNKNOWN) { 422 link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = NULL; 423 link->dc->res_pool->dig_link_enc_count--; 424 } 425 link->link_enc->funcs->destroy(&link->link_enc); 426 } 427 428 if (link->hpo_frl_link_enc) 429 link->hpo_frl_link_enc->funcs->destroy(&link->hpo_frl_link_enc); 430 if (link->local_sink) 431 dc_sink_release(link->local_sink); 432 433 for (i = 0; i < link->sink_count; ++i) 434 dc_sink_release(link->remote_sinks[i]); 435 } 436 437 static enum channel_id get_ddc_line(struct dc_link *link) 438 { 439 struct ddc *ddc; 440 enum channel_id channel; 441 442 channel = CHANNEL_ID_UNKNOWN; 443 444 if (link->ctx->dc->config.dp_connector_no_native_i2c && link->no_ddc_pin) { 445 channel = link->aux_hw_inst + 1; 446 } else { 447 ddc = get_ddc_pin(link->ddc); 448 449 if (ddc) { 450 switch (dal_ddc_get_line(ddc)) { 451 case GPIO_DDC_LINE_DDC1: 452 channel = CHANNEL_ID_DDC1; 453 break; 454 case GPIO_DDC_LINE_DDC2: 455 channel = CHANNEL_ID_DDC2; 456 break; 457 case GPIO_DDC_LINE_DDC3: 458 channel = CHANNEL_ID_DDC3; 459 break; 460 case GPIO_DDC_LINE_DDC4: 461 channel = CHANNEL_ID_DDC4; 462 break; 463 case GPIO_DDC_LINE_DDC5: 464 channel = CHANNEL_ID_DDC5; 465 break; 466 case GPIO_DDC_LINE_DDC6: 467 channel = CHANNEL_ID_DDC6; 468 break; 469 case GPIO_DDC_LINE_DDC_VGA: 470 channel = CHANNEL_ID_DDC_VGA; 471 break; 472 case GPIO_DDC_LINE_I2C_PAD: 473 channel = CHANNEL_ID_I2C_PAD; 474 break; 475 default: 476 BREAK_TO_DEBUGGER(); 477 break; 478 } 479 } 480 } 481 return channel; 482 } 483 484 static enum engine_id find_analog_engine(struct dc_link *link, struct graphics_object_id *enc) 485 { 486 struct dc_bios *bp = link->ctx->dc_bios; 487 enum bp_result bp_result = BP_RESULT_OK; 488 int i; 489 490 for (i = 0; i < 3; i++) { 491 bp_result = bp->funcs->get_src_obj(bp, link->link_id, i, enc); 492 493 if (bp_result != BP_RESULT_OK) 494 return ENGINE_ID_UNKNOWN; 495 496 switch (enc->id) { 497 case ENCODER_ID_INTERNAL_DAC1: 498 case ENCODER_ID_INTERNAL_KLDSCP_DAC1: 499 return ENGINE_ID_DACA; 500 case ENCODER_ID_INTERNAL_DAC2: 501 case ENCODER_ID_INTERNAL_KLDSCP_DAC2: 502 return ENGINE_ID_DACB; 503 } 504 } 505 506 memset(enc, 0, sizeof(*enc)); 507 return ENGINE_ID_UNKNOWN; 508 } 509 510 static bool analog_engine_supported(const enum engine_id engine_id) 511 { 512 return engine_id == ENGINE_ID_DACA || 513 engine_id == ENGINE_ID_DACB; 514 } 515 516 static bool construct_phy(struct dc_link *link, 517 const struct link_init_data *init_params) 518 { 519 uint8_t i; 520 struct ddc_service_init_data ddc_service_init_data = { 0 }; 521 struct dc_context *dc_ctx = init_params->ctx; 522 struct encoder_init_data enc_init_data = { 0 }; 523 struct panel_cntl_init_data panel_cntl_init_data = { 0 }; 524 struct dc_bios *bios = init_params->dc->ctx->dc_bios; 525 const struct dc_vbios_funcs *bp_funcs = bios->funcs; 526 struct bp_disp_connector_caps_info disp_connect_caps_info = { 0 }; 527 struct graphics_object_id link_encoder = { 0 }; 528 enum transmitter transmitter_from_encoder; 529 enum engine_id link_analog_engine; 530 531 DC_LOGGER_INIT(dc_ctx->logger); 532 533 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; 534 link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID; 535 link->irq_source_read_request = DC_IRQ_SOURCE_INVALID; 536 link->link_status.dpcd_caps = &link->dpcd_caps; 537 538 link->dc = init_params->dc; 539 link->ctx = dc_ctx; 540 link->link_index = init_params->link_index; 541 542 memset(&link->preferred_training_settings, 0, 543 sizeof(struct dc_link_training_overrides)); 544 memset(&link->preferred_link_setting, 0, 545 sizeof(struct dc_link_settings)); 546 547 link->link_id = 548 bios->funcs->get_connector_id(bios, (uint8_t)init_params->connector_index); 549 550 link->ep_type = DISPLAY_ENDPOINT_PHY; 551 552 DC_LOG_DC("BIOS object table - link_id: %d", link->link_id.id); 553 554 /* Determine early if the link has any supported encoders, 555 * so that we avoid initializing DDC and HPD, etc. 556 */ 557 bp_funcs->get_src_obj(bios, link->link_id, 0, &link_encoder); 558 559 if (encoder_is_external_dp(link_encoder)) { 560 /* External DP bridge encoders: find the actual link encoder and use that. */ 561 link->ext_enc_id = link_encoder; 562 bp_funcs->get_src_obj(bios, link->ext_enc_id, 0, &link_encoder); 563 } 564 565 transmitter_from_encoder = translate_encoder_to_transmitter(link_encoder); 566 link_analog_engine = find_analog_engine(link, &enc_init_data.analog_encoder); 567 568 if (transmitter_from_encoder == TRANSMITTER_UNKNOWN && 569 !analog_engine_supported(link_analog_engine)) { 570 DC_LOG_WARNING("link_id %d has unsupported encoder\n", link->link_id.id); 571 goto create_fail; 572 } 573 574 if (bios->funcs->get_disp_connector_caps_info) { 575 bios->funcs->get_disp_connector_caps_info(bios, link->link_id, &disp_connect_caps_info); 576 link->is_internal_display = (disp_connect_caps_info.INTERNAL_DISPLAY != 0); 577 DC_LOG_DC("BIOS object table - is_internal_display: %d", link->is_internal_display); 578 link->no_ddc_pin = disp_connect_caps_info.NO_DDC_PIN != 0; 579 } 580 581 if (link->link_id.type != OBJECT_TYPE_CONNECTOR) { 582 dm_output_to_console("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n", 583 __func__, init_params->connector_index, 584 link->link_id.type, OBJECT_TYPE_CONNECTOR); 585 goto create_fail; 586 } 587 588 if (link->dc->res_pool->funcs->link_init) 589 link->dc->res_pool->funcs->link_init(link); 590 591 ddc_service_init_data.ctx = link->ctx; 592 ddc_service_init_data.id = link->link_id; 593 ddc_service_init_data.link = link; 594 link->ddc = link_create_ddc_service(&ddc_service_init_data); 595 596 if (!link->ddc) { 597 DC_ERROR("Failed to create ddc_service!\n"); 598 goto ddc_create_fail; 599 } 600 601 if (link->ctx->dc->config.dp_connector_no_native_i2c && link->no_ddc_pin) { 602 link->ddc_hw_inst = link->aux_hw_inst; 603 } else { 604 /* Embedded display connectors such as LVDS may not have DDC. */ 605 if (!link->ddc->ddc_pin && 606 !dc_is_embedded_signal(link->connector_signal)) { 607 DC_ERROR("Failed to get I2C info for connector!\n"); 608 goto ddc_create_fail; 609 } 610 611 link->ddc_hw_inst = 612 dal_ddc_get_line(get_ddc_pin(link->ddc)); 613 } 614 615 enc_init_data.ctx = dc_ctx; 616 enc_init_data.connector = link->link_id; 617 enc_init_data.channel = get_ddc_line(link); 618 enc_init_data.transmitter = transmitter_from_encoder; 619 enc_init_data.encoder = link_encoder; 620 enc_init_data.analog_engine = link_analog_engine; 621 if (link->ctx->dce_version <= DCN_VERSION_4_01) 622 enc_init_data.hpd_gpio = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id, 623 link->ctx->gpio_service); 624 else 625 enc_init_data.hpd_gpio = NULL; 626 if (enc_init_data.hpd_gpio) { 627 dal_gpio_open(enc_init_data.hpd_gpio, GPIO_MODE_INTERRUPT); 628 dal_gpio_unlock_pin(enc_init_data.hpd_gpio); 629 link->irq_source_hpd = dal_irq_get_source(enc_init_data.hpd_gpio); 630 enc_init_data.hpd_source = get_hpd_line(link); 631 link->hpd_src = enc_init_data.hpd_source; 632 633 DC_LOG_DC("BIOS object table - hpd_gpio id: %d", enc_init_data.hpd_gpio->id); 634 DC_LOG_DC("BIOS object table - hpd_gpio en: %d", enc_init_data.hpd_gpio->en); 635 } else { 636 struct graphics_object_hpd_info hpd_info; 637 638 if (link->ctx->dc_bios->funcs->get_hpd_info(link->ctx->dc_bios, link->link_id, &hpd_info) == BP_RESULT_OK) { 639 link->hpd_src = hpd_info.hpd_int_gpio_uid - 1; 640 link->irq_source_hpd = DC_IRQ_SOURCE_HPD1 + link->hpd_src; 641 enc_init_data.hpd_source = link->hpd_src; 642 DC_LOG_DC("BIOS object table - hpd_int_gpio_uid id: %d", hpd_info.hpd_int_gpio_uid); 643 } else { 644 ASSERT(0); 645 enc_init_data.hpd_source = HPD_SOURCEID_UNKNOWN; 646 } 647 } 648 649 link->link_enc = 650 link->dc->res_pool->funcs->link_enc_create(dc_ctx, &enc_init_data); 651 652 if (!link->link_enc) { 653 DC_ERROR("Failed to create link encoder!\n"); 654 goto link_enc_create_fail; 655 } 656 657 DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C); 658 DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE); 659 DC_LOG_DC("BIOS object table - IS_HDMI_FRL_CAPABLE: %d", link->link_enc->features.flags.bits.IS_HDMI_FRL_CAPABLE); 660 661 switch (link->link_id.id) { 662 case CONNECTOR_ID_HDMI_TYPE_A: 663 link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A; 664 665 if (link->link_enc->hpd_gpio) 666 link->irq_source_read_request = 667 dal_irq_get_read_request(link->link_enc->hpd_gpio); 668 else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) 669 link->irq_source_read_request = DC_IRQ_SOURCE_DCI2C_RR_DDC1 + link->hpd_src; 670 break; 671 case CONNECTOR_ID_SINGLE_LINK_DVID: 672 case CONNECTOR_ID_SINGLE_LINK_DVII: 673 link->connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK; 674 break; 675 case CONNECTOR_ID_DUAL_LINK_DVID: 676 case CONNECTOR_ID_DUAL_LINK_DVII: 677 link->connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK; 678 break; 679 case CONNECTOR_ID_VGA: 680 link->connector_signal = SIGNAL_TYPE_RGB; 681 break; 682 case CONNECTOR_ID_DISPLAY_PORT: 683 case CONNECTOR_ID_MXM: 684 case CONNECTOR_ID_USBC: 685 link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; 686 687 if (link->link_enc->hpd_gpio) 688 link->irq_source_hpd_rx = 689 dal_irq_get_rx_source(link->link_enc->hpd_gpio); 690 else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) 691 link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src; 692 693 break; 694 case CONNECTOR_ID_EDP: 695 // If smartmux is supported, only create the link on the primary eDP. 696 // Dual eDP is not supported with smartmux. 697 if (!(!link->dc->config.smart_mux_version || dc_ctx->dc_edp_id_count == 0)) 698 goto create_fail; 699 700 link->connector_signal = SIGNAL_TYPE_EDP; 701 if (!link->dc->config.allow_edp_hotplug_detection 702 && !is_smartmux_suported(link)) 703 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; 704 705 switch (link->dc->config.allow_edp_hotplug_detection) { 706 case HPD_EN_FOR_ALL_EDP: 707 if (link->link_enc->hpd_gpio) { 708 link->irq_source_hpd_rx = 709 dal_irq_get_rx_source(link->link_enc->hpd_gpio); 710 } else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) { 711 link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src; 712 } 713 break; 714 case HPD_EN_FOR_PRIMARY_EDP_ONLY: 715 if (link->link_index == 0) { 716 if (link->link_enc->hpd_gpio) { 717 link->irq_source_hpd_rx = 718 dal_irq_get_rx_source(link->link_enc->hpd_gpio); 719 } else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) { 720 link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src; 721 } 722 } else 723 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; 724 break; 725 case HPD_EN_FOR_SECONDARY_EDP_ONLY: 726 if (link->link_index == 1) { 727 if (link->link_enc->hpd_gpio) { 728 link->irq_source_hpd_rx = 729 dal_irq_get_rx_source(link->link_enc->hpd_gpio); 730 } else if (link->hpd_src != HPD_SOURCEID_UNKNOWN) { 731 link->irq_source_hpd_rx = DC_IRQ_SOURCE_HPD1RX + link->hpd_src; 732 } 733 } else 734 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; 735 break; 736 default: 737 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; 738 break; 739 } 740 break; 741 case CONNECTOR_ID_LVDS: 742 link->connector_signal = SIGNAL_TYPE_LVDS; 743 break; 744 default: 745 DC_LOG_WARNING("Unsupported Connector type:%d!\n", 746 link->link_id.id); 747 goto create_fail; 748 } 749 750 /* For external DP bridge encoders: 751 * Set the connector signal to DisplayPort so that they can work with 752 * the pre-existing code paths for DP without a lot of code churn. 753 */ 754 if (link->ext_enc_id.id != ENCODER_ID_UNKNOWN) 755 link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; 756 757 LINK_INFO("Connector[%d] description: signal: %s\n", 758 init_params->connector_index, 759 signal_type_to_string(link->connector_signal)); 760 761 /* Update link encoder tracking variables. These are used for the dynamic 762 * assignment of link encoders to streams. 763 */ 764 link->eng_id = link->link_enc->preferred_engine; 765 link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = link->link_enc; 766 link->dc->res_pool->dig_link_enc_count++; 767 768 link->link_enc_hw_inst = link->link_enc->transmitter; 769 770 if (link->dc->res_pool->funcs->panel_cntl_create && 771 (link->link_id.id == CONNECTOR_ID_EDP || 772 link->link_id.id == CONNECTOR_ID_LVDS)) { 773 panel_cntl_init_data.ctx = dc_ctx; 774 panel_cntl_init_data.inst = panel_cntl_init_data.ctx->dc_edp_id_count; 775 panel_cntl_init_data.eng_id = link->eng_id; 776 link->panel_cntl = 777 link->dc->res_pool->funcs->panel_cntl_create( 778 &panel_cntl_init_data); 779 panel_cntl_init_data.ctx->dc_edp_id_count++; 780 781 if (link->panel_cntl == NULL) { 782 DC_ERROR("Failed to create link panel_cntl!\n"); 783 goto panel_cntl_create_fail; 784 } 785 } 786 for (i = 0; i < 4; i++) { 787 if (bp_funcs->get_device_tag(dc_ctx->dc_bios, 788 link->link_id, i, 789 &link->device_tag) != BP_RESULT_OK) { 790 DC_ERROR("Failed to find device tag!\n"); 791 goto device_tag_fail; 792 } 793 794 /* Look for device tag that matches connector signal, 795 * CRT for rgb, LCD for other supported signal types 796 */ 797 if (!bp_funcs->is_device_id_supported(dc_ctx->dc_bios, 798 link->device_tag.dev_id)) 799 continue; 800 if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT && 801 link->connector_signal != SIGNAL_TYPE_RGB && 802 link->ext_enc_id.id == ENCODER_ID_UNKNOWN) 803 continue; 804 if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD && 805 link->connector_signal == SIGNAL_TYPE_RGB) 806 continue; 807 808 DC_LOG_DC("BIOS object table - device_tag.acpi_device: %d", link->device_tag.acpi_device); 809 DC_LOG_DC("BIOS object table - device_tag.dev_id.device_type: %d", link->device_tag.dev_id.device_type); 810 DC_LOG_DC("BIOS object table - device_tag.dev_id.enum_id: %d", link->device_tag.dev_id.enum_id); 811 break; 812 } 813 814 if (bios->integrated_info) { 815 /* Look for channel mapping corresponding to connector and device tag */ 816 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; i++) { 817 struct external_display_path *path = 818 &bios->integrated_info->ext_disp_conn_info.path[i]; 819 820 if (path->device_connector_id.enum_id == link->link_id.enum_id && 821 path->device_connector_id.id == link->link_id.id && 822 path->device_connector_id.type == link->link_id.type) { 823 if (link->device_tag.acpi_device != 0 && 824 path->device_acpi_enum == link->device_tag.acpi_device) { 825 link->ddi_channel_mapping = path->channel_mapping; 826 link->chip_caps = path->caps; 827 DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X", 828 link->ddi_channel_mapping.raw); 829 DC_LOG_DC("BIOS object table - chip_caps: %d", 830 link->chip_caps); 831 } else if (path->device_tag == 832 link->device_tag.dev_id.raw_device_tag) { 833 link->ddi_channel_mapping = path->channel_mapping; 834 link->chip_caps = path->caps; 835 DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X", 836 link->ddi_channel_mapping.raw); 837 DC_LOG_DC("BIOS object table - chip_caps: %d", 838 link->chip_caps); 839 } 840 841 if ((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) { 842 link->bios_forced_drive_settings.VOLTAGE_SWING = 843 (bios->integrated_info->ext_disp_conn_info.fixdpvoltageswing & 0x3); 844 link->bios_forced_drive_settings.PRE_EMPHASIS = 845 ((bios->integrated_info->ext_disp_conn_info.fixdpvoltageswing >> 2) & 0x3); 846 } 847 848 break; 849 } 850 } 851 } 852 if (bios->funcs->get_atom_dc_golden_table) 853 bios->funcs->get_atom_dc_golden_table(bios); 854 855 /* 856 * TODO check if GPIO programmed correctly 857 * 858 * If GPIO isn't programmed correctly HPD might not rise or drain 859 * fast enough, leading to bounces. 860 */ 861 program_hpd_filter(link); 862 863 /* If the connector is HDMI FRL capable, also create an HPO link encoder */ 864 if ((link->link_enc->features.flags.bits.IS_HDMI_FRL_CAPABLE) && 865 (!link->link_enc->features.flags.bits.DP_IS_USB_C) && 866 (link->dc->res_pool->funcs->hpo_frl_link_enc_create)) { 867 enum engine_id hpo_eng_id; 868 hpo_eng_id = ENGINE_ID_HPO_0; 869 870 link->hpo_frl_link_enc = link->dc->res_pool->funcs->hpo_frl_link_enc_create( 871 hpo_eng_id, 872 dc_ctx); 873 if (link->hpo_frl_link_enc == NULL) { 874 DC_ERROR("Failed to create HPO link encoder!\n"); 875 goto hpo_enc_create_fail; 876 } 877 } 878 879 link->psr_settings.psr_vtotal_control_support = false; 880 link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; 881 link->replay_settings.config.replay_version = DC_REPLAY_VERSION_UNSUPPORTED; 882 883 DC_LOG_DC("BIOS object table - %s finished successfully.\n", __func__); 884 return true; 885 hpo_enc_create_fail: 886 device_tag_fail: 887 link_enc_create_fail: 888 panel_cntl_create_fail: 889 ddc_create_fail: 890 create_fail: 891 if (link->ddc) 892 link_destroy_ddc_service(&link->ddc); 893 if (link->panel_cntl) 894 link->panel_cntl->funcs->destroy(&link->panel_cntl); 895 if (link->link_enc) 896 link->link_enc->funcs->destroy(&link->link_enc); 897 898 DC_LOG_DC("BIOS object table - %s failed.\n", __func__); 899 return false; 900 } 901 902 static bool construct_dpia(struct dc_link *link, 903 const struct link_init_data *init_params) 904 { 905 struct ddc_service_init_data ddc_service_init_data = { 0 }; 906 struct dc_context *dc_ctx = init_params->ctx; 907 908 DC_LOGGER_INIT(dc_ctx->logger); 909 910 /* Initialized irq source for hpd and hpd rx */ 911 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; 912 link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID; 913 link->link_status.dpcd_caps = &link->dpcd_caps; 914 915 link->dc = init_params->dc; 916 link->ctx = dc_ctx; 917 link->link_index = init_params->link_index; 918 919 memset(&link->preferred_training_settings, 0, 920 sizeof(struct dc_link_training_overrides)); 921 memset(&link->preferred_link_setting, 0, 922 sizeof(struct dc_link_settings)); 923 924 /* Dummy Init for linkid */ 925 link->link_id.type = OBJECT_TYPE_CONNECTOR; 926 link->link_id.id = CONNECTOR_ID_DISPLAY_PORT; 927 link->link_id.enum_id = ENUM_ID_1 + init_params->connector_index; 928 link->is_internal_display = false; 929 link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; 930 LINK_INFO("Connector[%d] description:signal %d\n", 931 init_params->connector_index, 932 link->connector_signal); 933 934 link->ep_type = DISPLAY_ENDPOINT_USB4_DPIA; 935 link->is_dig_mapping_flexible = true; 936 937 /* TODO: Initialize link : funcs->link_init */ 938 939 ddc_service_init_data.ctx = link->ctx; 940 ddc_service_init_data.id = link->link_id; 941 ddc_service_init_data.link = link; 942 /* Set indicator for dpia link so that ddc wont be created */ 943 ddc_service_init_data.is_dpia_link = true; 944 945 link->ddc = link_create_ddc_service(&ddc_service_init_data); 946 if (!link->ddc) { 947 DC_ERROR("Failed to create ddc_service!\n"); 948 goto ddc_create_fail; 949 } 950 951 /* Set dpia port index : 0 to number of dpia ports */ 952 link->ddc_hw_inst = (uint8_t)init_params->connector_index; 953 954 // Assign Dpia preferred eng_id 955 if (link->dc->res_pool->funcs->get_preferred_eng_id_dpia) 956 link->dpia_preferred_eng_id = link->dc->res_pool->funcs->get_preferred_eng_id_dpia(link->ddc_hw_inst); 957 958 /* TODO: Create link encoder */ 959 960 link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; 961 link->replay_settings.config.replay_version = DC_REPLAY_VERSION_UNSUPPORTED; 962 963 return true; 964 965 ddc_create_fail: 966 return false; 967 } 968 969 static bool link_construct(struct dc_link *link, 970 const struct link_init_data *init_params) 971 { 972 /* Handle dpia case */ 973 if (init_params->is_dpia_link == true) 974 return construct_dpia(link, init_params); 975 else 976 return construct_phy(link, init_params); 977 } 978 979 struct dc_link *link_create(const struct link_init_data *init_params) 980 { 981 struct dc_link *link = kzalloc_obj(*link); 982 983 if (NULL == link) 984 goto alloc_fail; 985 986 if (false == link_construct(link, init_params)) 987 goto construct_fail; 988 989 return link; 990 991 construct_fail: 992 kfree(link); 993 994 alloc_fail: 995 return NULL; 996 } 997 998 void link_destroy(struct dc_link **link) 999 { 1000 link_destruct(*link); 1001 kfree(*link); 1002 *link = NULL; 1003 } 1004