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