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 #define CTX \ 32 enc10->base.ctx 33 #define DC_LOGGER \ 34 enc10->base.ctx->logger 35 36 #define REG(reg)\ 37 (enc10->link_regs->reg) 38 39 #undef FN 40 #define FN(reg_name, field_name) \ 41 enc10->link_shift->field_name, enc10->link_mask->field_name 42 /* 43 * @brief 44 * Trigger Source Select 45 * ASIC-dependent, actual values for register programming 46 */ 47 #define DCN35_DIG_FE_SOURCE_SELECT_INVALID 0x0 48 #define DCN35_DIG_FE_SOURCE_SELECT_DIGA 0x1 49 #define DCN35_DIG_FE_SOURCE_SELECT_DIGB 0x2 50 #define DCN35_DIG_FE_SOURCE_SELECT_DIGC 0x4 51 #define DCN35_DIG_FE_SOURCE_SELECT_DIGD 0x08 52 #define DCN35_DIG_FE_SOURCE_SELECT_DIGE 0x10 53 54 55 bool dcn35_is_dig_enabled(struct link_encoder *enc) 56 { 57 uint32_t enabled; 58 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 59 60 REG_GET(DIG_BE_CLK_CNTL, DIG_BE_CLK_EN, &enabled); 61 return (enabled == 1); 62 } 63 64 enum signal_type dcn35_get_dig_mode( 65 struct link_encoder *enc) 66 { 67 uint32_t value; 68 struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); 69 70 REG_GET(DIG_BE_CLK_CNTL, DIG_BE_MODE, &value); 71 switch (value) { 72 case 0: 73 return SIGNAL_TYPE_DISPLAY_PORT; 74 case 2: 75 return SIGNAL_TYPE_DVI_SINGLE_LINK; 76 case 3: 77 return SIGNAL_TYPE_HDMI_TYPE_A; 78 case 5: 79 return SIGNAL_TYPE_DISPLAY_PORT_MST; 80 default: 81 return SIGNAL_TYPE_NONE; 82 } 83 return SIGNAL_TYPE_NONE; 84 } 85 86 void 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 120 void dcn35_link_encoder_init(struct link_encoder *enc) 121 { 122 enc32_hw_init(enc); 123 dcn35_link_encoder_set_fgcg(enc, enc->ctx->dc->debug.enable_fine_grain_clock_gating.bits.dio); 124 } 125 126 void 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 133 static 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 = dcn31_link_encoder_enable_dp_output, 141 .enable_dp_mst_output = dcn31_link_encoder_enable_dp_mst_output, 142 .disable_output = dcn31_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 }; 164 165 void dcn35_link_encoder_construct( 166 struct dcn20_link_encoder *enc20, 167 const struct encoder_init_data *init_data, 168 const struct encoder_feature_support *enc_features, 169 const struct dcn10_link_enc_registers *link_regs, 170 const struct dcn10_link_enc_aux_registers *aux_regs, 171 const struct dcn10_link_enc_hpd_registers *hpd_regs, 172 const struct dcn10_link_enc_shift *link_shift, 173 const struct dcn10_link_enc_mask *link_mask) 174 { 175 struct bp_connector_speed_cap_info bp_cap_info = {0}; 176 const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; 177 enum bp_result result = BP_RESULT_OK; 178 struct dcn10_link_encoder *enc10 = &enc20->enc10; 179 180 enc10->base.funcs = &dcn35_link_enc_funcs; 181 enc10->base.ctx = init_data->ctx; 182 enc10->base.id = init_data->encoder; 183 184 enc10->base.hpd_source = init_data->hpd_source; 185 enc10->base.connector = init_data->connector; 186 187 188 enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; 189 190 enc10->base.features = *enc_features; 191 192 enc10->base.transmitter = init_data->transmitter; 193 194 /* set the flag to indicate whether driver poll the I2C data pin 195 * while doing the DP sink detect 196 */ 197 198 /* if (dal_adapter_service_is_feature_supported(as, 199 * FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) 200 * enc10->base.features.flags.bits. 201 * DP_SINK_DETECT_POLL_DATA_PIN = true; 202 */ 203 204 enc10->base.output_signals = 205 SIGNAL_TYPE_DVI_SINGLE_LINK | 206 SIGNAL_TYPE_DVI_DUAL_LINK | 207 SIGNAL_TYPE_LVDS | 208 SIGNAL_TYPE_DISPLAY_PORT | 209 SIGNAL_TYPE_DISPLAY_PORT_MST | 210 SIGNAL_TYPE_EDP | 211 SIGNAL_TYPE_HDMI_TYPE_A; 212 213 enc10->link_regs = link_regs; 214 enc10->aux_regs = aux_regs; 215 enc10->hpd_regs = hpd_regs; 216 enc10->link_shift = link_shift; 217 enc10->link_mask = link_mask; 218 219 switch (enc10->base.transmitter) { 220 case TRANSMITTER_UNIPHY_A: 221 enc10->base.preferred_engine = ENGINE_ID_DIGA; 222 break; 223 case TRANSMITTER_UNIPHY_B: 224 enc10->base.preferred_engine = ENGINE_ID_DIGB; 225 break; 226 case TRANSMITTER_UNIPHY_C: 227 enc10->base.preferred_engine = ENGINE_ID_DIGC; 228 break; 229 case TRANSMITTER_UNIPHY_D: 230 enc10->base.preferred_engine = ENGINE_ID_DIGD; 231 break; 232 case TRANSMITTER_UNIPHY_E: 233 enc10->base.preferred_engine = ENGINE_ID_DIGE; 234 break; 235 default: 236 ASSERT_CRITICAL(false); 237 enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; 238 } 239 240 enc10->base.features.flags.bits.HDMI_6GB_EN = 1; 241 if (enc10->base.connector.id == CONNECTOR_ID_USBC) 242 enc10->base.features.flags.bits.DP_IS_USB_C = 1; 243 244 if (bp_funcs->get_connector_speed_cap_info) 245 result = bp_funcs->get_connector_speed_cap_info(enc10->base.ctx->dc_bios, 246 enc10->base.connector, &bp_cap_info); 247 248 /* Override features with DCE-specific values */ 249 if (result == BP_RESULT_OK) { 250 enc10->base.features.flags.bits.IS_HBR2_CAPABLE = 251 bp_cap_info.DP_HBR2_EN; 252 enc10->base.features.flags.bits.IS_HBR3_CAPABLE = 253 bp_cap_info.DP_HBR3_EN; 254 enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; 255 enc10->base.features.flags.bits.IS_DP2_CAPABLE = 1; 256 enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; 257 enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; 258 enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; 259 if (bp_cap_info.DP_IS_USB_C) { 260 /*BIOS not switch to use CONNECTOR_ID_USBC = 24 yet*/ 261 enc10->base.features.flags.bits.DP_IS_USB_C = 1; 262 } 263 264 } else { 265 DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", 266 __func__, 267 result); 268 } 269 if (enc10->base.ctx->dc->debug.hdmi20_disable) 270 enc10->base.features.flags.bits.HDMI_6GB_EN = 0; 271 272 } 273