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, enabled: 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 | 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 | |