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