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 55bool 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 64enum 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 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 enc32_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 = 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 165void 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 if (enc10->base.connector.id == CONNECTOR_ID_USBC) 188 enc10->base.features.flags.bits.DP_IS_USB_C = 1; 189 190 enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; 191 192 enc10->base.features = *enc_features; 193 194 enc10->base.transmitter = init_data->transmitter; 195 196 /* set the flag to indicate whether driver poll the I2C data pin 197 * while doing the DP sink detect 198 */ 199 200/* if (dal_adapter_service_is_feature_supported(as, 201 * FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) 202 * enc10->base.features.flags.bits. 203 * DP_SINK_DETECT_POLL_DATA_PIN = true; 204 */ 205 206 enc10->base.output_signals = 207 SIGNAL_TYPE_DVI_SINGLE_LINK | 208 SIGNAL_TYPE_DVI_DUAL_LINK | 209 SIGNAL_TYPE_LVDS | 210 SIGNAL_TYPE_DISPLAY_PORT | 211 SIGNAL_TYPE_DISPLAY_PORT_MST | 212 SIGNAL_TYPE_EDP | 213 SIGNAL_TYPE_HDMI_TYPE_A; 214 215 enc10->link_regs = link_regs; 216 enc10->aux_regs = aux_regs; 217 enc10->hpd_regs = hpd_regs; 218 enc10->link_shift = link_shift; 219 enc10->link_mask = link_mask; 220 221 switch (enc10->base.transmitter) { 222 case TRANSMITTER_UNIPHY_A: 223 enc10->base.preferred_engine = ENGINE_ID_DIGA; 224 break; 225 case TRANSMITTER_UNIPHY_B: 226 enc10->base.preferred_engine = ENGINE_ID_DIGB; 227 break; 228 case TRANSMITTER_UNIPHY_C: 229 enc10->base.preferred_engine = ENGINE_ID_DIGC; 230 break; 231 case TRANSMITTER_UNIPHY_D: 232 enc10->base.preferred_engine = ENGINE_ID_DIGD; 233 break; 234 case TRANSMITTER_UNIPHY_E: 235 enc10->base.preferred_engine = ENGINE_ID_DIGE; 236 break; 237 default: 238 ASSERT_CRITICAL(false); 239 enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; 240 } 241 242 enc10->base.features.flags.bits.HDMI_6GB_EN = 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