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 #include <linux/delay.h>
0027 #include "dm_services.h"
0028 #include "basics/dc_common.h"
0029 #include "core_types.h"
0030 #include "resource.h"
0031 #include "custom_float.h"
0032 #include "dcn10_hw_sequencer.h"
0033 #include "dcn10_hw_sequencer_debug.h"
0034 #include "dce/dce_hwseq.h"
0035 #include "abm.h"
0036 #include "dmcu.h"
0037 #include "dcn10_optc.h"
0038 #include "dcn10_dpp.h"
0039 #include "dcn10_mpc.h"
0040 #include "timing_generator.h"
0041 #include "opp.h"
0042 #include "ipp.h"
0043 #include "mpc.h"
0044 #include "reg_helper.h"
0045 #include "dcn10_hubp.h"
0046 #include "dcn10_hubbub.h"
0047 #include "dcn10_cm_common.h"
0048 #include "dc_link_dp.h"
0049 #include "dccg.h"
0050 #include "clk_mgr.h"
0051 #include "link_hwss.h"
0052 #include "dpcd_defs.h"
0053 #include "dsc.h"
0054 #include "dce/dmub_psr.h"
0055 #include "dc_dmub_srv.h"
0056 #include "dce/dmub_hw_lock_mgr.h"
0057 #include "dc_trace.h"
0058 #include "dce/dmub_outbox.h"
0059 #include "inc/dc_link_dp.h"
0060 #include "inc/link_dpcd.h"
0061
0062 #define DC_LOGGER_INIT(logger)
0063
0064 #define CTX \
0065 hws->ctx
0066 #define REG(reg)\
0067 hws->regs->reg
0068
0069 #undef FN
0070 #define FN(reg_name, field_name) \
0071 hws->shifts->field_name, hws->masks->field_name
0072
0073
0074 #define DTN_INFO_MICRO_SEC(ref_cycle) \
0075 print_microsec(dc_ctx, log_ctx, ref_cycle)
0076
0077 #define GAMMA_HW_POINTS_NUM 256
0078
0079 #define PGFSM_POWER_ON 0
0080 #define PGFSM_POWER_OFF 2
0081
0082 static void print_microsec(struct dc_context *dc_ctx,
0083 struct dc_log_buffer_ctx *log_ctx,
0084 uint32_t ref_cycle)
0085 {
0086 const uint32_t ref_clk_mhz = dc_ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000;
0087 static const unsigned int frac = 1000;
0088 uint32_t us_x10 = (ref_cycle * frac) / ref_clk_mhz;
0089
0090 DTN_INFO(" %11d.%03d",
0091 us_x10 / frac,
0092 us_x10 % frac);
0093 }
0094
0095 void dcn10_lock_all_pipes(struct dc *dc,
0096 struct dc_state *context,
0097 bool lock)
0098 {
0099 struct pipe_ctx *pipe_ctx;
0100 struct timing_generator *tg;
0101 int i;
0102
0103 for (i = 0; i < dc->res_pool->pipe_count; i++) {
0104 pipe_ctx = &context->res_ctx.pipe_ctx[i];
0105 tg = pipe_ctx->stream_res.tg;
0106
0107
0108
0109
0110
0111 if (pipe_ctx->top_pipe ||
0112 !pipe_ctx->stream ||
0113 !pipe_ctx->plane_state ||
0114 !tg->funcs->is_tg_enabled(tg))
0115 continue;
0116
0117 if (lock)
0118 dc->hwss.pipe_control_lock(dc, pipe_ctx, true);
0119 else
0120 dc->hwss.pipe_control_lock(dc, pipe_ctx, false);
0121 }
0122 }
0123
0124 static void log_mpc_crc(struct dc *dc,
0125 struct dc_log_buffer_ctx *log_ctx)
0126 {
0127 struct dc_context *dc_ctx = dc->ctx;
0128 struct dce_hwseq *hws = dc->hwseq;
0129
0130 if (REG(MPC_CRC_RESULT_GB))
0131 DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n",
0132 REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR));
0133 if (REG(DPP_TOP0_DPP_CRC_VAL_B_A))
0134 DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n",
0135 REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G));
0136 }
0137
0138 static void dcn10_log_hubbub_state(struct dc *dc,
0139 struct dc_log_buffer_ctx *log_ctx)
0140 {
0141 struct dc_context *dc_ctx = dc->ctx;
0142 struct dcn_hubbub_wm wm;
0143 int i;
0144
0145 memset(&wm, 0, sizeof(struct dcn_hubbub_wm));
0146 dc->res_pool->hubbub->funcs->wm_read_state(dc->res_pool->hubbub, &wm);
0147
0148 DTN_INFO("HUBBUB WM: data_urgent pte_meta_urgent"
0149 " sr_enter sr_exit dram_clk_change\n");
0150
0151 for (i = 0; i < 4; i++) {
0152 struct dcn_hubbub_wm_set *s;
0153
0154 s = &wm.sets[i];
0155 DTN_INFO("WM_Set[%d]:", s->wm_set);
0156 DTN_INFO_MICRO_SEC(s->data_urgent);
0157 DTN_INFO_MICRO_SEC(s->pte_meta_urgent);
0158 DTN_INFO_MICRO_SEC(s->sr_enter);
0159 DTN_INFO_MICRO_SEC(s->sr_exit);
0160 DTN_INFO_MICRO_SEC(s->dram_clk_chanage);
0161 DTN_INFO("\n");
0162 }
0163
0164 DTN_INFO("\n");
0165 }
0166
0167 static void dcn10_log_hubp_states(struct dc *dc, void *log_ctx)
0168 {
0169 struct dc_context *dc_ctx = dc->ctx;
0170 struct resource_pool *pool = dc->res_pool;
0171 int i;
0172
0173 DTN_INFO(
0174 "HUBP: format addr_hi width height rot mir sw_mode dcc_en blank_en clock_en ttu_dis underflow min_ttu_vblank qos_low_wm qos_high_wm\n");
0175 for (i = 0; i < pool->pipe_count; i++) {
0176 struct hubp *hubp = pool->hubps[i];
0177 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(hubp)->state);
0178
0179 hubp->funcs->hubp_read_state(hubp);
0180
0181 if (!s->blank_en) {
0182 DTN_INFO("[%2d]: %5xh %6xh %5d %6d %2xh %2xh %6xh %6d %8d %8d %7d %8xh",
0183 hubp->inst,
0184 s->pixel_format,
0185 s->inuse_addr_hi,
0186 s->viewport_width,
0187 s->viewport_height,
0188 s->rotation_angle,
0189 s->h_mirror_en,
0190 s->sw_mode,
0191 s->dcc_en,
0192 s->blank_en,
0193 s->clock_en,
0194 s->ttu_disable,
0195 s->underflow_status);
0196 DTN_INFO_MICRO_SEC(s->min_ttu_vblank);
0197 DTN_INFO_MICRO_SEC(s->qos_level_low_wm);
0198 DTN_INFO_MICRO_SEC(s->qos_level_high_wm);
0199 DTN_INFO("\n");
0200 }
0201 }
0202
0203 DTN_INFO("\n=========RQ========\n");
0204 DTN_INFO("HUBP: drq_exp_m prq_exp_m mrq_exp_m crq_exp_m plane1_ba L:chunk_s min_chu_s meta_ch_s"
0205 " min_m_c_s dpte_gr_s mpte_gr_s swath_hei pte_row_h C:chunk_s min_chu_s meta_ch_s"
0206 " min_m_c_s dpte_gr_s mpte_gr_s swath_hei pte_row_h\n");
0207 for (i = 0; i < pool->pipe_count; i++) {
0208 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
0209 struct _vcs_dpi_display_rq_regs_st *rq_regs = &s->rq_regs;
0210
0211 if (!s->blank_en)
0212 DTN_INFO("[%2d]: %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh\n",
0213 pool->hubps[i]->inst, rq_regs->drq_expansion_mode, rq_regs->prq_expansion_mode, rq_regs->mrq_expansion_mode,
0214 rq_regs->crq_expansion_mode, rq_regs->plane1_base_address, rq_regs->rq_regs_l.chunk_size,
0215 rq_regs->rq_regs_l.min_chunk_size, rq_regs->rq_regs_l.meta_chunk_size,
0216 rq_regs->rq_regs_l.min_meta_chunk_size, rq_regs->rq_regs_l.dpte_group_size,
0217 rq_regs->rq_regs_l.mpte_group_size, rq_regs->rq_regs_l.swath_height,
0218 rq_regs->rq_regs_l.pte_row_height_linear, rq_regs->rq_regs_c.chunk_size, rq_regs->rq_regs_c.min_chunk_size,
0219 rq_regs->rq_regs_c.meta_chunk_size, rq_regs->rq_regs_c.min_meta_chunk_size,
0220 rq_regs->rq_regs_c.dpte_group_size, rq_regs->rq_regs_c.mpte_group_size,
0221 rq_regs->rq_regs_c.swath_height, rq_regs->rq_regs_c.pte_row_height_linear);
0222 }
0223
0224 DTN_INFO("========DLG========\n");
0225 DTN_INFO("HUBP: rc_hbe dlg_vbe min_d_y_n rc_per_ht rc_x_a_s "
0226 " dst_y_a_s dst_y_pf dst_y_vvb dst_y_rvb dst_y_vfl dst_y_rfl rf_pix_fq"
0227 " vratio_pf vrat_pf_c rc_pg_vbl rc_pg_vbc rc_mc_vbl rc_mc_vbc rc_pg_fll"
0228 " rc_pg_flc rc_mc_fll rc_mc_flc pr_nom_l pr_nom_c rc_pg_nl rc_pg_nc "
0229 " mr_nom_l mr_nom_c rc_mc_nl rc_mc_nc rc_ld_pl rc_ld_pc rc_ld_l "
0230 " rc_ld_c cha_cur0 ofst_cur1 cha_cur1 vr_af_vc0 ddrq_limt x_rt_dlay"
0231 " x_rp_dlay x_rr_sfl\n");
0232 for (i = 0; i < pool->pipe_count; i++) {
0233 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
0234 struct _vcs_dpi_display_dlg_regs_st *dlg_regs = &s->dlg_attr;
0235
0236 if (!s->blank_en)
0237 DTN_INFO("[%2d]: %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh"
0238 " %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh"
0239 " %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh\n",
0240 pool->hubps[i]->inst, dlg_regs->refcyc_h_blank_end, dlg_regs->dlg_vblank_end, dlg_regs->min_dst_y_next_start,
0241 dlg_regs->refcyc_per_htotal, dlg_regs->refcyc_x_after_scaler, dlg_regs->dst_y_after_scaler,
0242 dlg_regs->dst_y_prefetch, dlg_regs->dst_y_per_vm_vblank, dlg_regs->dst_y_per_row_vblank,
0243 dlg_regs->dst_y_per_vm_flip, dlg_regs->dst_y_per_row_flip, dlg_regs->ref_freq_to_pix_freq,
0244 dlg_regs->vratio_prefetch, dlg_regs->vratio_prefetch_c, dlg_regs->refcyc_per_pte_group_vblank_l,
0245 dlg_regs->refcyc_per_pte_group_vblank_c, dlg_regs->refcyc_per_meta_chunk_vblank_l,
0246 dlg_regs->refcyc_per_meta_chunk_vblank_c, dlg_regs->refcyc_per_pte_group_flip_l,
0247 dlg_regs->refcyc_per_pte_group_flip_c, dlg_regs->refcyc_per_meta_chunk_flip_l,
0248 dlg_regs->refcyc_per_meta_chunk_flip_c, dlg_regs->dst_y_per_pte_row_nom_l,
0249 dlg_regs->dst_y_per_pte_row_nom_c, dlg_regs->refcyc_per_pte_group_nom_l,
0250 dlg_regs->refcyc_per_pte_group_nom_c, dlg_regs->dst_y_per_meta_row_nom_l,
0251 dlg_regs->dst_y_per_meta_row_nom_c, dlg_regs->refcyc_per_meta_chunk_nom_l,
0252 dlg_regs->refcyc_per_meta_chunk_nom_c, dlg_regs->refcyc_per_line_delivery_pre_l,
0253 dlg_regs->refcyc_per_line_delivery_pre_c, dlg_regs->refcyc_per_line_delivery_l,
0254 dlg_regs->refcyc_per_line_delivery_c, dlg_regs->chunk_hdl_adjust_cur0, dlg_regs->dst_y_offset_cur1,
0255 dlg_regs->chunk_hdl_adjust_cur1, dlg_regs->vready_after_vcount0, dlg_regs->dst_y_delta_drq_limit,
0256 dlg_regs->xfc_reg_transfer_delay, dlg_regs->xfc_reg_precharge_delay,
0257 dlg_regs->xfc_reg_remote_surface_flip_latency);
0258 }
0259
0260 DTN_INFO("========TTU========\n");
0261 DTN_INFO("HUBP: qos_ll_wm qos_lh_wm mn_ttu_vb qos_l_flp rc_rd_p_l rc_rd_l rc_rd_p_c"
0262 " rc_rd_c rc_rd_c0 rc_rd_pc0 rc_rd_c1 rc_rd_pc1 qos_lf_l qos_rds_l"
0263 " qos_lf_c qos_rds_c qos_lf_c0 qos_rds_c0 qos_lf_c1 qos_rds_c1\n");
0264 for (i = 0; i < pool->pipe_count; i++) {
0265 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
0266 struct _vcs_dpi_display_ttu_regs_st *ttu_regs = &s->ttu_attr;
0267
0268 if (!s->blank_en)
0269 DTN_INFO("[%2d]: %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh\n",
0270 pool->hubps[i]->inst, ttu_regs->qos_level_low_wm, ttu_regs->qos_level_high_wm, ttu_regs->min_ttu_vblank,
0271 ttu_regs->qos_level_flip, ttu_regs->refcyc_per_req_delivery_pre_l, ttu_regs->refcyc_per_req_delivery_l,
0272 ttu_regs->refcyc_per_req_delivery_pre_c, ttu_regs->refcyc_per_req_delivery_c, ttu_regs->refcyc_per_req_delivery_cur0,
0273 ttu_regs->refcyc_per_req_delivery_pre_cur0, ttu_regs->refcyc_per_req_delivery_cur1,
0274 ttu_regs->refcyc_per_req_delivery_pre_cur1, ttu_regs->qos_level_fixed_l, ttu_regs->qos_ramp_disable_l,
0275 ttu_regs->qos_level_fixed_c, ttu_regs->qos_ramp_disable_c, ttu_regs->qos_level_fixed_cur0,
0276 ttu_regs->qos_ramp_disable_cur0, ttu_regs->qos_level_fixed_cur1, ttu_regs->qos_ramp_disable_cur1);
0277 }
0278 DTN_INFO("\n");
0279 }
0280
0281 void dcn10_log_hw_state(struct dc *dc,
0282 struct dc_log_buffer_ctx *log_ctx)
0283 {
0284 struct dc_context *dc_ctx = dc->ctx;
0285 struct resource_pool *pool = dc->res_pool;
0286 int i;
0287
0288 DTN_INFO_BEGIN();
0289
0290 dcn10_log_hubbub_state(dc, log_ctx);
0291
0292 dcn10_log_hubp_states(dc, log_ctx);
0293
0294 DTN_INFO("DPP: IGAM format IGAM mode DGAM mode RGAM mode"
0295 " GAMUT mode C11 C12 C13 C14 C21 C22 C23 C24 "
0296 "C31 C32 C33 C34\n");
0297 for (i = 0; i < pool->pipe_count; i++) {
0298 struct dpp *dpp = pool->dpps[i];
0299 struct dcn_dpp_state s = {0};
0300
0301 dpp->funcs->dpp_read_state(dpp, &s);
0302
0303 if (!s.is_enabled)
0304 continue;
0305
0306 DTN_INFO("[%2d]: %11xh %-11s %-11s %-11s"
0307 "%8x %08xh %08xh %08xh %08xh %08xh %08xh",
0308 dpp->inst,
0309 s.igam_input_format,
0310 (s.igam_lut_mode == 0) ? "BypassFixed" :
0311 ((s.igam_lut_mode == 1) ? "BypassFloat" :
0312 ((s.igam_lut_mode == 2) ? "RAM" :
0313 ((s.igam_lut_mode == 3) ? "RAM" :
0314 "Unknown"))),
0315 (s.dgam_lut_mode == 0) ? "Bypass" :
0316 ((s.dgam_lut_mode == 1) ? "sRGB" :
0317 ((s.dgam_lut_mode == 2) ? "Ycc" :
0318 ((s.dgam_lut_mode == 3) ? "RAM" :
0319 ((s.dgam_lut_mode == 4) ? "RAM" :
0320 "Unknown")))),
0321 (s.rgam_lut_mode == 0) ? "Bypass" :
0322 ((s.rgam_lut_mode == 1) ? "sRGB" :
0323 ((s.rgam_lut_mode == 2) ? "Ycc" :
0324 ((s.rgam_lut_mode == 3) ? "RAM" :
0325 ((s.rgam_lut_mode == 4) ? "RAM" :
0326 "Unknown")))),
0327 s.gamut_remap_mode,
0328 s.gamut_remap_c11_c12,
0329 s.gamut_remap_c13_c14,
0330 s.gamut_remap_c21_c22,
0331 s.gamut_remap_c23_c24,
0332 s.gamut_remap_c31_c32,
0333 s.gamut_remap_c33_c34);
0334 DTN_INFO("\n");
0335 }
0336 DTN_INFO("\n");
0337
0338 DTN_INFO("MPCC: OPP DPP MPCCBOT MODE ALPHA_MODE PREMULT OVERLAP_ONLY IDLE\n");
0339 for (i = 0; i < pool->pipe_count; i++) {
0340 struct mpcc_state s = {0};
0341
0342 pool->mpc->funcs->read_mpcc_state(pool->mpc, i, &s);
0343 if (s.opp_id != 0xf)
0344 DTN_INFO("[%2d]: %2xh %2xh %6xh %4d %10d %7d %12d %4d\n",
0345 i, s.opp_id, s.dpp_id, s.bot_mpcc_id,
0346 s.mode, s.alpha_mode, s.pre_multiplied_alpha, s.overlap_only,
0347 s.idle);
0348 }
0349 DTN_INFO("\n");
0350
0351 DTN_INFO("OTG: v_bs v_be v_ss v_se vpol vmax vmin vmax_sel vmin_sel h_bs h_be h_ss h_se hpol htot vtot underflow blank_en\n");
0352
0353 for (i = 0; i < pool->timing_generator_count; i++) {
0354 struct timing_generator *tg = pool->timing_generators[i];
0355 struct dcn_otg_state s = {0};
0356
0357 optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s);
0358
0359
0360
0361
0362
0363
0364
0365
0366 if (pool->opps[i]->funcs->dpg_is_blanked)
0367 s.blank_enabled = pool->opps[i]->funcs->dpg_is_blanked(pool->opps[i]);
0368 else
0369 s.blank_enabled = tg->funcs->is_blanked(tg);
0370
0371
0372 if ((s.otg_enabled & 1) == 0)
0373 continue;
0374
0375 DTN_INFO("[%d]: %5d %5d %5d %5d %5d %5d %5d %9d %9d %5d %5d %5d %5d %5d %5d %5d %9d %8d\n",
0376 tg->inst,
0377 s.v_blank_start,
0378 s.v_blank_end,
0379 s.v_sync_a_start,
0380 s.v_sync_a_end,
0381 s.v_sync_a_pol,
0382 s.v_total_max,
0383 s.v_total_min,
0384 s.v_total_max_sel,
0385 s.v_total_min_sel,
0386 s.h_blank_start,
0387 s.h_blank_end,
0388 s.h_sync_a_start,
0389 s.h_sync_a_end,
0390 s.h_sync_a_pol,
0391 s.h_total,
0392 s.v_total,
0393 s.underflow_occurred_status,
0394 s.blank_enabled);
0395
0396
0397
0398
0399
0400 tg->funcs->clear_optc_underflow(tg);
0401 }
0402 DTN_INFO("\n");
0403
0404
0405
0406 DTN_INFO("DSC: CLOCK_EN SLICE_WIDTH Bytes_pp\n");
0407 for (i = 0; i < pool->res_cap->num_dsc; i++) {
0408 struct display_stream_compressor *dsc = pool->dscs[i];
0409 struct dcn_dsc_state s = {0};
0410
0411 dsc->funcs->dsc_read_state(dsc, &s);
0412 DTN_INFO("[%d]: %-9d %-12d %-10d\n",
0413 dsc->inst,
0414 s.dsc_clock_en,
0415 s.dsc_slice_width,
0416 s.dsc_bits_per_pixel);
0417 DTN_INFO("\n");
0418 }
0419 DTN_INFO("\n");
0420
0421 DTN_INFO("S_ENC: DSC_MODE SEC_GSP7_LINE_NUM"
0422 " VBID6_LINE_REFERENCE VBID6_LINE_NUM SEC_GSP7_ENABLE SEC_STREAM_ENABLE\n");
0423 for (i = 0; i < pool->stream_enc_count; i++) {
0424 struct stream_encoder *enc = pool->stream_enc[i];
0425 struct enc_state s = {0};
0426
0427 if (enc->funcs->enc_read_state) {
0428 enc->funcs->enc_read_state(enc, &s);
0429 DTN_INFO("[%-3d]: %-9d %-18d %-21d %-15d %-16d %-17d\n",
0430 enc->id,
0431 s.dsc_mode,
0432 s.sec_gsp_pps_line_num,
0433 s.vbid6_line_reference,
0434 s.vbid6_line_num,
0435 s.sec_gsp_pps_enable,
0436 s.sec_stream_enable);
0437 DTN_INFO("\n");
0438 }
0439 }
0440 DTN_INFO("\n");
0441
0442 DTN_INFO("L_ENC: DPHY_FEC_EN DPHY_FEC_READY_SHADOW DPHY_FEC_ACTIVE_STATUS DP_LINK_TRAINING_COMPLETE\n");
0443 for (i = 0; i < dc->link_count; i++) {
0444 struct link_encoder *lenc = dc->links[i]->link_enc;
0445
0446 struct link_enc_state s = {0};
0447
0448 if (lenc && lenc->funcs->read_state) {
0449 lenc->funcs->read_state(lenc, &s);
0450 DTN_INFO("[%-3d]: %-12d %-22d %-22d %-25d\n",
0451 i,
0452 s.dphy_fec_en,
0453 s.dphy_fec_ready_shadow,
0454 s.dphy_fec_active_status,
0455 s.dp_link_training_complete);
0456 DTN_INFO("\n");
0457 }
0458 }
0459 DTN_INFO("\n");
0460
0461 DTN_INFO("\nCALCULATED Clocks: dcfclk_khz:%d dcfclk_deep_sleep_khz:%d dispclk_khz:%d\n"
0462 "dppclk_khz:%d max_supported_dppclk_khz:%d fclk_khz:%d socclk_khz:%d\n\n",
0463 dc->current_state->bw_ctx.bw.dcn.clk.dcfclk_khz,
0464 dc->current_state->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz,
0465 dc->current_state->bw_ctx.bw.dcn.clk.dispclk_khz,
0466 dc->current_state->bw_ctx.bw.dcn.clk.dppclk_khz,
0467 dc->current_state->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz,
0468 dc->current_state->bw_ctx.bw.dcn.clk.fclk_khz,
0469 dc->current_state->bw_ctx.bw.dcn.clk.socclk_khz);
0470
0471 log_mpc_crc(dc, log_ctx);
0472
0473 {
0474 if (pool->hpo_dp_stream_enc_count > 0) {
0475 DTN_INFO("DP HPO S_ENC: Enabled OTG Format Depth Vid SDP Compressed Link\n");
0476 for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) {
0477 struct hpo_dp_stream_encoder_state hpo_dp_se_state = {0};
0478 struct hpo_dp_stream_encoder *hpo_dp_stream_enc = pool->hpo_dp_stream_enc[i];
0479
0480 if (hpo_dp_stream_enc && hpo_dp_stream_enc->funcs->read_state) {
0481 hpo_dp_stream_enc->funcs->read_state(hpo_dp_stream_enc, &hpo_dp_se_state);
0482
0483 DTN_INFO("[%d]: %d %d %6s %d %d %d %d %d\n",
0484 hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0,
0485 hpo_dp_se_state.stream_enc_enabled,
0486 hpo_dp_se_state.otg_inst,
0487 (hpo_dp_se_state.pixel_encoding == 0) ? "4:4:4" :
0488 ((hpo_dp_se_state.pixel_encoding == 1) ? "4:2:2" :
0489 (hpo_dp_se_state.pixel_encoding == 2) ? "4:2:0" : "Y-Only"),
0490 (hpo_dp_se_state.component_depth == 0) ? 6 :
0491 ((hpo_dp_se_state.component_depth == 1) ? 8 :
0492 (hpo_dp_se_state.component_depth == 2) ? 10 : 12),
0493 hpo_dp_se_state.vid_stream_enabled,
0494 hpo_dp_se_state.sdp_enabled,
0495 hpo_dp_se_state.compressed_format,
0496 hpo_dp_se_state.mapped_to_link_enc);
0497 }
0498 }
0499
0500 DTN_INFO("\n");
0501 }
0502
0503
0504 if (pool->hpo_dp_link_enc_count) {
0505 DTN_INFO("DP HPO L_ENC: Enabled Mode Lanes Stream Slots VC Rate X VC Rate Y\n");
0506
0507 for (i = 0; i < pool->hpo_dp_link_enc_count; i++) {
0508 struct hpo_dp_link_encoder *hpo_dp_link_enc = pool->hpo_dp_link_enc[i];
0509 struct hpo_dp_link_enc_state hpo_dp_le_state = {0};
0510
0511 if (hpo_dp_link_enc->funcs->read_state) {
0512 hpo_dp_link_enc->funcs->read_state(hpo_dp_link_enc, &hpo_dp_le_state);
0513 DTN_INFO("[%d]: %d %6s %d %d %d %d %d\n",
0514 hpo_dp_link_enc->inst,
0515 hpo_dp_le_state.link_enc_enabled,
0516 (hpo_dp_le_state.link_mode == 0) ? "TPS1" :
0517 (hpo_dp_le_state.link_mode == 1) ? "TPS2" :
0518 (hpo_dp_le_state.link_mode == 2) ? "ACTIVE" : "TEST",
0519 hpo_dp_le_state.lane_count,
0520 hpo_dp_le_state.stream_src[0],
0521 hpo_dp_le_state.slot_count[0],
0522 hpo_dp_le_state.vc_rate_x[0],
0523 hpo_dp_le_state.vc_rate_y[0]);
0524 DTN_INFO("\n");
0525 }
0526 }
0527
0528 DTN_INFO("\n");
0529 }
0530 }
0531
0532 DTN_INFO_END();
0533 }
0534
0535 bool dcn10_did_underflow_occur(struct dc *dc, struct pipe_ctx *pipe_ctx)
0536 {
0537 struct hubp *hubp = pipe_ctx->plane_res.hubp;
0538 struct timing_generator *tg = pipe_ctx->stream_res.tg;
0539
0540 if (tg->funcs->is_optc_underflow_occurred(tg)) {
0541 tg->funcs->clear_optc_underflow(tg);
0542 return true;
0543 }
0544
0545 if (hubp->funcs->hubp_get_underflow_status(hubp)) {
0546 hubp->funcs->hubp_clear_underflow(hubp);
0547 return true;
0548 }
0549 return false;
0550 }
0551
0552 void dcn10_enable_power_gating_plane(
0553 struct dce_hwseq *hws,
0554 bool enable)
0555 {
0556 bool force_on = true;
0557
0558 if (enable)
0559 force_on = false;
0560
0561
0562 REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on);
0563 REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on);
0564 REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on);
0565 REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on);
0566
0567
0568 REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on);
0569 REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on);
0570 REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on);
0571 REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on);
0572 }
0573
0574 void dcn10_disable_vga(
0575 struct dce_hwseq *hws)
0576 {
0577 unsigned int in_vga1_mode = 0;
0578 unsigned int in_vga2_mode = 0;
0579 unsigned int in_vga3_mode = 0;
0580 unsigned int in_vga4_mode = 0;
0581
0582 REG_GET(D1VGA_CONTROL, D1VGA_MODE_ENABLE, &in_vga1_mode);
0583 REG_GET(D2VGA_CONTROL, D2VGA_MODE_ENABLE, &in_vga2_mode);
0584 REG_GET(D3VGA_CONTROL, D3VGA_MODE_ENABLE, &in_vga3_mode);
0585 REG_GET(D4VGA_CONTROL, D4VGA_MODE_ENABLE, &in_vga4_mode);
0586
0587 if (in_vga1_mode == 0 && in_vga2_mode == 0 &&
0588 in_vga3_mode == 0 && in_vga4_mode == 0)
0589 return;
0590
0591 REG_WRITE(D1VGA_CONTROL, 0);
0592 REG_WRITE(D2VGA_CONTROL, 0);
0593 REG_WRITE(D3VGA_CONTROL, 0);
0594 REG_WRITE(D4VGA_CONTROL, 0);
0595
0596
0597
0598
0599
0600
0601
0602
0603 REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_ENABLE, 1);
0604 REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_RENDER_START, 1);
0605 }
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616 void dcn10_dpp_pg_control(
0617 struct dce_hwseq *hws,
0618 unsigned int dpp_inst,
0619 bool power_on)
0620 {
0621 uint32_t power_gate = power_on ? 0 : 1;
0622 uint32_t pwr_status = power_on ? PGFSM_POWER_ON : PGFSM_POWER_OFF;
0623
0624 if (hws->ctx->dc->debug.disable_dpp_power_gate)
0625 return;
0626 if (REG(DOMAIN1_PG_CONFIG) == 0)
0627 return;
0628
0629 switch (dpp_inst) {
0630 case 0:
0631 REG_UPDATE(DOMAIN1_PG_CONFIG,
0632 DOMAIN1_POWER_GATE, power_gate);
0633
0634 REG_WAIT(DOMAIN1_PG_STATUS,
0635 DOMAIN1_PGFSM_PWR_STATUS, pwr_status,
0636 1, 1000);
0637 break;
0638 case 1:
0639 REG_UPDATE(DOMAIN3_PG_CONFIG,
0640 DOMAIN3_POWER_GATE, power_gate);
0641
0642 REG_WAIT(DOMAIN3_PG_STATUS,
0643 DOMAIN3_PGFSM_PWR_STATUS, pwr_status,
0644 1, 1000);
0645 break;
0646 case 2:
0647 REG_UPDATE(DOMAIN5_PG_CONFIG,
0648 DOMAIN5_POWER_GATE, power_gate);
0649
0650 REG_WAIT(DOMAIN5_PG_STATUS,
0651 DOMAIN5_PGFSM_PWR_STATUS, pwr_status,
0652 1, 1000);
0653 break;
0654 case 3:
0655 REG_UPDATE(DOMAIN7_PG_CONFIG,
0656 DOMAIN7_POWER_GATE, power_gate);
0657
0658 REG_WAIT(DOMAIN7_PG_STATUS,
0659 DOMAIN7_PGFSM_PWR_STATUS, pwr_status,
0660 1, 1000);
0661 break;
0662 default:
0663 BREAK_TO_DEBUGGER();
0664 break;
0665 }
0666 }
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677 void dcn10_hubp_pg_control(
0678 struct dce_hwseq *hws,
0679 unsigned int hubp_inst,
0680 bool power_on)
0681 {
0682 uint32_t power_gate = power_on ? 0 : 1;
0683 uint32_t pwr_status = power_on ? PGFSM_POWER_ON : PGFSM_POWER_OFF;
0684
0685 if (hws->ctx->dc->debug.disable_hubp_power_gate)
0686 return;
0687 if (REG(DOMAIN0_PG_CONFIG) == 0)
0688 return;
0689
0690 switch (hubp_inst) {
0691 case 0:
0692 REG_UPDATE(DOMAIN0_PG_CONFIG,
0693 DOMAIN0_POWER_GATE, power_gate);
0694
0695 REG_WAIT(DOMAIN0_PG_STATUS,
0696 DOMAIN0_PGFSM_PWR_STATUS, pwr_status,
0697 1, 1000);
0698 break;
0699 case 1:
0700 REG_UPDATE(DOMAIN2_PG_CONFIG,
0701 DOMAIN2_POWER_GATE, power_gate);
0702
0703 REG_WAIT(DOMAIN2_PG_STATUS,
0704 DOMAIN2_PGFSM_PWR_STATUS, pwr_status,
0705 1, 1000);
0706 break;
0707 case 2:
0708 REG_UPDATE(DOMAIN4_PG_CONFIG,
0709 DOMAIN4_POWER_GATE, power_gate);
0710
0711 REG_WAIT(DOMAIN4_PG_STATUS,
0712 DOMAIN4_PGFSM_PWR_STATUS, pwr_status,
0713 1, 1000);
0714 break;
0715 case 3:
0716 REG_UPDATE(DOMAIN6_PG_CONFIG,
0717 DOMAIN6_POWER_GATE, power_gate);
0718
0719 REG_WAIT(DOMAIN6_PG_STATUS,
0720 DOMAIN6_PGFSM_PWR_STATUS, pwr_status,
0721 1, 1000);
0722 break;
0723 default:
0724 BREAK_TO_DEBUGGER();
0725 break;
0726 }
0727 }
0728
0729 static void power_on_plane(
0730 struct dce_hwseq *hws,
0731 int plane_id)
0732 {
0733 DC_LOGGER_INIT(hws->ctx->logger);
0734 if (REG(DC_IP_REQUEST_CNTL)) {
0735 REG_SET(DC_IP_REQUEST_CNTL, 0,
0736 IP_REQUEST_EN, 1);
0737
0738 if (hws->funcs.dpp_pg_control)
0739 hws->funcs.dpp_pg_control(hws, plane_id, true);
0740
0741 if (hws->funcs.hubp_pg_control)
0742 hws->funcs.hubp_pg_control(hws, plane_id, true);
0743
0744 REG_SET(DC_IP_REQUEST_CNTL, 0,
0745 IP_REQUEST_EN, 0);
0746 DC_LOG_DEBUG(
0747 "Un-gated front end for pipe %d\n", plane_id);
0748 }
0749 }
0750
0751 static void undo_DEGVIDCN10_253_wa(struct dc *dc)
0752 {
0753 struct dce_hwseq *hws = dc->hwseq;
0754 struct hubp *hubp = dc->res_pool->hubps[0];
0755
0756 if (!hws->wa_state.DEGVIDCN10_253_applied)
0757 return;
0758
0759 hubp->funcs->set_blank(hubp, true);
0760
0761 REG_SET(DC_IP_REQUEST_CNTL, 0,
0762 IP_REQUEST_EN, 1);
0763
0764 hws->funcs.hubp_pg_control(hws, 0, false);
0765 REG_SET(DC_IP_REQUEST_CNTL, 0,
0766 IP_REQUEST_EN, 0);
0767
0768 hws->wa_state.DEGVIDCN10_253_applied = false;
0769 }
0770
0771 static void apply_DEGVIDCN10_253_wa(struct dc *dc)
0772 {
0773 struct dce_hwseq *hws = dc->hwseq;
0774 struct hubp *hubp = dc->res_pool->hubps[0];
0775 int i;
0776
0777 if (dc->debug.disable_stutter)
0778 return;
0779
0780 if (!hws->wa.DEGVIDCN10_253)
0781 return;
0782
0783 for (i = 0; i < dc->res_pool->pipe_count; i++) {
0784 if (!dc->res_pool->hubps[i]->power_gated)
0785 return;
0786 }
0787
0788
0789
0790 REG_SET(DC_IP_REQUEST_CNTL, 0,
0791 IP_REQUEST_EN, 1);
0792
0793 hws->funcs.hubp_pg_control(hws, 0, true);
0794 REG_SET(DC_IP_REQUEST_CNTL, 0,
0795 IP_REQUEST_EN, 0);
0796
0797 hubp->funcs->set_hubp_blank_en(hubp, false);
0798 hws->wa_state.DEGVIDCN10_253_applied = true;
0799 }
0800
0801 void dcn10_bios_golden_init(struct dc *dc)
0802 {
0803 struct dce_hwseq *hws = dc->hwseq;
0804 struct dc_bios *bp = dc->ctx->dc_bios;
0805 int i;
0806 bool allow_self_fresh_force_enable = true;
0807
0808 if (hws->funcs.s0i3_golden_init_wa && hws->funcs.s0i3_golden_init_wa(dc))
0809 return;
0810
0811 if (dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled)
0812 allow_self_fresh_force_enable =
0813 dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub);
0814
0815
0816
0817
0818
0819
0820
0821
0822
0823
0824 bp->funcs->enable_disp_power_gating(bp,
0825 CONTROLLER_ID_D0, ASIC_PIPE_INIT);
0826
0827 for (i = 0; i < dc->res_pool->pipe_count; i++) {
0828
0829 bp->funcs->enable_disp_power_gating(bp,
0830 CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE);
0831 }
0832
0833 if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
0834 if (allow_self_fresh_force_enable == false &&
0835 dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub))
0836 dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
0837 !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
0838
0839 }
0840
0841 static void false_optc_underflow_wa(
0842 struct dc *dc,
0843 const struct dc_stream_state *stream,
0844 struct timing_generator *tg)
0845 {
0846 int i;
0847 bool underflow;
0848
0849 if (!dc->hwseq->wa.false_optc_underflow)
0850 return;
0851
0852 underflow = tg->funcs->is_optc_underflow_occurred(tg);
0853
0854 for (i = 0; i < dc->res_pool->pipe_count; i++) {
0855 struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
0856
0857 if (old_pipe_ctx->stream != stream)
0858 continue;
0859
0860 dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, old_pipe_ctx);
0861 }
0862
0863 if (tg->funcs->set_blank_data_double_buffer)
0864 tg->funcs->set_blank_data_double_buffer(tg, true);
0865
0866 if (tg->funcs->is_optc_underflow_occurred(tg) && !underflow)
0867 tg->funcs->clear_optc_underflow(tg);
0868 }
0869
0870 enum dc_status dcn10_enable_stream_timing(
0871 struct pipe_ctx *pipe_ctx,
0872 struct dc_state *context,
0873 struct dc *dc)
0874 {
0875 struct dc_stream_state *stream = pipe_ctx->stream;
0876 enum dc_color_space color_space;
0877 struct tg_color black_color = {0};
0878
0879
0880
0881
0882
0883 if (pipe_ctx->top_pipe != NULL)
0884 return DC_OK;
0885
0886
0887
0888
0889
0890
0891 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, true);
0892
0893 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
0894 pipe_ctx->clock_source,
0895 &pipe_ctx->stream_res.pix_clk_params,
0896 dp_get_link_encoding_format(&pipe_ctx->link_config.dp_link_settings),
0897 &pipe_ctx->pll_settings)) {
0898 BREAK_TO_DEBUGGER();
0899 return DC_ERROR_UNEXPECTED;
0900 }
0901
0902 pipe_ctx->stream_res.tg->funcs->program_timing(
0903 pipe_ctx->stream_res.tg,
0904 &stream->timing,
0905 pipe_ctx->pipe_dlg_param.vready_offset,
0906 pipe_ctx->pipe_dlg_param.vstartup_start,
0907 pipe_ctx->pipe_dlg_param.vupdate_offset,
0908 pipe_ctx->pipe_dlg_param.vupdate_width,
0909 pipe_ctx->stream->signal,
0910 true);
0911
0912 #if 0
0913
0914
0915
0916 inst_offset = reg_offsets[pipe_ctx->stream_res.tg->inst].fmt;
0917
0918 pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
0919 pipe_ctx->stream_res.opp,
0920 &stream->bit_depth_params,
0921 &stream->clamping);
0922 #endif
0923
0924 color_space = stream->output_color_space;
0925 color_space_to_black_color(dc, color_space, &black_color);
0926
0927
0928
0929
0930
0931
0932 if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
0933 black_color.color_r_cr = black_color.color_g_y;
0934
0935 if (pipe_ctx->stream_res.tg->funcs->set_blank_color)
0936 pipe_ctx->stream_res.tg->funcs->set_blank_color(
0937 pipe_ctx->stream_res.tg,
0938 &black_color);
0939
0940 if (pipe_ctx->stream_res.tg->funcs->is_blanked &&
0941 !pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) {
0942 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true);
0943 hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg);
0944 false_optc_underflow_wa(dc, pipe_ctx->stream, pipe_ctx->stream_res.tg);
0945 }
0946
0947
0948 if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) {
0949 BREAK_TO_DEBUGGER();
0950 return DC_ERROR_UNEXPECTED;
0951 }
0952
0953
0954
0955
0956
0957
0958
0959
0960
0961 return DC_OK;
0962 }
0963
0964 static void dcn10_reset_back_end_for_pipe(
0965 struct dc *dc,
0966 struct pipe_ctx *pipe_ctx,
0967 struct dc_state *context)
0968 {
0969 int i;
0970 struct dc_link *link;
0971 DC_LOGGER_INIT(dc->ctx->logger);
0972 if (pipe_ctx->stream_res.stream_enc == NULL) {
0973 pipe_ctx->stream = NULL;
0974 return;
0975 }
0976
0977 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
0978 link = pipe_ctx->stream->link;
0979
0980
0981
0982
0983
0984
0985 if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
0986 core_link_disable_stream(pipe_ctx);
0987 else if (pipe_ctx->stream_res.audio)
0988 dc->hwss.disable_audio_stream(pipe_ctx);
0989
0990 if (pipe_ctx->stream_res.audio) {
0991
0992 pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
0993
0994
0995 if (dc->caps.dynamic_audio == true) {
0996
0997
0998 update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
0999 pipe_ctx->stream_res.audio, false);
1000 pipe_ctx->stream_res.audio = NULL;
1001 }
1002 }
1003 }
1004
1005
1006
1007
1008
1009 if (pipe_ctx->top_pipe == NULL) {
1010
1011 if (pipe_ctx->stream_res.abm)
1012 dc->hwss.set_abm_immediate_disable(pipe_ctx);
1013
1014 pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
1015
1016 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
1017 if (pipe_ctx->stream_res.tg->funcs->set_drr)
1018 pipe_ctx->stream_res.tg->funcs->set_drr(
1019 pipe_ctx->stream_res.tg, NULL);
1020 }
1021
1022 for (i = 0; i < dc->res_pool->pipe_count; i++)
1023 if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx)
1024 break;
1025
1026 if (i == dc->res_pool->pipe_count)
1027 return;
1028
1029 pipe_ctx->stream = NULL;
1030 DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n",
1031 pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst);
1032 }
1033
1034 static bool dcn10_hw_wa_force_recovery(struct dc *dc)
1035 {
1036 struct hubp *hubp ;
1037 unsigned int i;
1038 bool need_recover = true;
1039
1040 if (!dc->debug.recovery_enabled)
1041 return false;
1042
1043 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1044 struct pipe_ctx *pipe_ctx =
1045 &dc->current_state->res_ctx.pipe_ctx[i];
1046 if (pipe_ctx != NULL) {
1047 hubp = pipe_ctx->plane_res.hubp;
1048 if (hubp != NULL && hubp->funcs->hubp_get_underflow_status) {
1049 if (hubp->funcs->hubp_get_underflow_status(hubp) != 0) {
1050
1051 need_recover = true;
1052 }
1053 }
1054 }
1055 }
1056 if (!need_recover)
1057 return false;
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1069 struct pipe_ctx *pipe_ctx =
1070 &dc->current_state->res_ctx.pipe_ctx[i];
1071 if (pipe_ctx != NULL) {
1072 hubp = pipe_ctx->plane_res.hubp;
1073
1074 if (hubp != NULL && hubp->funcs->set_hubp_blank_en)
1075 hubp->funcs->set_hubp_blank_en(hubp, true);
1076 }
1077 }
1078
1079 hubbub1_soft_reset(dc->res_pool->hubbub, true);
1080
1081 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1082 struct pipe_ctx *pipe_ctx =
1083 &dc->current_state->res_ctx.pipe_ctx[i];
1084 if (pipe_ctx != NULL) {
1085 hubp = pipe_ctx->plane_res.hubp;
1086
1087 if (hubp != NULL && hubp->funcs->hubp_disable_control)
1088 hubp->funcs->hubp_disable_control(hubp, true);
1089 }
1090 }
1091 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1092 struct pipe_ctx *pipe_ctx =
1093 &dc->current_state->res_ctx.pipe_ctx[i];
1094 if (pipe_ctx != NULL) {
1095 hubp = pipe_ctx->plane_res.hubp;
1096
1097 if (hubp != NULL && hubp->funcs->hubp_disable_control)
1098 hubp->funcs->hubp_disable_control(hubp, true);
1099 }
1100 }
1101
1102 hubbub1_soft_reset(dc->res_pool->hubbub, false);
1103 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1104 struct pipe_ctx *pipe_ctx =
1105 &dc->current_state->res_ctx.pipe_ctx[i];
1106 if (pipe_ctx != NULL) {
1107 hubp = pipe_ctx->plane_res.hubp;
1108
1109 if (hubp != NULL && hubp->funcs->set_hubp_blank_en)
1110 hubp->funcs->set_hubp_blank_en(hubp, true);
1111 }
1112 }
1113 return true;
1114
1115 }
1116
1117 void dcn10_verify_allow_pstate_change_high(struct dc *dc)
1118 {
1119 struct hubbub *hubbub = dc->res_pool->hubbub;
1120 static bool should_log_hw_state;
1121
1122 if (!hubbub->funcs->verify_allow_pstate_change_high)
1123 return;
1124
1125 if (!hubbub->funcs->verify_allow_pstate_change_high(hubbub)) {
1126 int i = 0;
1127
1128 if (should_log_hw_state)
1129 dcn10_log_hw_state(dc, NULL);
1130
1131 TRACE_DC_PIPE_STATE(pipe_ctx, i, MAX_PIPES);
1132 BREAK_TO_DEBUGGER();
1133 if (dcn10_hw_wa_force_recovery(dc)) {
1134
1135 if (!hubbub->funcs->verify_allow_pstate_change_high(hubbub))
1136 BREAK_TO_DEBUGGER();
1137 }
1138 }
1139 }
1140
1141
1142 void dcn10_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx)
1143 {
1144 struct dce_hwseq *hws = dc->hwseq;
1145 struct hubp *hubp = pipe_ctx->plane_res.hubp;
1146 int dpp_id = pipe_ctx->plane_res.dpp->inst;
1147 struct mpc *mpc = dc->res_pool->mpc;
1148 struct mpc_tree *mpc_tree_params;
1149 struct mpcc *mpcc_to_remove = NULL;
1150 struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
1151
1152 mpc_tree_params = &(opp->mpc_tree_params);
1153 mpcc_to_remove = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, dpp_id);
1154
1155
1156 if (mpcc_to_remove == NULL)
1157 return;
1158
1159 mpc->funcs->remove_mpcc(mpc, mpc_tree_params, mpcc_to_remove);
1160
1161
1162 if (opp != NULL && !pipe_ctx->plane_state->is_phantom)
1163 opp->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
1164
1165 dc->optimized_required = true;
1166
1167 if (hubp->funcs->hubp_disconnect)
1168 hubp->funcs->hubp_disconnect(hubp);
1169
1170 if (dc->debug.sanity_checks)
1171 hws->funcs.verify_allow_pstate_change_high(dc);
1172 }
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187 void dcn10_plane_atomic_power_down(struct dc *dc,
1188 struct dpp *dpp,
1189 struct hubp *hubp)
1190 {
1191 struct dce_hwseq *hws = dc->hwseq;
1192 DC_LOGGER_INIT(dc->ctx->logger);
1193
1194 if (REG(DC_IP_REQUEST_CNTL)) {
1195 REG_SET(DC_IP_REQUEST_CNTL, 0,
1196 IP_REQUEST_EN, 1);
1197
1198 if (hws->funcs.dpp_pg_control)
1199 hws->funcs.dpp_pg_control(hws, dpp->inst, false);
1200
1201 if (hws->funcs.hubp_pg_control)
1202 hws->funcs.hubp_pg_control(hws, hubp->inst, false);
1203
1204 dpp->funcs->dpp_reset(dpp);
1205 REG_SET(DC_IP_REQUEST_CNTL, 0,
1206 IP_REQUEST_EN, 0);
1207 DC_LOG_DEBUG(
1208 "Power gated front end %d\n", hubp->inst);
1209 }
1210 }
1211
1212
1213
1214
1215 void dcn10_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
1216 {
1217 struct dce_hwseq *hws = dc->hwseq;
1218 struct hubp *hubp = pipe_ctx->plane_res.hubp;
1219 struct dpp *dpp = pipe_ctx->plane_res.dpp;
1220 int opp_id = hubp->opp_id;
1221
1222 dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx);
1223
1224 hubp->funcs->hubp_clk_cntl(hubp, false);
1225
1226 dpp->funcs->dpp_dppclk_control(dpp, false, false);
1227
1228 if (opp_id != 0xf && pipe_ctx->stream_res.opp->mpc_tree_params.opp_list == NULL)
1229 pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
1230 pipe_ctx->stream_res.opp,
1231 false);
1232
1233 hubp->power_gated = true;
1234 dc->optimized_required = false;
1235
1236 hws->funcs.plane_atomic_power_down(dc,
1237 pipe_ctx->plane_res.dpp,
1238 pipe_ctx->plane_res.hubp);
1239
1240 pipe_ctx->stream = NULL;
1241 memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res));
1242 memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res));
1243 pipe_ctx->top_pipe = NULL;
1244 pipe_ctx->bottom_pipe = NULL;
1245 pipe_ctx->plane_state = NULL;
1246 }
1247
1248 void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
1249 {
1250 struct dce_hwseq *hws = dc->hwseq;
1251 DC_LOGGER_INIT(dc->ctx->logger);
1252
1253 if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated)
1254 return;
1255
1256 hws->funcs.plane_atomic_disable(dc, pipe_ctx);
1257
1258 apply_DEGVIDCN10_253_wa(dc);
1259
1260 DC_LOG_DC("Power down front end %d\n",
1261 pipe_ctx->pipe_idx);
1262 }
1263
1264 void dcn10_init_pipes(struct dc *dc, struct dc_state *context)
1265 {
1266 int i;
1267 struct dce_hwseq *hws = dc->hwseq;
1268 struct hubbub *hubbub = dc->res_pool->hubbub;
1269 bool can_apply_seamless_boot = false;
1270
1271 for (i = 0; i < context->stream_count; i++) {
1272 if (context->streams[i]->apply_seamless_boot_optimization) {
1273 can_apply_seamless_boot = true;
1274 break;
1275 }
1276 }
1277
1278 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1279 struct timing_generator *tg = dc->res_pool->timing_generators[i];
1280 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1281
1282
1283
1284
1285
1286 if (pipe_ctx->stream != NULL && can_apply_seamless_boot)
1287 continue;
1288
1289
1290
1291
1292 if (tg->funcs->is_tg_enabled(tg)) {
1293 if (hws->funcs.init_blank != NULL) {
1294 hws->funcs.init_blank(dc, tg);
1295 tg->funcs->lock(tg);
1296 } else {
1297 tg->funcs->lock(tg);
1298 tg->funcs->set_blank(tg, true);
1299 hwss_wait_for_blank_complete(tg);
1300 }
1301 }
1302 }
1303
1304
1305 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1306 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1307 struct hubp *hubp = dc->res_pool->hubps[i];
1308
1309
1310 if (pipe_ctx->stream != NULL && can_apply_seamless_boot)
1311 continue;
1312
1313 if (hubbub && hubp) {
1314 if (hubbub->funcs->program_det_size)
1315 hubbub->funcs->program_det_size(hubbub, hubp->inst, 0);
1316 }
1317 }
1318
1319
1320 for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
1321 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1322
1323
1324 if (pipe_ctx->stream != NULL && can_apply_seamless_boot)
1325 continue;
1326
1327 dc->res_pool->mpc->funcs->mpc_init_single_inst(
1328 dc->res_pool->mpc, i);
1329 }
1330
1331 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1332 struct timing_generator *tg = dc->res_pool->timing_generators[i];
1333 struct hubp *hubp = dc->res_pool->hubps[i];
1334 struct dpp *dpp = dc->res_pool->dpps[i];
1335 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1336
1337
1338
1339
1340
1341 if (can_apply_seamless_boot &&
1342 pipe_ctx->stream != NULL &&
1343 pipe_ctx->stream_res.tg->funcs->is_tg_enabled(
1344 pipe_ctx->stream_res.tg)) {
1345
1346
1347
1348
1349 tg->funcs->tg_init(tg);
1350 hubp->power_gated = true;
1351 continue;
1352 }
1353
1354
1355 pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
1356
1357 dpp->funcs->dpp_reset(dpp);
1358
1359 pipe_ctx->stream_res.tg = tg;
1360 pipe_ctx->pipe_idx = i;
1361
1362 pipe_ctx->plane_res.hubp = hubp;
1363 pipe_ctx->plane_res.dpp = dpp;
1364 pipe_ctx->plane_res.mpcc_inst = dpp->inst;
1365 hubp->mpcc_id = dpp->inst;
1366 hubp->opp_id = OPP_ID_INVALID;
1367 hubp->power_gated = false;
1368
1369 dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst;
1370 dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
1371 dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
1372 pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
1373
1374 hws->funcs.plane_atomic_disconnect(dc, pipe_ctx);
1375
1376 if (tg->funcs->is_tg_enabled(tg))
1377 tg->funcs->unlock(tg);
1378
1379 dc->hwss.disable_plane(dc, pipe_ctx);
1380
1381 pipe_ctx->stream_res.tg = NULL;
1382 pipe_ctx->plane_res.hubp = NULL;
1383
1384 if (tg->funcs->is_tg_enabled(tg)) {
1385 if (tg->funcs->init_odm)
1386 tg->funcs->init_odm(tg);
1387 }
1388
1389 tg->funcs->tg_init(tg);
1390 }
1391
1392
1393 if (hws->funcs.dsc_pg_control != NULL) {
1394 uint32_t num_opps = 0;
1395 uint32_t opp_id_src0 = OPP_ID_INVALID;
1396 uint32_t opp_id_src1 = OPP_ID_INVALID;
1397
1398
1399
1400
1401
1402
1403
1404 for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
1405 uint32_t optc_dsc_state = 0;
1406 struct timing_generator *tg = dc->res_pool->timing_generators[i];
1407
1408 if (tg->funcs->is_tg_enabled(tg)) {
1409 if (tg->funcs->get_dsc_status)
1410 tg->funcs->get_dsc_status(tg, &optc_dsc_state);
1411
1412
1413 if (optc_dsc_state != 0) {
1414 tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1);
1415 break;
1416 }
1417 }
1418 }
1419
1420
1421 for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) {
1422 struct dcn_dsc_state s = {0};
1423
1424 dc->res_pool->dscs[i]->funcs->dsc_read_state(dc->res_pool->dscs[i], &s);
1425
1426 if ((s.dsc_opp_source == opp_id_src0 || s.dsc_opp_source == opp_id_src1) &&
1427 s.dsc_clock_en && s.dsc_fw_en)
1428 continue;
1429
1430 hws->funcs.dsc_pg_control(hws, dc->res_pool->dscs[i]->inst, false);
1431 }
1432 }
1433 }
1434
1435 void dcn10_init_hw(struct dc *dc)
1436 {
1437 int i;
1438 struct abm *abm = dc->res_pool->abm;
1439 struct dmcu *dmcu = dc->res_pool->dmcu;
1440 struct dce_hwseq *hws = dc->hwseq;
1441 struct dc_bios *dcb = dc->ctx->dc_bios;
1442 struct resource_pool *res_pool = dc->res_pool;
1443 uint32_t backlight = MAX_BACKLIGHT_LEVEL;
1444 bool is_optimized_init_done = false;
1445
1446 if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
1447 dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
1448
1449
1450 if (dc->clk_mgr->clks.dispclk_khz != 0 && dc->clk_mgr->clks.dppclk_khz != 0) {
1451 dc->current_state->bw_ctx.bw.dcn.clk.dispclk_khz = dc->clk_mgr->clks.dispclk_khz;
1452 dc->current_state->bw_ctx.bw.dcn.clk.dppclk_khz = dc->clk_mgr->clks.dppclk_khz;
1453 }
1454
1455
1456 if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->dccg_init)
1457 dc->res_pool->dccg->funcs->dccg_init(res_pool->dccg);
1458
1459 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
1460
1461 REG_WRITE(REFCLK_CNTL, 0);
1462 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
1463 REG_WRITE(DIO_MEM_PWR_CTRL, 0);
1464
1465 if (!dc->debug.disable_clock_gate) {
1466
1467 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
1468
1469 REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
1470
1471 REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
1472 }
1473
1474
1475 if (hws->funcs.enable_power_gating_plane)
1476 hws->funcs.enable_power_gating_plane(hws, true);
1477
1478 return;
1479 }
1480
1481 if (!dcb->funcs->is_accelerated_mode(dcb))
1482 hws->funcs.disable_vga(dc->hwseq);
1483
1484 hws->funcs.bios_golden_init(dc);
1485
1486 if (dc->ctx->dc_bios->fw_info_valid) {
1487 res_pool->ref_clocks.xtalin_clock_inKhz =
1488 dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
1489
1490 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
1491 if (res_pool->dccg && res_pool->hubbub) {
1492
1493 (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
1494 dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
1495 &res_pool->ref_clocks.dccg_ref_clock_inKhz);
1496
1497 (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
1498 res_pool->ref_clocks.dccg_ref_clock_inKhz,
1499 &res_pool->ref_clocks.dchub_ref_clock_inKhz);
1500 } else {
1501
1502 res_pool->ref_clocks.dccg_ref_clock_inKhz =
1503 res_pool->ref_clocks.xtalin_clock_inKhz;
1504 res_pool->ref_clocks.dchub_ref_clock_inKhz =
1505 res_pool->ref_clocks.xtalin_clock_inKhz;
1506 }
1507 }
1508 } else
1509 ASSERT_CRITICAL(false);
1510
1511 for (i = 0; i < dc->link_count; i++) {
1512
1513
1514
1515
1516 struct dc_link *link = dc->links[i];
1517
1518 if (!is_optimized_init_done)
1519 link->link_enc->funcs->hw_init(link->link_enc);
1520
1521
1522 if (link->link_enc->funcs->is_dig_enabled &&
1523 link->link_enc->funcs->is_dig_enabled(link->link_enc)) {
1524 link->link_status.link_active = true;
1525 if (link->link_enc->funcs->fec_is_active &&
1526 link->link_enc->funcs->fec_is_active(link->link_enc))
1527 link->fec_state = dc_link_fec_enabled;
1528 }
1529 }
1530
1531
1532 dc_link_blank_all_dp_displays(dc);
1533
1534 if (hws->funcs.enable_power_gating_plane)
1535 hws->funcs.enable_power_gating_plane(dc->hwseq, true);
1536
1537
1538
1539
1540
1541
1542
1543 if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) {
1544 if (!is_optimized_init_done) {
1545 hws->funcs.init_pipes(dc, dc->current_state);
1546 if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
1547 dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
1548 !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
1549 }
1550 }
1551
1552 if (!is_optimized_init_done) {
1553
1554 for (i = 0; i < res_pool->audio_count; i++) {
1555 struct audio *audio = res_pool->audios[i];
1556
1557 audio->funcs->hw_init(audio);
1558 }
1559
1560 for (i = 0; i < dc->link_count; i++) {
1561 struct dc_link *link = dc->links[i];
1562
1563 if (link->panel_cntl)
1564 backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
1565 }
1566
1567 if (abm != NULL)
1568 abm->funcs->abm_init(abm, backlight);
1569
1570 if (dmcu != NULL && !dmcu->auto_load_dmcu)
1571 dmcu->funcs->dmcu_init(dmcu);
1572 }
1573
1574 if (abm != NULL && dmcu != NULL)
1575 abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu);
1576
1577
1578 if (!is_optimized_init_done)
1579 REG_WRITE(DIO_MEM_PWR_CTRL, 0);
1580
1581 if (!dc->debug.disable_clock_gate) {
1582
1583 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
1584
1585 REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
1586
1587 REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
1588 }
1589
1590 if (dc->clk_mgr->funcs->notify_wm_ranges)
1591 dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
1592 }
1593
1594
1595
1596
1597
1598
1599 void dcn10_power_down_on_boot(struct dc *dc)
1600 {
1601 struct dc_link *edp_links[MAX_NUM_EDP];
1602 struct dc_link *edp_link = NULL;
1603 int edp_num;
1604 int i = 0;
1605
1606 get_edp_links(dc, edp_links, &edp_num);
1607 if (edp_num)
1608 edp_link = edp_links[0];
1609
1610 if (edp_link && edp_link->link_enc->funcs->is_dig_enabled &&
1611 edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
1612 dc->hwseq->funcs.edp_backlight_control &&
1613 dc->hwss.power_down &&
1614 dc->hwss.edp_power_control) {
1615 dc->hwseq->funcs.edp_backlight_control(edp_link, false);
1616 dc->hwss.power_down(dc);
1617 dc->hwss.edp_power_control(edp_link, false);
1618 } else {
1619 for (i = 0; i < dc->link_count; i++) {
1620 struct dc_link *link = dc->links[i];
1621
1622 if (link->link_enc && link->link_enc->funcs->is_dig_enabled &&
1623 link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
1624 dc->hwss.power_down) {
1625 dc->hwss.power_down(dc);
1626 break;
1627 }
1628
1629 }
1630 }
1631
1632
1633
1634
1635
1636
1637 if (dc->clk_mgr->funcs->set_low_power_state)
1638 dc->clk_mgr->funcs->set_low_power_state(dc->clk_mgr);
1639 }
1640
1641 void dcn10_reset_hw_ctx_wrap(
1642 struct dc *dc,
1643 struct dc_state *context)
1644 {
1645 int i;
1646 struct dce_hwseq *hws = dc->hwseq;
1647
1648
1649 for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
1650 struct pipe_ctx *pipe_ctx_old =
1651 &dc->current_state->res_ctx.pipe_ctx[i];
1652 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1653
1654 if (!pipe_ctx_old->stream)
1655 continue;
1656
1657 if (pipe_ctx_old->top_pipe)
1658 continue;
1659
1660 if (!pipe_ctx->stream ||
1661 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
1662 struct clock_source *old_clk = pipe_ctx_old->clock_source;
1663
1664 dcn10_reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state);
1665 if (hws->funcs.enable_stream_gating)
1666 hws->funcs.enable_stream_gating(dc, pipe_ctx_old);
1667 if (old_clk)
1668 old_clk->funcs->cs_power_down(old_clk);
1669 }
1670 }
1671 }
1672
1673 static bool patch_address_for_sbs_tb_stereo(
1674 struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr)
1675 {
1676 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1677 bool sec_split = pipe_ctx->top_pipe &&
1678 pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state;
1679 if (sec_split && plane_state->address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
1680 (pipe_ctx->stream->timing.timing_3d_format ==
1681 TIMING_3D_FORMAT_SIDE_BY_SIDE ||
1682 pipe_ctx->stream->timing.timing_3d_format ==
1683 TIMING_3D_FORMAT_TOP_AND_BOTTOM)) {
1684 *addr = plane_state->address.grph_stereo.left_addr;
1685 plane_state->address.grph_stereo.left_addr =
1686 plane_state->address.grph_stereo.right_addr;
1687 return true;
1688 } else {
1689 if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE &&
1690 plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO) {
1691 plane_state->address.type = PLN_ADDR_TYPE_GRPH_STEREO;
1692 plane_state->address.grph_stereo.right_addr =
1693 plane_state->address.grph_stereo.left_addr;
1694 plane_state->address.grph_stereo.right_meta_addr =
1695 plane_state->address.grph_stereo.left_meta_addr;
1696 }
1697 }
1698 return false;
1699 }
1700
1701 void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)
1702 {
1703 bool addr_patched = false;
1704 PHYSICAL_ADDRESS_LOC addr;
1705 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1706
1707 if (plane_state == NULL)
1708 return;
1709
1710 addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr);
1711
1712 pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr(
1713 pipe_ctx->plane_res.hubp,
1714 &plane_state->address,
1715 plane_state->flip_immediate);
1716
1717 plane_state->status.requested_address = plane_state->address;
1718
1719 if (plane_state->flip_immediate)
1720 plane_state->status.current_address = plane_state->address;
1721
1722 if (addr_patched)
1723 pipe_ctx->plane_state->address.grph_stereo.left_addr = addr;
1724 }
1725
1726 bool dcn10_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
1727 const struct dc_plane_state *plane_state)
1728 {
1729 struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
1730 const struct dc_transfer_func *tf = NULL;
1731 bool result = true;
1732
1733 if (dpp_base == NULL)
1734 return false;
1735
1736 if (plane_state->in_transfer_func)
1737 tf = plane_state->in_transfer_func;
1738
1739 if (plane_state->gamma_correction &&
1740 !dpp_base->ctx->dc->debug.always_use_regamma
1741 && !plane_state->gamma_correction->is_identity
1742 && dce_use_lut(plane_state->format))
1743 dpp_base->funcs->dpp_program_input_lut(dpp_base, plane_state->gamma_correction);
1744
1745 if (tf == NULL)
1746 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
1747 else if (tf->type == TF_TYPE_PREDEFINED) {
1748 switch (tf->tf) {
1749 case TRANSFER_FUNCTION_SRGB:
1750 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_sRGB);
1751 break;
1752 case TRANSFER_FUNCTION_BT709:
1753 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_xvYCC);
1754 break;
1755 case TRANSFER_FUNCTION_LINEAR:
1756 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
1757 break;
1758 case TRANSFER_FUNCTION_PQ:
1759 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_USER_PWL);
1760 cm_helper_translate_curve_to_degamma_hw_format(tf, &dpp_base->degamma_params);
1761 dpp_base->funcs->dpp_program_degamma_pwl(dpp_base, &dpp_base->degamma_params);
1762 result = true;
1763 break;
1764 default:
1765 result = false;
1766 break;
1767 }
1768 } else if (tf->type == TF_TYPE_BYPASS) {
1769 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
1770 } else {
1771 cm_helper_translate_curve_to_degamma_hw_format(tf,
1772 &dpp_base->degamma_params);
1773 dpp_base->funcs->dpp_program_degamma_pwl(dpp_base,
1774 &dpp_base->degamma_params);
1775 result = true;
1776 }
1777
1778 return result;
1779 }
1780
1781 #define MAX_NUM_HW_POINTS 0x200
1782
1783 static void log_tf(struct dc_context *ctx,
1784 struct dc_transfer_func *tf, uint32_t hw_points_num)
1785 {
1786
1787
1788
1789 int i = 0;
1790
1791 DC_LOGGER_INIT(ctx->logger);
1792 DC_LOG_GAMMA("Gamma Correction TF");
1793 DC_LOG_ALL_GAMMA("Logging all tf points...");
1794 DC_LOG_ALL_TF_CHANNELS("Logging all channels...");
1795
1796 for (i = 0; i < hw_points_num; i++) {
1797 DC_LOG_GAMMA("R\t%d\t%llu", i, tf->tf_pts.red[i].value);
1798 DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu", i, tf->tf_pts.green[i].value);
1799 DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu", i, tf->tf_pts.blue[i].value);
1800 }
1801
1802 for (i = hw_points_num; i < MAX_NUM_HW_POINTS; i++) {
1803 DC_LOG_ALL_GAMMA("R\t%d\t%llu", i, tf->tf_pts.red[i].value);
1804 DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu", i, tf->tf_pts.green[i].value);
1805 DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu", i, tf->tf_pts.blue[i].value);
1806 }
1807 }
1808
1809 bool dcn10_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
1810 const struct dc_stream_state *stream)
1811 {
1812 struct dpp *dpp = pipe_ctx->plane_res.dpp;
1813
1814 if (dpp == NULL)
1815 return false;
1816
1817 dpp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM;
1818
1819 if (stream->out_transfer_func &&
1820 stream->out_transfer_func->type == TF_TYPE_PREDEFINED &&
1821 stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB)
1822 dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_SRGB);
1823
1824
1825
1826
1827 else if (cm_helper_translate_curve_to_hw_format(
1828 stream->out_transfer_func,
1829 &dpp->regamma_params, false)) {
1830 dpp->funcs->dpp_program_regamma_pwl(
1831 dpp,
1832 &dpp->regamma_params, OPP_REGAMMA_USER);
1833 } else
1834 dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_BYPASS);
1835
1836 if (stream != NULL && stream->ctx != NULL &&
1837 stream->out_transfer_func != NULL) {
1838 log_tf(stream->ctx,
1839 stream->out_transfer_func,
1840 dpp->regamma_params.hw_points_num);
1841 }
1842
1843 return true;
1844 }
1845
1846 void dcn10_pipe_control_lock(
1847 struct dc *dc,
1848 struct pipe_ctx *pipe,
1849 bool lock)
1850 {
1851 struct dce_hwseq *hws = dc->hwseq;
1852
1853
1854
1855
1856 if (!pipe || pipe->top_pipe)
1857 return;
1858
1859 if (dc->debug.sanity_checks)
1860 hws->funcs.verify_allow_pstate_change_high(dc);
1861
1862 if (lock)
1863 pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
1864 else
1865 pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
1866
1867 if (dc->debug.sanity_checks)
1868 hws->funcs.verify_allow_pstate_change_high(dc);
1869 }
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884 static void delay_cursor_until_vupdate(struct dc *dc, struct pipe_ctx *pipe_ctx)
1885 {
1886 struct dc_stream_state *stream = pipe_ctx->stream;
1887 struct crtc_position position;
1888 uint32_t vupdate_start, vupdate_end;
1889 unsigned int lines_to_vupdate, us_to_vupdate, vpos;
1890 unsigned int us_per_line, us_vupdate;
1891
1892 if (!dc->hwss.calc_vupdate_position || !dc->hwss.get_position)
1893 return;
1894
1895 if (!pipe_ctx->stream_res.stream_enc || !pipe_ctx->stream_res.tg)
1896 return;
1897
1898 dc->hwss.calc_vupdate_position(dc, pipe_ctx, &vupdate_start,
1899 &vupdate_end);
1900
1901 dc->hwss.get_position(&pipe_ctx, 1, &position);
1902 vpos = position.vertical_count;
1903
1904
1905 vupdate_start += stream->timing.v_total;
1906 vupdate_end += stream->timing.v_total;
1907 vpos += stream->timing.v_total;
1908
1909 if (vpos <= vupdate_start) {
1910
1911 lines_to_vupdate = vupdate_start - vpos;
1912 } else if (vpos > vupdate_end) {
1913
1914 return;
1915 } else {
1916
1917 lines_to_vupdate = 0;
1918 }
1919
1920
1921 us_per_line =
1922 stream->timing.h_total * 10000u / stream->timing.pix_clk_100hz;
1923 us_to_vupdate = lines_to_vupdate * us_per_line;
1924
1925
1926 if (us_to_vupdate > 70)
1927 return;
1928
1929
1930 if (vupdate_end < vupdate_start)
1931 vupdate_end += stream->timing.v_total;
1932 us_vupdate = (vupdate_end - vupdate_start + 1) * us_per_line;
1933 udelay(us_to_vupdate + us_vupdate);
1934 }
1935
1936 void dcn10_cursor_lock(struct dc *dc, struct pipe_ctx *pipe, bool lock)
1937 {
1938
1939 if (!pipe || pipe->top_pipe)
1940 return;
1941
1942
1943 if (lock)
1944 delay_cursor_until_vupdate(dc, pipe);
1945
1946 if (pipe->stream && should_use_dmub_lock(pipe->stream->link)) {
1947 union dmub_hw_lock_flags hw_locks = { 0 };
1948 struct dmub_hw_lock_inst_flags inst_flags = { 0 };
1949
1950 hw_locks.bits.lock_cursor = 1;
1951 inst_flags.opp_inst = pipe->stream_res.opp->inst;
1952
1953 dmub_hw_lock_mgr_cmd(dc->ctx->dmub_srv,
1954 lock,
1955 &hw_locks,
1956 &inst_flags);
1957 } else
1958 dc->res_pool->mpc->funcs->cursor_lock(dc->res_pool->mpc,
1959 pipe->stream_res.opp->inst, lock);
1960 }
1961
1962 static bool wait_for_reset_trigger_to_occur(
1963 struct dc_context *dc_ctx,
1964 struct timing_generator *tg)
1965 {
1966 bool rc = false;
1967
1968
1969
1970 const uint32_t frames_to_wait_on_triggered_reset = 10;
1971 int i;
1972
1973 for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
1974
1975 if (!tg->funcs->is_counter_moving(tg)) {
1976 DC_ERROR("TG counter is not moving!\n");
1977 break;
1978 }
1979
1980 if (tg->funcs->did_triggered_reset_occur(tg)) {
1981 rc = true;
1982
1983 DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
1984 i);
1985 break;
1986 }
1987
1988
1989 tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
1990 tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
1991 }
1992
1993 if (false == rc)
1994 DC_ERROR("GSL: Timeout on reset trigger!\n");
1995
1996 return rc;
1997 }
1998
1999 static uint64_t reduceSizeAndFraction(uint64_t *numerator,
2000 uint64_t *denominator,
2001 bool checkUint32Bounary)
2002 {
2003 int i;
2004 bool ret = checkUint32Bounary == false;
2005 uint64_t max_int32 = 0xffffffff;
2006 uint64_t num, denom;
2007 static const uint16_t prime_numbers[] = {
2008 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
2009 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,
2010 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,
2011 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
2012 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
2013 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353,
2014 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421,
2015 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487,
2016 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569,
2017 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631,
2018 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
2019 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773,
2020 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857,
2021 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
2022 941, 947, 953, 967, 971, 977, 983, 991, 997};
2023 int count = ARRAY_SIZE(prime_numbers);
2024
2025 num = *numerator;
2026 denom = *denominator;
2027 for (i = 0; i < count; i++) {
2028 uint32_t num_remainder, denom_remainder;
2029 uint64_t num_result, denom_result;
2030 if (checkUint32Bounary &&
2031 num <= max_int32 && denom <= max_int32) {
2032 ret = true;
2033 break;
2034 }
2035 do {
2036 num_result = div_u64_rem(num, prime_numbers[i], &num_remainder);
2037 denom_result = div_u64_rem(denom, prime_numbers[i], &denom_remainder);
2038 if (num_remainder == 0 && denom_remainder == 0) {
2039 num = num_result;
2040 denom = denom_result;
2041 }
2042 } while (num_remainder == 0 && denom_remainder == 0);
2043 }
2044 *numerator = num;
2045 *denominator = denom;
2046 return ret;
2047 }
2048
2049 static bool is_low_refresh_rate(struct pipe_ctx *pipe)
2050 {
2051 uint32_t master_pipe_refresh_rate =
2052 pipe->stream->timing.pix_clk_100hz * 100 /
2053 pipe->stream->timing.h_total /
2054 pipe->stream->timing.v_total;
2055 return master_pipe_refresh_rate <= 30;
2056 }
2057
2058 static uint8_t get_clock_divider(struct pipe_ctx *pipe,
2059 bool account_low_refresh_rate)
2060 {
2061 uint32_t clock_divider = 1;
2062 uint32_t numpipes = 1;
2063
2064 if (account_low_refresh_rate && is_low_refresh_rate(pipe))
2065 clock_divider *= 2;
2066
2067 if (pipe->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420)
2068 clock_divider *= 2;
2069
2070 while (pipe->next_odm_pipe) {
2071 pipe = pipe->next_odm_pipe;
2072 numpipes++;
2073 }
2074 clock_divider *= numpipes;
2075
2076 return clock_divider;
2077 }
2078
2079 static int dcn10_align_pixel_clocks(struct dc *dc, int group_size,
2080 struct pipe_ctx *grouped_pipes[])
2081 {
2082 struct dc_context *dc_ctx = dc->ctx;
2083 int i, master = -1, embedded = -1;
2084 struct dc_crtc_timing *hw_crtc_timing;
2085 uint64_t phase[MAX_PIPES];
2086 uint64_t modulo[MAX_PIPES];
2087 unsigned int pclk;
2088
2089 uint32_t embedded_pix_clk_100hz;
2090 uint16_t embedded_h_total;
2091 uint16_t embedded_v_total;
2092 uint32_t dp_ref_clk_100hz =
2093 dc->res_pool->dp_clock_source->ctx->dc->clk_mgr->dprefclk_khz*10;
2094
2095 hw_crtc_timing = kcalloc(MAX_PIPES, sizeof(*hw_crtc_timing), GFP_KERNEL);
2096 if (!hw_crtc_timing)
2097 return master;
2098
2099 if (dc->config.vblank_alignment_dto_params &&
2100 dc->res_pool->dp_clock_source->funcs->override_dp_pix_clk) {
2101 embedded_h_total =
2102 (dc->config.vblank_alignment_dto_params >> 32) & 0x7FFF;
2103 embedded_v_total =
2104 (dc->config.vblank_alignment_dto_params >> 48) & 0x7FFF;
2105 embedded_pix_clk_100hz =
2106 dc->config.vblank_alignment_dto_params & 0xFFFFFFFF;
2107
2108 for (i = 0; i < group_size; i++) {
2109 grouped_pipes[i]->stream_res.tg->funcs->get_hw_timing(
2110 grouped_pipes[i]->stream_res.tg,
2111 &hw_crtc_timing[i]);
2112 dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
2113 dc->res_pool->dp_clock_source,
2114 grouped_pipes[i]->stream_res.tg->inst,
2115 &pclk);
2116 hw_crtc_timing[i].pix_clk_100hz = pclk;
2117 if (dc_is_embedded_signal(
2118 grouped_pipes[i]->stream->signal)) {
2119 embedded = i;
2120 master = i;
2121 phase[i] = embedded_pix_clk_100hz*100;
2122 modulo[i] = dp_ref_clk_100hz*100;
2123 } else {
2124
2125 phase[i] = (uint64_t)embedded_pix_clk_100hz*
2126 hw_crtc_timing[i].h_total*
2127 hw_crtc_timing[i].v_total;
2128 phase[i] = div_u64(phase[i], get_clock_divider(grouped_pipes[i], true));
2129 modulo[i] = (uint64_t)dp_ref_clk_100hz*
2130 embedded_h_total*
2131 embedded_v_total;
2132
2133 if (reduceSizeAndFraction(&phase[i],
2134 &modulo[i], true) == false) {
2135
2136
2137
2138
2139 DC_SYNC_INFO("Failed to reduce DTO parameters\n");
2140 grouped_pipes[i]->stream->has_non_synchronizable_pclk = true;
2141 }
2142 }
2143 }
2144
2145 for (i = 0; i < group_size; i++) {
2146 if (i != embedded && !grouped_pipes[i]->stream->has_non_synchronizable_pclk) {
2147 dc->res_pool->dp_clock_source->funcs->override_dp_pix_clk(
2148 dc->res_pool->dp_clock_source,
2149 grouped_pipes[i]->stream_res.tg->inst,
2150 phase[i], modulo[i]);
2151 dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
2152 dc->res_pool->dp_clock_source,
2153 grouped_pipes[i]->stream_res.tg->inst, &pclk);
2154 grouped_pipes[i]->stream->timing.pix_clk_100hz =
2155 pclk*get_clock_divider(grouped_pipes[i], false);
2156 if (master == -1)
2157 master = i;
2158 }
2159 }
2160
2161 }
2162
2163 kfree(hw_crtc_timing);
2164 return master;
2165 }
2166
2167 void dcn10_enable_vblanks_synchronization(
2168 struct dc *dc,
2169 int group_index,
2170 int group_size,
2171 struct pipe_ctx *grouped_pipes[])
2172 {
2173 struct dc_context *dc_ctx = dc->ctx;
2174 struct output_pixel_processor *opp;
2175 struct timing_generator *tg;
2176 int i, width, height, master;
2177
2178 for (i = 1; i < group_size; i++) {
2179 opp = grouped_pipes[i]->stream_res.opp;
2180 tg = grouped_pipes[i]->stream_res.tg;
2181 tg->funcs->get_otg_active_size(tg, &width, &height);
2182 if (opp->funcs->opp_program_dpg_dimensions)
2183 opp->funcs->opp_program_dpg_dimensions(opp, width, 2*(height) + 1);
2184 }
2185
2186 for (i = 0; i < group_size; i++) {
2187 if (grouped_pipes[i]->stream == NULL)
2188 continue;
2189 grouped_pipes[i]->stream->vblank_synchronized = false;
2190 grouped_pipes[i]->stream->has_non_synchronizable_pclk = false;
2191 }
2192
2193 DC_SYNC_INFO("Aligning DP DTOs\n");
2194
2195 master = dcn10_align_pixel_clocks(dc, group_size, grouped_pipes);
2196
2197 DC_SYNC_INFO("Synchronizing VBlanks\n");
2198
2199 if (master >= 0) {
2200 for (i = 0; i < group_size; i++) {
2201 if (i != master && !grouped_pipes[i]->stream->has_non_synchronizable_pclk)
2202 grouped_pipes[i]->stream_res.tg->funcs->align_vblanks(
2203 grouped_pipes[master]->stream_res.tg,
2204 grouped_pipes[i]->stream_res.tg,
2205 grouped_pipes[master]->stream->timing.pix_clk_100hz,
2206 grouped_pipes[i]->stream->timing.pix_clk_100hz,
2207 get_clock_divider(grouped_pipes[master], false),
2208 get_clock_divider(grouped_pipes[i], false));
2209 grouped_pipes[i]->stream->vblank_synchronized = true;
2210 }
2211 grouped_pipes[master]->stream->vblank_synchronized = true;
2212 DC_SYNC_INFO("Sync complete\n");
2213 }
2214
2215 for (i = 1; i < group_size; i++) {
2216 opp = grouped_pipes[i]->stream_res.opp;
2217 tg = grouped_pipes[i]->stream_res.tg;
2218 tg->funcs->get_otg_active_size(tg, &width, &height);
2219 if (opp->funcs->opp_program_dpg_dimensions)
2220 opp->funcs->opp_program_dpg_dimensions(opp, width, height);
2221 }
2222 }
2223
2224 void dcn10_enable_timing_synchronization(
2225 struct dc *dc,
2226 int group_index,
2227 int group_size,
2228 struct pipe_ctx *grouped_pipes[])
2229 {
2230 struct dc_context *dc_ctx = dc->ctx;
2231 struct output_pixel_processor *opp;
2232 struct timing_generator *tg;
2233 int i, width, height;
2234
2235 DC_SYNC_INFO("Setting up OTG reset trigger\n");
2236
2237 for (i = 1; i < group_size; i++) {
2238 opp = grouped_pipes[i]->stream_res.opp;
2239 tg = grouped_pipes[i]->stream_res.tg;
2240 tg->funcs->get_otg_active_size(tg, &width, &height);
2241 if (opp->funcs->opp_program_dpg_dimensions)
2242 opp->funcs->opp_program_dpg_dimensions(opp, width, 2*(height) + 1);
2243 }
2244
2245 for (i = 0; i < group_size; i++) {
2246 if (grouped_pipes[i]->stream == NULL)
2247 continue;
2248 grouped_pipes[i]->stream->vblank_synchronized = false;
2249 }
2250
2251 for (i = 1; i < group_size; i++)
2252 grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
2253 grouped_pipes[i]->stream_res.tg,
2254 grouped_pipes[0]->stream_res.tg->inst);
2255
2256 DC_SYNC_INFO("Waiting for trigger\n");
2257
2258
2259
2260
2261
2262 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->stream_res.tg);
2263 for (i = 1; i < group_size; i++)
2264 grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
2265 grouped_pipes[i]->stream_res.tg);
2266
2267 for (i = 1; i < group_size; i++) {
2268 opp = grouped_pipes[i]->stream_res.opp;
2269 tg = grouped_pipes[i]->stream_res.tg;
2270 tg->funcs->get_otg_active_size(tg, &width, &height);
2271 if (opp->funcs->opp_program_dpg_dimensions)
2272 opp->funcs->opp_program_dpg_dimensions(opp, width, height);
2273 }
2274
2275 DC_SYNC_INFO("Sync complete\n");
2276 }
2277
2278 void dcn10_enable_per_frame_crtc_position_reset(
2279 struct dc *dc,
2280 int group_size,
2281 struct pipe_ctx *grouped_pipes[])
2282 {
2283 struct dc_context *dc_ctx = dc->ctx;
2284 int i;
2285
2286 DC_SYNC_INFO("Setting up\n");
2287 for (i = 0; i < group_size; i++)
2288 if (grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset)
2289 grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset(
2290 grouped_pipes[i]->stream_res.tg,
2291 0,
2292 &grouped_pipes[i]->stream->triggered_crtc_reset);
2293
2294 DC_SYNC_INFO("Waiting for trigger\n");
2295
2296 for (i = 0; i < group_size; i++)
2297 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
2298
2299 DC_SYNC_INFO("Multi-display sync is complete\n");
2300 }
2301
2302 static void mmhub_read_vm_system_aperture_settings(struct dcn10_hubp *hubp1,
2303 struct vm_system_aperture_param *apt,
2304 struct dce_hwseq *hws)
2305 {
2306 PHYSICAL_ADDRESS_LOC physical_page_number;
2307 uint32_t logical_addr_low;
2308 uint32_t logical_addr_high;
2309
2310 REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
2311 PHYSICAL_PAGE_NUMBER_MSB, &physical_page_number.high_part);
2312 REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
2313 PHYSICAL_PAGE_NUMBER_LSB, &physical_page_number.low_part);
2314
2315 REG_GET(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
2316 LOGICAL_ADDR, &logical_addr_low);
2317
2318 REG_GET(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
2319 LOGICAL_ADDR, &logical_addr_high);
2320
2321 apt->sys_default.quad_part = physical_page_number.quad_part << 12;
2322 apt->sys_low.quad_part = (int64_t)logical_addr_low << 18;
2323 apt->sys_high.quad_part = (int64_t)logical_addr_high << 18;
2324 }
2325
2326
2327 static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1,
2328 struct vm_context0_param *vm0,
2329 struct dce_hwseq *hws)
2330 {
2331 PHYSICAL_ADDRESS_LOC fb_base;
2332 PHYSICAL_ADDRESS_LOC fb_offset;
2333 uint32_t fb_base_value;
2334 uint32_t fb_offset_value;
2335
2336 REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, &fb_base_value);
2337 REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, &fb_offset_value);
2338
2339 REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
2340 PAGE_DIRECTORY_ENTRY_HI32, &vm0->pte_base.high_part);
2341 REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
2342 PAGE_DIRECTORY_ENTRY_LO32, &vm0->pte_base.low_part);
2343
2344 REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
2345 LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_start.high_part);
2346 REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
2347 LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_start.low_part);
2348
2349 REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
2350 LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_end.high_part);
2351 REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
2352 LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_end.low_part);
2353
2354 REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
2355 PHYSICAL_PAGE_ADDR_HI4, &vm0->fault_default.high_part);
2356 REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
2357 PHYSICAL_PAGE_ADDR_LO32, &vm0->fault_default.low_part);
2358
2359
2360
2361
2362
2363
2364
2365 fb_base.quad_part = (uint64_t)fb_base_value << 24;
2366 fb_offset.quad_part = (uint64_t)fb_offset_value << 24;
2367 vm0->pte_base.quad_part += fb_base.quad_part;
2368 vm0->pte_base.quad_part -= fb_offset.quad_part;
2369 }
2370
2371
2372 static void dcn10_program_pte_vm(struct dce_hwseq *hws, struct hubp *hubp)
2373 {
2374 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
2375 struct vm_system_aperture_param apt = {0};
2376 struct vm_context0_param vm0 = {0};
2377
2378 mmhub_read_vm_system_aperture_settings(hubp1, &apt, hws);
2379 mmhub_read_vm_context0_settings(hubp1, &vm0, hws);
2380
2381 hubp->funcs->hubp_set_vm_system_aperture_settings(hubp, &apt);
2382 hubp->funcs->hubp_set_vm_context0_settings(hubp, &vm0);
2383 }
2384
2385 static void dcn10_enable_plane(
2386 struct dc *dc,
2387 struct pipe_ctx *pipe_ctx,
2388 struct dc_state *context)
2389 {
2390 struct dce_hwseq *hws = dc->hwseq;
2391
2392 if (dc->debug.sanity_checks) {
2393 hws->funcs.verify_allow_pstate_change_high(dc);
2394 }
2395
2396 undo_DEGVIDCN10_253_wa(dc);
2397
2398 power_on_plane(dc->hwseq,
2399 pipe_ctx->plane_res.hubp->inst);
2400
2401
2402 pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true);
2403
2404
2405 pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
2406 pipe_ctx->stream_res.opp,
2407 true);
2408
2409 if (dc->config.gpu_vm_support)
2410 dcn10_program_pte_vm(hws, pipe_ctx->plane_res.hubp);
2411
2412 if (dc->debug.sanity_checks) {
2413 hws->funcs.verify_allow_pstate_change_high(dc);
2414 }
2415
2416 if (!pipe_ctx->top_pipe
2417 && pipe_ctx->plane_state
2418 && pipe_ctx->plane_state->flip_int_enabled
2419 && pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_int)
2420 pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_int(pipe_ctx->plane_res.hubp);
2421
2422 }
2423
2424 void dcn10_program_gamut_remap(struct pipe_ctx *pipe_ctx)
2425 {
2426 int i = 0;
2427 struct dpp_grph_csc_adjustment adjust;
2428 memset(&adjust, 0, sizeof(adjust));
2429 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2430
2431
2432 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
2433 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2434 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
2435 adjust.temperature_matrix[i] =
2436 pipe_ctx->stream->gamut_remap_matrix.matrix[i];
2437 } else if (pipe_ctx->plane_state &&
2438 pipe_ctx->plane_state->gamut_remap_matrix.enable_remap == true) {
2439 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2440 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
2441 adjust.temperature_matrix[i] =
2442 pipe_ctx->plane_state->gamut_remap_matrix.matrix[i];
2443 }
2444
2445 pipe_ctx->plane_res.dpp->funcs->dpp_set_gamut_remap(pipe_ctx->plane_res.dpp, &adjust);
2446 }
2447
2448
2449 static bool dcn10_is_rear_mpo_fix_required(struct pipe_ctx *pipe_ctx, enum dc_color_space colorspace)
2450 {
2451 if (pipe_ctx->plane_state && pipe_ctx->plane_state->layer_index > 0 && is_rgb_cspace(colorspace)) {
2452 if (pipe_ctx->top_pipe) {
2453 struct pipe_ctx *top = pipe_ctx->top_pipe;
2454
2455 while (top->top_pipe)
2456 top = top->top_pipe;
2457 if (top->plane_state && top->plane_state->layer_index == 0)
2458 return true;
2459 }
2460 }
2461 return false;
2462 }
2463
2464 static void dcn10_set_csc_adjustment_rgb_mpo_fix(struct pipe_ctx *pipe_ctx, uint16_t *matrix)
2465 {
2466
2467 uint16_t rgb_bias = matrix[3];
2468
2469 matrix[3] = 0;
2470 matrix[7] = 0;
2471 matrix[11] = 0;
2472 pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
2473 matrix[3] = rgb_bias;
2474 matrix[7] = rgb_bias;
2475 matrix[11] = rgb_bias;
2476 }
2477
2478 void dcn10_program_output_csc(struct dc *dc,
2479 struct pipe_ctx *pipe_ctx,
2480 enum dc_color_space colorspace,
2481 uint16_t *matrix,
2482 int opp_id)
2483 {
2484 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
2485 if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL) {
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495 int16_t rgb_bias = matrix[3];
2496
2497
2498 if (rgb_bias > 0 && dcn10_is_rear_mpo_fix_required(pipe_ctx, colorspace)) {
2499 dcn10_set_csc_adjustment_rgb_mpo_fix(pipe_ctx, matrix);
2500 } else {
2501 pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
2502 }
2503 }
2504 } else {
2505 if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default != NULL)
2506 pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default(pipe_ctx->plane_res.dpp, colorspace);
2507 }
2508 }
2509
2510 static void dcn10_update_dpp(struct dpp *dpp, struct dc_plane_state *plane_state)
2511 {
2512 struct dc_bias_and_scale bns_params = {0};
2513
2514
2515 dpp->funcs->dpp_setup(dpp,
2516 plane_state->format,
2517 EXPANSION_MODE_ZERO,
2518 plane_state->input_csc_color_matrix,
2519 plane_state->color_space,
2520 NULL);
2521
2522
2523 build_prescale_params(&bns_params, plane_state);
2524 if (dpp->funcs->dpp_program_bias_and_scale)
2525 dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
2526 }
2527
2528 void dcn10_update_visual_confirm_color(struct dc *dc, struct pipe_ctx *pipe_ctx, struct tg_color *color, int mpcc_id)
2529 {
2530 struct mpc *mpc = dc->res_pool->mpc;
2531
2532 if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR)
2533 get_hdr_visual_confirm_color(pipe_ctx, color);
2534 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE)
2535 get_surface_visual_confirm_color(pipe_ctx, color);
2536 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SWIZZLE)
2537 get_surface_tile_visual_confirm_color(pipe_ctx, color);
2538 else
2539 color_space_to_black_color(
2540 dc, pipe_ctx->stream->output_color_space, color);
2541
2542 if (mpc->funcs->set_bg_color)
2543 mpc->funcs->set_bg_color(mpc, color, mpcc_id);
2544 }
2545
2546 void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
2547 {
2548 struct hubp *hubp = pipe_ctx->plane_res.hubp;
2549 struct mpcc_blnd_cfg blnd_cfg = {0};
2550 bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
2551 int mpcc_id;
2552 struct mpcc *new_mpcc;
2553 struct mpc *mpc = dc->res_pool->mpc;
2554 struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
2555
2556 blnd_cfg.overlap_only = false;
2557 blnd_cfg.global_gain = 0xff;
2558
2559 if (per_pixel_alpha) {
2560
2561
2562
2563 blnd_cfg.pre_multiplied_alpha = (is_rgb_cspace(
2564 pipe_ctx->stream->output_color_space)
2565 && pipe_ctx->plane_state->pre_multiplied_alpha);
2566 if (pipe_ctx->plane_state->global_alpha) {
2567 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN;
2568 blnd_cfg.global_gain = pipe_ctx->plane_state->global_alpha_value;
2569 } else {
2570 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
2571 }
2572 } else {
2573 blnd_cfg.pre_multiplied_alpha = false;
2574 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
2575 }
2576
2577 if (pipe_ctx->plane_state->global_alpha)
2578 blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value;
2579 else
2580 blnd_cfg.global_alpha = 0xff;
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590 mpcc_id = hubp->inst;
2591
2592
2593 if (!pipe_ctx->plane_state->update_flags.bits.full_update) {
2594 mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id);
2595 dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
2596 return;
2597 }
2598
2599
2600 new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id);
2601
2602 if (new_mpcc != NULL)
2603 mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc);
2604 else
2605 if (dc->debug.sanity_checks)
2606 mpc->funcs->assert_mpcc_idle_before_connect(
2607 dc->res_pool->mpc, mpcc_id);
2608
2609
2610 new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc,
2611 mpc_tree_params,
2612 &blnd_cfg,
2613 NULL,
2614 NULL,
2615 hubp->inst,
2616 mpcc_id);
2617 dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
2618
2619 ASSERT(new_mpcc != NULL);
2620 hubp->opp_id = pipe_ctx->stream_res.opp->inst;
2621 hubp->mpcc_id = mpcc_id;
2622 }
2623
2624 static void update_scaler(struct pipe_ctx *pipe_ctx)
2625 {
2626 bool per_pixel_alpha =
2627 pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
2628
2629 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha;
2630 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_36BPP;
2631
2632 pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler(
2633 pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data);
2634 }
2635
2636 static void dcn10_update_dchubp_dpp(
2637 struct dc *dc,
2638 struct pipe_ctx *pipe_ctx,
2639 struct dc_state *context)
2640 {
2641 struct dce_hwseq *hws = dc->hwseq;
2642 struct hubp *hubp = pipe_ctx->plane_res.hubp;
2643 struct dpp *dpp = pipe_ctx->plane_res.dpp;
2644 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2645 struct plane_size size = plane_state->plane_size;
2646 unsigned int compat_level = 0;
2647 bool should_divided_by_2 = false;
2648
2649
2650
2651
2652
2653 if (plane_state->update_flags.bits.full_update) {
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680 if (context->bw_ctx.bw.dcn.clk.dispclk_khz <
2681 dc->clk_mgr->clks.dispclk_khz)
2682 should_divided_by_2 = false;
2683 else
2684 should_divided_by_2 =
2685 context->bw_ctx.bw.dcn.clk.dppclk_khz <=
2686 dc->clk_mgr->clks.dispclk_khz / 2;
2687
2688 dpp->funcs->dpp_dppclk_control(
2689 dpp,
2690 should_divided_by_2,
2691 true);
2692
2693 if (dc->res_pool->dccg)
2694 dc->res_pool->dccg->funcs->update_dpp_dto(
2695 dc->res_pool->dccg,
2696 dpp->inst,
2697 pipe_ctx->plane_res.bw.dppclk_khz);
2698 else
2699 dc->clk_mgr->clks.dppclk_khz = should_divided_by_2 ?
2700 dc->clk_mgr->clks.dispclk_khz / 2 :
2701 dc->clk_mgr->clks.dispclk_khz;
2702 }
2703
2704
2705
2706
2707
2708 if (plane_state->update_flags.bits.full_update) {
2709 hubp->funcs->hubp_vtg_sel(hubp, pipe_ctx->stream_res.tg->inst);
2710
2711 hubp->funcs->hubp_setup(
2712 hubp,
2713 &pipe_ctx->dlg_regs,
2714 &pipe_ctx->ttu_regs,
2715 &pipe_ctx->rq_regs,
2716 &pipe_ctx->pipe_dlg_param);
2717 hubp->funcs->hubp_setup_interdependent(
2718 hubp,
2719 &pipe_ctx->dlg_regs,
2720 &pipe_ctx->ttu_regs);
2721 }
2722
2723 size.surface_size = pipe_ctx->plane_res.scl_data.viewport;
2724
2725 if (plane_state->update_flags.bits.full_update ||
2726 plane_state->update_flags.bits.bpp_change)
2727 dcn10_update_dpp(dpp, plane_state);
2728
2729 if (plane_state->update_flags.bits.full_update ||
2730 plane_state->update_flags.bits.per_pixel_alpha_change ||
2731 plane_state->update_flags.bits.global_alpha_change)
2732 hws->funcs.update_mpcc(dc, pipe_ctx);
2733
2734 if (plane_state->update_flags.bits.full_update ||
2735 plane_state->update_flags.bits.per_pixel_alpha_change ||
2736 plane_state->update_flags.bits.global_alpha_change ||
2737 plane_state->update_flags.bits.scaling_change ||
2738 plane_state->update_flags.bits.position_change) {
2739 update_scaler(pipe_ctx);
2740 }
2741
2742 if (plane_state->update_flags.bits.full_update ||
2743 plane_state->update_flags.bits.scaling_change ||
2744 plane_state->update_flags.bits.position_change) {
2745 hubp->funcs->mem_program_viewport(
2746 hubp,
2747 &pipe_ctx->plane_res.scl_data.viewport,
2748 &pipe_ctx->plane_res.scl_data.viewport_c);
2749 }
2750
2751 if (pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {
2752 dc->hwss.set_cursor_position(pipe_ctx);
2753 dc->hwss.set_cursor_attribute(pipe_ctx);
2754
2755 if (dc->hwss.set_cursor_sdr_white_level)
2756 dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
2757 }
2758
2759 if (plane_state->update_flags.bits.full_update) {
2760
2761 dc->hwss.program_gamut_remap(pipe_ctx);
2762
2763 dc->hwss.program_output_csc(dc,
2764 pipe_ctx,
2765 pipe_ctx->stream->output_color_space,
2766 pipe_ctx->stream->csc_color_matrix.matrix,
2767 pipe_ctx->stream_res.opp->inst);
2768 }
2769
2770 if (plane_state->update_flags.bits.full_update ||
2771 plane_state->update_flags.bits.pixel_format_change ||
2772 plane_state->update_flags.bits.horizontal_mirror_change ||
2773 plane_state->update_flags.bits.rotation_change ||
2774 plane_state->update_flags.bits.swizzle_change ||
2775 plane_state->update_flags.bits.dcc_change ||
2776 plane_state->update_flags.bits.bpp_change ||
2777 plane_state->update_flags.bits.scaling_change ||
2778 plane_state->update_flags.bits.plane_size_change) {
2779 hubp->funcs->hubp_program_surface_config(
2780 hubp,
2781 plane_state->format,
2782 &plane_state->tiling_info,
2783 &size,
2784 plane_state->rotation,
2785 &plane_state->dcc,
2786 plane_state->horizontal_mirror,
2787 compat_level);
2788 }
2789
2790 hubp->power_gated = false;
2791
2792 hws->funcs.update_plane_addr(dc, pipe_ctx);
2793
2794 if (is_pipe_tree_visible(pipe_ctx))
2795 hubp->funcs->set_blank(hubp, false);
2796 }
2797
2798 void dcn10_blank_pixel_data(
2799 struct dc *dc,
2800 struct pipe_ctx *pipe_ctx,
2801 bool blank)
2802 {
2803 enum dc_color_space color_space;
2804 struct tg_color black_color = {0};
2805 struct stream_resource *stream_res = &pipe_ctx->stream_res;
2806 struct dc_stream_state *stream = pipe_ctx->stream;
2807
2808
2809 color_space = stream->output_color_space;
2810 color_space_to_black_color(dc, color_space, &black_color);
2811
2812
2813
2814
2815
2816
2817 if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
2818 black_color.color_r_cr = black_color.color_g_y;
2819
2820
2821 if (stream_res->tg->funcs->set_blank_color)
2822 stream_res->tg->funcs->set_blank_color(
2823 stream_res->tg,
2824 &black_color);
2825
2826 if (!blank) {
2827 if (stream_res->tg->funcs->set_blank)
2828 stream_res->tg->funcs->set_blank(stream_res->tg, blank);
2829 if (stream_res->abm) {
2830 dc->hwss.set_pipe(pipe_ctx);
2831 stream_res->abm->funcs->set_abm_level(stream_res->abm, stream->abm_level);
2832 }
2833 } else if (blank) {
2834 dc->hwss.set_abm_immediate_disable(pipe_ctx);
2835 if (stream_res->tg->funcs->set_blank) {
2836 stream_res->tg->funcs->wait_for_state(stream_res->tg, CRTC_STATE_VBLANK);
2837 stream_res->tg->funcs->set_blank(stream_res->tg, blank);
2838 }
2839 }
2840 }
2841
2842 void dcn10_set_hdr_multiplier(struct pipe_ctx *pipe_ctx)
2843 {
2844 struct fixed31_32 multiplier = pipe_ctx->plane_state->hdr_mult;
2845 uint32_t hw_mult = 0x1f000;
2846 struct custom_float_format fmt;
2847
2848 fmt.exponenta_bits = 6;
2849 fmt.mantissa_bits = 12;
2850 fmt.sign = true;
2851
2852
2853 if (!dc_fixpt_eq(multiplier, dc_fixpt_from_int(0)))
2854 convert_to_custom_float_format(multiplier, &fmt, &hw_mult);
2855
2856 pipe_ctx->plane_res.dpp->funcs->dpp_set_hdr_multiplier(
2857 pipe_ctx->plane_res.dpp, hw_mult);
2858 }
2859
2860 void dcn10_program_pipe(
2861 struct dc *dc,
2862 struct pipe_ctx *pipe_ctx,
2863 struct dc_state *context)
2864 {
2865 struct dce_hwseq *hws = dc->hwseq;
2866
2867 if (pipe_ctx->top_pipe == NULL) {
2868 bool blank = !is_pipe_tree_visible(pipe_ctx);
2869
2870 pipe_ctx->stream_res.tg->funcs->program_global_sync(
2871 pipe_ctx->stream_res.tg,
2872 pipe_ctx->pipe_dlg_param.vready_offset,
2873 pipe_ctx->pipe_dlg_param.vstartup_start,
2874 pipe_ctx->pipe_dlg_param.vupdate_offset,
2875 pipe_ctx->pipe_dlg_param.vupdate_width);
2876
2877 pipe_ctx->stream_res.tg->funcs->set_vtg_params(
2878 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, true);
2879
2880 if (hws->funcs.setup_vupdate_interrupt)
2881 hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
2882
2883 hws->funcs.blank_pixel_data(dc, pipe_ctx, blank);
2884 }
2885
2886 if (pipe_ctx->plane_state->update_flags.bits.full_update)
2887 dcn10_enable_plane(dc, pipe_ctx, context);
2888
2889 dcn10_update_dchubp_dpp(dc, pipe_ctx, context);
2890
2891 hws->funcs.set_hdr_multiplier(pipe_ctx);
2892
2893 if (pipe_ctx->plane_state->update_flags.bits.full_update ||
2894 pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
2895 pipe_ctx->plane_state->update_flags.bits.gamma_change)
2896 hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state);
2897
2898
2899
2900
2901
2902
2903
2904 if (pipe_ctx->plane_state->update_flags.bits.full_update)
2905 hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
2906 }
2907
2908 void dcn10_wait_for_pending_cleared(struct dc *dc,
2909 struct dc_state *context)
2910 {
2911 struct pipe_ctx *pipe_ctx;
2912 struct timing_generator *tg;
2913 int i;
2914
2915 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2916 pipe_ctx = &context->res_ctx.pipe_ctx[i];
2917 tg = pipe_ctx->stream_res.tg;
2918
2919
2920
2921
2922
2923 if (pipe_ctx->top_pipe ||
2924 !pipe_ctx->stream || !pipe_ctx->plane_state ||
2925 !tg->funcs->is_tg_enabled(tg))
2926 continue;
2927
2928
2929
2930
2931
2932
2933
2934
2935 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK);
2936 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
2937 }
2938 }
2939
2940 void dcn10_post_unlock_program_front_end(
2941 struct dc *dc,
2942 struct dc_state *context)
2943 {
2944 int i;
2945
2946 DC_LOGGER_INIT(dc->ctx->logger);
2947
2948 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2949 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2950
2951 if (!pipe_ctx->top_pipe &&
2952 !pipe_ctx->prev_odm_pipe &&
2953 pipe_ctx->stream) {
2954 struct timing_generator *tg = pipe_ctx->stream_res.tg;
2955
2956 if (context->stream_status[i].plane_count == 0)
2957 false_optc_underflow_wa(dc, pipe_ctx->stream, tg);
2958 }
2959 }
2960
2961 for (i = 0; i < dc->res_pool->pipe_count; i++)
2962 if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable)
2963 dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
2964
2965 for (i = 0; i < dc->res_pool->pipe_count; i++)
2966 if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) {
2967 dc->hwss.optimize_bandwidth(dc, context);
2968 break;
2969 }
2970
2971 if (dc->hwseq->wa.DEGVIDCN10_254)
2972 hubbub1_wm_change_req_wa(dc->res_pool->hubbub);
2973 }
2974
2975 static void dcn10_stereo_hw_frame_pack_wa(struct dc *dc, struct dc_state *context)
2976 {
2977 uint8_t i;
2978
2979 for (i = 0; i < context->stream_count; i++) {
2980 if (context->streams[i]->timing.timing_3d_format
2981 == TIMING_3D_FORMAT_HW_FRAME_PACKING) {
2982
2983
2984
2985 hubbub1_allow_self_refresh_control(dc->res_pool->hubbub, false);
2986 break;
2987 }
2988 }
2989 }
2990
2991 void dcn10_prepare_bandwidth(
2992 struct dc *dc,
2993 struct dc_state *context)
2994 {
2995 struct dce_hwseq *hws = dc->hwseq;
2996 struct hubbub *hubbub = dc->res_pool->hubbub;
2997
2998 if (dc->debug.sanity_checks)
2999 hws->funcs.verify_allow_pstate_change_high(dc);
3000
3001 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
3002 if (context->stream_count == 0)
3003 context->bw_ctx.bw.dcn.clk.phyclk_khz = 0;
3004
3005 dc->clk_mgr->funcs->update_clocks(
3006 dc->clk_mgr,
3007 context,
3008 false);
3009 }
3010
3011 dc->wm_optimized_required = hubbub->funcs->program_watermarks(hubbub,
3012 &context->bw_ctx.bw.dcn.watermarks,
3013 dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
3014 true);
3015 dcn10_stereo_hw_frame_pack_wa(dc, context);
3016
3017 if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) {
3018 DC_FP_START();
3019 dcn_bw_notify_pplib_of_wm_ranges(dc);
3020 DC_FP_END();
3021 }
3022
3023 if (dc->debug.sanity_checks)
3024 hws->funcs.verify_allow_pstate_change_high(dc);
3025 }
3026
3027 void dcn10_optimize_bandwidth(
3028 struct dc *dc,
3029 struct dc_state *context)
3030 {
3031 struct dce_hwseq *hws = dc->hwseq;
3032 struct hubbub *hubbub = dc->res_pool->hubbub;
3033
3034 if (dc->debug.sanity_checks)
3035 hws->funcs.verify_allow_pstate_change_high(dc);
3036
3037 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
3038 if (context->stream_count == 0)
3039 context->bw_ctx.bw.dcn.clk.phyclk_khz = 0;
3040
3041 dc->clk_mgr->funcs->update_clocks(
3042 dc->clk_mgr,
3043 context,
3044 true);
3045 }
3046
3047 hubbub->funcs->program_watermarks(hubbub,
3048 &context->bw_ctx.bw.dcn.watermarks,
3049 dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
3050 true);
3051
3052 dcn10_stereo_hw_frame_pack_wa(dc, context);
3053
3054 if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) {
3055 DC_FP_START();
3056 dcn_bw_notify_pplib_of_wm_ranges(dc);
3057 DC_FP_END();
3058 }
3059
3060 if (dc->debug.sanity_checks)
3061 hws->funcs.verify_allow_pstate_change_high(dc);
3062 }
3063
3064 void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
3065 int num_pipes, struct dc_crtc_timing_adjust adjust)
3066 {
3067 int i = 0;
3068 struct drr_params params = {0};
3069
3070 unsigned int event_triggers = 0x800;
3071
3072 unsigned int num_frames = 2;
3073
3074 params.vertical_total_max = adjust.v_total_max;
3075 params.vertical_total_min = adjust.v_total_min;
3076 params.vertical_total_mid = adjust.v_total_mid;
3077 params.vertical_total_mid_frame_num = adjust.v_total_mid_frame_num;
3078
3079
3080
3081
3082 for (i = 0; i < num_pipes; i++) {
3083 if ((pipe_ctx[i]->stream_res.tg != NULL) && pipe_ctx[i]->stream_res.tg->funcs) {
3084 if (pipe_ctx[i]->stream_res.tg->funcs->set_drr)
3085 pipe_ctx[i]->stream_res.tg->funcs->set_drr(
3086 pipe_ctx[i]->stream_res.tg, ¶ms);
3087 if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
3088 if (pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control)
3089 pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control(
3090 pipe_ctx[i]->stream_res.tg,
3091 event_triggers, num_frames);
3092 }
3093 }
3094 }
3095
3096 void dcn10_get_position(struct pipe_ctx **pipe_ctx,
3097 int num_pipes,
3098 struct crtc_position *position)
3099 {
3100 int i = 0;
3101
3102
3103
3104 for (i = 0; i < num_pipes; i++)
3105 pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position);
3106 }
3107
3108 void dcn10_set_static_screen_control(struct pipe_ctx **pipe_ctx,
3109 int num_pipes, const struct dc_static_screen_params *params)
3110 {
3111 unsigned int i;
3112 unsigned int triggers = 0;
3113
3114 if (params->triggers.surface_update)
3115 triggers |= 0x80;
3116 if (params->triggers.cursor_update)
3117 triggers |= 0x2;
3118 if (params->triggers.force_trigger)
3119 triggers |= 0x1;
3120
3121 for (i = 0; i < num_pipes; i++)
3122 pipe_ctx[i]->stream_res.tg->funcs->
3123 set_static_screen_control(pipe_ctx[i]->stream_res.tg,
3124 triggers, params->num_frames);
3125 }
3126
3127 static void dcn10_config_stereo_parameters(
3128 struct dc_stream_state *stream, struct crtc_stereo_flags *flags)
3129 {
3130 enum view_3d_format view_format = stream->view_format;
3131 enum dc_timing_3d_format timing_3d_format =\
3132 stream->timing.timing_3d_format;
3133 bool non_stereo_timing = false;
3134
3135 if (timing_3d_format == TIMING_3D_FORMAT_NONE ||
3136 timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE ||
3137 timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM)
3138 non_stereo_timing = true;
3139
3140 if (non_stereo_timing == false &&
3141 view_format == VIEW_3D_FORMAT_FRAME_SEQUENTIAL) {
3142
3143 flags->PROGRAM_STEREO = 1;
3144 flags->PROGRAM_POLARITY = 1;
3145 if (timing_3d_format == TIMING_3D_FORMAT_FRAME_ALTERNATE ||
3146 timing_3d_format == TIMING_3D_FORMAT_INBAND_FA ||
3147 timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA ||
3148 timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) {
3149 enum display_dongle_type dongle = \
3150 stream->link->ddc->dongle_type;
3151 if (dongle == DISPLAY_DONGLE_DP_VGA_CONVERTER ||
3152 dongle == DISPLAY_DONGLE_DP_DVI_CONVERTER ||
3153 dongle == DISPLAY_DONGLE_DP_HDMI_CONVERTER)
3154 flags->DISABLE_STEREO_DP_SYNC = 1;
3155 }
3156 flags->RIGHT_EYE_POLARITY =\
3157 stream->timing.flags.RIGHT_EYE_3D_POLARITY;
3158 if (timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
3159 flags->FRAME_PACKED = 1;
3160 }
3161
3162 return;
3163 }
3164
3165 void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc)
3166 {
3167 struct crtc_stereo_flags flags = { 0 };
3168 struct dc_stream_state *stream = pipe_ctx->stream;
3169
3170 dcn10_config_stereo_parameters(stream, &flags);
3171
3172 if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) {
3173 if (!dc_set_generic_gpio_for_stereo(true, dc->ctx->gpio_service))
3174 dc_set_generic_gpio_for_stereo(false, dc->ctx->gpio_service);
3175 } else {
3176 dc_set_generic_gpio_for_stereo(false, dc->ctx->gpio_service);
3177 }
3178
3179 pipe_ctx->stream_res.opp->funcs->opp_program_stereo(
3180 pipe_ctx->stream_res.opp,
3181 flags.PROGRAM_STEREO == 1,
3182 &stream->timing);
3183
3184 pipe_ctx->stream_res.tg->funcs->program_stereo(
3185 pipe_ctx->stream_res.tg,
3186 &stream->timing,
3187 &flags);
3188
3189 return;
3190 }
3191
3192 static struct hubp *get_hubp_by_inst(struct resource_pool *res_pool, int mpcc_inst)
3193 {
3194 int i;
3195
3196 for (i = 0; i < res_pool->pipe_count; i++) {
3197 if (res_pool->hubps[i]->inst == mpcc_inst)
3198 return res_pool->hubps[i];
3199 }
3200 ASSERT(false);
3201 return NULL;
3202 }
3203
3204 void dcn10_wait_for_mpcc_disconnect(
3205 struct dc *dc,
3206 struct resource_pool *res_pool,
3207 struct pipe_ctx *pipe_ctx)
3208 {
3209 struct dce_hwseq *hws = dc->hwseq;
3210 int mpcc_inst;
3211
3212 if (dc->debug.sanity_checks) {
3213 hws->funcs.verify_allow_pstate_change_high(dc);
3214 }
3215
3216 if (!pipe_ctx->stream_res.opp)
3217 return;
3218
3219 for (mpcc_inst = 0; mpcc_inst < MAX_PIPES; mpcc_inst++) {
3220 if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst]) {
3221 struct hubp *hubp = get_hubp_by_inst(res_pool, mpcc_inst);
3222
3223 if (pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg))
3224 res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst);
3225 pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false;
3226 hubp->funcs->set_blank(hubp, true);
3227 }
3228 }
3229
3230 if (dc->debug.sanity_checks) {
3231 hws->funcs.verify_allow_pstate_change_high(dc);
3232 }
3233
3234 }
3235
3236 bool dcn10_dummy_display_power_gating(
3237 struct dc *dc,
3238 uint8_t controller_id,
3239 struct dc_bios *dcb,
3240 enum pipe_gating_control power_gating)
3241 {
3242 return true;
3243 }
3244
3245 void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx)
3246 {
3247 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
3248 struct timing_generator *tg = pipe_ctx->stream_res.tg;
3249 bool flip_pending;
3250 struct dc *dc = pipe_ctx->stream->ctx->dc;
3251
3252 if (plane_state == NULL)
3253 return;
3254
3255 flip_pending = pipe_ctx->plane_res.hubp->funcs->hubp_is_flip_pending(
3256 pipe_ctx->plane_res.hubp);
3257
3258 plane_state->status.is_flip_pending = plane_state->status.is_flip_pending || flip_pending;
3259
3260 if (!flip_pending)
3261 plane_state->status.current_address = plane_state->status.requested_address;
3262
3263 if (plane_state->status.current_address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
3264 tg->funcs->is_stereo_left_eye) {
3265 plane_state->status.is_right_eye =
3266 !tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg);
3267 }
3268
3269 if (dc->hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied) {
3270 struct dce_hwseq *hwseq = dc->hwseq;
3271 struct timing_generator *tg = dc->res_pool->timing_generators[0];
3272 unsigned int cur_frame = tg->funcs->get_frame_count(tg);
3273
3274 if (cur_frame != hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied_on_frame) {
3275 struct hubbub *hubbub = dc->res_pool->hubbub;
3276
3277 hubbub->funcs->allow_self_refresh_control(hubbub, !dc->debug.disable_stutter);
3278 hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied = false;
3279 }
3280 }
3281 }
3282
3283 void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data)
3284 {
3285 struct hubbub *hubbub = hws->ctx->dc->res_pool->hubbub;
3286
3287
3288 hubbub->funcs->update_dchub(hubbub, dh_data);
3289 }
3290
3291 static bool dcn10_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx)
3292 {
3293 struct pipe_ctx *test_pipe, *split_pipe;
3294 const struct scaler_data *scl_data = &pipe_ctx->plane_res.scl_data;
3295 struct rect r1 = scl_data->recout, r2, r2_half;
3296 int r1_r = r1.x + r1.width, r1_b = r1.y + r1.height, r2_r, r2_b;
3297 int cur_layer = pipe_ctx->plane_state->layer_index;
3298
3299
3300
3301
3302
3303
3304 for (test_pipe = pipe_ctx->top_pipe; test_pipe;
3305 test_pipe = test_pipe->top_pipe) {
3306
3307 if (!test_pipe->plane_state->visible || test_pipe->plane_state->layer_index == cur_layer)
3308 continue;
3309
3310 r2 = test_pipe->plane_res.scl_data.recout;
3311 r2_r = r2.x + r2.width;
3312 r2_b = r2.y + r2.height;
3313 split_pipe = test_pipe;
3314
3315
3316
3317
3318
3319 for (split_pipe = pipe_ctx->top_pipe; split_pipe;
3320 split_pipe = split_pipe->top_pipe)
3321 if (split_pipe->plane_state->layer_index == test_pipe->plane_state->layer_index) {
3322 r2_half = split_pipe->plane_res.scl_data.recout;
3323 r2.x = (r2_half.x < r2.x) ? r2_half.x : r2.x;
3324 r2.width = r2.width + r2_half.width;
3325 r2_r = r2.x + r2.width;
3326 break;
3327 }
3328
3329 if (r1.x >= r2.x && r1.y >= r2.y && r1_r <= r2_r && r1_b <= r2_b)
3330 return true;
3331 }
3332
3333 return false;
3334 }
3335
3336 static bool dcn10_dmub_should_update_cursor_data(
3337 struct pipe_ctx *pipe_ctx,
3338 struct dc_debug_options *debug)
3339 {
3340 if (pipe_ctx->plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
3341 return false;
3342
3343 if (pipe_ctx->stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1)
3344 return true;
3345
3346 if (pipe_ctx->stream->link->psr_settings.psr_version == DC_PSR_VERSION_1 &&
3347 debug->enable_sw_cntl_psr)
3348 return true;
3349
3350 return false;
3351 }
3352
3353 static void dcn10_dmub_update_cursor_data(
3354 struct pipe_ctx *pipe_ctx,
3355 struct hubp *hubp,
3356 const struct dc_cursor_mi_param *param,
3357 const struct dc_cursor_position *cur_pos,
3358 const struct dc_cursor_attributes *cur_attr)
3359 {
3360 union dmub_rb_cmd cmd;
3361 struct dmub_cmd_update_cursor_info_data *update_cursor_info;
3362 const struct dc_cursor_position *pos;
3363 const struct dc_cursor_attributes *attr;
3364 int src_x_offset = 0;
3365 int src_y_offset = 0;
3366 int x_hotspot = 0;
3367 int cursor_height = 0;
3368 int cursor_width = 0;
3369 uint32_t cur_en = 0;
3370 unsigned int panel_inst = 0;
3371
3372 struct dc_debug_options *debug = &hubp->ctx->dc->debug;
3373
3374 if (!dcn10_dmub_should_update_cursor_data(pipe_ctx, debug))
3375 return;
3376
3377
3378
3379
3380
3381
3382
3383 if (cur_pos != NULL)
3384 pos = cur_pos;
3385 else
3386 pos = &hubp->curs_pos;
3387
3388 if (cur_attr != NULL)
3389 attr = cur_attr;
3390 else
3391 attr = &hubp->curs_attr;
3392
3393 if (!dc_get_edp_link_panel_inst(hubp->ctx->dc, pipe_ctx->stream->link, &panel_inst))
3394 return;
3395
3396 src_x_offset = pos->x - pos->x_hotspot - param->viewport.x;
3397 src_y_offset = pos->y - pos->y_hotspot - param->viewport.y;
3398 x_hotspot = pos->x_hotspot;
3399 cursor_height = (int)attr->height;
3400 cursor_width = (int)attr->width;
3401 cur_en = pos->enable ? 1:0;
3402
3403
3404 if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) {
3405 swap(cursor_height, cursor_width);
3406 if (param->rotation == ROTATION_ANGLE_90) {
3407 src_x_offset = pos->x - pos->y_hotspot - param->viewport.x;
3408 src_y_offset = pos->y - pos->x_hotspot - param->viewport.y;
3409 }
3410 } else if (param->rotation == ROTATION_ANGLE_180) {
3411 src_x_offset = pos->x - param->viewport.x;
3412 src_y_offset = pos->y - param->viewport.y;
3413 }
3414
3415 if (param->mirror) {
3416 x_hotspot = param->viewport.width - x_hotspot;
3417 src_x_offset = param->viewport.x + param->viewport.width - src_x_offset;
3418 }
3419
3420 if (src_x_offset >= (int)param->viewport.width)
3421 cur_en = 0;
3422
3423 if (src_x_offset + cursor_width <= 0)
3424 cur_en = 0;
3425
3426 if (src_y_offset >= (int)param->viewport.height)
3427 cur_en = 0;
3428
3429 if (src_y_offset + cursor_height <= 0)
3430 cur_en = 0;
3431
3432
3433
3434 if (src_x_offset < 0)
3435 src_x_offset = 0;
3436 if (src_y_offset < 0)
3437 src_y_offset = 0;
3438
3439 memset(&cmd, 0x0, sizeof(cmd));
3440 cmd.update_cursor_info.header.type = DMUB_CMD__UPDATE_CURSOR_INFO;
3441 cmd.update_cursor_info.header.payload_bytes =
3442 sizeof(cmd.update_cursor_info.update_cursor_info_data);
3443 update_cursor_info = &cmd.update_cursor_info.update_cursor_info_data;
3444 update_cursor_info->cursor_rect.x = src_x_offset + param->viewport.x;
3445 update_cursor_info->cursor_rect.y = src_y_offset + param->viewport.y;
3446 update_cursor_info->cursor_rect.width = attr->width;
3447 update_cursor_info->cursor_rect.height = attr->height;
3448 update_cursor_info->enable = cur_en;
3449 update_cursor_info->pipe_idx = pipe_ctx->pipe_idx;
3450 update_cursor_info->cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
3451 update_cursor_info->panel_inst = panel_inst;
3452 dc_dmub_srv_cmd_queue(pipe_ctx->stream->ctx->dmub_srv, &cmd);
3453 dc_dmub_srv_cmd_execute(pipe_ctx->stream->ctx->dmub_srv);
3454 dc_dmub_srv_wait_idle(pipe_ctx->stream->ctx->dmub_srv);
3455 }
3456
3457 void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
3458 {
3459 struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
3460 struct hubp *hubp = pipe_ctx->plane_res.hubp;
3461 struct dpp *dpp = pipe_ctx->plane_res.dpp;
3462 struct dc_cursor_mi_param param = {
3463 .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10,
3464 .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz,
3465 .viewport = pipe_ctx->plane_res.scl_data.viewport,
3466 .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz,
3467 .v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert,
3468 .rotation = pipe_ctx->plane_state->rotation,
3469 .mirror = pipe_ctx->plane_state->horizontal_mirror
3470 };
3471 bool pipe_split_on = (pipe_ctx->top_pipe != NULL) ||
3472 (pipe_ctx->bottom_pipe != NULL);
3473 bool odm_combine_on = (pipe_ctx->next_odm_pipe != NULL) ||
3474 (pipe_ctx->prev_odm_pipe != NULL);
3475
3476 int x_plane = pipe_ctx->plane_state->dst_rect.x;
3477 int y_plane = pipe_ctx->plane_state->dst_rect.y;
3478 int x_pos = pos_cpy.x;
3479 int y_pos = pos_cpy.y;
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498 if (param.rotation == ROTATION_ANGLE_90 || param.rotation == ROTATION_ANGLE_270) {
3499 x_pos = (x_pos - x_plane) * pipe_ctx->plane_state->src_rect.height /
3500 pipe_ctx->plane_state->dst_rect.width;
3501 y_pos = (y_pos - y_plane) * pipe_ctx->plane_state->src_rect.width /
3502 pipe_ctx->plane_state->dst_rect.height;
3503 } else {
3504 x_pos = (x_pos - x_plane) * pipe_ctx->plane_state->src_rect.width /
3505 pipe_ctx->plane_state->dst_rect.width;
3506 y_pos = (y_pos - y_plane) * pipe_ctx->plane_state->src_rect.height /
3507 pipe_ctx->plane_state->dst_rect.height;
3508 }
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522 if (pos_cpy.translate_by_source) {
3523 x_pos += pipe_ctx->plane_state->src_rect.x;
3524 y_pos += pipe_ctx->plane_state->src_rect.y;
3525 }
3526
3527
3528
3529
3530
3531
3532 if (x_pos < 0) {
3533 pos_cpy.x_hotspot -= x_pos;
3534 x_pos = 0;
3535 }
3536
3537 if (y_pos < 0) {
3538 pos_cpy.y_hotspot -= y_pos;
3539 y_pos = 0;
3540 }
3541
3542 pos_cpy.x = (uint32_t)x_pos;
3543 pos_cpy.y = (uint32_t)y_pos;
3544
3545 if (pipe_ctx->plane_state->address.type
3546 == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
3547 pos_cpy.enable = false;
3548
3549 if (pos_cpy.enable && dcn10_can_pipe_disable_cursor(pipe_ctx))
3550 pos_cpy.enable = false;
3551
3552
3553 if (param.rotation == ROTATION_ANGLE_90) {
3554 uint32_t temp_x = pos_cpy.x;
3555
3556 pos_cpy.x = pipe_ctx->plane_res.scl_data.viewport.width -
3557 (pos_cpy.y - pipe_ctx->plane_res.scl_data.viewport.x) + pipe_ctx->plane_res.scl_data.viewport.x;
3558 pos_cpy.y = temp_x;
3559 }
3560
3561 else if (param.rotation == ROTATION_ANGLE_270) {
3562 uint32_t temp_y = pos_cpy.y;
3563 int viewport_height =
3564 pipe_ctx->plane_res.scl_data.viewport.height;
3565 int viewport_y =
3566 pipe_ctx->plane_res.scl_data.viewport.y;
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581 if (pipe_split_on || odm_combine_on) {
3582 int pos_cpy_x_offset;
3583 int other_pipe_viewport_y;
3584
3585 if (pipe_split_on) {
3586 if (pipe_ctx->bottom_pipe) {
3587 other_pipe_viewport_y =
3588 pipe_ctx->bottom_pipe->plane_res.scl_data.viewport.y;
3589 } else {
3590 other_pipe_viewport_y =
3591 pipe_ctx->top_pipe->plane_res.scl_data.viewport.y;
3592 }
3593 } else {
3594 if (pipe_ctx->next_odm_pipe) {
3595 other_pipe_viewport_y =
3596 pipe_ctx->next_odm_pipe->plane_res.scl_data.viewport.y;
3597 } else {
3598 other_pipe_viewport_y =
3599 pipe_ctx->prev_odm_pipe->plane_res.scl_data.viewport.y;
3600 }
3601 }
3602 pos_cpy_x_offset = (viewport_y > other_pipe_viewport_y) ?
3603 other_pipe_viewport_y : viewport_y;
3604 pos_cpy.x -= pos_cpy_x_offset;
3605 if (pos_cpy.x > viewport_height) {
3606 pos_cpy.x = pos_cpy.x - viewport_height;
3607 pos_cpy.y = viewport_height - pos_cpy.x;
3608 } else {
3609 pos_cpy.y = 2 * viewport_height - pos_cpy.x;
3610 }
3611 pos_cpy.y += pos_cpy_x_offset;
3612 } else {
3613 pos_cpy.y = (2 * viewport_y) + viewport_height - pos_cpy.x;
3614 }
3615 pos_cpy.x = temp_y;
3616 }
3617
3618 else if (param.rotation == ROTATION_ANGLE_180) {
3619 int viewport_width =
3620 pipe_ctx->plane_res.scl_data.viewport.width;
3621 int viewport_x =
3622 pipe_ctx->plane_res.scl_data.viewport.x;
3623
3624 if (pipe_split_on || odm_combine_on) {
3625 if (pos_cpy.x >= viewport_width + viewport_x) {
3626 pos_cpy.x = 2 * viewport_width
3627 - pos_cpy.x + 2 * viewport_x;
3628 } else {
3629 uint32_t temp_x = pos_cpy.x;
3630
3631 pos_cpy.x = 2 * viewport_x - pos_cpy.x;
3632 if (temp_x >= viewport_x +
3633 (int)hubp->curs_attr.width || pos_cpy.x
3634 <= (int)hubp->curs_attr.width +
3635 pipe_ctx->plane_state->src_rect.x) {
3636 pos_cpy.x = temp_x + viewport_width;
3637 }
3638 }
3639 } else {
3640 pos_cpy.x = viewport_width - pos_cpy.x + 2 * viewport_x;
3641 }
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651 pos_cpy.y = (2 * pipe_ctx->plane_res.scl_data.viewport.y) +
3652 pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.y;
3653 }
3654
3655 dcn10_dmub_update_cursor_data(pipe_ctx, hubp, ¶m, &pos_cpy, NULL);
3656 hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m);
3657 dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width, hubp->curs_attr.height);
3658 }
3659
3660 void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
3661 {
3662 struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
3663 struct dc_cursor_mi_param param = { 0 };
3664
3665
3666
3667
3668
3669
3670
3671
3672 if (pipe_ctx->plane_state != NULL) {
3673 param.pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10;
3674 param.ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz;
3675 param.viewport = pipe_ctx->plane_res.scl_data.viewport;
3676 param.h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz;
3677 param.v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert;
3678 param.rotation = pipe_ctx->plane_state->rotation;
3679 param.mirror = pipe_ctx->plane_state->horizontal_mirror;
3680 dcn10_dmub_update_cursor_data(pipe_ctx, pipe_ctx->plane_res.hubp, ¶m, NULL, attributes);
3681 }
3682
3683 pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes(
3684 pipe_ctx->plane_res.hubp, attributes);
3685 pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes(
3686 pipe_ctx->plane_res.dpp, attributes);
3687 }
3688
3689 void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx)
3690 {
3691 uint32_t sdr_white_level = pipe_ctx->stream->cursor_attributes.sdr_white_level;
3692 struct fixed31_32 multiplier;
3693 struct dpp_cursor_attributes opt_attr = { 0 };
3694 uint32_t hw_scale = 0x3c00;
3695 struct custom_float_format fmt;
3696
3697 if (!pipe_ctx->plane_res.dpp->funcs->set_optional_cursor_attributes)
3698 return;
3699
3700 fmt.exponenta_bits = 5;
3701 fmt.mantissa_bits = 10;
3702 fmt.sign = true;
3703
3704 if (sdr_white_level > 80) {
3705 multiplier = dc_fixpt_from_fraction(sdr_white_level, 80);
3706 convert_to_custom_float_format(multiplier, &fmt, &hw_scale);
3707 }
3708
3709 opt_attr.scale = hw_scale;
3710 opt_attr.bias = 0;
3711
3712 pipe_ctx->plane_res.dpp->funcs->set_optional_cursor_attributes(
3713 pipe_ctx->plane_res.dpp, &opt_attr);
3714 }
3715
3716
3717
3718
3719
3720
3721
3722 static void apply_front_porch_workaround(
3723 struct dc_crtc_timing *timing)
3724 {
3725 if (timing->flags.INTERLACE == 1) {
3726 if (timing->v_front_porch < 2)
3727 timing->v_front_porch = 2;
3728 } else {
3729 if (timing->v_front_porch < 1)
3730 timing->v_front_porch = 1;
3731 }
3732 }
3733
3734 int dcn10_get_vupdate_offset_from_vsync(struct pipe_ctx *pipe_ctx)
3735 {
3736 const struct dc_crtc_timing *dc_crtc_timing = &pipe_ctx->stream->timing;
3737 struct dc_crtc_timing patched_crtc_timing;
3738 int vesa_sync_start;
3739 int asic_blank_end;
3740 int interlace_factor;
3741 int vertical_line_start;
3742
3743 patched_crtc_timing = *dc_crtc_timing;
3744 apply_front_porch_workaround(&patched_crtc_timing);
3745
3746 interlace_factor = patched_crtc_timing.flags.INTERLACE ? 2 : 1;
3747
3748 vesa_sync_start = patched_crtc_timing.v_addressable +
3749 patched_crtc_timing.v_border_bottom +
3750 patched_crtc_timing.v_front_porch;
3751
3752 asic_blank_end = (patched_crtc_timing.v_total -
3753 vesa_sync_start -
3754 patched_crtc_timing.v_border_top)
3755 * interlace_factor;
3756
3757 vertical_line_start = asic_blank_end -
3758 pipe_ctx->pipe_dlg_param.vstartup_start + 1;
3759
3760 return vertical_line_start;
3761 }
3762
3763 void dcn10_calc_vupdate_position(
3764 struct dc *dc,
3765 struct pipe_ctx *pipe_ctx,
3766 uint32_t *start_line,
3767 uint32_t *end_line)
3768 {
3769 const struct dc_crtc_timing *dc_crtc_timing = &pipe_ctx->stream->timing;
3770 int vline_int_offset_from_vupdate =
3771 pipe_ctx->stream->periodic_interrupt0.lines_offset;
3772 int vupdate_offset_from_vsync = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
3773 int start_position;
3774
3775 if (vline_int_offset_from_vupdate > 0)
3776 vline_int_offset_from_vupdate--;
3777 else if (vline_int_offset_from_vupdate < 0)
3778 vline_int_offset_from_vupdate++;
3779
3780 start_position = vline_int_offset_from_vupdate + vupdate_offset_from_vsync;
3781
3782 if (start_position >= 0)
3783 *start_line = start_position;
3784 else
3785 *start_line = dc_crtc_timing->v_total + start_position - 1;
3786
3787 *end_line = *start_line + 2;
3788
3789 if (*end_line >= dc_crtc_timing->v_total)
3790 *end_line = 2;
3791 }
3792
3793 static void dcn10_cal_vline_position(
3794 struct dc *dc,
3795 struct pipe_ctx *pipe_ctx,
3796 enum vline_select vline,
3797 uint32_t *start_line,
3798 uint32_t *end_line)
3799 {
3800 enum vertical_interrupt_ref_point ref_point = INVALID_POINT;
3801
3802 if (vline == VLINE0)
3803 ref_point = pipe_ctx->stream->periodic_interrupt0.ref_point;
3804 else if (vline == VLINE1)
3805 ref_point = pipe_ctx->stream->periodic_interrupt1.ref_point;
3806
3807 switch (ref_point) {
3808 case START_V_UPDATE:
3809 dcn10_calc_vupdate_position(
3810 dc,
3811 pipe_ctx,
3812 start_line,
3813 end_line);
3814 break;
3815 case START_V_SYNC:
3816
3817 break;
3818 default:
3819 ASSERT(0);
3820 break;
3821 }
3822 }
3823
3824 void dcn10_setup_periodic_interrupt(
3825 struct dc *dc,
3826 struct pipe_ctx *pipe_ctx,
3827 enum vline_select vline)
3828 {
3829 struct timing_generator *tg = pipe_ctx->stream_res.tg;
3830
3831 if (vline == VLINE0) {
3832 uint32_t start_line = 0;
3833 uint32_t end_line = 0;
3834
3835 dcn10_cal_vline_position(dc, pipe_ctx, vline, &start_line, &end_line);
3836
3837 tg->funcs->setup_vertical_interrupt0(tg, start_line, end_line);
3838
3839 } else if (vline == VLINE1) {
3840 pipe_ctx->stream_res.tg->funcs->setup_vertical_interrupt1(
3841 tg,
3842 pipe_ctx->stream->periodic_interrupt1.lines_offset);
3843 }
3844 }
3845
3846 void dcn10_setup_vupdate_interrupt(struct dc *dc, struct pipe_ctx *pipe_ctx)
3847 {
3848 struct timing_generator *tg = pipe_ctx->stream_res.tg;
3849 int start_line = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
3850
3851 if (start_line < 0) {
3852 ASSERT(0);
3853 start_line = 0;
3854 }
3855
3856 if (tg->funcs->setup_vertical_interrupt2)
3857 tg->funcs->setup_vertical_interrupt2(tg, start_line);
3858 }
3859
3860 void dcn10_unblank_stream(struct pipe_ctx *pipe_ctx,
3861 struct dc_link_settings *link_settings)
3862 {
3863 struct encoder_unblank_param params = {0};
3864 struct dc_stream_state *stream = pipe_ctx->stream;
3865 struct dc_link *link = stream->link;
3866 struct dce_hwseq *hws = link->dc->hwseq;
3867
3868
3869 params.timing = pipe_ctx->stream->timing;
3870
3871 params.link_settings.link_rate = link_settings->link_rate;
3872
3873 if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
3874 if (params.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
3875 params.timing.pix_clk_100hz /= 2;
3876 pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, ¶ms);
3877 }
3878
3879 if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
3880 hws->funcs.edp_backlight_control(link, true);
3881 }
3882 }
3883
3884 void dcn10_send_immediate_sdp_message(struct pipe_ctx *pipe_ctx,
3885 const uint8_t *custom_sdp_message,
3886 unsigned int sdp_message_size)
3887 {
3888 if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
3889 pipe_ctx->stream_res.stream_enc->funcs->send_immediate_sdp_message(
3890 pipe_ctx->stream_res.stream_enc,
3891 custom_sdp_message,
3892 sdp_message_size);
3893 }
3894 }
3895 enum dc_status dcn10_set_clock(struct dc *dc,
3896 enum dc_clock_type clock_type,
3897 uint32_t clk_khz,
3898 uint32_t stepping)
3899 {
3900 struct dc_state *context = dc->current_state;
3901 struct dc_clock_config clock_cfg = {0};
3902 struct dc_clocks *current_clocks = &context->bw_ctx.bw.dcn.clk;
3903
3904 if (!dc->clk_mgr || !dc->clk_mgr->funcs->get_clock)
3905 return DC_FAIL_UNSUPPORTED_1;
3906
3907 dc->clk_mgr->funcs->get_clock(dc->clk_mgr,
3908 context, clock_type, &clock_cfg);
3909
3910 if (clk_khz > clock_cfg.max_clock_khz)
3911 return DC_FAIL_CLK_EXCEED_MAX;
3912
3913 if (clk_khz < clock_cfg.min_clock_khz)
3914 return DC_FAIL_CLK_BELOW_MIN;
3915
3916 if (clk_khz < clock_cfg.bw_requirequired_clock_khz)
3917 return DC_FAIL_CLK_BELOW_CFG_REQUIRED;
3918
3919
3920 if (clock_type == DC_CLOCK_TYPE_DISPCLK)
3921 current_clocks->dispclk_khz = clk_khz;
3922 else if (clock_type == DC_CLOCK_TYPE_DPPCLK)
3923 current_clocks->dppclk_khz = clk_khz;
3924 else
3925 return DC_ERROR_UNEXPECTED;
3926
3927 if (dc->clk_mgr->funcs->update_clocks)
3928 dc->clk_mgr->funcs->update_clocks(dc->clk_mgr,
3929 context, true);
3930 return DC_OK;
3931
3932 }
3933
3934 void dcn10_get_clock(struct dc *dc,
3935 enum dc_clock_type clock_type,
3936 struct dc_clock_config *clock_cfg)
3937 {
3938 struct dc_state *context = dc->current_state;
3939
3940 if (dc->clk_mgr && dc->clk_mgr->funcs->get_clock)
3941 dc->clk_mgr->funcs->get_clock(dc->clk_mgr, context, clock_type, clock_cfg);
3942
3943 }
3944
3945 void dcn10_get_dcc_en_bits(struct dc *dc, int *dcc_en_bits)
3946 {
3947 struct resource_pool *pool = dc->res_pool;
3948 int i;
3949
3950 for (i = 0; i < pool->pipe_count; i++) {
3951 struct hubp *hubp = pool->hubps[i];
3952 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(hubp)->state);
3953
3954 hubp->funcs->hubp_read_state(hubp);
3955
3956 if (!s->blank_en)
3957 dcc_en_bits[i] = s->dcc_en ? 1 : 0;
3958 }
3959 }