1 /* 2 * Copyright 2022 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 #include "link_hwss_dio.h" 26 #include "core_types.h" 27 #include "link_enc_cfg.h" 28 29 void set_dio_throttled_vcp_size(struct pipe_ctx *pipe_ctx, 30 struct fixed31_32 throttled_vcp_size) 31 { 32 struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; 33 34 stream_encoder->funcs->set_throttled_vcp_size( 35 stream_encoder, 36 throttled_vcp_size); 37 } 38 39 void setup_dio_stream_encoder(struct pipe_ctx *pipe_ctx) 40 { 41 struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); 42 struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; 43 44 link_enc->funcs->connect_dig_be_to_fe(link_enc, 45 pipe_ctx->stream_res.stream_enc->id, true); 46 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 47 link_dp_source_sequence_trace(pipe_ctx->stream->link, 48 DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE); 49 if (stream_enc->funcs->enable_fifo) 50 stream_enc->funcs->enable_fifo(stream_enc); 51 } 52 53 void reset_dio_stream_encoder(struct pipe_ctx *pipe_ctx) 54 { 55 struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); 56 struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; 57 58 if (stream_enc && stream_enc->funcs->disable_fifo) 59 stream_enc->funcs->disable_fifo(stream_enc); 60 61 link_enc->funcs->connect_dig_be_to_fe( 62 link_enc, 63 pipe_ctx->stream_res.stream_enc->id, 64 false); 65 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 66 link_dp_source_sequence_trace(pipe_ctx->stream->link, 67 DPCD_SOURCE_SEQ_AFTER_DISCONNECT_DIG_FE_BE); 68 69 } 70 71 void setup_dio_stream_attribute(struct pipe_ctx *pipe_ctx) 72 { 73 struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; 74 struct dc_stream_state *stream = pipe_ctx->stream; 75 struct dc_link *link = stream->link; 76 77 if (!dc_is_virtual_signal(stream->signal)) 78 stream_encoder->funcs->setup_stereo_sync( 79 stream_encoder, 80 pipe_ctx->stream_res.tg->inst, 81 stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE); 82 83 if (dc_is_dp_signal(stream->signal)) 84 stream_encoder->funcs->dp_set_stream_attribute( 85 stream_encoder, 86 &stream->timing, 87 stream->output_color_space, 88 stream->use_vsc_sdp_for_colorimetry, 89 link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP); 90 else if (dc_is_hdmi_tmds_signal(stream->signal)) 91 stream_encoder->funcs->hdmi_set_stream_attribute( 92 stream_encoder, 93 &stream->timing, 94 stream->phy_pix_clk, 95 pipe_ctx->stream_res.audio != NULL); 96 else if (dc_is_dvi_signal(stream->signal)) 97 stream_encoder->funcs->dvi_set_stream_attribute( 98 stream_encoder, 99 &stream->timing, 100 (stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ? 101 true : false); 102 else if (dc_is_lvds_signal(stream->signal)) 103 stream_encoder->funcs->lvds_set_stream_attribute( 104 stream_encoder, 105 &stream->timing); 106 107 if (dc_is_dp_signal(stream->signal)) 108 link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR); 109 } 110 111 void enable_dio_dp_link_output(struct dc_link *link, 112 const struct link_resource *link_res, 113 enum signal_type signal, 114 enum clock_source_id clock_source, 115 const struct dc_link_settings *link_settings) 116 { 117 struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); 118 119 if (dc_is_dp_sst_signal(signal)) 120 link_enc->funcs->enable_dp_output( 121 link_enc, 122 link_settings, 123 clock_source); 124 else 125 link_enc->funcs->enable_dp_mst_output( 126 link_enc, 127 link_settings, 128 clock_source); 129 link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY); 130 } 131 132 void disable_dio_link_output(struct dc_link *link, 133 const struct link_resource *link_res, 134 enum signal_type signal) 135 { 136 struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); 137 138 link_enc->funcs->disable_output(link_enc, signal); 139 link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); 140 } 141 142 void set_dio_dp_link_test_pattern(struct dc_link *link, 143 const struct link_resource *link_res, 144 struct encoder_set_dp_phy_pattern_param *tp_params) 145 { 146 struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); 147 148 link_enc->funcs->dp_set_phy_pattern(link_enc, tp_params); 149 link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); 150 } 151 152 void set_dio_dp_lane_settings(struct dc_link *link, 153 const struct link_resource *link_res, 154 const struct dc_link_settings *link_settings, 155 const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) 156 { 157 struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); 158 159 link_enc->funcs->dp_set_lane_settings(link_enc, link_settings, lane_settings); 160 } 161 162 static void update_dio_stream_allocation_table(struct dc_link *link, 163 const struct link_resource *link_res, 164 const struct link_mst_stream_allocation_table *table) 165 { 166 struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); 167 168 ASSERT(link_enc); 169 link_enc->funcs->update_mst_stream_allocation_table(link_enc, table); 170 } 171 172 void setup_dio_audio_output(struct pipe_ctx *pipe_ctx, 173 struct audio_output *audio_output, uint32_t audio_inst) 174 { 175 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 176 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( 177 pipe_ctx->stream_res.stream_enc, 178 audio_inst, 179 &pipe_ctx->stream->audio_info); 180 else 181 pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( 182 pipe_ctx->stream_res.stream_enc, 183 audio_inst, 184 &pipe_ctx->stream->audio_info, 185 &audio_output->crtc_info); 186 } 187 188 void enable_dio_audio_packet(struct pipe_ctx *pipe_ctx) 189 { 190 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 191 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable( 192 pipe_ctx->stream_res.stream_enc); 193 194 pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( 195 pipe_ctx->stream_res.stream_enc, false); 196 197 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 198 link_dp_source_sequence_trace(pipe_ctx->stream->link, 199 DPCD_SOURCE_SEQ_AFTER_ENABLE_AUDIO_STREAM); 200 } 201 202 void disable_dio_audio_packet(struct pipe_ctx *pipe_ctx) 203 { 204 pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( 205 pipe_ctx->stream_res.stream_enc, true); 206 207 if (pipe_ctx->stream_res.audio) { 208 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 209 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( 210 pipe_ctx->stream_res.stream_enc); 211 else 212 pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( 213 pipe_ctx->stream_res.stream_enc); 214 } 215 216 if (dc_is_dp_signal(pipe_ctx->stream->signal)) 217 link_dp_source_sequence_trace(pipe_ctx->stream->link, 218 DPCD_SOURCE_SEQ_AFTER_DISABLE_AUDIO_STREAM); 219 } 220 221 static const struct link_hwss dio_link_hwss = { 222 .setup_stream_encoder = setup_dio_stream_encoder, 223 .reset_stream_encoder = reset_dio_stream_encoder, 224 .setup_stream_attribute = setup_dio_stream_attribute, 225 .disable_link_output = disable_dio_link_output, 226 .setup_audio_output = setup_dio_audio_output, 227 .enable_audio_packet = enable_dio_audio_packet, 228 .disable_audio_packet = disable_dio_audio_packet, 229 .ext = { 230 .set_throttled_vcp_size = set_dio_throttled_vcp_size, 231 .enable_dp_link_output = enable_dio_dp_link_output, 232 .set_dp_link_test_pattern = set_dio_dp_link_test_pattern, 233 .set_dp_lane_settings = set_dio_dp_lane_settings, 234 .update_stream_allocation_table = update_dio_stream_allocation_table, 235 }, 236 }; 237 238 bool can_use_dio_link_hwss(const struct dc_link *link, 239 const struct link_resource *link_res) 240 { 241 return link->link_enc != NULL; 242 } 243 244 const struct link_hwss *get_dio_link_hwss(void) 245 { 246 return &dio_link_hwss; 247 } 248