1 /* 2 * Copyright 2012-15 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 27 #include "reg_helper.h" 28 29 #include "core_types.h" 30 #include "link_encoder.h" 31 #include "dcn31_dio_link_encoder.h" 32 #include "stream_encoder.h" 33 #include "dc_bios_types.h" 34 35 #include "gpio_service_interface.h" 36 37 #include "link_enc_cfg.h" 38 #include "dc_dmub_srv.h" 39 #include "dal_asic_id.h" 40 #include "link.h" 41 42 #define CTX \ 43 enc10->base.ctx 44 #define DC_LOGGER \ 45 enc10->base.ctx->logger 46 47 #define REG(reg)\ 48 (enc10->link_regs->reg) 49 50 #undef FN 51 #define FN(reg_name, field_name) \ 52 enc10->link_shift->field_name, enc10->link_mask->field_name 53 54 #define IND_REG(index) \ 55 (enc10->link_regs->index) 56 57 #define AUX_REG(reg)\ 58 (enc10->aux_regs->reg) 59 60 #define AUX_REG_READ(reg_name) \ 61 dm_read_reg(CTX, AUX_REG(reg_name)) 62 63 #define AUX_REG_WRITE(reg_name, val) \ 64 dm_write_reg(CTX, AUX_REG(reg_name), val) 65 66 #ifndef MIN 67 #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) 68 #endif 69 70 static uint8_t phy_id_from_transmitter(enum transmitter t) 71 { 72 uint8_t phy_id; 73 74 switch (t) { 75 case TRANSMITTER_UNIPHY_A: 76 phy_id = 0; 77 break; 78 case TRANSMITTER_UNIPHY_B: 79 phy_id = 1; 80 break; 81 case TRANSMITTER_UNIPHY_C: 82 phy_id = 2; 83 break; 84 case TRANSMITTER_UNIPHY_D: 85 phy_id = 3; 86 break; 87 case TRANSMITTER_UNIPHY_E: 88 phy_id = 4; 89 break; 90 case TRANSMITTER_UNIPHY_F: 91 phy_id = 5; 92 break; 93 case TRANSMITTER_UNIPHY_G: 94 phy_id = 6; 95 break; 96 default: 97 phy_id = 0; 98 break; 99 } 100 return phy_id; 101 } 102 103 static bool has_query_dp_alt(struct link_encoder *enc) 104 { 105 struct dc_dmub_srv *dc_dmub_srv = enc->ctx->dmub_srv; 106 107 if (enc->ctx->dce_version >= DCN_VERSION_3_15) 108 return true; 109 110 /* Supports development firmware and firmware >= 4.0.11 */ 111 return dc_dmub_srv && 112 !(dc_dmub_srv->dmub->fw_version >= DMUB_FW_VERSION(4, 0, 0) && 113 dc_dmub_srv->dmub->fw_version <= DMUB_FW_VERSION(4, 0, 10)); 114 } 115 116 static bool query_dp_alt_from_dmub(struct link_encoder *enc, 117 union dmub_rb_cmd *cmd) 118 { 119 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 120 struct dc_dmub_srv *dc_dmub_srv = enc->ctx->dmub_srv; 121 122 memset(cmd, 0, sizeof(*cmd)); 123 cmd->query_dp_alt.header.type = DMUB_CMD__VBIOS; 124 cmd->query_dp_alt.header.sub_type = 125 DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT; 126 cmd->query_dp_alt.header.payload_bytes = sizeof(cmd->query_dp_alt.data); 127 cmd->query_dp_alt.data.phy_id = phy_id_from_transmitter(enc10->base.transmitter); 128 129 if (!dc_dmub_srv_cmd_with_reply_data(dc_dmub_srv, cmd)) 130 return false; 131 132 return true; 133 } 134 135 void dcn31_link_encoder_set_dio_phy_mux( 136 struct link_encoder *enc, 137 enum encoder_type_select sel, 138 uint32_t hpo_inst) 139 { 140 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 141 142 switch (enc->transmitter) { 143 case TRANSMITTER_UNIPHY_A: 144 if (sel == ENCODER_TYPE_HDMI_FRL) 145 REG_UPDATE(DIO_LINKA_CNTL, 146 HPO_HDMI_ENC_SEL, hpo_inst); 147 else if (sel == ENCODER_TYPE_DP_128B132B) 148 REG_UPDATE(DIO_LINKA_CNTL, 149 HPO_DP_ENC_SEL, hpo_inst); 150 REG_UPDATE(DIO_LINKA_CNTL, 151 ENC_TYPE_SEL, sel); 152 break; 153 case TRANSMITTER_UNIPHY_B: 154 if (sel == ENCODER_TYPE_HDMI_FRL) 155 REG_UPDATE(DIO_LINKB_CNTL, 156 HPO_HDMI_ENC_SEL, hpo_inst); 157 else if (sel == ENCODER_TYPE_DP_128B132B) 158 REG_UPDATE(DIO_LINKB_CNTL, 159 HPO_DP_ENC_SEL, hpo_inst); 160 REG_UPDATE(DIO_LINKB_CNTL, 161 ENC_TYPE_SEL, sel); 162 break; 163 case TRANSMITTER_UNIPHY_C: 164 if (sel == ENCODER_TYPE_HDMI_FRL) 165 REG_UPDATE(DIO_LINKC_CNTL, 166 HPO_HDMI_ENC_SEL, hpo_inst); 167 else if (sel == ENCODER_TYPE_DP_128B132B) 168 REG_UPDATE(DIO_LINKC_CNTL, 169 HPO_DP_ENC_SEL, hpo_inst); 170 REG_UPDATE(DIO_LINKC_CNTL, 171 ENC_TYPE_SEL, sel); 172 break; 173 case TRANSMITTER_UNIPHY_D: 174 if (sel == ENCODER_TYPE_HDMI_FRL) 175 REG_UPDATE(DIO_LINKD_CNTL, 176 HPO_HDMI_ENC_SEL, hpo_inst); 177 else if (sel == ENCODER_TYPE_DP_128B132B) 178 REG_UPDATE(DIO_LINKD_CNTL, 179 HPO_DP_ENC_SEL, hpo_inst); 180 REG_UPDATE(DIO_LINKD_CNTL, 181 ENC_TYPE_SEL, sel); 182 break; 183 case TRANSMITTER_UNIPHY_E: 184 if (sel == ENCODER_TYPE_HDMI_FRL) 185 REG_UPDATE(DIO_LINKE_CNTL, 186 HPO_HDMI_ENC_SEL, hpo_inst); 187 else if (sel == ENCODER_TYPE_DP_128B132B) 188 REG_UPDATE(DIO_LINKE_CNTL, 189 HPO_DP_ENC_SEL, hpo_inst); 190 REG_UPDATE(DIO_LINKE_CNTL, 191 ENC_TYPE_SEL, sel); 192 break; 193 case TRANSMITTER_UNIPHY_F: 194 if (sel == ENCODER_TYPE_HDMI_FRL) 195 REG_UPDATE(DIO_LINKF_CNTL, 196 HPO_HDMI_ENC_SEL, hpo_inst); 197 else if (sel == ENCODER_TYPE_DP_128B132B) 198 REG_UPDATE(DIO_LINKF_CNTL, 199 HPO_DP_ENC_SEL, hpo_inst); 200 REG_UPDATE(DIO_LINKF_CNTL, 201 ENC_TYPE_SEL, sel); 202 break; 203 default: 204 /* Do nothing */ 205 break; 206 } 207 } 208 209 static void enc31_hw_init(struct link_encoder *enc) 210 { 211 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 212 213 /* 214 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 215 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 216 02 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8 : 7/8 217 03 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16 : 15/16 218 04 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32 : 31/32 219 05 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64 : 63/64 220 06 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128 : 127/128 221 07 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256 : 255/256 222 */ 223 224 /* 225 AUX_REG_UPDATE_5(AUX_DPHY_RX_CONTROL0, 226 AUX_RX_START_WINDOW = 1 [6:4] 227 AUX_RX_RECEIVE_WINDOW = 1 default is 2 [10:8] 228 AUX_RX_HALF_SYM_DETECT_LEN = 1 [13:12] default is 1 229 AUX_RX_TRANSITION_FILTER_EN = 1 [16] default is 1 230 AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT [17] is 0 default is 0 231 AUX_RX_ALLOW_BELOW_THRESHOLD_START [18] is 1 default is 1 232 AUX_RX_ALLOW_BELOW_THRESHOLD_STOP [19] is 1 default is 1 233 AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 234 AUX_RX_DETECTION_THRESHOLD [30:28] = 1 235 */ 236 // dmub will read AUX_DPHY_RX_CONTROL0/AUX_DPHY_TX_CONTROL from vbios table in dp_aux_init 237 238 //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; 239 // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk 240 // 27MHz -> 0xd 241 // 100MHz -> 0x32 242 // 48MHz -> 0x18 243 244 // Set TMDS_CTL0 to 1. This is a legacy setting. 245 REG_UPDATE(TMDS_CTL_BITS, TMDS_CTL0, 1); 246 247 dcn10_aux_initialize(enc10); 248 } 249 250 static const struct link_encoder_funcs dcn31_link_enc_funcs = { 251 .read_state = link_enc2_read_state, 252 .validate_output_with_stream = 253 dcn30_link_encoder_validate_output_with_stream, 254 .hw_init = enc31_hw_init, 255 .setup = dcn10_link_encoder_setup, 256 .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, 257 .enable_dp_output = dcn31_link_encoder_enable_dp_output, 258 .enable_dp_mst_output = dcn31_link_encoder_enable_dp_mst_output, 259 .disable_output = dcn31_link_encoder_disable_output, 260 .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, 261 .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, 262 .update_mst_stream_allocation_table = 263 dcn10_link_encoder_update_mst_stream_allocation_table, 264 .psr_program_dp_dphy_fast_training = 265 dcn10_psr_program_dp_dphy_fast_training, 266 .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, 267 .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, 268 .enable_hpd = dcn10_link_encoder_enable_hpd, 269 .disable_hpd = dcn10_link_encoder_disable_hpd, 270 .is_dig_enabled = dcn10_is_dig_enabled, 271 .destroy = dcn10_link_encoder_destroy, 272 .fec_set_enable = enc2_fec_set_enable, 273 .fec_set_ready = enc2_fec_set_ready, 274 .fec_is_active = enc2_fec_is_active, 275 .get_dig_frontend = dcn10_get_dig_frontend, 276 .get_dig_mode = dcn10_get_dig_mode, 277 .is_in_alt_mode = dcn31_link_encoder_is_in_alt_mode, 278 .get_max_link_cap = dcn31_link_encoder_get_max_link_cap, 279 .set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux, 280 }; 281 282 void dcn31_link_encoder_construct( 283 struct dcn20_link_encoder *enc20, 284 const struct encoder_init_data *init_data, 285 const struct encoder_feature_support *enc_features, 286 const struct dcn10_link_enc_registers *link_regs, 287 const struct dcn10_link_enc_aux_registers *aux_regs, 288 const struct dcn10_link_enc_hpd_registers *hpd_regs, 289 const struct dcn10_link_enc_shift *link_shift, 290 const struct dcn10_link_enc_mask *link_mask) 291 { 292 struct bp_encoder_cap_info bp_cap_info = {0}; 293 const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; 294 enum bp_result result = BP_RESULT_OK; 295 struct dcn10_link_encoder *enc10 = &enc20->enc10; 296 297 enc10->base.funcs = &dcn31_link_enc_funcs; 298 enc10->base.ctx = init_data->ctx; 299 enc10->base.id = init_data->encoder; 300 301 enc10->base.hpd_source = init_data->hpd_source; 302 enc10->base.connector = init_data->connector; 303 304 enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; 305 306 enc10->base.features = *enc_features; 307 308 enc10->base.transmitter = init_data->transmitter; 309 310 /* set the flag to indicate whether driver poll the I2C data pin 311 * while doing the DP sink detect 312 */ 313 314 /* if (dal_adapter_service_is_feature_supported(as, 315 FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) 316 enc10->base.features.flags.bits. 317 DP_SINK_DETECT_POLL_DATA_PIN = true;*/ 318 319 enc10->base.output_signals = 320 SIGNAL_TYPE_DVI_SINGLE_LINK | 321 SIGNAL_TYPE_DVI_DUAL_LINK | 322 SIGNAL_TYPE_LVDS | 323 SIGNAL_TYPE_DISPLAY_PORT | 324 SIGNAL_TYPE_DISPLAY_PORT_MST | 325 SIGNAL_TYPE_EDP | 326 SIGNAL_TYPE_HDMI_TYPE_A; 327 328 /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. 329 * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. 330 * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer 331 * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. 332 * Prefer DIG assignment is decided by board design. 333 * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design 334 * and VBIOS will filter out 7 UNIPHY for DCE 8.0. 335 * By this, adding DIGG should not hurt DCE 8.0. 336 * This will let DCE 8.1 share DCE 8.0 as much as possible 337 */ 338 339 enc10->link_regs = link_regs; 340 enc10->aux_regs = aux_regs; 341 enc10->hpd_regs = hpd_regs; 342 enc10->link_shift = link_shift; 343 enc10->link_mask = link_mask; 344 345 switch (enc10->base.transmitter) { 346 case TRANSMITTER_UNIPHY_A: 347 enc10->base.preferred_engine = ENGINE_ID_DIGA; 348 break; 349 case TRANSMITTER_UNIPHY_B: 350 enc10->base.preferred_engine = ENGINE_ID_DIGB; 351 break; 352 case TRANSMITTER_UNIPHY_C: 353 enc10->base.preferred_engine = ENGINE_ID_DIGC; 354 break; 355 case TRANSMITTER_UNIPHY_D: 356 enc10->base.preferred_engine = ENGINE_ID_DIGD; 357 break; 358 case TRANSMITTER_UNIPHY_E: 359 enc10->base.preferred_engine = ENGINE_ID_DIGE; 360 break; 361 case TRANSMITTER_UNIPHY_F: 362 enc10->base.preferred_engine = ENGINE_ID_DIGF; 363 break; 364 default: 365 ASSERT_CRITICAL(false); 366 enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; 367 } 368 369 /* default to one to mirror Windows behavior */ 370 enc10->base.features.flags.bits.HDMI_6GB_EN = 1; 371 372 result = bp_funcs->get_encoder_cap_info(enc10->base.ctx->dc_bios, 373 enc10->base.id, &bp_cap_info); 374 375 /* Override features with DCE-specific values */ 376 if (result == BP_RESULT_OK) { 377 enc10->base.features.flags.bits.IS_HBR2_CAPABLE = 378 bp_cap_info.DP_HBR2_EN; 379 enc10->base.features.flags.bits.IS_HBR3_CAPABLE = 380 bp_cap_info.DP_HBR3_EN; 381 enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; 382 enc10->base.features.flags.bits.IS_DP2_CAPABLE = bp_cap_info.IS_DP2_CAPABLE; 383 enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; 384 enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; 385 enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; 386 enc10->base.features.flags.bits.DP_IS_USB_C = 387 bp_cap_info.DP_IS_USB_C; 388 } else { 389 DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", 390 __func__, 391 result); 392 } 393 if (enc10->base.ctx->dc->debug.hdmi20_disable) { 394 enc10->base.features.flags.bits.HDMI_6GB_EN = 0; 395 } 396 } 397 398 void dcn31_link_encoder_construct_minimal( 399 struct dcn20_link_encoder *enc20, 400 struct dc_context *ctx, 401 const struct encoder_feature_support *enc_features, 402 const struct dcn10_link_enc_registers *link_regs, 403 enum engine_id eng_id) 404 { 405 struct dcn10_link_encoder *enc10 = &enc20->enc10; 406 407 enc10->base.funcs = &dcn31_link_enc_funcs; 408 enc10->base.ctx = ctx; 409 enc10->base.id.type = OBJECT_TYPE_ENCODER; 410 enc10->base.hpd_source = HPD_SOURCEID_UNKNOWN; 411 enc10->base.connector.type = OBJECT_TYPE_CONNECTOR; 412 enc10->base.preferred_engine = eng_id; 413 enc10->base.features = *enc_features; 414 enc10->base.transmitter = TRANSMITTER_UNKNOWN; 415 enc10->link_regs = link_regs; 416 417 enc10->base.output_signals = 418 SIGNAL_TYPE_DISPLAY_PORT | 419 SIGNAL_TYPE_DISPLAY_PORT_MST | 420 SIGNAL_TYPE_EDP; 421 } 422 423 /* DPIA equivalent of link_transmitter_control. */ 424 static bool link_dpia_control(struct dc_context *dc_ctx, 425 struct dmub_cmd_dig_dpia_control_data *dpia_control) 426 { 427 union dmub_rb_cmd cmd; 428 struct dc_dmub_srv *dmub = dc_ctx->dmub_srv; 429 430 memset(&cmd, 0, sizeof(cmd)); 431 432 cmd.dig1_dpia_control.header.type = DMUB_CMD__DPIA; 433 cmd.dig1_dpia_control.header.sub_type = 434 DMUB_CMD__DPIA_DIG1_DPIA_CONTROL; 435 cmd.dig1_dpia_control.header.payload_bytes = 436 sizeof(cmd.dig1_dpia_control) - 437 sizeof(cmd.dig1_dpia_control.header); 438 439 cmd.dig1_dpia_control.dpia_control = *dpia_control; 440 441 dc_dmub_srv_cmd_queue(dmub, &cmd); 442 dc_dmub_srv_cmd_execute(dmub); 443 dc_dmub_srv_wait_idle(dmub); 444 445 return true; 446 } 447 448 static void link_encoder_disable(struct dcn10_link_encoder *enc10) 449 { 450 /* reset training complete */ 451 REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0); 452 } 453 454 void dcn31_link_encoder_enable_dp_output( 455 struct link_encoder *enc, 456 const struct dc_link_settings *link_settings, 457 enum clock_source_id clock_source) 458 { 459 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 460 461 /* Enable transmitter and encoder. */ 462 if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { 463 464 DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); 465 dcn20_link_encoder_enable_dp_output(enc, link_settings, clock_source); 466 467 } else { 468 469 struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; 470 struct dc_link *link; 471 472 link = link_enc_cfg_get_link_using_link_enc(enc->ctx->dc, enc->preferred_engine); 473 474 enc1_configure_encoder(enc10, link_settings); 475 476 dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_ENABLE; 477 dpia_control.enc_id = enc->preferred_engine; 478 dpia_control.mode_laneset.digmode = 0; /* 0 for SST; 5 for MST */ 479 dpia_control.lanenum = (uint8_t)link_settings->lane_count; 480 dpia_control.symclk_10khz = link_settings->link_rate * 481 LINK_RATE_REF_FREQ_IN_KHZ / 10; 482 /* DIG_BE_CNTL.DIG_HPD_SELECT set to 5 (hpdsel - 1) to indicate HPD pin 483 * unused by DPIA. 484 */ 485 dpia_control.hpdsel = 6; 486 487 if (link) { 488 dpia_control.dpia_id = link->ddc_hw_inst; 489 dpia_control.fec_rdy = link->dc->link_srv->dp_should_enable_fec(link); 490 } else { 491 DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__); 492 BREAK_TO_DEBUGGER(); 493 return; 494 } 495 496 DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); 497 link_dpia_control(enc->ctx, &dpia_control); 498 } 499 } 500 501 void dcn31_link_encoder_enable_dp_mst_output( 502 struct link_encoder *enc, 503 const struct dc_link_settings *link_settings, 504 enum clock_source_id clock_source) 505 { 506 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 507 508 /* Enable transmitter and encoder. */ 509 if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { 510 511 DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); 512 dcn10_link_encoder_enable_dp_mst_output(enc, link_settings, clock_source); 513 514 } else { 515 516 struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; 517 struct dc_link *link; 518 519 link = link_enc_cfg_get_link_using_link_enc(enc->ctx->dc, enc->preferred_engine); 520 521 enc1_configure_encoder(enc10, link_settings); 522 523 dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_ENABLE; 524 dpia_control.enc_id = enc->preferred_engine; 525 dpia_control.mode_laneset.digmode = 5; /* 0 for SST; 5 for MST */ 526 dpia_control.lanenum = (uint8_t)link_settings->lane_count; 527 dpia_control.symclk_10khz = link_settings->link_rate * 528 LINK_RATE_REF_FREQ_IN_KHZ / 10; 529 /* DIG_BE_CNTL.DIG_HPD_SELECT set to 5 (hpdsel - 1) to indicate HPD pin 530 * unused by DPIA. 531 */ 532 dpia_control.hpdsel = 6; 533 534 if (link) { 535 dpia_control.dpia_id = link->ddc_hw_inst; 536 dpia_control.fec_rdy = link->dc->link_srv->dp_should_enable_fec(link); 537 } else { 538 DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__); 539 BREAK_TO_DEBUGGER(); 540 return; 541 } 542 543 DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); 544 link_dpia_control(enc->ctx, &dpia_control); 545 } 546 } 547 548 void dcn31_link_encoder_disable_output( 549 struct link_encoder *enc, 550 enum signal_type signal) 551 { 552 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 553 554 /* Disable transmitter and encoder. */ 555 if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { 556 557 DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); 558 dcn10_link_encoder_disable_output(enc, signal); 559 560 } else { 561 562 struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; 563 struct dc_link *link; 564 565 if (!dcn10_is_dig_enabled(enc)) 566 return; 567 568 link = link_enc_cfg_get_link_using_link_enc(enc->ctx->dc, enc->preferred_engine); 569 570 dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_DISABLE; 571 dpia_control.enc_id = enc->preferred_engine; 572 if (signal == SIGNAL_TYPE_DISPLAY_PORT) { 573 dpia_control.mode_laneset.digmode = 0; /* 0 for SST; 5 for MST */ 574 } else if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { 575 dpia_control.mode_laneset.digmode = 5; /* 0 for SST; 5 for MST */ 576 } else { 577 DC_LOG_ERROR("%s: USB4 DPIA only supports DisplayPort.\n", __func__); 578 BREAK_TO_DEBUGGER(); 579 } 580 581 if (link) { 582 dpia_control.dpia_id = link->ddc_hw_inst; 583 } else { 584 DC_LOG_ERROR("%s: Failed to execute DPIA enable DMUB command.\n", __func__); 585 BREAK_TO_DEBUGGER(); 586 return; 587 } 588 589 DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); 590 link_dpia_control(enc->ctx, &dpia_control); 591 592 link_encoder_disable(enc10); 593 } 594 } 595 596 bool dcn31_link_encoder_is_in_alt_mode(struct link_encoder *enc) 597 { 598 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 599 union dmub_rb_cmd cmd; 600 uint32_t dp_alt_mode_disable; 601 602 /* Only applicable to USB-C PHY. */ 603 if (!enc->features.flags.bits.DP_IS_USB_C) 604 return false; 605 606 /* 607 * Use the new interface from DMCUB if available. 608 * Avoids hanging the RDCPSPIPE if DMCUB wasn't already running. 609 */ 610 if (has_query_dp_alt(enc)) { 611 if (!query_dp_alt_from_dmub(enc, &cmd)) 612 return false; 613 614 return (cmd.query_dp_alt.data.is_dp_alt_disable == 0); 615 } 616 617 /* Legacy path, avoid if possible. */ 618 if (enc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_B0) { 619 REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, 620 &dp_alt_mode_disable); 621 } else { 622 /* 623 * B0 phys use a new set of registers to check whether alt mode is disabled. 624 * if value == 1 alt mode is disabled, otherwise it is enabled. 625 */ 626 if ((enc10->base.transmitter == TRANSMITTER_UNIPHY_A) || 627 (enc10->base.transmitter == TRANSMITTER_UNIPHY_B) || 628 (enc10->base.transmitter == TRANSMITTER_UNIPHY_E)) { 629 REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, 630 &dp_alt_mode_disable); 631 } else { 632 REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, 633 &dp_alt_mode_disable); 634 } 635 } 636 637 return (dp_alt_mode_disable == 0); 638 } 639 640 void dcn31_link_encoder_get_max_link_cap(struct link_encoder *enc, struct dc_link_settings *link_settings) 641 { 642 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 643 union dmub_rb_cmd cmd; 644 uint32_t is_in_usb_c_dp4_mode = 0; 645 646 dcn10_link_encoder_get_max_link_cap(enc, link_settings); 647 648 /* Take the link cap directly if not USB */ 649 if (!enc->features.flags.bits.DP_IS_USB_C) 650 return; 651 652 /* 653 * Use the new interface from DMCUB if available. 654 * Avoids hanging the RDCPSPIPE if DMCUB wasn't already running. 655 */ 656 if (has_query_dp_alt(enc)) { 657 if (!query_dp_alt_from_dmub(enc, &cmd)) 658 return; 659 660 if (cmd.query_dp_alt.data.is_usb && 661 cmd.query_dp_alt.data.is_dp4 == 0) 662 link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count); 663 664 return; 665 } 666 667 /* Legacy path, avoid if possible. */ 668 if (enc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_B0) { 669 REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, 670 &is_in_usb_c_dp4_mode); 671 } else { 672 if ((enc10->base.transmitter == TRANSMITTER_UNIPHY_A) || 673 (enc10->base.transmitter == TRANSMITTER_UNIPHY_B) || 674 (enc10->base.transmitter == TRANSMITTER_UNIPHY_E)) { 675 REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, 676 &is_in_usb_c_dp4_mode); 677 } else { 678 REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, 679 &is_in_usb_c_dp4_mode); 680 } 681 } 682 683 if (!is_in_usb_c_dp4_mode) 684 link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count); 685 } 686