FILE
dcn35_dio_link_encoder.c
File preview with syntax highlighting.
linux-6.19.14/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_link_encoder.c
1/* SPDX-License-Identifier: MIT */ 2/* 3 * Copyright 2023 Advanced Micro Devices, Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 * OTHER DEALINGS IN THE SOFTWARE. 22 * 23 */ 24 25#include "reg_helper.h" 26 27#include "core_types.h" 28#include "link_encoder.h" 29#include "dcn31/dcn31_dio_link_encoder.h" 30#include "dcn35_dio_link_encoder.h" 31#include "dc_dmub_srv.h" 32#define CTX \ 33 enc10->base.ctx 34#define DC_LOGGER \ 35 enc10->base.ctx->logger 36 37#define REG(reg)\ 38 (enc10->link_regs->reg) 39 40#undef FN 41#define FN(reg_name, field_name) \ 42 enc10->link_shift->field_name, enc10->link_mask->field_name 43/* 44 * @brief 45 * Trigger Source Select 46 * ASIC-dependent, actual values for register programming 47 */ 48#define DCN35_DIG_FE_SOURCE_SELECT_INVALID 0x0 49#define DCN35_DIG_FE_SOURCE_SELECT_DIGA 0x1 50#define DCN35_DIG_FE_SOURCE_SELECT_DIGB 0x2 51#define DCN35_DIG_FE_SOURCE_SELECT_DIGC 0x4 52#define DCN35_DIG_FE_SOURCE_SELECT_DIGD 0x08 53#define DCN35_DIG_FE_SOURCE_SELECT_DIGE 0x10 54 55 56bool dcn35_is_dig_enabled(struct link_encoder *enc) 57{ 58 uint32_t enabled; 59 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 60 61 REG_GET(DIG_BE_CLK_CNTL, DIG_BE_CLK_EN, &enabled); 62 return (enabled == 1); 63} 64 65enum signal_type dcn35_get_dig_mode( 66 struct link_encoder *enc) 67{ 68 uint32_t value; 69 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 70 71 REG_GET(DIG_BE_CLK_CNTL, DIG_BE_MODE, &value); 72 switch (value) { 73 case 0: 74 return SIGNAL_TYPE_DISPLAY_PORT; 75 case 2: 76 return SIGNAL_TYPE_DVI_SINGLE_LINK; 77 case 3: 78 return SIGNAL_TYPE_HDMI_TYPE_A; 79 case 5: 80 return SIGNAL_TYPE_DISPLAY_PORT_MST; 81 default: 82 return SIGNAL_TYPE_NONE; 83 } 84} 85 86void dcn35_link_encoder_setup( 87 struct link_encoder *enc, 88 enum signal_type signal) 89{ 90 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 91 92 switch (signal) { 93 case SIGNAL_TYPE_EDP: 94 case SIGNAL_TYPE_DISPLAY_PORT: 95 /* DP SST */ 96 REG_UPDATE(DIG_BE_CLK_CNTL, DIG_BE_MODE, 0); 97 break; 98 case SIGNAL_TYPE_DVI_SINGLE_LINK: 99 case SIGNAL_TYPE_DVI_DUAL_LINK: 100 /* TMDS-DVI */ 101 REG_UPDATE(DIG_BE_CLK_CNTL, DIG_BE_MODE, 2); 102 break; 103 case SIGNAL_TYPE_HDMI_TYPE_A: 104 /* TMDS-HDMI */ 105 REG_UPDATE(DIG_BE_CLK_CNTL, DIG_BE_MODE, 3); 106 break; 107 case SIGNAL_TYPE_DISPLAY_PORT_MST: 108 /* DP MST */ 109 REG_UPDATE(DIG_BE_CLK_CNTL, DIG_BE_MODE, 5); 110 break; 111 default: 112 ASSERT_CRITICAL(false); 113 /* invalid mode ! */ 114 break; 115 } 116 REG_UPDATE(DIG_BE_CLK_CNTL, DIG_BE_CLK_EN, 1); 117 118} 119 120void dcn35_link_encoder_init(struct link_encoder *enc) 121{ 122 enc31_hw_init(enc); 123 dcn35_link_encoder_set_fgcg(enc, enc->ctx->dc->debug.enable_fine_grain_clock_gating.bits.dio); 124} 125 126void dcn35_link_encoder_set_fgcg(struct link_encoder *enc, bool enable) 127{ 128 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 129 130 REG_UPDATE(DIO_CLK_CNTL, DIO_FGCG_REP_DIS, !enable); 131} 132 133static const struct link_encoder_funcs dcn35_link_enc_funcs = { 134 .read_state = link_enc2_read_state, 135 .validate_output_with_stream = 136 dcn30_link_encoder_validate_output_with_stream, 137 .hw_init = dcn35_link_encoder_init, 138 .setup = dcn35_link_encoder_setup, 139 .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, 140 .enable_dp_output = dcn35_link_encoder_enable_dp_output, 141 .enable_dp_mst_output = dcn35_link_encoder_enable_dp_mst_output, 142 .disable_output = dcn35_link_encoder_disable_output, 143 .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings, 144 .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern, 145 .update_mst_stream_allocation_table = 146 dcn10_link_encoder_update_mst_stream_allocation_table, 147 .psr_program_dp_dphy_fast_training = 148 dcn10_psr_program_dp_dphy_fast_training, 149 .psr_program_secondary_packet = dcn10_psr_program_secondary_packet, 150 .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe, 151 .enable_hpd = dcn10_link_encoder_enable_hpd, 152 .disable_hpd = dcn10_link_encoder_disable_hpd, 153 .is_dig_enabled = dcn35_is_dig_enabled, 154 .destroy = dcn10_link_encoder_destroy, 155 .fec_set_enable = enc2_fec_set_enable, 156 .fec_set_ready = enc2_fec_set_ready, 157 .fec_is_active = enc2_fec_is_active, 158 .get_dig_frontend = dcn10_get_dig_frontend, 159 .get_dig_mode = dcn35_get_dig_mode, 160 .is_in_alt_mode = dcn31_link_encoder_is_in_alt_mode, 161 .get_max_link_cap = dcn31_link_encoder_get_max_link_cap, 162 .set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux, 163 .enable_dpia_output = dcn35_link_encoder_enable_dpia_output, 164 .disable_dpia_output = dcn35_link_encoder_disable_dpia_output, 165}; 166 167void dcn35_link_encoder_construct( 168 struct dcn20_link_encoder *enc20, 169 const struct encoder_init_data *init_data, 170 const struct encoder_feature_support *enc_features, 171 const struct dcn10_link_enc_registers *link_regs, 172 const struct dcn10_link_enc_aux_registers *aux_regs, 173 const struct dcn10_link_enc_hpd_registers *hpd_regs, 174 const struct dcn10_link_enc_shift *link_shift, 175 const struct dcn10_link_enc_mask *link_mask) 176{ 177 struct bp_connector_speed_cap_info bp_cap_info = {0}; 178 const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; 179 enum bp_result result = BP_RESULT_OK; 180 struct dcn10_link_encoder *enc10 = &enc20->enc10; 181 182 enc10->base.funcs = &dcn35_link_enc_funcs; 183 enc10->base.ctx = init_data->ctx; 184 enc10->base.id = init_data->encoder; 185 186 enc10->base.hpd_source = init_data->hpd_source; 187 enc10->base.connector = init_data->connector; 188 189 enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; 190 191 enc10->base.features = *enc_features; 192 193 if (enc10->base.connector.id == CONNECTOR_ID_USBC) 194 enc10->base.features.flags.bits.DP_IS_USB_C = 1; 195 196 enc10->base.transmitter = init_data->transmitter; 197 198 /* set the flag to indicate whether driver poll the I2C data pin 199 * while doing the DP sink detect 200 */ 201 202/* if (dal_adapter_service_is_feature_supported(as, 203 * FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) 204 * enc10->base.features.flags.bits. 205 * DP_SINK_DETECT_POLL_DATA_PIN = true; 206 */ 207 208 enc10->base.output_signals = 209 SIGNAL_TYPE_DVI_SINGLE_LINK | 210 SIGNAL_TYPE_DVI_DUAL_LINK | 211 SIGNAL_TYPE_LVDS | 212 SIGNAL_TYPE_DISPLAY_PORT | 213 SIGNAL_TYPE_DISPLAY_PORT_MST | 214 SIGNAL_TYPE_EDP | 215 SIGNAL_TYPE_HDMI_TYPE_A; 216 217 enc10->link_regs = link_regs; 218 enc10->aux_regs = aux_regs; 219 enc10->hpd_regs = hpd_regs; 220 enc10->link_shift = link_shift; 221 enc10->link_mask = link_mask; 222 223 switch (enc10->base.transmitter) { 224 case TRANSMITTER_UNIPHY_A: 225 enc10->base.preferred_engine = ENGINE_ID_DIGA; 226 break; 227 case TRANSMITTER_UNIPHY_B: 228 enc10->base.preferred_engine = ENGINE_ID_DIGB; 229 break; 230 case TRANSMITTER_UNIPHY_C: 231 enc10->base.preferred_engine = ENGINE_ID_DIGC; 232 break; 233 case TRANSMITTER_UNIPHY_D: 234 enc10->base.preferred_engine = ENGINE_ID_DIGD; 235 break; 236 case TRANSMITTER_UNIPHY_E: 237 enc10->base.preferred_engine = ENGINE_ID_DIGE; 238 break; 239 default: 240 ASSERT_CRITICAL(false); 241 enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; 242 } 243 244 enc10->base.features.flags.bits.HDMI_6GB_EN = 1; 245 246 if (bp_funcs->get_connector_speed_cap_info) 247 result = bp_funcs->get_connector_speed_cap_info(enc10->base.ctx->dc_bios, 248 enc10->base.connector, &bp_cap_info); 249 250 /* Override features with DCE-specific values */ 251 if (result == BP_RESULT_OK) { 252 enc10->base.features.flags.bits.IS_HBR2_CAPABLE = 253 bp_cap_info.DP_HBR2_EN; 254 enc10->base.features.flags.bits.IS_HBR3_CAPABLE = 255 bp_cap_info.DP_HBR3_EN; 256 enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; 257 enc10->base.features.flags.bits.IS_DP2_CAPABLE = 1; 258 enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; 259 enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; 260 enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; 261 262 } else { 263 DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", 264 __func__, 265 result); 266 } 267 if (enc10->base.ctx->dc->debug.hdmi20_disable) 268 enc10->base.features.flags.bits.HDMI_6GB_EN = 0; 269 270} 271 272/* DPIA equivalent of link_transmitter_control. */ 273static bool link_dpia_control(struct dc_context *dc_ctx, 274 struct dmub_cmd_dig_dpia_control_data *dpia_control) 275{ 276 union dmub_rb_cmd cmd; 277 278 memset(&cmd, 0, sizeof(cmd)); 279 280 cmd.dig1_dpia_control.header.type = DMUB_CMD__DPIA; 281 cmd.dig1_dpia_control.header.sub_type = 282 DMUB_CMD__DPIA_DIG1_DPIA_CONTROL; 283 cmd.dig1_dpia_control.header.payload_bytes = 284 sizeof(cmd.dig1_dpia_control) - 285 sizeof(cmd.dig1_dpia_control.header); 286 287 cmd.dig1_dpia_control.dpia_control = *dpia_control; 288 289 dc_wake_and_execute_dmub_cmd(dc_ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 290 291 return true; 292} 293 294static void link_encoder_disable(struct dcn10_link_encoder *enc10) 295{ 296 /* reset training complete */ 297 REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0); 298} 299 300void dcn35_link_encoder_enable_dp_output( 301 struct link_encoder *enc, 302 const struct dc_link_settings *link_settings, 303 enum clock_source_id clock_source) 304{ 305 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 306 307 if (!enc->ctx->dc->config.unify_link_enc_assignment) 308 dcn31_link_encoder_enable_dp_output(enc, link_settings, clock_source); 309 else { 310 DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); 311 dcn20_link_encoder_enable_dp_output(enc, link_settings, clock_source); 312 } 313} 314 315void dcn35_link_encoder_enable_dp_mst_output( 316 struct link_encoder *enc, 317 const struct dc_link_settings *link_settings, 318 enum clock_source_id clock_source) 319{ 320 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 321 322 if (!enc->ctx->dc->config.unify_link_enc_assignment) 323 dcn31_link_encoder_enable_dp_mst_output(enc, link_settings, clock_source); 324 else { 325 DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); 326 dcn10_link_encoder_enable_dp_mst_output(enc, link_settings, clock_source); 327 } 328} 329 330void dcn35_link_encoder_disable_output( 331 struct link_encoder *enc, 332 enum signal_type signal) 333{ 334 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 335 336 if (!enc->ctx->dc->config.unify_link_enc_assignment) 337 dcn31_link_encoder_disable_output(enc, signal); 338 else { 339 DC_LOG_DEBUG("%s: enc_id(%d)\n", __func__, enc->preferred_engine); 340 dcn10_link_encoder_disable_output(enc, signal); 341 } 342} 343 344void dcn35_link_encoder_enable_dpia_output( 345 struct link_encoder *enc, 346 const struct dc_link_settings *link_settings, 347 uint8_t dpia_id, 348 uint8_t digmode, 349 uint8_t fec_rdy) 350{ 351 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 352 struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; 353 354 enc1_configure_encoder(enc10, link_settings); 355 356 dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_ENABLE; 357 dpia_control.enc_id = enc->preferred_engine; 358 dpia_control.mode_laneset.digmode = digmode; 359 dpia_control.lanenum = (uint8_t)link_settings->lane_count; 360 dpia_control.symclk_10khz = link_settings->link_rate * 361 LINK_RATE_REF_FREQ_IN_KHZ / 10; 362 /* DIG_BE_CNTL.DIG_HPD_SELECT set to 5 (hpdsel - 1) to indicate HPD pin unused by DPIA. */ 363 dpia_control.hpdsel = 6; 364 dpia_control.dpia_id = dpia_id; 365 dpia_control.fec_rdy = fec_rdy; 366 367 DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); 368 link_dpia_control(enc->ctx, &dpia_control); 369} 370 371void dcn35_link_encoder_disable_dpia_output( 372 struct link_encoder *enc, 373 uint8_t dpia_id, 374 uint8_t digmode) 375{ 376 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 377 struct dmub_cmd_dig_dpia_control_data dpia_control = { 0 }; 378 379 if (enc->funcs->is_dig_enabled && !enc->funcs->is_dig_enabled(enc)) 380 return; 381 382 dpia_control.action = (uint8_t)TRANSMITTER_CONTROL_DISABLE; 383 dpia_control.enc_id = enc->preferred_engine; 384 dpia_control.mode_laneset.digmode = digmode; 385 dpia_control.dpia_id = dpia_id; 386 387 DC_LOG_DEBUG("%s: DPIA(%d) - enc_id(%d)\n", __func__, dpia_control.dpia_id, dpia_control.enc_id); 388 link_dpia_control(enc->ctx, &dpia_control); 389 390 link_encoder_disable(enc10); 391}
~/
Read-only file preview.