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 <linux/delay.h>
0026
0027 #include "dm_services.h"
0028 #include "basics/dc_common.h"
0029 #include "dm_helpers.h"
0030 #include "core_types.h"
0031 #include "resource.h"
0032 #include "dcn20_resource.h"
0033 #include "dcn20_hwseq.h"
0034 #include "dce/dce_hwseq.h"
0035 #include "dcn20_dsc.h"
0036 #include "dcn20_optc.h"
0037 #include "abm.h"
0038 #include "clk_mgr.h"
0039 #include "dmcu.h"
0040 #include "hubp.h"
0041 #include "timing_generator.h"
0042 #include "opp.h"
0043 #include "ipp.h"
0044 #include "mpc.h"
0045 #include "mcif_wb.h"
0046 #include "dchubbub.h"
0047 #include "reg_helper.h"
0048 #include "dcn10/dcn10_cm_common.h"
0049 #include "dc_link_dp.h"
0050 #include "vm_helper.h"
0051 #include "dccg.h"
0052 #include "dc_dmub_srv.h"
0053 #include "dce/dmub_hw_lock_mgr.h"
0054 #include "hw_sequencer.h"
0055 #include "inc/link_dpcd.h"
0056 #include "dpcd_defs.h"
0057 #include "inc/link_enc_cfg.h"
0058 #include "link_hwss.h"
0059
0060 #define DC_LOGGER_INIT(logger)
0061
0062 #define CTX \
0063 hws->ctx
0064 #define REG(reg)\
0065 hws->regs->reg
0066
0067 #undef FN
0068 #define FN(reg_name, field_name) \
0069 hws->shifts->field_name, hws->masks->field_name
0070
0071 static int find_free_gsl_group(const struct dc *dc)
0072 {
0073 if (dc->res_pool->gsl_groups.gsl_0 == 0)
0074 return 1;
0075 if (dc->res_pool->gsl_groups.gsl_1 == 0)
0076 return 2;
0077 if (dc->res_pool->gsl_groups.gsl_2 == 0)
0078 return 3;
0079
0080 return 0;
0081 }
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 static void dcn20_setup_gsl_group_as_lock(
0099 const struct dc *dc,
0100 struct pipe_ctx *pipe_ctx,
0101 bool enable)
0102 {
0103 struct gsl_params gsl;
0104 int group_idx;
0105
0106 memset(&gsl, 0, sizeof(struct gsl_params));
0107
0108 if (enable) {
0109
0110
0111
0112 if (pipe_ctx->stream_res.gsl_group > 0)
0113 return;
0114
0115 group_idx = find_free_gsl_group(dc);
0116 ASSERT(group_idx != 0);
0117 pipe_ctx->stream_res.gsl_group = group_idx;
0118
0119
0120 switch (group_idx) {
0121 case 1:
0122 gsl.gsl0_en = 1;
0123 dc->res_pool->gsl_groups.gsl_0 = 1;
0124 break;
0125 case 2:
0126 gsl.gsl1_en = 1;
0127 dc->res_pool->gsl_groups.gsl_1 = 1;
0128 break;
0129 case 3:
0130 gsl.gsl2_en = 1;
0131 dc->res_pool->gsl_groups.gsl_2 = 1;
0132 break;
0133 default:
0134 BREAK_TO_DEBUGGER();
0135 return;
0136 }
0137 gsl.gsl_master_en = 1;
0138 } else {
0139 group_idx = pipe_ctx->stream_res.gsl_group;
0140 if (group_idx == 0)
0141 return;
0142
0143 pipe_ctx->stream_res.gsl_group = 0;
0144
0145
0146 switch (group_idx) {
0147 case 1:
0148 gsl.gsl0_en = 0;
0149 dc->res_pool->gsl_groups.gsl_0 = 0;
0150 break;
0151 case 2:
0152 gsl.gsl1_en = 0;
0153 dc->res_pool->gsl_groups.gsl_1 = 0;
0154 break;
0155 case 3:
0156 gsl.gsl2_en = 0;
0157 dc->res_pool->gsl_groups.gsl_2 = 0;
0158 break;
0159 default:
0160 BREAK_TO_DEBUGGER();
0161 return;
0162 }
0163 gsl.gsl_master_en = 0;
0164 }
0165
0166
0167 if (pipe_ctx->stream_res.tg->funcs->set_gsl != NULL &&
0168 pipe_ctx->stream_res.tg->funcs->set_gsl_source_select != NULL) {
0169 pipe_ctx->stream_res.tg->funcs->set_gsl(
0170 pipe_ctx->stream_res.tg,
0171 &gsl);
0172
0173 pipe_ctx->stream_res.tg->funcs->set_gsl_source_select(
0174 pipe_ctx->stream_res.tg, group_idx, enable ? 4 : 0);
0175 } else
0176 BREAK_TO_DEBUGGER();
0177 }
0178
0179 void dcn20_set_flip_control_gsl(
0180 struct pipe_ctx *pipe_ctx,
0181 bool flip_immediate)
0182 {
0183 if (pipe_ctx && pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_control_surface_gsl)
0184 pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_control_surface_gsl(
0185 pipe_ctx->plane_res.hubp, flip_immediate);
0186
0187 }
0188
0189 void dcn20_enable_power_gating_plane(
0190 struct dce_hwseq *hws,
0191 bool enable)
0192 {
0193 bool force_on = true;
0194
0195 if (enable)
0196 force_on = false;
0197
0198
0199 REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on);
0200 REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on);
0201 REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on);
0202 REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on);
0203 if (REG(DOMAIN8_PG_CONFIG))
0204 REG_UPDATE(DOMAIN8_PG_CONFIG, DOMAIN8_POWER_FORCEON, force_on);
0205 if (REG(DOMAIN10_PG_CONFIG))
0206 REG_UPDATE(DOMAIN10_PG_CONFIG, DOMAIN8_POWER_FORCEON, force_on);
0207
0208
0209 REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on);
0210 REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on);
0211 REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on);
0212 REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on);
0213 if (REG(DOMAIN9_PG_CONFIG))
0214 REG_UPDATE(DOMAIN9_PG_CONFIG, DOMAIN9_POWER_FORCEON, force_on);
0215 if (REG(DOMAIN11_PG_CONFIG))
0216 REG_UPDATE(DOMAIN11_PG_CONFIG, DOMAIN9_POWER_FORCEON, force_on);
0217
0218
0219 REG_UPDATE(DOMAIN16_PG_CONFIG, DOMAIN16_POWER_FORCEON, force_on);
0220 REG_UPDATE(DOMAIN17_PG_CONFIG, DOMAIN17_POWER_FORCEON, force_on);
0221 REG_UPDATE(DOMAIN18_PG_CONFIG, DOMAIN18_POWER_FORCEON, force_on);
0222 if (REG(DOMAIN19_PG_CONFIG))
0223 REG_UPDATE(DOMAIN19_PG_CONFIG, DOMAIN19_POWER_FORCEON, force_on);
0224 if (REG(DOMAIN20_PG_CONFIG))
0225 REG_UPDATE(DOMAIN20_PG_CONFIG, DOMAIN20_POWER_FORCEON, force_on);
0226 if (REG(DOMAIN21_PG_CONFIG))
0227 REG_UPDATE(DOMAIN21_PG_CONFIG, DOMAIN21_POWER_FORCEON, force_on);
0228 }
0229
0230 void dcn20_dccg_init(struct dce_hwseq *hws)
0231 {
0232
0233
0234
0235
0236
0237
0238
0239 REG_WRITE(MICROSECOND_TIME_BASE_DIV, 0x120264);
0240
0241
0242
0243
0244
0245
0246
0247
0248 REG_WRITE(MILLISECOND_TIME_BASE_DIV, 0x1186a0);
0249
0250
0251 REG_WRITE(DISPCLK_FREQ_CHANGE_CNTL, 0xe01003c);
0252 }
0253
0254 void dcn20_disable_vga(
0255 struct dce_hwseq *hws)
0256 {
0257 REG_WRITE(D1VGA_CONTROL, 0);
0258 REG_WRITE(D2VGA_CONTROL, 0);
0259 REG_WRITE(D3VGA_CONTROL, 0);
0260 REG_WRITE(D4VGA_CONTROL, 0);
0261 REG_WRITE(D5VGA_CONTROL, 0);
0262 REG_WRITE(D6VGA_CONTROL, 0);
0263 }
0264
0265 void dcn20_program_triple_buffer(
0266 const struct dc *dc,
0267 struct pipe_ctx *pipe_ctx,
0268 bool enable_triple_buffer)
0269 {
0270 if (pipe_ctx->plane_res.hubp && pipe_ctx->plane_res.hubp->funcs) {
0271 pipe_ctx->plane_res.hubp->funcs->hubp_enable_tripleBuffer(
0272 pipe_ctx->plane_res.hubp,
0273 enable_triple_buffer);
0274 }
0275 }
0276
0277
0278 void dcn20_init_blank(
0279 struct dc *dc,
0280 struct timing_generator *tg)
0281 {
0282 struct dce_hwseq *hws = dc->hwseq;
0283 enum dc_color_space color_space;
0284 struct tg_color black_color = {0};
0285 struct output_pixel_processor *opp = NULL;
0286 struct output_pixel_processor *bottom_opp = NULL;
0287 uint32_t num_opps, opp_id_src0, opp_id_src1;
0288 uint32_t otg_active_width, otg_active_height;
0289
0290
0291 color_space = COLOR_SPACE_SRGB;
0292 color_space_to_black_color(dc, color_space, &black_color);
0293
0294
0295 tg->funcs->get_otg_active_size(tg,
0296 &otg_active_width,
0297 &otg_active_height);
0298
0299
0300 tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1);
0301
0302 if (opp_id_src0 >= dc->res_pool->res_cap->num_opp) {
0303 ASSERT(false);
0304 return;
0305 }
0306 opp = dc->res_pool->opps[opp_id_src0];
0307
0308 if (num_opps == 2) {
0309 otg_active_width = otg_active_width / 2;
0310
0311 if (opp_id_src1 >= dc->res_pool->res_cap->num_opp) {
0312 ASSERT(false);
0313 return;
0314 }
0315 bottom_opp = dc->res_pool->opps[opp_id_src1];
0316 }
0317
0318 opp->funcs->opp_set_disp_pattern_generator(
0319 opp,
0320 CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR,
0321 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
0322 COLOR_DEPTH_UNDEFINED,
0323 &black_color,
0324 otg_active_width,
0325 otg_active_height,
0326 0);
0327
0328 if (num_opps == 2) {
0329 bottom_opp->funcs->opp_set_disp_pattern_generator(
0330 bottom_opp,
0331 CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR,
0332 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
0333 COLOR_DEPTH_UNDEFINED,
0334 &black_color,
0335 otg_active_width,
0336 otg_active_height,
0337 0);
0338 }
0339
0340 hws->funcs.wait_for_blank_complete(opp);
0341 }
0342
0343 void dcn20_dsc_pg_control(
0344 struct dce_hwseq *hws,
0345 unsigned int dsc_inst,
0346 bool power_on)
0347 {
0348 uint32_t power_gate = power_on ? 0 : 1;
0349 uint32_t pwr_status = power_on ? 0 : 2;
0350 uint32_t org_ip_request_cntl = 0;
0351
0352 if (hws->ctx->dc->debug.disable_dsc_power_gate)
0353 return;
0354
0355 if (REG(DOMAIN16_PG_CONFIG) == 0)
0356 return;
0357
0358 REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
0359 if (org_ip_request_cntl == 0)
0360 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
0361
0362 switch (dsc_inst) {
0363 case 0:
0364 REG_UPDATE(DOMAIN16_PG_CONFIG,
0365 DOMAIN16_POWER_GATE, power_gate);
0366
0367 REG_WAIT(DOMAIN16_PG_STATUS,
0368 DOMAIN16_PGFSM_PWR_STATUS, pwr_status,
0369 1, 1000);
0370 break;
0371 case 1:
0372 REG_UPDATE(DOMAIN17_PG_CONFIG,
0373 DOMAIN17_POWER_GATE, power_gate);
0374
0375 REG_WAIT(DOMAIN17_PG_STATUS,
0376 DOMAIN17_PGFSM_PWR_STATUS, pwr_status,
0377 1, 1000);
0378 break;
0379 case 2:
0380 REG_UPDATE(DOMAIN18_PG_CONFIG,
0381 DOMAIN18_POWER_GATE, power_gate);
0382
0383 REG_WAIT(DOMAIN18_PG_STATUS,
0384 DOMAIN18_PGFSM_PWR_STATUS, pwr_status,
0385 1, 1000);
0386 break;
0387 case 3:
0388 REG_UPDATE(DOMAIN19_PG_CONFIG,
0389 DOMAIN19_POWER_GATE, power_gate);
0390
0391 REG_WAIT(DOMAIN19_PG_STATUS,
0392 DOMAIN19_PGFSM_PWR_STATUS, pwr_status,
0393 1, 1000);
0394 break;
0395 case 4:
0396 REG_UPDATE(DOMAIN20_PG_CONFIG,
0397 DOMAIN20_POWER_GATE, power_gate);
0398
0399 REG_WAIT(DOMAIN20_PG_STATUS,
0400 DOMAIN20_PGFSM_PWR_STATUS, pwr_status,
0401 1, 1000);
0402 break;
0403 case 5:
0404 REG_UPDATE(DOMAIN21_PG_CONFIG,
0405 DOMAIN21_POWER_GATE, power_gate);
0406
0407 REG_WAIT(DOMAIN21_PG_STATUS,
0408 DOMAIN21_PGFSM_PWR_STATUS, pwr_status,
0409 1, 1000);
0410 break;
0411 default:
0412 BREAK_TO_DEBUGGER();
0413 break;
0414 }
0415
0416 if (org_ip_request_cntl == 0)
0417 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
0418 }
0419
0420 void dcn20_dpp_pg_control(
0421 struct dce_hwseq *hws,
0422 unsigned int dpp_inst,
0423 bool power_on)
0424 {
0425 uint32_t power_gate = power_on ? 0 : 1;
0426 uint32_t pwr_status = power_on ? 0 : 2;
0427
0428 if (hws->ctx->dc->debug.disable_dpp_power_gate)
0429 return;
0430 if (REG(DOMAIN1_PG_CONFIG) == 0)
0431 return;
0432
0433 switch (dpp_inst) {
0434 case 0:
0435 REG_UPDATE(DOMAIN1_PG_CONFIG,
0436 DOMAIN1_POWER_GATE, power_gate);
0437
0438 REG_WAIT(DOMAIN1_PG_STATUS,
0439 DOMAIN1_PGFSM_PWR_STATUS, pwr_status,
0440 1, 1000);
0441 break;
0442 case 1:
0443 REG_UPDATE(DOMAIN3_PG_CONFIG,
0444 DOMAIN3_POWER_GATE, power_gate);
0445
0446 REG_WAIT(DOMAIN3_PG_STATUS,
0447 DOMAIN3_PGFSM_PWR_STATUS, pwr_status,
0448 1, 1000);
0449 break;
0450 case 2:
0451 REG_UPDATE(DOMAIN5_PG_CONFIG,
0452 DOMAIN5_POWER_GATE, power_gate);
0453
0454 REG_WAIT(DOMAIN5_PG_STATUS,
0455 DOMAIN5_PGFSM_PWR_STATUS, pwr_status,
0456 1, 1000);
0457 break;
0458 case 3:
0459 REG_UPDATE(DOMAIN7_PG_CONFIG,
0460 DOMAIN7_POWER_GATE, power_gate);
0461
0462 REG_WAIT(DOMAIN7_PG_STATUS,
0463 DOMAIN7_PGFSM_PWR_STATUS, pwr_status,
0464 1, 1000);
0465 break;
0466 case 4:
0467 REG_UPDATE(DOMAIN9_PG_CONFIG,
0468 DOMAIN9_POWER_GATE, power_gate);
0469
0470 REG_WAIT(DOMAIN9_PG_STATUS,
0471 DOMAIN9_PGFSM_PWR_STATUS, pwr_status,
0472 1, 1000);
0473 break;
0474 case 5:
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486 break;
0487 default:
0488 BREAK_TO_DEBUGGER();
0489 break;
0490 }
0491 }
0492
0493
0494 void dcn20_hubp_pg_control(
0495 struct dce_hwseq *hws,
0496 unsigned int hubp_inst,
0497 bool power_on)
0498 {
0499 uint32_t power_gate = power_on ? 0 : 1;
0500 uint32_t pwr_status = power_on ? 0 : 2;
0501
0502 if (hws->ctx->dc->debug.disable_hubp_power_gate)
0503 return;
0504 if (REG(DOMAIN0_PG_CONFIG) == 0)
0505 return;
0506
0507 switch (hubp_inst) {
0508 case 0:
0509 REG_UPDATE(DOMAIN0_PG_CONFIG,
0510 DOMAIN0_POWER_GATE, power_gate);
0511
0512 REG_WAIT(DOMAIN0_PG_STATUS,
0513 DOMAIN0_PGFSM_PWR_STATUS, pwr_status,
0514 1, 1000);
0515 break;
0516 case 1:
0517 REG_UPDATE(DOMAIN2_PG_CONFIG,
0518 DOMAIN2_POWER_GATE, power_gate);
0519
0520 REG_WAIT(DOMAIN2_PG_STATUS,
0521 DOMAIN2_PGFSM_PWR_STATUS, pwr_status,
0522 1, 1000);
0523 break;
0524 case 2:
0525 REG_UPDATE(DOMAIN4_PG_CONFIG,
0526 DOMAIN4_POWER_GATE, power_gate);
0527
0528 REG_WAIT(DOMAIN4_PG_STATUS,
0529 DOMAIN4_PGFSM_PWR_STATUS, pwr_status,
0530 1, 1000);
0531 break;
0532 case 3:
0533 REG_UPDATE(DOMAIN6_PG_CONFIG,
0534 DOMAIN6_POWER_GATE, power_gate);
0535
0536 REG_WAIT(DOMAIN6_PG_STATUS,
0537 DOMAIN6_PGFSM_PWR_STATUS, pwr_status,
0538 1, 1000);
0539 break;
0540 case 4:
0541 REG_UPDATE(DOMAIN8_PG_CONFIG,
0542 DOMAIN8_POWER_GATE, power_gate);
0543
0544 REG_WAIT(DOMAIN8_PG_STATUS,
0545 DOMAIN8_PGFSM_PWR_STATUS, pwr_status,
0546 1, 1000);
0547 break;
0548 case 5:
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560 break;
0561 default:
0562 BREAK_TO_DEBUGGER();
0563 break;
0564 }
0565 }
0566
0567
0568
0569
0570
0571 void dcn20_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
0572 {
0573 struct dce_hwseq *hws = dc->hwseq;
0574 struct hubp *hubp = pipe_ctx->plane_res.hubp;
0575 struct dpp *dpp = pipe_ctx->plane_res.dpp;
0576
0577 dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx);
0578
0579
0580
0581
0582 if (pipe_ctx->stream_res.gsl_group != 0)
0583 dcn20_setup_gsl_group_as_lock(dc, pipe_ctx, false);
0584
0585 dc->hwss.set_flip_control_gsl(pipe_ctx, false);
0586
0587 hubp->funcs->hubp_clk_cntl(hubp, false);
0588
0589 dpp->funcs->dpp_dppclk_control(dpp, false, false);
0590
0591 hubp->power_gated = true;
0592
0593 hws->funcs.plane_atomic_power_down(dc,
0594 pipe_ctx->plane_res.dpp,
0595 pipe_ctx->plane_res.hubp);
0596
0597 pipe_ctx->stream = NULL;
0598 memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res));
0599 memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res));
0600 pipe_ctx->top_pipe = NULL;
0601 pipe_ctx->bottom_pipe = NULL;
0602 pipe_ctx->plane_state = NULL;
0603 }
0604
0605
0606 void dcn20_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
0607 {
0608 DC_LOGGER_INIT(dc->ctx->logger);
0609
0610 if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated)
0611 return;
0612
0613 dcn20_plane_atomic_disable(dc, pipe_ctx);
0614
0615 DC_LOG_DC("Power down front end %d\n",
0616 pipe_ctx->pipe_idx);
0617 }
0618
0619 void dcn20_disable_pixel_data(struct dc *dc, struct pipe_ctx *pipe_ctx, bool blank)
0620 {
0621 dcn20_blank_pixel_data(dc, pipe_ctx, blank);
0622 }
0623
0624 static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream,
0625 int opp_cnt)
0626 {
0627 bool hblank_halved = optc2_is_two_pixels_per_containter(&stream->timing);
0628 int flow_ctrl_cnt;
0629
0630 if (opp_cnt >= 2)
0631 hblank_halved = true;
0632
0633 flow_ctrl_cnt = stream->timing.h_total - stream->timing.h_addressable -
0634 stream->timing.h_border_left -
0635 stream->timing.h_border_right;
0636
0637 if (hblank_halved)
0638 flow_ctrl_cnt /= 2;
0639
0640
0641 if (opp_cnt == 4)
0642 flow_ctrl_cnt /= 2;
0643
0644 return flow_ctrl_cnt;
0645 }
0646
0647 enum dc_status dcn20_enable_stream_timing(
0648 struct pipe_ctx *pipe_ctx,
0649 struct dc_state *context,
0650 struct dc *dc)
0651 {
0652 struct dce_hwseq *hws = dc->hwseq;
0653 struct dc_stream_state *stream = pipe_ctx->stream;
0654 struct drr_params params = {0};
0655 unsigned int event_triggers = 0;
0656 struct pipe_ctx *odm_pipe;
0657 int opp_cnt = 1;
0658 int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst };
0659 bool interlace = stream->timing.flags.INTERLACE;
0660 int i;
0661 struct mpc_dwb_flow_control flow_control;
0662 struct mpc *mpc = dc->res_pool->mpc;
0663 bool rate_control_2x_pclk = (interlace || optc2_is_two_pixels_per_containter(&stream->timing));
0664 unsigned int k1_div = PIXEL_RATE_DIV_NA;
0665 unsigned int k2_div = PIXEL_RATE_DIV_NA;
0666
0667 if (hws->funcs.calculate_dccg_k1_k2_values && dc->res_pool->dccg->funcs->set_pixel_rate_div) {
0668 hws->funcs.calculate_dccg_k1_k2_values(pipe_ctx, &k1_div, &k2_div);
0669
0670 dc->res_pool->dccg->funcs->set_pixel_rate_div(
0671 dc->res_pool->dccg,
0672 pipe_ctx->stream_res.tg->inst,
0673 k1_div, k2_div);
0674 }
0675
0676
0677
0678
0679 if (pipe_ctx->top_pipe != NULL)
0680 return DC_OK;
0681
0682
0683
0684 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
0685 opp_inst[opp_cnt] = odm_pipe->stream_res.opp->inst;
0686 opp_cnt++;
0687 }
0688
0689 if (opp_cnt > 1)
0690 pipe_ctx->stream_res.tg->funcs->set_odm_combine(
0691 pipe_ctx->stream_res.tg,
0692 opp_inst, opp_cnt,
0693 &pipe_ctx->stream->timing);
0694
0695
0696
0697
0698 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, true);
0699
0700 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
0701 pipe_ctx->clock_source,
0702 &pipe_ctx->stream_res.pix_clk_params,
0703 dp_get_link_encoding_format(&pipe_ctx->link_config.dp_link_settings),
0704 &pipe_ctx->pll_settings)) {
0705 BREAK_TO_DEBUGGER();
0706 return DC_ERROR_UNEXPECTED;
0707 }
0708
0709 if (dc->hwseq->funcs.PLAT_58856_wa && (!dc_is_dp_signal(stream->signal)))
0710 dc->hwseq->funcs.PLAT_58856_wa(context, pipe_ctx);
0711
0712 pipe_ctx->stream_res.tg->funcs->program_timing(
0713 pipe_ctx->stream_res.tg,
0714 &stream->timing,
0715 pipe_ctx->pipe_dlg_param.vready_offset,
0716 pipe_ctx->pipe_dlg_param.vstartup_start,
0717 pipe_ctx->pipe_dlg_param.vupdate_offset,
0718 pipe_ctx->pipe_dlg_param.vupdate_width,
0719 pipe_ctx->stream->signal,
0720 true);
0721
0722 rate_control_2x_pclk = rate_control_2x_pclk || opp_cnt > 1;
0723 flow_control.flow_ctrl_mode = 0;
0724 flow_control.flow_ctrl_cnt0 = 0x80;
0725 flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(stream, opp_cnt);
0726 if (mpc->funcs->set_out_rate_control) {
0727 for (i = 0; i < opp_cnt; ++i) {
0728 mpc->funcs->set_out_rate_control(
0729 mpc, opp_inst[i],
0730 true,
0731 rate_control_2x_pclk,
0732 &flow_control);
0733 }
0734 }
0735
0736 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
0737 odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
0738 odm_pipe->stream_res.opp,
0739 true);
0740
0741 pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
0742 pipe_ctx->stream_res.opp,
0743 true);
0744
0745 hws->funcs.blank_pixel_data(dc, pipe_ctx, true);
0746
0747
0748 if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) {
0749 BREAK_TO_DEBUGGER();
0750 return DC_ERROR_UNEXPECTED;
0751 }
0752
0753 hws->funcs.wait_for_blank_complete(pipe_ctx->stream_res.opp);
0754
0755 params.vertical_total_min = stream->adjust.v_total_min;
0756 params.vertical_total_max = stream->adjust.v_total_max;
0757 params.vertical_total_mid = stream->adjust.v_total_mid;
0758 params.vertical_total_mid_frame_num = stream->adjust.v_total_mid_frame_num;
0759 if (pipe_ctx->stream_res.tg->funcs->set_drr)
0760 pipe_ctx->stream_res.tg->funcs->set_drr(
0761 pipe_ctx->stream_res.tg, ¶ms);
0762
0763
0764 if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
0765 event_triggers = 0x80;
0766
0767
0768
0769
0770 if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control)
0771 pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
0772 pipe_ctx->stream_res.tg, event_triggers, 2);
0773
0774
0775
0776
0777
0778
0779
0780
0781
0782 if (pipe_ctx->stream && pipe_ctx->stream->mall_stream_config.type == SUBVP_PHANTOM) {
0783 if (pipe_ctx->stream_res.tg && pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable)
0784 pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable(pipe_ctx->stream_res.tg);
0785 }
0786 return DC_OK;
0787 }
0788
0789 void dcn20_program_output_csc(struct dc *dc,
0790 struct pipe_ctx *pipe_ctx,
0791 enum dc_color_space colorspace,
0792 uint16_t *matrix,
0793 int opp_id)
0794 {
0795 struct mpc *mpc = dc->res_pool->mpc;
0796 enum mpc_output_csc_mode ocsc_mode = MPC_OUTPUT_CSC_COEF_A;
0797 int mpcc_id = pipe_ctx->plane_res.hubp->inst;
0798
0799 if (mpc->funcs->power_on_mpc_mem_pwr)
0800 mpc->funcs->power_on_mpc_mem_pwr(mpc, mpcc_id, true);
0801
0802 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
0803 if (mpc->funcs->set_output_csc != NULL)
0804 mpc->funcs->set_output_csc(mpc,
0805 opp_id,
0806 matrix,
0807 ocsc_mode);
0808 } else {
0809 if (mpc->funcs->set_ocsc_default != NULL)
0810 mpc->funcs->set_ocsc_default(mpc,
0811 opp_id,
0812 colorspace,
0813 ocsc_mode);
0814 }
0815 }
0816
0817 bool dcn20_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
0818 const struct dc_stream_state *stream)
0819 {
0820 int mpcc_id = pipe_ctx->plane_res.hubp->inst;
0821 struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
0822 struct pwl_params *params = NULL;
0823
0824
0825
0826
0827
0828
0829
0830 if (mpc->funcs->power_on_mpc_mem_pwr)
0831 mpc->funcs->power_on_mpc_mem_pwr(mpc, mpcc_id, true);
0832 if (pipe_ctx->top_pipe == NULL
0833 && mpc->funcs->set_output_gamma && stream->out_transfer_func) {
0834 if (stream->out_transfer_func->type == TF_TYPE_HWPWL)
0835 params = &stream->out_transfer_func->pwl;
0836 else if (pipe_ctx->stream->out_transfer_func->type ==
0837 TF_TYPE_DISTRIBUTED_POINTS &&
0838 cm_helper_translate_curve_to_hw_format(
0839 stream->out_transfer_func,
0840 &mpc->blender_params, false))
0841 params = &mpc->blender_params;
0842
0843
0844
0845 if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED)
0846 BREAK_TO_DEBUGGER();
0847 }
0848
0849
0850
0851 mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
0852
0853 return true;
0854 }
0855
0856 bool dcn20_set_blend_lut(
0857 struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state)
0858 {
0859 struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
0860 bool result = true;
0861 struct pwl_params *blend_lut = NULL;
0862
0863 if (plane_state->blend_tf) {
0864 if (plane_state->blend_tf->type == TF_TYPE_HWPWL)
0865 blend_lut = &plane_state->blend_tf->pwl;
0866 else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) {
0867 cm_helper_translate_curve_to_hw_format(
0868 plane_state->blend_tf,
0869 &dpp_base->regamma_params, false);
0870 blend_lut = &dpp_base->regamma_params;
0871 }
0872 }
0873 result = dpp_base->funcs->dpp_program_blnd_lut(dpp_base, blend_lut);
0874
0875 return result;
0876 }
0877
0878 bool dcn20_set_shaper_3dlut(
0879 struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state)
0880 {
0881 struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
0882 bool result = true;
0883 struct pwl_params *shaper_lut = NULL;
0884
0885 if (plane_state->in_shaper_func) {
0886 if (plane_state->in_shaper_func->type == TF_TYPE_HWPWL)
0887 shaper_lut = &plane_state->in_shaper_func->pwl;
0888 else if (plane_state->in_shaper_func->type == TF_TYPE_DISTRIBUTED_POINTS) {
0889 cm_helper_translate_curve_to_hw_format(
0890 plane_state->in_shaper_func,
0891 &dpp_base->shaper_params, true);
0892 shaper_lut = &dpp_base->shaper_params;
0893 }
0894 }
0895
0896 result = dpp_base->funcs->dpp_program_shaper_lut(dpp_base, shaper_lut);
0897 if (plane_state->lut3d_func &&
0898 plane_state->lut3d_func->state.bits.initialized == 1)
0899 result = dpp_base->funcs->dpp_program_3dlut(dpp_base,
0900 &plane_state->lut3d_func->lut_3d);
0901 else
0902 result = dpp_base->funcs->dpp_program_3dlut(dpp_base, NULL);
0903
0904 return result;
0905 }
0906
0907 bool dcn20_set_input_transfer_func(struct dc *dc,
0908 struct pipe_ctx *pipe_ctx,
0909 const struct dc_plane_state *plane_state)
0910 {
0911 struct dce_hwseq *hws = dc->hwseq;
0912 struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
0913 const struct dc_transfer_func *tf = NULL;
0914 bool result = true;
0915 bool use_degamma_ram = false;
0916
0917 if (dpp_base == NULL || plane_state == NULL)
0918 return false;
0919
0920 hws->funcs.set_shaper_3dlut(pipe_ctx, plane_state);
0921 hws->funcs.set_blend_lut(pipe_ctx, plane_state);
0922
0923 if (plane_state->in_transfer_func)
0924 tf = plane_state->in_transfer_func;
0925
0926
0927 if (tf == NULL) {
0928 dpp_base->funcs->dpp_set_degamma(dpp_base,
0929 IPP_DEGAMMA_MODE_BYPASS);
0930 return true;
0931 }
0932
0933 if (tf->type == TF_TYPE_HWPWL || tf->type == TF_TYPE_DISTRIBUTED_POINTS)
0934 use_degamma_ram = true;
0935
0936 if (use_degamma_ram == true) {
0937 if (tf->type == TF_TYPE_HWPWL)
0938 dpp_base->funcs->dpp_program_degamma_pwl(dpp_base,
0939 &tf->pwl);
0940 else if (tf->type == TF_TYPE_DISTRIBUTED_POINTS) {
0941 cm_helper_translate_curve_to_degamma_hw_format(tf,
0942 &dpp_base->degamma_params);
0943 dpp_base->funcs->dpp_program_degamma_pwl(dpp_base,
0944 &dpp_base->degamma_params);
0945 }
0946 return true;
0947 }
0948
0949
0950
0951 if (tf->type == TF_TYPE_PREDEFINED) {
0952 switch (tf->tf) {
0953 case TRANSFER_FUNCTION_SRGB:
0954 dpp_base->funcs->dpp_set_degamma(dpp_base,
0955 IPP_DEGAMMA_MODE_HW_sRGB);
0956 break;
0957 case TRANSFER_FUNCTION_BT709:
0958 dpp_base->funcs->dpp_set_degamma(dpp_base,
0959 IPP_DEGAMMA_MODE_HW_xvYCC);
0960 break;
0961 case TRANSFER_FUNCTION_LINEAR:
0962 dpp_base->funcs->dpp_set_degamma(dpp_base,
0963 IPP_DEGAMMA_MODE_BYPASS);
0964 break;
0965 case TRANSFER_FUNCTION_PQ:
0966 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_USER_PWL);
0967 cm_helper_translate_curve_to_degamma_hw_format(tf, &dpp_base->degamma_params);
0968 dpp_base->funcs->dpp_program_degamma_pwl(dpp_base, &dpp_base->degamma_params);
0969 result = true;
0970 break;
0971 default:
0972 result = false;
0973 break;
0974 }
0975 } else if (tf->type == TF_TYPE_BYPASS)
0976 dpp_base->funcs->dpp_set_degamma(dpp_base,
0977 IPP_DEGAMMA_MODE_BYPASS);
0978 else {
0979
0980
0981
0982
0983 BREAK_TO_DEBUGGER();
0984 dpp_base->funcs->dpp_set_degamma(dpp_base,
0985 IPP_DEGAMMA_MODE_BYPASS);
0986 }
0987
0988 return result;
0989 }
0990
0991 void dcn20_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
0992 {
0993 struct pipe_ctx *odm_pipe;
0994 int opp_cnt = 1;
0995 int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst };
0996
0997 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
0998 opp_inst[opp_cnt] = odm_pipe->stream_res.opp->inst;
0999 opp_cnt++;
1000 }
1001
1002 if (opp_cnt > 1)
1003 pipe_ctx->stream_res.tg->funcs->set_odm_combine(
1004 pipe_ctx->stream_res.tg,
1005 opp_inst, opp_cnt,
1006 &pipe_ctx->stream->timing);
1007 else
1008 pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
1009 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
1010 }
1011
1012 void dcn20_blank_pixel_data(
1013 struct dc *dc,
1014 struct pipe_ctx *pipe_ctx,
1015 bool blank)
1016 {
1017 struct tg_color black_color = {0};
1018 struct stream_resource *stream_res = &pipe_ctx->stream_res;
1019 struct dc_stream_state *stream = pipe_ctx->stream;
1020 enum dc_color_space color_space = stream->output_color_space;
1021 enum controller_dp_test_pattern test_pattern = CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR;
1022 enum controller_dp_color_space test_pattern_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
1023 struct pipe_ctx *odm_pipe;
1024 int odm_cnt = 1;
1025
1026 int width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
1027 int height = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
1028
1029 if (stream->link->test_pattern_enabled)
1030 return;
1031
1032
1033 color_space_to_black_color(dc, color_space, &black_color);
1034
1035 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
1036 odm_cnt++;
1037
1038 width = width / odm_cnt;
1039
1040 if (blank) {
1041 dc->hwss.set_abm_immediate_disable(pipe_ctx);
1042
1043 if (dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE) {
1044 test_pattern = CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
1045 test_pattern_color_space = CONTROLLER_DP_COLOR_SPACE_RGB;
1046 }
1047 } else {
1048 test_pattern = CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
1049 }
1050
1051 dc->hwss.set_disp_pattern_generator(dc,
1052 pipe_ctx,
1053 test_pattern,
1054 test_pattern_color_space,
1055 stream->timing.display_color_depth,
1056 &black_color,
1057 width,
1058 height,
1059 0);
1060
1061 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
1062 dc->hwss.set_disp_pattern_generator(dc,
1063 odm_pipe,
1064 dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE && blank ?
1065 CONTROLLER_DP_TEST_PATTERN_COLORRAMP : test_pattern,
1066 test_pattern_color_space,
1067 stream->timing.display_color_depth,
1068 &black_color,
1069 width,
1070 height,
1071 0);
1072 }
1073
1074 if (!blank)
1075 if (stream_res->abm) {
1076 dc->hwss.set_pipe(pipe_ctx);
1077 stream_res->abm->funcs->set_abm_level(stream_res->abm, stream->abm_level);
1078 }
1079 }
1080
1081
1082 static void dcn20_power_on_plane(
1083 struct dce_hwseq *hws,
1084 struct pipe_ctx *pipe_ctx)
1085 {
1086 DC_LOGGER_INIT(hws->ctx->logger);
1087 if (REG(DC_IP_REQUEST_CNTL)) {
1088 REG_SET(DC_IP_REQUEST_CNTL, 0,
1089 IP_REQUEST_EN, 1);
1090
1091 if (hws->funcs.dpp_pg_control)
1092 hws->funcs.dpp_pg_control(hws, pipe_ctx->plane_res.dpp->inst, true);
1093
1094 if (hws->funcs.hubp_pg_control)
1095 hws->funcs.hubp_pg_control(hws, pipe_ctx->plane_res.hubp->inst, true);
1096
1097 REG_SET(DC_IP_REQUEST_CNTL, 0,
1098 IP_REQUEST_EN, 0);
1099 DC_LOG_DEBUG(
1100 "Un-gated front end for pipe %d\n", pipe_ctx->plane_res.hubp->inst);
1101 }
1102 }
1103
1104 static void dcn20_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx,
1105 struct dc_state *context)
1106 {
1107
1108
1109
1110 dcn20_power_on_plane(dc->hwseq, pipe_ctx);
1111
1112
1113 pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true);
1114
1115
1116 pipe_ctx->plane_res.hubp->funcs->hubp_init(pipe_ctx->plane_res.hubp);
1117
1118
1119 pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
1120 pipe_ctx->stream_res.opp,
1121 true);
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160 if (dc->vm_pa_config.valid) {
1161 struct vm_system_aperture_param apt;
1162
1163 apt.sys_default.quad_part = 0;
1164
1165 apt.sys_low.quad_part = dc->vm_pa_config.system_aperture.start_addr;
1166 apt.sys_high.quad_part = dc->vm_pa_config.system_aperture.end_addr;
1167
1168
1169 pipe_ctx->plane_res.hubp->funcs->hubp_set_vm_system_aperture_settings(pipe_ctx->plane_res.hubp, &apt);
1170 }
1171
1172 if (!pipe_ctx->top_pipe
1173 && pipe_ctx->plane_state
1174 && pipe_ctx->plane_state->flip_int_enabled
1175 && pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_int)
1176 pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_int(pipe_ctx->plane_res.hubp);
1177
1178
1179
1180
1181 }
1182
1183 void dcn20_pipe_control_lock(
1184 struct dc *dc,
1185 struct pipe_ctx *pipe,
1186 bool lock)
1187 {
1188 struct pipe_ctx *temp_pipe;
1189 bool flip_immediate = false;
1190
1191
1192
1193
1194 if (!pipe || pipe->top_pipe)
1195 return;
1196
1197 if (pipe->plane_state != NULL)
1198 flip_immediate = pipe->plane_state->flip_immediate;
1199
1200 if (pipe->stream_res.gsl_group > 0) {
1201 temp_pipe = pipe->bottom_pipe;
1202 while (!flip_immediate && temp_pipe) {
1203 if (temp_pipe->plane_state != NULL)
1204 flip_immediate = temp_pipe->plane_state->flip_immediate;
1205 temp_pipe = temp_pipe->bottom_pipe;
1206 }
1207 }
1208
1209 if (flip_immediate && lock) {
1210 const int TIMEOUT_FOR_FLIP_PENDING = 100000;
1211 int i;
1212
1213 temp_pipe = pipe;
1214 while (temp_pipe) {
1215 if (temp_pipe->plane_state && temp_pipe->plane_state->flip_immediate) {
1216 for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING; ++i) {
1217 if (!temp_pipe->plane_res.hubp->funcs->hubp_is_flip_pending(temp_pipe->plane_res.hubp))
1218 break;
1219 udelay(1);
1220 }
1221
1222
1223 ASSERT(i != TIMEOUT_FOR_FLIP_PENDING);
1224 }
1225 temp_pipe = temp_pipe->bottom_pipe;
1226 }
1227 }
1228
1229
1230
1231
1232 if (lock && (pipe->bottom_pipe != NULL || !flip_immediate))
1233 if ((flip_immediate && pipe->stream_res.gsl_group == 0) ||
1234 (!flip_immediate && pipe->stream_res.gsl_group > 0))
1235 dcn20_setup_gsl_group_as_lock(dc, pipe, flip_immediate);
1236
1237 if (pipe->plane_state != NULL)
1238 flip_immediate = pipe->plane_state->flip_immediate;
1239
1240 temp_pipe = pipe->bottom_pipe;
1241 while (flip_immediate && temp_pipe) {
1242 if (temp_pipe->plane_state != NULL)
1243 flip_immediate = temp_pipe->plane_state->flip_immediate;
1244 temp_pipe = temp_pipe->bottom_pipe;
1245 }
1246
1247 if (!lock && pipe->stream_res.gsl_group > 0 && pipe->plane_state &&
1248 !flip_immediate)
1249 dcn20_setup_gsl_group_as_lock(dc, pipe, false);
1250
1251 if (pipe->stream && should_use_dmub_lock(pipe->stream->link)) {
1252 union dmub_hw_lock_flags hw_locks = { 0 };
1253 struct dmub_hw_lock_inst_flags inst_flags = { 0 };
1254
1255 hw_locks.bits.lock_pipe = 1;
1256 inst_flags.otg_inst = pipe->stream_res.tg->inst;
1257
1258 if (pipe->plane_state != NULL)
1259 hw_locks.bits.triple_buffer_lock = pipe->plane_state->triplebuffer_flips;
1260
1261 dmub_hw_lock_mgr_cmd(dc->ctx->dmub_srv,
1262 lock,
1263 &hw_locks,
1264 &inst_flags);
1265 } else if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
1266 union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
1267 hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
1268 hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
1269 hw_lock_cmd.bits.lock_pipe = 1;
1270 hw_lock_cmd.bits.otg_inst = pipe->stream_res.tg->inst;
1271 hw_lock_cmd.bits.lock = lock;
1272 if (!lock)
1273 hw_lock_cmd.bits.should_release = 1;
1274 dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd);
1275 } else if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) {
1276 if (lock)
1277 pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg);
1278 else
1279 pipe->stream_res.tg->funcs->triplebuffer_unlock(pipe->stream_res.tg);
1280 } else {
1281 if (lock)
1282 pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
1283 else
1284 pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
1285 }
1286 }
1287
1288 static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx *new_pipe)
1289 {
1290 new_pipe->update_flags.raw = 0;
1291
1292
1293 if (!old_pipe->plane_state && !new_pipe->plane_state)
1294 return;
1295
1296 if (!old_pipe->plane_state && new_pipe->plane_state) {
1297 new_pipe->update_flags.bits.enable = 1;
1298 new_pipe->update_flags.bits.mpcc = 1;
1299 new_pipe->update_flags.bits.dppclk = 1;
1300 new_pipe->update_flags.bits.hubp_interdependent = 1;
1301 new_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1;
1302 new_pipe->update_flags.bits.gamut_remap = 1;
1303 new_pipe->update_flags.bits.scaler = 1;
1304 new_pipe->update_flags.bits.viewport = 1;
1305 new_pipe->update_flags.bits.det_size = 1;
1306 if (!new_pipe->top_pipe && !new_pipe->prev_odm_pipe) {
1307 new_pipe->update_flags.bits.odm = 1;
1308 new_pipe->update_flags.bits.global_sync = 1;
1309 }
1310 return;
1311 }
1312
1313
1314
1315
1316
1317
1318 if (new_pipe->stream && new_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM)
1319 new_pipe->update_flags.bits.enable = 1;
1320
1321
1322
1323
1324 if (old_pipe->plane_state && old_pipe->plane_state->is_phantom &&
1325 new_pipe->plane_state && !new_pipe->plane_state->is_phantom)
1326 new_pipe->update_flags.bits.enable = 1;
1327
1328 if (old_pipe->plane_state && !new_pipe->plane_state) {
1329 new_pipe->update_flags.bits.disable = 1;
1330 return;
1331 }
1332
1333
1334 if (old_pipe->plane_state != new_pipe->plane_state) {
1335 new_pipe->update_flags.bits.plane_changed = true;
1336 }
1337
1338
1339 if (!new_pipe->top_pipe && !new_pipe->prev_odm_pipe) {
1340
1341 if ((old_pipe->next_odm_pipe && new_pipe->next_odm_pipe
1342 && old_pipe->next_odm_pipe->pipe_idx != new_pipe->next_odm_pipe->pipe_idx)
1343 || (!old_pipe->next_odm_pipe && new_pipe->next_odm_pipe)
1344 || (old_pipe->next_odm_pipe && !new_pipe->next_odm_pipe)
1345 || old_pipe->stream_res.opp != new_pipe->stream_res.opp)
1346 new_pipe->update_flags.bits.odm = 1;
1347
1348
1349 if (old_pipe->pipe_dlg_param.vready_offset != new_pipe->pipe_dlg_param.vready_offset
1350 || old_pipe->pipe_dlg_param.vstartup_start != new_pipe->pipe_dlg_param.vstartup_start
1351 || old_pipe->pipe_dlg_param.vupdate_offset != new_pipe->pipe_dlg_param.vupdate_offset
1352 || old_pipe->pipe_dlg_param.vupdate_width != new_pipe->pipe_dlg_param.vupdate_width)
1353 new_pipe->update_flags.bits.global_sync = 1;
1354 }
1355
1356 if (old_pipe->det_buffer_size_kb != new_pipe->det_buffer_size_kb)
1357 new_pipe->update_flags.bits.det_size = 1;
1358
1359
1360
1361
1362
1363
1364
1365
1366 if (old_pipe->stream_res.opp != new_pipe->stream_res.opp)
1367 new_pipe->update_flags.bits.opp_changed = 1;
1368 if (old_pipe->stream_res.tg != new_pipe->stream_res.tg)
1369 new_pipe->update_flags.bits.tg_changed = 1;
1370
1371
1372
1373
1374
1375
1376 if (old_pipe->plane_res.dpp != new_pipe->plane_res.dpp
1377 || old_pipe->stream_res.opp != new_pipe->stream_res.opp)
1378 new_pipe->update_flags.bits.mpcc = 1;
1379
1380
1381 if (old_pipe->plane_res.bw.dppclk_khz != new_pipe->plane_res.bw.dppclk_khz)
1382 new_pipe->update_flags.bits.dppclk = 1;
1383
1384
1385 if (memcmp(&old_pipe->plane_res.scl_data, &new_pipe->plane_res.scl_data, sizeof(struct scaler_data)))
1386 new_pipe->update_flags.bits.scaler = 1;
1387
1388 if (memcmp(&old_pipe->plane_res.scl_data.viewport, &new_pipe->plane_res.scl_data.viewport, sizeof(struct rect))
1389 || memcmp(&old_pipe->plane_res.scl_data.viewport_c,
1390 &new_pipe->plane_res.scl_data.viewport_c, sizeof(struct rect)))
1391 new_pipe->update_flags.bits.viewport = 1;
1392
1393
1394 {
1395 struct _vcs_dpi_display_dlg_regs_st old_dlg_attr = old_pipe->dlg_regs;
1396 struct _vcs_dpi_display_ttu_regs_st old_ttu_attr = old_pipe->ttu_regs;
1397 struct _vcs_dpi_display_dlg_regs_st *new_dlg_attr = &new_pipe->dlg_regs;
1398 struct _vcs_dpi_display_ttu_regs_st *new_ttu_attr = &new_pipe->ttu_regs;
1399
1400
1401 if (old_dlg_attr.dst_y_prefetch != new_dlg_attr->dst_y_prefetch ||
1402 old_dlg_attr.vratio_prefetch != new_dlg_attr->vratio_prefetch ||
1403 old_dlg_attr.vratio_prefetch_c != new_dlg_attr->vratio_prefetch_c ||
1404 old_dlg_attr.dst_y_per_vm_vblank != new_dlg_attr->dst_y_per_vm_vblank ||
1405 old_dlg_attr.dst_y_per_row_vblank != new_dlg_attr->dst_y_per_row_vblank ||
1406 old_dlg_attr.dst_y_per_vm_flip != new_dlg_attr->dst_y_per_vm_flip ||
1407 old_dlg_attr.dst_y_per_row_flip != new_dlg_attr->dst_y_per_row_flip ||
1408 old_dlg_attr.refcyc_per_meta_chunk_vblank_l != new_dlg_attr->refcyc_per_meta_chunk_vblank_l ||
1409 old_dlg_attr.refcyc_per_meta_chunk_vblank_c != new_dlg_attr->refcyc_per_meta_chunk_vblank_c ||
1410 old_dlg_attr.refcyc_per_meta_chunk_flip_l != new_dlg_attr->refcyc_per_meta_chunk_flip_l ||
1411 old_dlg_attr.refcyc_per_line_delivery_pre_l != new_dlg_attr->refcyc_per_line_delivery_pre_l ||
1412 old_dlg_attr.refcyc_per_line_delivery_pre_c != new_dlg_attr->refcyc_per_line_delivery_pre_c ||
1413 old_ttu_attr.refcyc_per_req_delivery_pre_l != new_ttu_attr->refcyc_per_req_delivery_pre_l ||
1414 old_ttu_attr.refcyc_per_req_delivery_pre_c != new_ttu_attr->refcyc_per_req_delivery_pre_c ||
1415 old_ttu_attr.refcyc_per_req_delivery_pre_cur0 != new_ttu_attr->refcyc_per_req_delivery_pre_cur0 ||
1416 old_ttu_attr.refcyc_per_req_delivery_pre_cur1 != new_ttu_attr->refcyc_per_req_delivery_pre_cur1 ||
1417 old_ttu_attr.min_ttu_vblank != new_ttu_attr->min_ttu_vblank ||
1418 old_ttu_attr.qos_level_flip != new_ttu_attr->qos_level_flip) {
1419 old_dlg_attr.dst_y_prefetch = new_dlg_attr->dst_y_prefetch;
1420 old_dlg_attr.vratio_prefetch = new_dlg_attr->vratio_prefetch;
1421 old_dlg_attr.vratio_prefetch_c = new_dlg_attr->vratio_prefetch_c;
1422 old_dlg_attr.dst_y_per_vm_vblank = new_dlg_attr->dst_y_per_vm_vblank;
1423 old_dlg_attr.dst_y_per_row_vblank = new_dlg_attr->dst_y_per_row_vblank;
1424 old_dlg_attr.dst_y_per_vm_flip = new_dlg_attr->dst_y_per_vm_flip;
1425 old_dlg_attr.dst_y_per_row_flip = new_dlg_attr->dst_y_per_row_flip;
1426 old_dlg_attr.refcyc_per_meta_chunk_vblank_l = new_dlg_attr->refcyc_per_meta_chunk_vblank_l;
1427 old_dlg_attr.refcyc_per_meta_chunk_vblank_c = new_dlg_attr->refcyc_per_meta_chunk_vblank_c;
1428 old_dlg_attr.refcyc_per_meta_chunk_flip_l = new_dlg_attr->refcyc_per_meta_chunk_flip_l;
1429 old_dlg_attr.refcyc_per_line_delivery_pre_l = new_dlg_attr->refcyc_per_line_delivery_pre_l;
1430 old_dlg_attr.refcyc_per_line_delivery_pre_c = new_dlg_attr->refcyc_per_line_delivery_pre_c;
1431 old_ttu_attr.refcyc_per_req_delivery_pre_l = new_ttu_attr->refcyc_per_req_delivery_pre_l;
1432 old_ttu_attr.refcyc_per_req_delivery_pre_c = new_ttu_attr->refcyc_per_req_delivery_pre_c;
1433 old_ttu_attr.refcyc_per_req_delivery_pre_cur0 = new_ttu_attr->refcyc_per_req_delivery_pre_cur0;
1434 old_ttu_attr.refcyc_per_req_delivery_pre_cur1 = new_ttu_attr->refcyc_per_req_delivery_pre_cur1;
1435 old_ttu_attr.min_ttu_vblank = new_ttu_attr->min_ttu_vblank;
1436 old_ttu_attr.qos_level_flip = new_ttu_attr->qos_level_flip;
1437 new_pipe->update_flags.bits.hubp_interdependent = 1;
1438 }
1439
1440 if (memcmp(&old_dlg_attr, &new_pipe->dlg_regs, sizeof(old_dlg_attr)) ||
1441 memcmp(&old_ttu_attr, &new_pipe->ttu_regs, sizeof(old_ttu_attr)) ||
1442 memcmp(&old_pipe->rq_regs, &new_pipe->rq_regs, sizeof(old_pipe->rq_regs)))
1443 new_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1;
1444 }
1445 }
1446
1447 static void dcn20_update_dchubp_dpp(
1448 struct dc *dc,
1449 struct pipe_ctx *pipe_ctx,
1450 struct dc_state *context)
1451 {
1452 struct dce_hwseq *hws = dc->hwseq;
1453 struct hubp *hubp = pipe_ctx->plane_res.hubp;
1454 struct dpp *dpp = pipe_ctx->plane_res.dpp;
1455 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1456 struct dccg *dccg = dc->res_pool->dccg;
1457 bool viewport_changed = false;
1458
1459 if (pipe_ctx->update_flags.bits.dppclk)
1460 dpp->funcs->dpp_dppclk_control(dpp, false, true);
1461
1462 if (pipe_ctx->update_flags.bits.enable)
1463 dccg->funcs->update_dpp_dto(dccg, dpp->inst, pipe_ctx->plane_res.bw.dppclk_khz);
1464
1465
1466
1467
1468
1469 if (pipe_ctx->update_flags.bits.hubp_rq_dlg_ttu) {
1470 hubp->funcs->hubp_vtg_sel(hubp, pipe_ctx->stream_res.tg->inst);
1471
1472 hubp->funcs->hubp_setup(
1473 hubp,
1474 &pipe_ctx->dlg_regs,
1475 &pipe_ctx->ttu_regs,
1476 &pipe_ctx->rq_regs,
1477 &pipe_ctx->pipe_dlg_param);
1478
1479 if (hubp->funcs->set_unbounded_requesting)
1480 hubp->funcs->set_unbounded_requesting(hubp, pipe_ctx->unbounded_req);
1481 }
1482 if (pipe_ctx->update_flags.bits.hubp_interdependent)
1483 hubp->funcs->hubp_setup_interdependent(
1484 hubp,
1485 &pipe_ctx->dlg_regs,
1486 &pipe_ctx->ttu_regs);
1487
1488 if (pipe_ctx->update_flags.bits.enable ||
1489 pipe_ctx->update_flags.bits.plane_changed ||
1490 plane_state->update_flags.bits.bpp_change ||
1491 plane_state->update_flags.bits.input_csc_change ||
1492 plane_state->update_flags.bits.color_space_change ||
1493 plane_state->update_flags.bits.coeff_reduction_change) {
1494 struct dc_bias_and_scale bns_params = {0};
1495
1496
1497 dpp->funcs->dpp_setup(dpp,
1498 plane_state->format,
1499 EXPANSION_MODE_ZERO,
1500 plane_state->input_csc_color_matrix,
1501 plane_state->color_space,
1502 NULL);
1503
1504 if (dpp->funcs->dpp_program_bias_and_scale) {
1505
1506 build_prescale_params(&bns_params, plane_state);
1507 dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
1508 }
1509 }
1510
1511 if (pipe_ctx->update_flags.bits.mpcc
1512 || pipe_ctx->update_flags.bits.plane_changed
1513 || plane_state->update_flags.bits.global_alpha_change
1514 || plane_state->update_flags.bits.per_pixel_alpha_change) {
1515
1516 int mpcc_inst = hubp->inst;
1517 int opp_inst;
1518 int opp_count = dc->res_pool->pipe_count;
1519
1520 for (opp_inst = 0; opp_inst < opp_count; opp_inst++) {
1521 if (dc->res_pool->opps[opp_inst]->mpcc_disconnect_pending[mpcc_inst]) {
1522 dc->res_pool->mpc->funcs->wait_for_idle(dc->res_pool->mpc, mpcc_inst);
1523 dc->res_pool->opps[opp_inst]->mpcc_disconnect_pending[mpcc_inst] = false;
1524 break;
1525 }
1526 }
1527 hws->funcs.update_mpcc(dc, pipe_ctx);
1528 }
1529
1530 if (pipe_ctx->update_flags.bits.scaler ||
1531 plane_state->update_flags.bits.scaling_change ||
1532 plane_state->update_flags.bits.position_change ||
1533 plane_state->update_flags.bits.per_pixel_alpha_change ||
1534 pipe_ctx->stream->update_flags.bits.scaling) {
1535 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->plane_state->per_pixel_alpha;
1536 ASSERT(pipe_ctx->plane_res.scl_data.lb_params.depth == LB_PIXEL_DEPTH_36BPP);
1537
1538 pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler(
1539 pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data);
1540 }
1541
1542 if (pipe_ctx->update_flags.bits.viewport ||
1543 (context == dc->current_state && plane_state->update_flags.bits.position_change) ||
1544 (context == dc->current_state && plane_state->update_flags.bits.scaling_change) ||
1545 (context == dc->current_state && pipe_ctx->stream->update_flags.bits.scaling)) {
1546
1547 hubp->funcs->mem_program_viewport(
1548 hubp,
1549 &pipe_ctx->plane_res.scl_data.viewport,
1550 &pipe_ctx->plane_res.scl_data.viewport_c);
1551 viewport_changed = true;
1552 }
1553
1554
1555 if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed ||
1556 pipe_ctx->update_flags.bits.scaler || viewport_changed == true) &&
1557 pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {
1558 dc->hwss.set_cursor_position(pipe_ctx);
1559 dc->hwss.set_cursor_attribute(pipe_ctx);
1560
1561 if (dc->hwss.set_cursor_sdr_white_level)
1562 dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
1563 }
1564
1565
1566
1567 if (pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed
1568 || pipe_ctx->update_flags.bits.plane_changed
1569 || pipe_ctx->stream->update_flags.bits.gamut_remap
1570 || pipe_ctx->stream->update_flags.bits.out_csc) {
1571
1572 dc->hwss.program_gamut_remap(pipe_ctx);
1573
1574
1575 dc->hwss.program_output_csc(dc,
1576 pipe_ctx,
1577 pipe_ctx->stream->output_color_space,
1578 pipe_ctx->stream->csc_color_matrix.matrix,
1579 hubp->opp_id);
1580 }
1581
1582 if (pipe_ctx->update_flags.bits.enable ||
1583 pipe_ctx->update_flags.bits.plane_changed ||
1584 pipe_ctx->update_flags.bits.opp_changed ||
1585 plane_state->update_flags.bits.pixel_format_change ||
1586 plane_state->update_flags.bits.horizontal_mirror_change ||
1587 plane_state->update_flags.bits.rotation_change ||
1588 plane_state->update_flags.bits.swizzle_change ||
1589 plane_state->update_flags.bits.dcc_change ||
1590 plane_state->update_flags.bits.bpp_change ||
1591 plane_state->update_flags.bits.scaling_change ||
1592 plane_state->update_flags.bits.plane_size_change) {
1593 struct plane_size size = plane_state->plane_size;
1594
1595 size.surface_size = pipe_ctx->plane_res.scl_data.viewport;
1596 hubp->funcs->hubp_program_surface_config(
1597 hubp,
1598 plane_state->format,
1599 &plane_state->tiling_info,
1600 &size,
1601 plane_state->rotation,
1602 &plane_state->dcc,
1603 plane_state->horizontal_mirror,
1604 0);
1605 hubp->power_gated = false;
1606 }
1607
1608 if (pipe_ctx->update_flags.bits.enable ||
1609 pipe_ctx->update_flags.bits.plane_changed ||
1610 plane_state->update_flags.bits.addr_update)
1611 hws->funcs.update_plane_addr(dc, pipe_ctx);
1612
1613 if (pipe_ctx->update_flags.bits.enable)
1614 hubp->funcs->set_blank(hubp, false);
1615
1616 if (pipe_ctx->stream && pipe_ctx->stream->mall_stream_config.type == SUBVP_PHANTOM
1617 && hubp->funcs->phantom_hubp_post_enable)
1618 hubp->funcs->phantom_hubp_post_enable(hubp);
1619 }
1620
1621
1622 static void dcn20_program_pipe(
1623 struct dc *dc,
1624 struct pipe_ctx *pipe_ctx,
1625 struct dc_state *context)
1626 {
1627 struct dce_hwseq *hws = dc->hwseq;
1628
1629
1630 if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->stream->update_flags.bits.abm_level)
1631 && !pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe)
1632 hws->funcs.blank_pixel_data(dc, pipe_ctx, !pipe_ctx->plane_state->visible);
1633
1634
1635 if (pipe_ctx->update_flags.bits.global_sync && !pipe_ctx->top_pipe
1636 && !pipe_ctx->prev_odm_pipe) {
1637 pipe_ctx->stream_res.tg->funcs->program_global_sync(
1638 pipe_ctx->stream_res.tg,
1639 pipe_ctx->pipe_dlg_param.vready_offset,
1640 pipe_ctx->pipe_dlg_param.vstartup_start,
1641 pipe_ctx->pipe_dlg_param.vupdate_offset,
1642 pipe_ctx->pipe_dlg_param.vupdate_width);
1643
1644 if (pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) {
1645 pipe_ctx->stream_res.tg->funcs->wait_for_state(
1646 pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK);
1647 pipe_ctx->stream_res.tg->funcs->wait_for_state(
1648 pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
1649 }
1650
1651 pipe_ctx->stream_res.tg->funcs->set_vtg_params(
1652 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, true);
1653
1654 if (hws->funcs.setup_vupdate_interrupt)
1655 hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
1656 }
1657
1658 if (pipe_ctx->update_flags.bits.odm)
1659 hws->funcs.update_odm(dc, context, pipe_ctx);
1660
1661 if (pipe_ctx->update_flags.bits.enable) {
1662 dcn20_enable_plane(dc, pipe_ctx, context);
1663 if (dc->res_pool->hubbub->funcs->force_wm_propagate_to_pipes)
1664 dc->res_pool->hubbub->funcs->force_wm_propagate_to_pipes(dc->res_pool->hubbub);
1665 }
1666
1667 if (dc->res_pool->hubbub->funcs->program_det_size && pipe_ctx->update_flags.bits.det_size)
1668 dc->res_pool->hubbub->funcs->program_det_size(
1669 dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->det_buffer_size_kb);
1670
1671 if (pipe_ctx->update_flags.raw || pipe_ctx->plane_state->update_flags.raw || pipe_ctx->stream->update_flags.raw)
1672 dcn20_update_dchubp_dpp(dc, pipe_ctx, context);
1673
1674 if (pipe_ctx->update_flags.bits.enable
1675 || pipe_ctx->plane_state->update_flags.bits.hdr_mult)
1676 hws->funcs.set_hdr_multiplier(pipe_ctx);
1677
1678 if (pipe_ctx->update_flags.bits.enable ||
1679 pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
1680 pipe_ctx->plane_state->update_flags.bits.gamma_change)
1681 hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state);
1682
1683
1684
1685
1686
1687 if (pipe_ctx->update_flags.bits.enable || pipe_ctx->stream->update_flags.bits.out_tf)
1688 hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
1689
1690
1691
1692
1693
1694
1695 if (pipe_ctx->update_flags.bits.enable
1696 || pipe_ctx->update_flags.bits.opp_changed) {
1697
1698 pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
1699 pipe_ctx->stream_res.opp,
1700 COLOR_SPACE_YCBCR601,
1701 pipe_ctx->stream->timing.display_color_depth,
1702 pipe_ctx->stream->signal);
1703
1704 pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
1705 pipe_ctx->stream_res.opp,
1706 &pipe_ctx->stream->bit_depth_params,
1707 &pipe_ctx->stream->clamping);
1708 }
1709 }
1710
1711 void dcn20_program_front_end_for_ctx(
1712 struct dc *dc,
1713 struct dc_state *context)
1714 {
1715 int i;
1716 struct dce_hwseq *hws = dc->hwseq;
1717 DC_LOGGER_INIT(dc->ctx->logger);
1718
1719
1720 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1721 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1722 struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
1723
1724 if (pipe_ctx->stream == old_pipe_ctx->stream)
1725 pipe_ctx->stream_res.gsl_group = old_pipe_ctx->stream_res.gsl_group;
1726 }
1727
1728 if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
1729 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1730 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1731
1732 if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->plane_state) {
1733 ASSERT(!pipe_ctx->plane_state->triplebuffer_flips);
1734
1735 dc->hwss.program_triplebuffer(
1736 dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips);
1737 }
1738 }
1739 }
1740
1741
1742 for (i = 0; i < dc->res_pool->pipe_count; i++)
1743 dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i],
1744 &context->res_ctx.pipe_ctx[i]);
1745
1746
1747 for (i = 0; i < dc->res_pool->pipe_count; i++)
1748 if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable
1749 && !context->res_ctx.pipe_ctx[i].top_pipe
1750 && !context->res_ctx.pipe_ctx[i].prev_odm_pipe
1751 && context->res_ctx.pipe_ctx[i].stream)
1752 hws->funcs.blank_pixel_data(dc, &context->res_ctx.pipe_ctx[i], true);
1753
1754
1755
1756 for (i = 0; i < dc->res_pool->pipe_count; i++)
1757 if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable
1758 || context->res_ctx.pipe_ctx[i].update_flags.bits.opp_changed) {
1759 struct hubbub *hubbub = dc->res_pool->hubbub;
1760
1761
1762
1763
1764
1765
1766
1767 if (hubbub->funcs->program_det_size && (context->res_ctx.pipe_ctx[i].update_flags.bits.disable ||
1768 (context->res_ctx.pipe_ctx[i].plane_state && context->res_ctx.pipe_ctx[i].plane_state->is_phantom)))
1769 hubbub->funcs->program_det_size(hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
1770 hws->funcs.plane_atomic_disconnect(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
1771 DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx);
1772 }
1773
1774
1775
1776
1777
1778 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1779 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1780
1781 if (pipe->plane_state && !pipe->top_pipe) {
1782 while (pipe) {
1783 if (hws->funcs.program_pipe)
1784 hws->funcs.program_pipe(dc, pipe, context);
1785 else {
1786
1787
1788
1789
1790
1791
1792
1793 if (pipe->stream && pipe->stream->mall_stream_config.type != SUBVP_PHANTOM)
1794 dcn20_program_pipe(dc, pipe, context);
1795 }
1796
1797 pipe = pipe->bottom_pipe;
1798 }
1799 }
1800
1801 pipe = &context->res_ctx.pipe_ctx[i];
1802 if (!pipe->top_pipe && !pipe->prev_odm_pipe
1803 && pipe->stream && pipe->stream->num_wb_info > 0
1804 && (pipe->update_flags.raw || (pipe->plane_state && pipe->plane_state->update_flags.raw)
1805 || pipe->stream->update_flags.raw)
1806 && hws->funcs.program_all_writeback_pipes_in_tree)
1807 hws->funcs.program_all_writeback_pipes_in_tree(dc, pipe->stream, context);
1808
1809
1810 if (hws->wa.wait_hubpret_read_start_during_mpo_transition &&
1811 !pipe->top_pipe &&
1812 pipe->stream &&
1813 pipe->plane_res.hubp->funcs->hubp_wait_pipe_read_start &&
1814 dc->current_state->stream_status[0].plane_count == 1 &&
1815 context->stream_status[0].plane_count > 1) {
1816 pipe->plane_res.hubp->funcs->hubp_wait_pipe_read_start(pipe->plane_res.hubp);
1817 }
1818 }
1819 }
1820
1821 void dcn20_post_unlock_program_front_end(
1822 struct dc *dc,
1823 struct dc_state *context)
1824 {
1825 int i;
1826 const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100;
1827 struct dce_hwseq *hwseq = dc->hwseq;
1828
1829 DC_LOGGER_INIT(dc->ctx->logger);
1830
1831 for (i = 0; i < dc->res_pool->pipe_count; i++)
1832 if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable)
1833 dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
1834
1835
1836
1837
1838
1839
1840
1841 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1842 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1843
1844 if (pipe->plane_state && !pipe->top_pipe && pipe->update_flags.bits.enable &&
1845 pipe->stream->mall_stream_config.type != SUBVP_PHANTOM) {
1846 struct hubp *hubp = pipe->plane_res.hubp;
1847 int j = 0;
1848
1849 for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS*1000
1850 && hubp->funcs->hubp_is_flip_pending(hubp); j++)
1851 mdelay(1);
1852 }
1853 }
1854
1855 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1856 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1857 struct pipe_ctx *mpcc_pipe;
1858
1859 if (pipe->vtp_locked) {
1860 dc->hwseq->funcs.wait_for_blank_complete(pipe->stream_res.opp);
1861 pipe->plane_res.hubp->funcs->set_blank(pipe->plane_res.hubp, true);
1862 pipe->vtp_locked = false;
1863
1864 for (mpcc_pipe = pipe->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe)
1865 mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, true);
1866
1867 for (i = 0; i < dc->res_pool->pipe_count; i++)
1868 if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable)
1869 dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
1870 }
1871 }
1872
1873 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1874 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1875 struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
1876
1877
1878
1879
1880
1881
1882 if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM &&
1883 old_pipe->stream && old_pipe->stream->mall_stream_config.type != SUBVP_PHANTOM) {
1884 old_pipe->stream_res.tg->funcs->wait_for_state(
1885 old_pipe->stream_res.tg,
1886 CRTC_STATE_VBLANK);
1887 old_pipe->stream_res.tg->funcs->wait_for_state(
1888 old_pipe->stream_res.tg,
1889 CRTC_STATE_VACTIVE);
1890 }
1891 }
1892
1893 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1894 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1895
1896 if (pipe->plane_state && !pipe->top_pipe) {
1897
1898
1899
1900
1901
1902 if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM)
1903 dcn20_program_pipe(dc, pipe, context);
1904 }
1905 }
1906
1907
1908
1909
1910 if (hwseq->funcs.program_mall_pipe_config)
1911 hwseq->funcs.program_mall_pipe_config(dc, context);
1912
1913
1914 if (hwseq->wa.DEGVIDCN21)
1915 dc->res_pool->hubbub->funcs->apply_DEDCN21_147_wa(dc->res_pool->hubbub);
1916
1917
1918
1919 if (hwseq->wa.disallow_self_refresh_during_multi_plane_transition) {
1920
1921 if (dc->current_state->stream_status[0].plane_count == 1 &&
1922 context->stream_status[0].plane_count > 1) {
1923
1924 struct timing_generator *tg = dc->res_pool->timing_generators[0];
1925
1926 dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, false);
1927
1928 hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied = true;
1929 hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied_on_frame = tg->funcs->get_frame_count(tg);
1930 }
1931 }
1932 }
1933
1934 void dcn20_prepare_bandwidth(
1935 struct dc *dc,
1936 struct dc_state *context)
1937 {
1938 struct hubbub *hubbub = dc->res_pool->hubbub;
1939 unsigned int compbuf_size_kb = 0;
1940 unsigned int cache_wm_a = context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns;
1941 unsigned int i;
1942
1943 dc->clk_mgr->funcs->update_clocks(
1944 dc->clk_mgr,
1945 context,
1946 false);
1947
1948 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1949 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1950
1951
1952 if (pipe->stream && pipe->stream->mall_stream_config.type != SUBVP_NONE) {
1953 context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = 4U * 1000U * 1000U * 1000U;
1954 break;
1955 }
1956 }
1957
1958
1959 dc->wm_optimized_required = hubbub->funcs->program_watermarks(hubbub,
1960 &context->bw_ctx.bw.dcn.watermarks,
1961 dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
1962 false);
1963
1964
1965
1966 context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = cache_wm_a;
1967
1968
1969 if (hubbub->funcs->program_compbuf_size) {
1970 if (context->bw_ctx.dml.ip.min_comp_buffer_size_kbytes)
1971 compbuf_size_kb = context->bw_ctx.dml.ip.min_comp_buffer_size_kbytes;
1972 else
1973 compbuf_size_kb = context->bw_ctx.bw.dcn.compbuf_size_kb;
1974
1975 hubbub->funcs->program_compbuf_size(hubbub, compbuf_size_kb, false);
1976 }
1977 }
1978
1979 void dcn20_optimize_bandwidth(
1980 struct dc *dc,
1981 struct dc_state *context)
1982 {
1983 struct hubbub *hubbub = dc->res_pool->hubbub;
1984 int i;
1985
1986 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1987 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1988
1989
1990 if (pipe->stream && pipe->stream->mall_stream_config.type != SUBVP_NONE) {
1991 context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = 4U * 1000U * 1000U * 1000U;
1992 break;
1993 }
1994 }
1995
1996
1997 hubbub->funcs->program_watermarks(hubbub,
1998 &context->bw_ctx.bw.dcn.watermarks,
1999 dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
2000 true);
2001
2002 if (dc->clk_mgr->dc_mode_softmax_enabled)
2003 if (dc->clk_mgr->clks.dramclk_khz > dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000 &&
2004 context->bw_ctx.bw.dcn.clk.dramclk_khz <= dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000)
2005 dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->dc_mode_softmax_memclk);
2006
2007 dc->clk_mgr->funcs->update_clocks(
2008 dc->clk_mgr,
2009 context,
2010 true);
2011 if (dc_extended_blank_supported(dc) && context->bw_ctx.bw.dcn.clk.zstate_support == DCN_ZSTATE_SUPPORT_ALLOW) {
2012 for (i = 0; i < dc->res_pool->pipe_count; ++i) {
2013 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2014
2015 if (pipe_ctx->stream && pipe_ctx->plane_res.hubp->funcs->program_extended_blank
2016 && pipe_ctx->stream->adjust.v_total_min == pipe_ctx->stream->adjust.v_total_max
2017 && pipe_ctx->stream->adjust.v_total_max > pipe_ctx->stream->timing.v_total)
2018 pipe_ctx->plane_res.hubp->funcs->program_extended_blank(pipe_ctx->plane_res.hubp,
2019 pipe_ctx->dlg_regs.optimized_min_dst_y_next_start);
2020 }
2021 }
2022
2023 if (hubbub->funcs->program_compbuf_size)
2024 hubbub->funcs->program_compbuf_size(hubbub, context->bw_ctx.bw.dcn.compbuf_size_kb, true);
2025 }
2026
2027 bool dcn20_update_bandwidth(
2028 struct dc *dc,
2029 struct dc_state *context)
2030 {
2031 int i;
2032 struct dce_hwseq *hws = dc->hwseq;
2033
2034
2035 if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false))
2036 return false;
2037
2038
2039 dc->hwss.prepare_bandwidth(dc, context);
2040
2041
2042 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2043 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2044
2045 if (pipe_ctx->plane_state == NULL)
2046 continue;
2047
2048 if (pipe_ctx->top_pipe == NULL) {
2049 bool blank = !is_pipe_tree_visible(pipe_ctx);
2050
2051 pipe_ctx->stream_res.tg->funcs->program_global_sync(
2052 pipe_ctx->stream_res.tg,
2053 pipe_ctx->pipe_dlg_param.vready_offset,
2054 pipe_ctx->pipe_dlg_param.vstartup_start,
2055 pipe_ctx->pipe_dlg_param.vupdate_offset,
2056 pipe_ctx->pipe_dlg_param.vupdate_width);
2057
2058 pipe_ctx->stream_res.tg->funcs->set_vtg_params(
2059 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, false);
2060
2061 if (pipe_ctx->prev_odm_pipe == NULL)
2062 hws->funcs.blank_pixel_data(dc, pipe_ctx, blank);
2063
2064 if (hws->funcs.setup_vupdate_interrupt)
2065 hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
2066 }
2067
2068 pipe_ctx->plane_res.hubp->funcs->hubp_setup(
2069 pipe_ctx->plane_res.hubp,
2070 &pipe_ctx->dlg_regs,
2071 &pipe_ctx->ttu_regs,
2072 &pipe_ctx->rq_regs,
2073 &pipe_ctx->pipe_dlg_param);
2074 }
2075
2076 return true;
2077 }
2078
2079 void dcn20_enable_writeback(
2080 struct dc *dc,
2081 struct dc_writeback_info *wb_info,
2082 struct dc_state *context)
2083 {
2084 struct dwbc *dwb;
2085 struct mcif_wb *mcif_wb;
2086 struct timing_generator *optc;
2087
2088 ASSERT(wb_info->dwb_pipe_inst < MAX_DWB_PIPES);
2089 ASSERT(wb_info->wb_enabled);
2090 dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
2091 mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst];
2092
2093
2094 optc = dc->res_pool->timing_generators[dwb->otg_inst];
2095 optc->funcs->set_dwb_source(optc, wb_info->dwb_pipe_inst);
2096
2097 mcif_wb->funcs->config_mcif_buf(mcif_wb, &wb_info->mcif_buf_params, wb_info->dwb_params.dest_height);
2098 mcif_wb->funcs->config_mcif_arb(mcif_wb, &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[wb_info->dwb_pipe_inst]);
2099
2100 mcif_wb->funcs->enable_mcif(mcif_wb);
2101
2102 dwb->funcs->enable(dwb, &wb_info->dwb_params);
2103
2104 }
2105
2106 void dcn20_disable_writeback(
2107 struct dc *dc,
2108 unsigned int dwb_pipe_inst)
2109 {
2110 struct dwbc *dwb;
2111 struct mcif_wb *mcif_wb;
2112
2113 ASSERT(dwb_pipe_inst < MAX_DWB_PIPES);
2114 dwb = dc->res_pool->dwbc[dwb_pipe_inst];
2115 mcif_wb = dc->res_pool->mcif_wb[dwb_pipe_inst];
2116
2117 dwb->funcs->disable(dwb);
2118 mcif_wb->funcs->disable_mcif(mcif_wb);
2119 }
2120
2121 bool dcn20_wait_for_blank_complete(
2122 struct output_pixel_processor *opp)
2123 {
2124 int counter;
2125
2126 for (counter = 0; counter < 1000; counter++) {
2127 if (opp->funcs->dpg_is_blanked(opp))
2128 break;
2129
2130 udelay(100);
2131 }
2132
2133 if (counter == 1000) {
2134 dm_error("DC: failed to blank crtc!\n");
2135 return false;
2136 }
2137
2138 return true;
2139 }
2140
2141 bool dcn20_dmdata_status_done(struct pipe_ctx *pipe_ctx)
2142 {
2143 struct hubp *hubp = pipe_ctx->plane_res.hubp;
2144
2145 if (!hubp)
2146 return false;
2147 return hubp->funcs->dmdata_status_done(hubp);
2148 }
2149
2150 void dcn20_disable_stream_gating(struct dc *dc, struct pipe_ctx *pipe_ctx)
2151 {
2152 struct dce_hwseq *hws = dc->hwseq;
2153
2154 if (pipe_ctx->stream_res.dsc) {
2155 struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
2156
2157 hws->funcs.dsc_pg_control(hws, pipe_ctx->stream_res.dsc->inst, true);
2158 while (odm_pipe) {
2159 hws->funcs.dsc_pg_control(hws, odm_pipe->stream_res.dsc->inst, true);
2160 odm_pipe = odm_pipe->next_odm_pipe;
2161 }
2162 }
2163 }
2164
2165 void dcn20_enable_stream_gating(struct dc *dc, struct pipe_ctx *pipe_ctx)
2166 {
2167 struct dce_hwseq *hws = dc->hwseq;
2168
2169 if (pipe_ctx->stream_res.dsc) {
2170 struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
2171
2172 hws->funcs.dsc_pg_control(hws, pipe_ctx->stream_res.dsc->inst, false);
2173 while (odm_pipe) {
2174 hws->funcs.dsc_pg_control(hws, odm_pipe->stream_res.dsc->inst, false);
2175 odm_pipe = odm_pipe->next_odm_pipe;
2176 }
2177 }
2178 }
2179
2180 void dcn20_set_dmdata_attributes(struct pipe_ctx *pipe_ctx)
2181 {
2182 struct dc_dmdata_attributes attr = { 0 };
2183 struct hubp *hubp = pipe_ctx->plane_res.hubp;
2184
2185 attr.dmdata_mode = DMDATA_HW_MODE;
2186 attr.dmdata_size =
2187 dc_is_hdmi_signal(pipe_ctx->stream->signal) ? 32 : 36;
2188 attr.address.quad_part =
2189 pipe_ctx->stream->dmdata_address.quad_part;
2190 attr.dmdata_dl_delta = 0;
2191 attr.dmdata_qos_mode = 0;
2192 attr.dmdata_qos_level = 0;
2193 attr.dmdata_repeat = 1;
2194 attr.dmdata_updated = 1;
2195 attr.dmdata_sw_data = NULL;
2196
2197 hubp->funcs->dmdata_set_attributes(hubp, &attr);
2198 }
2199
2200 void dcn20_init_vm_ctx(
2201 struct dce_hwseq *hws,
2202 struct dc *dc,
2203 struct dc_virtual_addr_space_config *va_config,
2204 int vmid)
2205 {
2206 struct dcn_hubbub_virt_addr_config config;
2207
2208 if (vmid == 0) {
2209 ASSERT(0);
2210 return;
2211 }
2212
2213 config.page_table_start_addr = va_config->page_table_start_addr;
2214 config.page_table_end_addr = va_config->page_table_end_addr;
2215 config.page_table_block_size = va_config->page_table_block_size_in_bytes;
2216 config.page_table_depth = va_config->page_table_depth;
2217 config.page_table_base_addr = va_config->page_table_base_addr;
2218
2219 dc->res_pool->hubbub->funcs->init_vm_ctx(dc->res_pool->hubbub, &config, vmid);
2220 }
2221
2222 int dcn20_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config)
2223 {
2224 struct dcn_hubbub_phys_addr_config config;
2225
2226 config.system_aperture.fb_top = pa_config->system_aperture.fb_top;
2227 config.system_aperture.fb_offset = pa_config->system_aperture.fb_offset;
2228 config.system_aperture.fb_base = pa_config->system_aperture.fb_base;
2229 config.system_aperture.agp_top = pa_config->system_aperture.agp_top;
2230 config.system_aperture.agp_bot = pa_config->system_aperture.agp_bot;
2231 config.system_aperture.agp_base = pa_config->system_aperture.agp_base;
2232 config.gart_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr;
2233 config.gart_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr;
2234 config.gart_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;
2235 config.page_table_default_page_addr = pa_config->page_table_default_page_addr;
2236
2237 return dc->res_pool->hubbub->funcs->init_dchub_sys_ctx(dc->res_pool->hubbub, &config);
2238 }
2239
2240 static bool patch_address_for_sbs_tb_stereo(
2241 struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr)
2242 {
2243 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2244 bool sec_split = pipe_ctx->top_pipe &&
2245 pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state;
2246 if (sec_split && plane_state->address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
2247 (pipe_ctx->stream->timing.timing_3d_format ==
2248 TIMING_3D_FORMAT_SIDE_BY_SIDE ||
2249 pipe_ctx->stream->timing.timing_3d_format ==
2250 TIMING_3D_FORMAT_TOP_AND_BOTTOM)) {
2251 *addr = plane_state->address.grph_stereo.left_addr;
2252 plane_state->address.grph_stereo.left_addr =
2253 plane_state->address.grph_stereo.right_addr;
2254 return true;
2255 }
2256
2257 if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE &&
2258 plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO) {
2259 plane_state->address.type = PLN_ADDR_TYPE_GRPH_STEREO;
2260 plane_state->address.grph_stereo.right_addr =
2261 plane_state->address.grph_stereo.left_addr;
2262 plane_state->address.grph_stereo.right_meta_addr =
2263 plane_state->address.grph_stereo.left_meta_addr;
2264 }
2265 return false;
2266 }
2267
2268 void dcn20_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)
2269 {
2270 bool addr_patched = false;
2271 PHYSICAL_ADDRESS_LOC addr;
2272 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2273
2274 if (plane_state == NULL)
2275 return;
2276
2277 addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr);
2278
2279
2280 vm_helper_mark_vmid_used(dc->vm_helper, plane_state->address.vmid, pipe_ctx->plane_res.hubp->inst);
2281
2282 pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr(
2283 pipe_ctx->plane_res.hubp,
2284 &plane_state->address,
2285 plane_state->flip_immediate);
2286
2287 plane_state->status.requested_address = plane_state->address;
2288
2289 if (plane_state->flip_immediate)
2290 plane_state->status.current_address = plane_state->address;
2291
2292 if (addr_patched)
2293 pipe_ctx->plane_state->address.grph_stereo.left_addr = addr;
2294 }
2295
2296 void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx,
2297 struct dc_link_settings *link_settings)
2298 {
2299 struct encoder_unblank_param params = {0};
2300 struct dc_stream_state *stream = pipe_ctx->stream;
2301 struct dc_link *link = stream->link;
2302 struct dce_hwseq *hws = link->dc->hwseq;
2303 struct pipe_ctx *odm_pipe;
2304
2305 params.opp_cnt = 1;
2306 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
2307 params.opp_cnt++;
2308 }
2309
2310 params.timing = pipe_ctx->stream->timing;
2311
2312 params.link_settings.link_rate = link_settings->link_rate;
2313
2314 if (is_dp_128b_132b_signal(pipe_ctx)) {
2315
2316 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_unblank(
2317 pipe_ctx->stream_res.hpo_dp_stream_enc,
2318 pipe_ctx->stream_res.tg->inst);
2319 } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
2320 if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1)
2321 params.timing.pix_clk_100hz /= 2;
2322 pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine(
2323 pipe_ctx->stream_res.stream_enc, params.opp_cnt > 1);
2324 pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, ¶ms);
2325 }
2326
2327 if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
2328 hws->funcs.edp_backlight_control(link, true);
2329 }
2330 }
2331
2332 void dcn20_setup_vupdate_interrupt(struct dc *dc, struct pipe_ctx *pipe_ctx)
2333 {
2334 struct timing_generator *tg = pipe_ctx->stream_res.tg;
2335 int start_line = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
2336
2337 if (start_line < 0)
2338 start_line = 0;
2339
2340 if (tg->funcs->setup_vertical_interrupt2)
2341 tg->funcs->setup_vertical_interrupt2(tg, start_line);
2342 }
2343
2344 static void dcn20_reset_back_end_for_pipe(
2345 struct dc *dc,
2346 struct pipe_ctx *pipe_ctx,
2347 struct dc_state *context)
2348 {
2349 int i;
2350 struct dc_link *link;
2351 DC_LOGGER_INIT(dc->ctx->logger);
2352 if (pipe_ctx->stream_res.stream_enc == NULL) {
2353 pipe_ctx->stream = NULL;
2354 return;
2355 }
2356
2357 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
2358 link = pipe_ctx->stream->link;
2359
2360
2361
2362
2363
2364
2365 if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
2366 core_link_disable_stream(pipe_ctx);
2367 else if (pipe_ctx->stream_res.audio)
2368 dc->hwss.disable_audio_stream(pipe_ctx);
2369
2370
2371 if (pipe_ctx->stream_res.audio) {
2372
2373 pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
2374
2375
2376 if (dc->caps.dynamic_audio == true) {
2377
2378
2379 update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
2380 pipe_ctx->stream_res.audio, false);
2381 pipe_ctx->stream_res.audio = NULL;
2382 }
2383 }
2384 }
2385 else if (pipe_ctx->stream_res.dsc) {
2386 dp_set_dsc_enable(pipe_ctx, false);
2387 }
2388
2389
2390
2391
2392
2393 if (pipe_ctx->top_pipe == NULL) {
2394
2395 dc->hwss.set_abm_immediate_disable(pipe_ctx);
2396
2397 pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
2398
2399 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
2400 if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass)
2401 pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
2402 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
2403
2404 if (pipe_ctx->stream_res.tg->funcs->set_drr)
2405 pipe_ctx->stream_res.tg->funcs->set_drr(
2406 pipe_ctx->stream_res.tg, NULL);
2407 }
2408
2409 for (i = 0; i < dc->res_pool->pipe_count; i++)
2410 if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx)
2411 break;
2412
2413 if (i == dc->res_pool->pipe_count)
2414 return;
2415
2416 pipe_ctx->stream = NULL;
2417 DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n",
2418 pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst);
2419 }
2420
2421 void dcn20_reset_hw_ctx_wrap(
2422 struct dc *dc,
2423 struct dc_state *context)
2424 {
2425 int i;
2426 struct dce_hwseq *hws = dc->hwseq;
2427
2428
2429 for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
2430 struct pipe_ctx *pipe_ctx_old =
2431 &dc->current_state->res_ctx.pipe_ctx[i];
2432 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2433
2434 if (!pipe_ctx_old->stream)
2435 continue;
2436
2437 if (pipe_ctx_old->top_pipe || pipe_ctx_old->prev_odm_pipe)
2438 continue;
2439
2440 if (!pipe_ctx->stream ||
2441 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
2442 struct clock_source *old_clk = pipe_ctx_old->clock_source;
2443
2444 dcn20_reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state);
2445 if (hws->funcs.enable_stream_gating)
2446 hws->funcs.enable_stream_gating(dc, pipe_ctx_old);
2447 if (old_clk)
2448 old_clk->funcs->cs_power_down(old_clk);
2449 }
2450 }
2451 }
2452
2453 void dcn20_update_visual_confirm_color(struct dc *dc, struct pipe_ctx *pipe_ctx, struct tg_color *color, int mpcc_id)
2454 {
2455 struct mpc *mpc = dc->res_pool->mpc;
2456
2457
2458 if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR)
2459 get_hdr_visual_confirm_color(pipe_ctx, color);
2460 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE)
2461 get_surface_visual_confirm_color(pipe_ctx, color);
2462 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_MPCTREE)
2463 get_mpctree_visual_confirm_color(pipe_ctx, color);
2464 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SWIZZLE)
2465 get_surface_tile_visual_confirm_color(pipe_ctx, color);
2466
2467 if (mpc->funcs->set_bg_color)
2468 mpc->funcs->set_bg_color(mpc, color, mpcc_id);
2469 }
2470
2471 void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
2472 {
2473 struct hubp *hubp = pipe_ctx->plane_res.hubp;
2474 struct mpcc_blnd_cfg blnd_cfg = {0};
2475 bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha;
2476 int mpcc_id;
2477 struct mpcc *new_mpcc;
2478 struct mpc *mpc = dc->res_pool->mpc;
2479 struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
2480
2481 blnd_cfg.overlap_only = false;
2482 blnd_cfg.global_gain = 0xff;
2483
2484 if (per_pixel_alpha) {
2485 blnd_cfg.pre_multiplied_alpha = pipe_ctx->plane_state->pre_multiplied_alpha;
2486 if (pipe_ctx->plane_state->global_alpha) {
2487 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN;
2488 blnd_cfg.global_gain = pipe_ctx->plane_state->global_alpha_value;
2489 } else {
2490 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
2491 }
2492 } else {
2493 blnd_cfg.pre_multiplied_alpha = false;
2494 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
2495 }
2496
2497 if (pipe_ctx->plane_state->global_alpha)
2498 blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value;
2499 else
2500 blnd_cfg.global_alpha = 0xff;
2501
2502 blnd_cfg.background_color_bpc = 4;
2503 blnd_cfg.bottom_gain_mode = 0;
2504 blnd_cfg.top_gain = 0x1f000;
2505 blnd_cfg.bottom_inside_gain = 0x1f000;
2506 blnd_cfg.bottom_outside_gain = 0x1f000;
2507
2508 if (pipe_ctx->plane_state->format
2509 == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA)
2510 blnd_cfg.pre_multiplied_alpha = false;
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520 mpcc_id = hubp->inst;
2521
2522
2523 if (!pipe_ctx->plane_state->update_flags.bits.full_update &&
2524 !pipe_ctx->update_flags.bits.mpcc) {
2525 mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id);
2526 dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
2527 return;
2528 }
2529
2530
2531 new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id);
2532
2533 if (new_mpcc != NULL)
2534 mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc);
2535 else
2536 if (dc->debug.sanity_checks)
2537 mpc->funcs->assert_mpcc_idle_before_connect(
2538 dc->res_pool->mpc, mpcc_id);
2539
2540
2541 new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc,
2542 mpc_tree_params,
2543 &blnd_cfg,
2544 NULL,
2545 NULL,
2546 hubp->inst,
2547 mpcc_id);
2548 dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
2549
2550 ASSERT(new_mpcc != NULL);
2551 hubp->opp_id = pipe_ctx->stream_res.opp->inst;
2552 hubp->mpcc_id = mpcc_id;
2553 }
2554
2555 void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
2556 {
2557 enum dc_lane_count lane_count =
2558 pipe_ctx->stream->link->cur_link_settings.lane_count;
2559
2560 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
2561 struct dc_link *link = pipe_ctx->stream->link;
2562
2563 uint32_t active_total_with_borders;
2564 uint32_t early_control = 0;
2565 struct timing_generator *tg = pipe_ctx->stream_res.tg;
2566 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
2567 struct dc *dc = pipe_ctx->stream->ctx->dc;
2568
2569 if (is_dp_128b_132b_signal(pipe_ctx)) {
2570 if (dc->hwseq->funcs.setup_hpo_hw_control)
2571 dc->hwseq->funcs.setup_hpo_hw_control(dc->hwseq, true);
2572 }
2573
2574 link_hwss->setup_stream_encoder(pipe_ctx);
2575
2576 if (pipe_ctx->plane_state && pipe_ctx->plane_state->flip_immediate != 1) {
2577 if (dc->hwss.program_dmdata_engine)
2578 dc->hwss.program_dmdata_engine(pipe_ctx);
2579 }
2580
2581 dc->hwss.update_info_frame(pipe_ctx);
2582
2583 if (dc_is_dp_signal(pipe_ctx->stream->signal))
2584 dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME);
2585
2586
2587 active_total_with_borders =
2588 timing->h_addressable
2589 + timing->h_border_left
2590 + timing->h_border_right;
2591
2592 if (lane_count != 0)
2593 early_control = active_total_with_borders % lane_count;
2594
2595 if (early_control == 0)
2596 early_control = lane_count;
2597
2598 tg->funcs->set_early_control(tg, early_control);
2599
2600 if (dc->hwseq->funcs.set_pixels_per_cycle)
2601 dc->hwseq->funcs.set_pixels_per_cycle(pipe_ctx);
2602
2603
2604 if (pipe_ctx->stream_res.audio != NULL) {
2605 if (is_dp_128b_132b_signal(pipe_ctx))
2606 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.hpo_dp_stream_enc);
2607 else if (dc_is_dp_signal(pipe_ctx->stream->signal))
2608 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
2609 }
2610 }
2611
2612 void dcn20_program_dmdata_engine(struct pipe_ctx *pipe_ctx)
2613 {
2614 struct dc_stream_state *stream = pipe_ctx->stream;
2615 struct hubp *hubp = pipe_ctx->plane_res.hubp;
2616 bool enable = false;
2617 struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc;
2618 enum dynamic_metadata_mode mode = dc_is_dp_signal(stream->signal)
2619 ? dmdata_dp
2620 : dmdata_hdmi;
2621
2622
2623 if (pipe_ctx->stream->dmdata_address.quad_part != 0) {
2624 pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false;
2625 enable = true;
2626 }
2627
2628 if (!hubp)
2629 return;
2630
2631 if (!stream_enc || !stream_enc->funcs->set_dynamic_metadata)
2632 return;
2633
2634 stream_enc->funcs->set_dynamic_metadata(stream_enc, enable,
2635 hubp->inst, mode);
2636 }
2637
2638 void dcn20_fpga_init_hw(struct dc *dc)
2639 {
2640 int i, j;
2641 struct dce_hwseq *hws = dc->hwseq;
2642 struct resource_pool *res_pool = dc->res_pool;
2643 struct dc_state *context = dc->current_state;
2644
2645 if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
2646 dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
2647
2648
2649 if (res_pool->dccg->funcs->dccg_init)
2650 res_pool->dccg->funcs->dccg_init(res_pool->dccg);
2651
2652
2653 hws->funcs.enable_power_gating_plane(hws, true);
2654
2655
2656 REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF);
2657 REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF);
2658
2659 hws->funcs.dccg_init(hws);
2660
2661 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
2662 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
2663 if (REG(REFCLK_CNTL))
2664 REG_WRITE(REFCLK_CNTL, 0);
2665
2666
2667
2668
2669 for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
2670 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2671
2672 if (tg->funcs->is_tg_enabled(tg))
2673 dcn20_init_blank(dc, tg);
2674 }
2675
2676 for (i = 0; i < res_pool->timing_generator_count; i++) {
2677 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2678
2679 if (tg->funcs->is_tg_enabled(tg))
2680 tg->funcs->lock(tg);
2681 }
2682
2683 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2684 struct dpp *dpp = res_pool->dpps[i];
2685
2686 dpp->funcs->dpp_reset(dpp);
2687 }
2688
2689
2690 res_pool->mpc->funcs->mpc_init(res_pool->mpc);
2691
2692
2693 for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
2694 res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst;
2695 res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
2696 for (j = 0; j < MAX_PIPES; j++)
2697 res_pool->opps[i]->mpcc_disconnect_pending[j] = false;
2698 }
2699
2700 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2701 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2702 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2703 struct hubp *hubp = dc->res_pool->hubps[i];
2704 struct dpp *dpp = dc->res_pool->dpps[i];
2705
2706 pipe_ctx->stream_res.tg = tg;
2707 pipe_ctx->pipe_idx = i;
2708
2709 pipe_ctx->plane_res.hubp = hubp;
2710 pipe_ctx->plane_res.dpp = dpp;
2711 pipe_ctx->plane_res.mpcc_inst = dpp->inst;
2712 hubp->mpcc_id = dpp->inst;
2713 hubp->opp_id = OPP_ID_INVALID;
2714 hubp->power_gated = false;
2715 pipe_ctx->stream_res.opp = NULL;
2716
2717 hubp->funcs->hubp_init(hubp);
2718
2719
2720
2721 dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
2722 pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
2723
2724 hws->funcs.plane_atomic_disconnect(dc, pipe_ctx);
2725 }
2726
2727
2728 for (i = 0; i < res_pool->res_cap->num_dwb; i++)
2729 res_pool->dwbc[i]->mcif = res_pool->mcif_wb[i];
2730
2731 for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
2732 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2733
2734 if (tg->funcs->is_tg_enabled(tg))
2735 tg->funcs->unlock(tg);
2736 }
2737
2738 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2739 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2740
2741 dc->hwss.disable_plane(dc, pipe_ctx);
2742
2743 pipe_ctx->stream_res.tg = NULL;
2744 pipe_ctx->plane_res.hubp = NULL;
2745 }
2746
2747 for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
2748 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2749
2750 tg->funcs->tg_init(tg);
2751 }
2752
2753 if (dc->res_pool->hubbub->funcs->init_crb)
2754 dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
2755 }
2756 #ifndef TRIM_FSFT
2757 bool dcn20_optimize_timing_for_fsft(struct dc *dc,
2758 struct dc_crtc_timing *timing,
2759 unsigned int max_input_rate_in_khz)
2760 {
2761 unsigned int old_v_front_porch;
2762 unsigned int old_v_total;
2763 unsigned int max_input_rate_in_100hz;
2764 unsigned long long new_v_total;
2765
2766 max_input_rate_in_100hz = max_input_rate_in_khz * 10;
2767 if (max_input_rate_in_100hz < timing->pix_clk_100hz)
2768 return false;
2769
2770 old_v_total = timing->v_total;
2771 old_v_front_porch = timing->v_front_porch;
2772
2773 timing->fast_transport_output_rate_100hz = timing->pix_clk_100hz;
2774 timing->pix_clk_100hz = max_input_rate_in_100hz;
2775
2776 new_v_total = div_u64((unsigned long long)old_v_total * max_input_rate_in_100hz, timing->pix_clk_100hz);
2777
2778 timing->v_total = new_v_total;
2779 timing->v_front_porch = old_v_front_porch + (timing->v_total - old_v_total);
2780 return true;
2781 }
2782 #endif
2783
2784 void dcn20_set_disp_pattern_generator(const struct dc *dc,
2785 struct pipe_ctx *pipe_ctx,
2786 enum controller_dp_test_pattern test_pattern,
2787 enum controller_dp_color_space color_space,
2788 enum dc_color_depth color_depth,
2789 const struct tg_color *solid_color,
2790 int width, int height, int offset)
2791 {
2792 pipe_ctx->stream_res.opp->funcs->opp_set_disp_pattern_generator(pipe_ctx->stream_res.opp, test_pattern,
2793 color_space, color_depth, solid_color, width, height, offset);
2794 }