0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #include "link_hwss_hpo_dp.h"
0026 #include "dm_helpers.h"
0027 #include "core_types.h"
0028 #include "dccg.h"
0029 #include "dc_link_dp.h"
0030 #include "clk_mgr.h"
0031
0032 static enum phyd32clk_clock_source get_phyd32clk_src(struct dc_link *link)
0033 {
0034 switch (link->link_enc->transmitter) {
0035 case TRANSMITTER_UNIPHY_A:
0036 return PHYD32CLKA;
0037 case TRANSMITTER_UNIPHY_B:
0038 return PHYD32CLKB;
0039 case TRANSMITTER_UNIPHY_C:
0040 return PHYD32CLKC;
0041 case TRANSMITTER_UNIPHY_D:
0042 return PHYD32CLKD;
0043 case TRANSMITTER_UNIPHY_E:
0044 return PHYD32CLKE;
0045 default:
0046 return PHYD32CLKA;
0047 }
0048 }
0049
0050 static void set_hpo_dp_throttled_vcp_size(struct pipe_ctx *pipe_ctx,
0051 struct fixed31_32 throttled_vcp_size)
0052 {
0053 struct hpo_dp_stream_encoder *hpo_dp_stream_encoder =
0054 pipe_ctx->stream_res.hpo_dp_stream_enc;
0055 struct hpo_dp_link_encoder *hpo_dp_link_encoder =
0056 pipe_ctx->link_res.hpo_dp_link_enc;
0057
0058 hpo_dp_link_encoder->funcs->set_throttled_vcp_size(hpo_dp_link_encoder,
0059 hpo_dp_stream_encoder->inst,
0060 throttled_vcp_size);
0061 }
0062
0063 static void set_hpo_dp_hblank_min_symbol_width(struct pipe_ctx *pipe_ctx,
0064 const struct dc_link_settings *link_settings,
0065 struct fixed31_32 throttled_vcp_size)
0066 {
0067 struct hpo_dp_stream_encoder *hpo_dp_stream_encoder =
0068 pipe_ctx->stream_res.hpo_dp_stream_enc;
0069 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
0070 struct fixed31_32 h_blank_in_ms, time_slot_in_ms, mtp_cnt_per_h_blank;
0071 uint32_t link_bw_in_kbps =
0072 dc_link_bandwidth_kbps(pipe_ctx->stream->link, link_settings);
0073 uint16_t hblank_min_symbol_width = 0;
0074
0075 if (link_bw_in_kbps > 0) {
0076 h_blank_in_ms = dc_fixpt_div(dc_fixpt_from_int(
0077 timing->h_total - timing->h_addressable),
0078 dc_fixpt_from_fraction(timing->pix_clk_100hz, 10));
0079 time_slot_in_ms = dc_fixpt_from_fraction(32 * 4, link_bw_in_kbps);
0080 mtp_cnt_per_h_blank = dc_fixpt_div(h_blank_in_ms,
0081 dc_fixpt_mul_int(time_slot_in_ms, 64));
0082 hblank_min_symbol_width = dc_fixpt_floor(
0083 dc_fixpt_mul(mtp_cnt_per_h_blank, throttled_vcp_size));
0084 }
0085
0086 hpo_dp_stream_encoder->funcs->set_hblank_min_symbol_width(hpo_dp_stream_encoder,
0087 hblank_min_symbol_width);
0088 }
0089
0090 static int get_odm_segment_count(struct pipe_ctx *pipe_ctx)
0091 {
0092 struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
0093 int count = 1;
0094
0095 while (odm_pipe != NULL) {
0096 count++;
0097 odm_pipe = odm_pipe->next_odm_pipe;
0098 }
0099
0100 return count;
0101 }
0102
0103 static void setup_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx)
0104 {
0105 struct dc *dc = pipe_ctx->stream->ctx->dc;
0106 struct hpo_dp_stream_encoder *stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc;
0107 struct hpo_dp_link_encoder *link_enc = pipe_ctx->link_res.hpo_dp_link_enc;
0108 struct dccg *dccg = dc->res_pool->dccg;
0109 struct timing_generator *tg = pipe_ctx->stream_res.tg;
0110 struct dtbclk_dto_params dto_params = {0};
0111 enum phyd32clk_clock_source phyd32clk = get_phyd32clk_src(pipe_ctx->stream->link);
0112
0113 dto_params.otg_inst = tg->inst;
0114 dto_params.pixclk_khz = pipe_ctx->stream->phy_pix_clk;
0115 dto_params.num_odm_segments = get_odm_segment_count(pipe_ctx);
0116 dto_params.timing = &pipe_ctx->stream->timing;
0117 dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr);
0118
0119 dccg->funcs->set_dpstreamclk(dccg, DTBCLK0, tg->inst, stream_enc->inst);
0120 dccg->funcs->enable_symclk32_se(dccg, stream_enc->inst, phyd32clk);
0121 dccg->funcs->set_dtbclk_dto(dccg, &dto_params);
0122 stream_enc->funcs->enable_stream(stream_enc);
0123 stream_enc->funcs->map_stream_to_link(stream_enc, stream_enc->inst, link_enc->inst);
0124 }
0125
0126 static void reset_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx)
0127 {
0128 struct dc *dc = pipe_ctx->stream->ctx->dc;
0129 struct hpo_dp_stream_encoder *stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc;
0130 struct dccg *dccg = dc->res_pool->dccg;
0131 struct timing_generator *tg = pipe_ctx->stream_res.tg;
0132 struct dtbclk_dto_params dto_params = {0};
0133
0134 dto_params.otg_inst = tg->inst;
0135 dto_params.timing = &pipe_ctx->stream->timing;
0136
0137 stream_enc->funcs->disable(stream_enc);
0138 dccg->funcs->set_dtbclk_dto(dccg, &dto_params);
0139 dccg->funcs->disable_symclk32_se(dccg, stream_enc->inst);
0140 dccg->funcs->set_dpstreamclk(dccg, REFCLK, tg->inst, stream_enc->inst);
0141 }
0142
0143 static void setup_hpo_dp_stream_attribute(struct pipe_ctx *pipe_ctx)
0144 {
0145 struct hpo_dp_stream_encoder *stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc;
0146 struct dc_stream_state *stream = pipe_ctx->stream;
0147 struct dc_link *link = stream->link;
0148
0149 stream_enc->funcs->set_stream_attribute(
0150 stream_enc,
0151 &stream->timing,
0152 stream->output_color_space,
0153 stream->use_vsc_sdp_for_colorimetry,
0154 stream->timing.flags.DSC,
0155 false);
0156 dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR);
0157 }
0158
0159 static void enable_hpo_dp_fpga_link_output(struct dc_link *link,
0160 const struct link_resource *link_res,
0161 enum signal_type signal,
0162 enum clock_source_id clock_source,
0163 const struct dc_link_settings *link_settings)
0164 {
0165 const struct dc *dc = link->dc;
0166 enum phyd32clk_clock_source phyd32clk = get_phyd32clk_src(link);
0167 int phyd32clk_freq_khz = link_settings->link_rate == LINK_RATE_UHBR10 ? 312500 :
0168 link_settings->link_rate == LINK_RATE_UHBR13_5 ? 412875 :
0169 link_settings->link_rate == LINK_RATE_UHBR20 ? 625000 : 0;
0170
0171 dm_set_phyd32clk(dc->ctx, phyd32clk_freq_khz);
0172 dc->res_pool->dccg->funcs->set_physymclk(
0173 dc->res_pool->dccg,
0174 link->link_enc_hw_inst,
0175 PHYSYMCLK_FORCE_SRC_PHYD32CLK,
0176 true);
0177 dc->res_pool->dccg->funcs->enable_symclk32_le(
0178 dc->res_pool->dccg,
0179 link_res->hpo_dp_link_enc->inst,
0180 phyd32clk);
0181 link_res->hpo_dp_link_enc->funcs->link_enable(
0182 link_res->hpo_dp_link_enc,
0183 link_settings->lane_count);
0184
0185 }
0186
0187 static void enable_hpo_dp_link_output(struct dc_link *link,
0188 const struct link_resource *link_res,
0189 enum signal_type signal,
0190 enum clock_source_id clock_source,
0191 const struct dc_link_settings *link_settings)
0192 {
0193 if (IS_FPGA_MAXIMUS_DC(link->dc->ctx->dce_environment))
0194 enable_hpo_dp_fpga_link_output(link, link_res, signal,
0195 clock_source, link_settings);
0196 else
0197 link_res->hpo_dp_link_enc->funcs->enable_link_phy(
0198 link_res->hpo_dp_link_enc,
0199 link_settings,
0200 link->link_enc->transmitter,
0201 link->link_enc->hpd_source);
0202 }
0203
0204
0205 static void disable_hpo_dp_fpga_link_output(struct dc_link *link,
0206 const struct link_resource *link_res,
0207 enum signal_type signal)
0208 {
0209 const struct dc *dc = link->dc;
0210
0211 link_res->hpo_dp_link_enc->funcs->link_disable(link_res->hpo_dp_link_enc);
0212 dc->res_pool->dccg->funcs->disable_symclk32_le(
0213 dc->res_pool->dccg,
0214 link_res->hpo_dp_link_enc->inst);
0215 dc->res_pool->dccg->funcs->set_physymclk(
0216 dc->res_pool->dccg,
0217 link->link_enc_hw_inst,
0218 PHYSYMCLK_FORCE_SRC_SYMCLK,
0219 false);
0220 dm_set_phyd32clk(dc->ctx, 0);
0221 }
0222
0223 static void disable_hpo_dp_link_output(struct dc_link *link,
0224 const struct link_resource *link_res,
0225 enum signal_type signal)
0226 {
0227 if (IS_FPGA_MAXIMUS_DC(link->dc->ctx->dce_environment)) {
0228 disable_hpo_dp_fpga_link_output(link, link_res, signal);
0229 } else {
0230 link_res->hpo_dp_link_enc->funcs->link_disable(link_res->hpo_dp_link_enc);
0231 link_res->hpo_dp_link_enc->funcs->disable_link_phy(
0232 link_res->hpo_dp_link_enc, signal);
0233 }
0234 }
0235
0236 static void set_hpo_dp_link_test_pattern(struct dc_link *link,
0237 const struct link_resource *link_res,
0238 struct encoder_set_dp_phy_pattern_param *tp_params)
0239 {
0240 link_res->hpo_dp_link_enc->funcs->set_link_test_pattern(
0241 link_res->hpo_dp_link_enc, tp_params);
0242 dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
0243 }
0244
0245 static void set_hpo_dp_lane_settings(struct dc_link *link,
0246 const struct link_resource *link_res,
0247 const struct dc_link_settings *link_settings,
0248 const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
0249 {
0250 link_res->hpo_dp_link_enc->funcs->set_ffe(
0251 link_res->hpo_dp_link_enc,
0252 link_settings,
0253 lane_settings[0].FFE_PRESET.raw);
0254 }
0255
0256 static void update_hpo_dp_stream_allocation_table(struct dc_link *link,
0257 const struct link_resource *link_res,
0258 const struct link_mst_stream_allocation_table *table)
0259 {
0260 link_res->hpo_dp_link_enc->funcs->update_stream_allocation_table(
0261 link_res->hpo_dp_link_enc,
0262 table);
0263 }
0264
0265 static const struct link_hwss hpo_dp_link_hwss = {
0266 .setup_stream_encoder = setup_hpo_dp_stream_encoder,
0267 .reset_stream_encoder = reset_hpo_dp_stream_encoder,
0268 .setup_stream_attribute = setup_hpo_dp_stream_attribute,
0269 .ext = {
0270 .set_throttled_vcp_size = set_hpo_dp_throttled_vcp_size,
0271 .set_hblank_min_symbol_width = set_hpo_dp_hblank_min_symbol_width,
0272 .enable_dp_link_output = enable_hpo_dp_link_output,
0273 .disable_dp_link_output = disable_hpo_dp_link_output,
0274 .set_dp_link_test_pattern = set_hpo_dp_link_test_pattern,
0275 .set_dp_lane_settings = set_hpo_dp_lane_settings,
0276 .update_stream_allocation_table = update_hpo_dp_stream_allocation_table,
0277 },
0278 };
0279
0280 bool can_use_hpo_dp_link_hwss(const struct dc_link *link,
0281 const struct link_resource *link_res)
0282 {
0283 return link_res->hpo_dp_link_enc != NULL;
0284 }
0285
0286 const struct link_hwss *get_hpo_dp_link_hwss(void)
0287 {
0288 return &hpo_dp_link_hwss;
0289 }
0290