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
0026
0027
0028 #include "dm_services.h"
0029 #include "dm_helpers.h"
0030 #include "core_types.h"
0031 #include "resource.h"
0032 #include "dccg.h"
0033 #include "dce/dce_hwseq.h"
0034 #include "clk_mgr.h"
0035 #include "reg_helper.h"
0036 #include "abm.h"
0037 #include "hubp.h"
0038 #include "dchubbub.h"
0039 #include "timing_generator.h"
0040 #include "opp.h"
0041 #include "ipp.h"
0042 #include "mpc.h"
0043 #include "mcif_wb.h"
0044 #include "dc_dmub_srv.h"
0045 #include "dcn314_hwseq.h"
0046 #include "link_hwss.h"
0047 #include "dpcd_defs.h"
0048 #include "dce/dmub_outbox.h"
0049 #include "dc_link_dp.h"
0050 #include "inc/dc_link_dp.h"
0051 #include "inc/link_dpcd.h"
0052 #include "dcn10/dcn10_hw_sequencer.h"
0053 #include "inc/link_enc_cfg.h"
0054 #include "dcn30/dcn30_vpg.h"
0055 #include "dce/dce_i2c_hw.h"
0056 #include "dsc.h"
0057 #include "dcn20/dcn20_optc.h"
0058 #include "dcn30/dcn30_cm_common.h"
0059
0060 #define DC_LOGGER_INIT(logger)
0061
0062 #define CTX \
0063 hws->ctx
0064 #define REG(reg)\
0065 hws->regs->reg
0066 #define DC_LOGGER \
0067 dc->ctx->logger
0068
0069
0070 #undef FN
0071 #define FN(reg_name, field_name) \
0072 hws->shifts->field_name, hws->masks->field_name
0073
0074 static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream,
0075 int opp_cnt)
0076 {
0077 bool hblank_halved = optc2_is_two_pixels_per_containter(&stream->timing);
0078 int flow_ctrl_cnt;
0079
0080 if (opp_cnt >= 2)
0081 hblank_halved = true;
0082
0083 flow_ctrl_cnt = stream->timing.h_total - stream->timing.h_addressable -
0084 stream->timing.h_border_left -
0085 stream->timing.h_border_right;
0086
0087 if (hblank_halved)
0088 flow_ctrl_cnt /= 2;
0089
0090
0091 if (opp_cnt == 4)
0092 flow_ctrl_cnt /= 2;
0093
0094 return flow_ctrl_cnt;
0095 }
0096
0097 static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
0098 {
0099 struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
0100 struct dc_stream_state *stream = pipe_ctx->stream;
0101 struct pipe_ctx *odm_pipe;
0102 int opp_cnt = 1;
0103
0104 ASSERT(dsc);
0105 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
0106 opp_cnt++;
0107
0108 if (enable) {
0109 struct dsc_config dsc_cfg;
0110 struct dsc_optc_config dsc_optc_cfg;
0111 enum optc_dsc_mode optc_dsc_mode;
0112
0113
0114 dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
0115 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
0116 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
0117 dsc_cfg.color_depth = stream->timing.display_color_depth;
0118 dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
0119 dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
0120 ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
0121 dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
0122
0123 dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
0124 dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
0125 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
0126 struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;
0127
0128 ASSERT(odm_dsc);
0129 odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
0130 odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
0131 }
0132 dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
0133 dsc_cfg.pic_width *= opp_cnt;
0134
0135 optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED;
0136
0137
0138 DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst);
0139 pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg,
0140 optc_dsc_mode,
0141 dsc_optc_cfg.bytes_per_pixel,
0142 dsc_optc_cfg.slice_width);
0143 } else {
0144
0145 pipe_ctx->stream_res.tg->funcs->set_dsc_config(
0146 pipe_ctx->stream_res.tg,
0147 OPTC_DSC_DISABLED, 0, 0);
0148
0149
0150 dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
0151 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
0152 ASSERT(odm_pipe->stream_res.dsc);
0153 odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
0154 }
0155 }
0156 }
0157
0158
0159
0160 static unsigned int get_odm_config(struct pipe_ctx *pipe_ctx, unsigned int *opp_instances)
0161 {
0162 unsigned int opp_count = 1;
0163 struct pipe_ctx *odm_pipe;
0164
0165
0166 for (odm_pipe = pipe_ctx; odm_pipe->prev_odm_pipe; odm_pipe = odm_pipe->prev_odm_pipe)
0167 ;
0168
0169
0170 if (opp_instances)
0171 opp_instances[0] = odm_pipe->stream_res.opp->inst;
0172
0173
0174 for (odm_pipe = odm_pipe->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
0175 if (opp_instances)
0176 opp_instances[opp_count] = odm_pipe->stream_res.opp->inst;
0177 opp_count++;
0178 }
0179
0180 return opp_count;
0181 }
0182
0183 void dcn314_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
0184 {
0185 struct pipe_ctx *odm_pipe;
0186 int opp_cnt = 0;
0187 int opp_inst[MAX_PIPES] = {0};
0188 bool rate_control_2x_pclk = (pipe_ctx->stream->timing.flags.INTERLACE || optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing));
0189 struct mpc_dwb_flow_control flow_control;
0190 struct mpc *mpc = dc->res_pool->mpc;
0191 int i;
0192
0193 opp_cnt = get_odm_config(pipe_ctx, opp_inst);
0194
0195 if (opp_cnt > 1)
0196 pipe_ctx->stream_res.tg->funcs->set_odm_combine(
0197 pipe_ctx->stream_res.tg,
0198 opp_inst, opp_cnt,
0199 &pipe_ctx->stream->timing);
0200 else
0201 pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
0202 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
0203
0204 rate_control_2x_pclk = rate_control_2x_pclk || opp_cnt > 1;
0205 flow_control.flow_ctrl_mode = 0;
0206 flow_control.flow_ctrl_cnt0 = 0x80;
0207 flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(pipe_ctx->stream, opp_cnt);
0208 if (mpc->funcs->set_out_rate_control) {
0209 for (i = 0; i < opp_cnt; ++i) {
0210 mpc->funcs->set_out_rate_control(
0211 mpc, opp_inst[i],
0212 true,
0213 rate_control_2x_pclk,
0214 &flow_control);
0215 }
0216 }
0217
0218 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
0219 odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
0220 odm_pipe->stream_res.opp,
0221 true);
0222 }
0223
0224 if (pipe_ctx->stream_res.dsc) {
0225 struct pipe_ctx *current_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
0226
0227 update_dsc_on_stream(pipe_ctx, pipe_ctx->stream->timing.flags.DSC);
0228
0229
0230 if (!pipe_ctx->next_odm_pipe && current_pipe_ctx->next_odm_pipe &&
0231 current_pipe_ctx->next_odm_pipe->stream_res.dsc) {
0232 struct display_stream_compressor *dsc = current_pipe_ctx->next_odm_pipe->stream_res.dsc;
0233
0234 dsc->funcs->dsc_disconnect(dsc);
0235 }
0236 }
0237 }
0238
0239 void dcn314_dsc_pg_control(
0240 struct dce_hwseq *hws,
0241 unsigned int dsc_inst,
0242 bool power_on)
0243 {
0244 uint32_t power_gate = power_on ? 0 : 1;
0245 uint32_t pwr_status = power_on ? 0 : 2;
0246 uint32_t org_ip_request_cntl = 0;
0247
0248 if (hws->ctx->dc->debug.disable_dsc_power_gate)
0249 return;
0250
0251 if (hws->ctx->dc->debug.root_clock_optimization.bits.dsc &&
0252 hws->ctx->dc->res_pool->dccg->funcs->enable_dsc &&
0253 power_on)
0254 hws->ctx->dc->res_pool->dccg->funcs->enable_dsc(
0255 hws->ctx->dc->res_pool->dccg, dsc_inst);
0256
0257 REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
0258 if (org_ip_request_cntl == 0)
0259 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
0260
0261 switch (dsc_inst) {
0262 case 0:
0263 REG_UPDATE(DOMAIN16_PG_CONFIG,
0264 DOMAIN_POWER_GATE, power_gate);
0265
0266 REG_WAIT(DOMAIN16_PG_STATUS,
0267 DOMAIN_PGFSM_PWR_STATUS, pwr_status,
0268 1, 1000);
0269 break;
0270 case 1:
0271 REG_UPDATE(DOMAIN17_PG_CONFIG,
0272 DOMAIN_POWER_GATE, power_gate);
0273
0274 REG_WAIT(DOMAIN17_PG_STATUS,
0275 DOMAIN_PGFSM_PWR_STATUS, pwr_status,
0276 1, 1000);
0277 break;
0278 case 2:
0279 REG_UPDATE(DOMAIN18_PG_CONFIG,
0280 DOMAIN_POWER_GATE, power_gate);
0281
0282 REG_WAIT(DOMAIN18_PG_STATUS,
0283 DOMAIN_PGFSM_PWR_STATUS, pwr_status,
0284 1, 1000);
0285 break;
0286 case 3:
0287 REG_UPDATE(DOMAIN19_PG_CONFIG,
0288 DOMAIN_POWER_GATE, power_gate);
0289
0290 REG_WAIT(DOMAIN19_PG_STATUS,
0291 DOMAIN_PGFSM_PWR_STATUS, pwr_status,
0292 1, 1000);
0293 break;
0294 default:
0295 BREAK_TO_DEBUGGER();
0296 break;
0297 }
0298
0299 if (org_ip_request_cntl == 0)
0300 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
0301
0302 if (hws->ctx->dc->debug.root_clock_optimization.bits.dsc) {
0303 if (hws->ctx->dc->res_pool->dccg->funcs->disable_dsc && !power_on)
0304 hws->ctx->dc->res_pool->dccg->funcs->disable_dsc(
0305 hws->ctx->dc->res_pool->dccg, dsc_inst);
0306 }
0307
0308 }
0309
0310 void dcn314_enable_power_gating_plane(struct dce_hwseq *hws, bool enable)
0311 {
0312 bool force_on = true;
0313 uint32_t org_ip_request_cntl = 0;
0314
0315 if (enable && !hws->ctx->dc->debug.disable_hubp_power_gate)
0316 force_on = false;
0317
0318 REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
0319 if (org_ip_request_cntl == 0)
0320 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
0321
0322 REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
0323 REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
0324
0325 REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
0326 REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
0327
0328 force_on = true;
0329 if (enable && !hws->ctx->dc->debug.disable_dsc_power_gate)
0330 force_on = false;
0331
0332
0333 REG_UPDATE(DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
0334 REG_UPDATE(DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
0335 REG_UPDATE(DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
0336 REG_UPDATE(DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
0337
0338 if (org_ip_request_cntl == 0)
0339 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
0340 }
0341
0342 unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div)
0343 {
0344 struct dc_stream_state *stream = pipe_ctx->stream;
0345 unsigned int odm_combine_factor = 0;
0346 bool two_pix_per_container = false;
0347
0348 two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing);
0349 odm_combine_factor = get_odm_config(pipe_ctx, NULL);
0350
0351 if (is_dp_128b_132b_signal(pipe_ctx)) {
0352 *k2_div = PIXEL_RATE_DIV_BY_1;
0353 } else if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) || dc_is_dvi_signal(pipe_ctx->stream->signal)) {
0354 *k1_div = PIXEL_RATE_DIV_BY_1;
0355 if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
0356 *k2_div = PIXEL_RATE_DIV_BY_2;
0357 else
0358 *k2_div = PIXEL_RATE_DIV_BY_4;
0359 } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
0360 if (two_pix_per_container) {
0361 *k1_div = PIXEL_RATE_DIV_BY_1;
0362 *k2_div = PIXEL_RATE_DIV_BY_2;
0363 } else {
0364 *k1_div = PIXEL_RATE_DIV_BY_1;
0365 *k2_div = PIXEL_RATE_DIV_BY_4;
0366 if (odm_combine_factor == 2)
0367 *k2_div = PIXEL_RATE_DIV_BY_2;
0368 }
0369 }
0370
0371 if ((*k1_div == PIXEL_RATE_DIV_NA) && (*k2_div == PIXEL_RATE_DIV_NA))
0372 ASSERT(false);
0373
0374 return odm_combine_factor;
0375 }
0376
0377 void dcn314_set_pixels_per_cycle(struct pipe_ctx *pipe_ctx)
0378 {
0379 uint32_t pix_per_cycle = 1;
0380 uint32_t odm_combine_factor = 1;
0381
0382 if (!pipe_ctx || !pipe_ctx->stream || !pipe_ctx->stream_res.stream_enc)
0383 return;
0384
0385 odm_combine_factor = get_odm_config(pipe_ctx, NULL);
0386 if (optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing) || odm_combine_factor > 1)
0387 pix_per_cycle = 2;
0388
0389 if (pipe_ctx->stream_res.stream_enc->funcs->set_input_mode)
0390 pipe_ctx->stream_res.stream_enc->funcs->set_input_mode(pipe_ctx->stream_res.stream_enc,
0391 pix_per_cycle);
0392 }