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